def test_boids(smarts, scenarios, bubble): # TODO: this is a hack to specify a seed to make this test pass seed(int(os.getenv("PYTHONHASHSEED", 42))) scenario = next(scenarios) smarts.reset(scenario) index = smarts.vehicle_index geometry = bubble_geometry(bubble, smarts.road_network) triggered_multiple_vehicles_in_bubble = False triggered_multiple_vehicles_airlocked = False # vehicle: steps per zone steps_driven_in_zones = defaultdict(lambda: ZoneSteps()) # TODO: It's possible that multiple vehicles get spawned within the 500 steps but # not all of them make it through the bubble completely causing the test to # fail. for _ in range(500): smarts.step({}) hijacked_actor_ids = [] shadowed_actor_ids = [] for vehicle in index.vehicles: position = Point(vehicle.position) in_bubble = position.within(geometry.bubble) is_shadowing = index.shadow_actor_id_from_vehicle_id( vehicle.id) is not None is_agent_controlled = vehicle.id in index.agent_vehicle_ids zone_steps = steps_driven_in_zones[vehicle.id] if position.within(geometry.bubble): zone_steps.in_bubble += 1 hijacked_actor_ids.append( index.actor_id_from_vehicle_id(vehicle.id)) assert in_bubble and not is_shadowing and is_agent_controlled elif position.within(geometry.airlock_entry): zone_steps.airlock_entry += 1 shadowed_actor_ids.append( index.shadow_actor_id_from_vehicle_id(vehicle.id)) assert not in_bubble and is_shadowing and not is_agent_controlled elif position.within(geometry.airlock_exit): zone_steps.airlock_exit += 1 # TODO: Presently not implemented, but `is_shadowing` should be True assert not in_bubble and not is_shadowing and is_agent_controlled else: zone_steps.outside_bubble += 1 assert not in_bubble and not is_shadowing and not is_agent_controlled if len(hijacked_actor_ids) > 1: triggered_multiple_vehicles_in_bubble = True if len(shadowed_actor_ids) > 1: triggered_multiple_vehicles_airlocked = True assert (len(set(hijacked_actor_ids)) <= 1), "Boid vehicles must be controlled by the same actor" assert (len(set(shadowed_actor_ids)) <= 1), "Boid vehicles must be shadowed by the same actor" # Just to have some padding, we want to be in each region at least 5 steps min_steps = 5 for vehicle_id, zone in steps_driven_in_zones.items(): assert all([ zone.in_bubble > min_steps, zone.outside_bubble > min_steps, zone.airlock_entry > min_steps, zone.airlock_exit > min_steps, ]), (f"vehicle_id={vehicle_id}, zone={zone} doesn't meet " f"min_steps={min_steps} requirement") assert (triggered_multiple_vehicles_in_bubble ), "Multiple vehicles did not enter the bubble simultaneously" assert (triggered_multiple_vehicles_airlocked ), "Multiple vehicles were not airlocked simultaneously"
def test_bubble_hijacking(smarts, scenarios, bubbles, num_vehicles): """Ensures bubble airlocking, hijacking, and relinquishing are functional. Additionally, we test with multiple bubbles and vehicles to ensure operation is correct in these conditions as well. """ scenario = next(scenarios) smarts.reset(scenario) index = smarts.vehicle_index geometries = [bubble_geometry(b, smarts.road_network) for b in bubbles] # bubble: vehicle: steps per zone steps_driven_in_zones = { b.id: defaultdict(lambda: ZoneSteps()) for b in bubbles } vehicles_made_to_through_bubble = {b.id: [] for b in bubbles} for _ in range(300): smarts.step({}) for vehicle in index.vehicles: for bubble, geometry in zip(bubbles, geometries): position = Point(vehicle.position) in_bubble = position.within(geometry.bubble) is_shadowing = (index.shadow_actor_id_from_vehicle_id( vehicle.id) is not None) is_agent_controlled = vehicle.id in index.agent_vehicle_ids() zone_steps = steps_driven_in_zones[bubble.id][vehicle.id] if position.within(geometry.bubble): zone_steps.in_bubble += 1 assert in_bubble and not is_shadowing and is_agent_controlled elif position.within(geometry.airlock_entry): zone_steps.airlock_entry += 1 assert not in_bubble and is_shadowing and not is_agent_controlled elif position.within(geometry.airlock_exit): zone_steps.airlock_exit += 1 # TODO: Presently not implemented, but `is_shadowing` should be True assert not in_bubble and not is_shadowing and is_agent_controlled if vehicle.id not in vehicles_made_to_through_bubble[ bubble.id]: vehicles_made_to_through_bubble[bubble.id].append( vehicle.id) elif not any( [position.within(geom.airlock) for geom in geometries]): # Not in any bubble; airlock is the encompassing region zone_steps.outside_bubble += 1 assert (not in_bubble and not is_shadowing and not is_agent_controlled) # Just to have some padding, we want to be in each region at least 5 steps min_steps = 5 for bubble_id, zones in steps_driven_in_zones.items(): vehicle_ids = vehicles_made_to_through_bubble[bubble_id] assert (len(vehicle_ids) >= num_vehicles), "Insufficient no. vehicles drove through bubble" for vehicle_id in vehicle_ids[:num_vehicles]: zone = zones[vehicle_id] assert all([ zone.in_bubble > min_steps, zone.outside_bubble > min_steps, zone.airlock_entry > min_steps, zone.airlock_exit > min_steps, ]), ( f"bubble={bubble_id}, vehicle_id={vehicle_id}, zone={zone} doesn't meet " f"min_steps={min_steps} requirement")