// // ConcurrencyTests.swift // SportsTimeTests // // Phase 10: Concurrency Tests // Documents current thread-safety behavior for future refactoring reference. // import Testing import CoreLocation @testable import SportsTime @Suite("Concurrency Tests", .serialized) struct ConcurrencyTests { // MARK: - Test Fixtures private let calendar = Calendar.current /// Creates a date with specific year/month/day/hour private func makeDate(year: Int = 2026, month: Int = 6, day: Int, hour: Int = 19) -> Date { var components = DateComponents() components.year = year components.month = month components.day = day components.hour = hour components.minute = 0 return calendar.date(from: components)! } /// Creates a stadium at a known location private func makeStadium( id: UUID = UUID(), city: String, lat: Double, lon: Double, sport: Sport = .mlb ) -> Stadium { Stadium( id: id, name: "\(city) Stadium", city: city, state: "ST", latitude: lat, longitude: lon, capacity: 40000, sport: sport ) } /// Creates a game at a stadium private func makeGame( id: UUID = UUID(), stadiumId: UUID, homeTeamId: UUID = UUID(), awayTeamId: UUID = UUID(), dateTime: Date, sport: Sport = .mlb ) -> Game { Game( id: id, homeTeamId: homeTeamId, awayTeamId: awayTeamId, stadiumId: stadiumId, dateTime: dateTime, sport: sport, season: "2026" ) } /// Creates a PlanningRequest for Scenario A (date range only) private func makeScenarioARequest( startDate: Date, endDate: Date, games: [Game], stadiums: [UUID: Stadium] ) -> PlanningRequest { let preferences = TripPreferences( planningMode: .dateRange, sports: [.mlb], startDate: startDate, endDate: endDate, leisureLevel: .moderate, numberOfDrivers: 1, maxDrivingHoursPerDriver: 8.0, allowRepeatCities: true ) return PlanningRequest( preferences: preferences, availableGames: games, teams: [:], stadiums: stadiums ) } /// Creates a valid test request with nearby cities private func makeValidTestRequest(requestIndex: Int) -> PlanningRequest { // Use different but nearby city pairs for each request to create variety let cityPairs: [(city1: (String, Double, Double), city2: (String, Double, Double))] = [ (("Chicago", 41.8781, -87.6298), ("Milwaukee", 43.0389, -87.9065)), (("New York", 40.7128, -73.9352), ("Philadelphia", 39.9526, -75.1652)), (("Boston", 42.3601, -71.0589), ("Providence", 41.8240, -71.4128)), (("Los Angeles", 34.0522, -118.2437), ("San Diego", 32.7157, -117.1611)), (("Seattle", 47.6062, -122.3321), ("Portland", 45.5152, -122.6784)), ] let pair = cityPairs[requestIndex % cityPairs.count] let stadium1Id = UUID() let stadium2Id = UUID() let stadium1 = makeStadium(id: stadium1Id, city: pair.city1.0, lat: pair.city1.1, lon: pair.city1.2) let stadium2 = makeStadium(id: stadium2Id, city: pair.city2.0, lat: pair.city2.1, lon: pair.city2.2) let stadiums = [stadium1Id: stadium1, stadium2Id: stadium2] // Games on different days for feasible routing let baseDay = 5 + (requestIndex * 2) % 20 let game1 = makeGame(stadiumId: stadium1Id, dateTime: makeDate(day: baseDay, hour: 19)) let game2 = makeGame(stadiumId: stadium2Id, dateTime: makeDate(day: baseDay + 2, hour: 19)) return makeScenarioARequest( startDate: makeDate(day: baseDay - 1, hour: 0), endDate: makeDate(day: baseDay + 5, hour: 23), games: [game1, game2], stadiums: stadiums ) } // MARK: - 10.1: Concurrent Requests Test @Test("10.1 - Concurrent requests behavior documentation") func test_engine_ConcurrentRequests_CurrentlyUnsafe() async { // DOCUMENTATION TEST // Purpose: Document the current behavior when TripPlanningEngine is called concurrently. // // Current Implementation Status: // - TripPlanningEngine is a `final class` (not an actor) // - It appears stateless - no mutable instance state persists between calls // - Each call to planItineraries creates fresh planner instances // // Expected Behavior: // - If truly stateless: concurrent calls should succeed independently // - If hidden state exists: may see race conditions or crashes // // This test documents the current behavior for future refactoring reference. let concurrentRequestCount = 10 let engine = TripPlanningEngine() // Create unique requests for each concurrent task let requests = (0..