Path: blob/main/tests/tools/turndefs/generateTurnDefs/unit_tests/unittests.py
428465 views
#!/usr/bin/env python1# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2# Copyright (C) 2018-2026 German Aerospace Center (DLR) and others.3# This program and the accompanying materials are made available under the4# terms of the Eclipse Public License 2.0 which is available at5# https://www.eclipse.org/legal/epl-2.0/6# This Source Code may also be made available under the following Secondary7# Licenses when the conditions for such availability set forth in the Eclipse8# Public License 2.0 are satisfied: GNU General Public License, version 29# or later which is available at10# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later1213# @file unittests.py14# @author Michael Behrisch15# @date 2019-01-091617from __future__ import absolute_import18from __future__ import print_function1920import sys21import os22import logging23import unittest2425# Do not use SUMO_HOME here to ensure you are always testing the26# functions from the same tree the test is in27sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', '..', 'tools', 'turn-defs'))28import connections # noqa29import turndefinitions # noqa303132class CollectingHandler(logging.Handler):3334""" Handler for loggers from logging module. Collects all log messages. """3536def __init__(self, level=0):37""" Constructor. The level parameter stands for logging level. """3839self.log_records = []40logging.Handler.__init__(self, level)4142def handle(self, record):43""" See logging.Handler.handle(self, record) docs. """4445self.log_records.append(record)4647def emit(self, record):48""" See logging.Handler.emit(self, record) docs. """4950pass # do not emit the record. Other handlers can do that.515253class TurnDefinitionsTestCase(unittest.TestCase):54# pylint: disable=C,R,W,E,F5556def setUp(self):57self.turn_definitions = turndefinitions.TurnDefinitions()5859def tearDown(self):60self.turn_definitions = None6162def test_new_turn_definitions_is_empty(self):63self.assertEqual([], self.turn_definitions.get_sources())6465def test_get_sources(self):66self.turn_definitions.add("source", "destination", 100)67self.assertEqual(["source"], self.turn_definitions.get_sources())6869def test_get_sources_is_sorted(self):70self.turn_definitions.add("source 1", "destination", 100)71self.turn_definitions.add("source 2", "destination", 100)72self.assertEqual(["source 1", "source 2"],73self.turn_definitions.get_sources())7475def test_get_destinations(self):76self.turn_definitions.add("source", "destination", 100)77self.assertEqual(["destination"],78self.turn_definitions.get_destinations("source"))7980def test_get_destinations_is_sorted(self):81self.turn_definitions.add("source", "destination 1", 100)82self.turn_definitions.add("source", "destination 2", 100)83self.assertEqual(["destination 1", "destination 2"],84self.turn_definitions.get_destinations("source"))8586def test_get_turning_probability(self):87self.turn_definitions.add("source", "destination", 100)88self.assertEqual(100,89self.turn_definitions.get_turning_probability("source",90"destination"))9192def test_probability_overflow_raises_warning_on_initial_add(self):93collecting_handler = CollectingHandler()94self.turn_definitions.logger.addHandler(collecting_handler)9596self.turn_definitions.add("source", "destination", 101)9798self.assertTrue(99"Turn probability overflow: 101.000000; lowered to 100"100in [record.getMessage()101for record in collecting_handler.log_records])102103def test_probability_overflow_raises_warning_after_addition(self):104collecting_handler = CollectingHandler()105self.turn_definitions.logger.addHandler(collecting_handler)106107self.turn_definitions.add("source", "destination", 90)108self.turn_definitions.add("source", "destination", 11)109110self.assertTrue(111"Turn probability overflow: 101.000000; lowered to 100"112in [record.getMessage()113for record in collecting_handler.log_records])114115116class CreateTurnDefinitionsTestCase(unittest.TestCase):117# pylint: disable=C,R,W,E,F118119def test_creation_with_0_sources(self):120self.assertEqual(turndefinitions.TurnDefinitions(),121turndefinitions.from_connections(connections.Connections()))122123def test_creation_with_one_source(self):124input_connections = connections.Connections()125input_connections.add("source 1", "source lane 1", "destination 1")126127turn_definitions = turndefinitions.TurnDefinitions()128turn_definitions.add("source 1", "destination 1", 100.0)129130self.assertEqual(turn_definitions,131turndefinitions.from_connections(input_connections))132133def test_creation_with_two_sources(self):134input_connections = connections.Connections()135input_connections.add("source 1", "source lane 1", "destination 1")136input_connections.add("source 2", "source lane 1", "destination 1")137138turn_definitions = turndefinitions.TurnDefinitions()139turn_definitions.add("source 1", "destination 1", 100.0)140turn_definitions.add("source 2", "destination 1", 100.0)141142self.assertEqual(turn_definitions,143turndefinitions.from_connections(input_connections))144145def test_creation_two_destinations_from_two_lanes_overlapping(self):146input_connections = connections.Connections()147input_connections.add("source 1", "source lane 1", "destination 1")148input_connections.add("source 1", "source lane 2", "destination 2")149input_connections.add("source 1", "source lane 2", "destination 1")150151turn_definitions = turndefinitions.TurnDefinitions()152turn_definitions.add(153"source 1", "destination 1", 100.0 / 2 / 2 + 100.0 / 2)154turn_definitions.add("source 1", "destination 2", 100.0 / 2 / 2)155156self.assertEqual(turn_definitions,157turndefinitions.from_connections(input_connections))158159def test_creation_one_destination_from_two_lanes(self):160input_connections = connections.Connections()161input_connections.add("source 1", "source lane 1", "destination 1")162input_connections.add("source 1", "source lane 2", "destination 1")163164turn_definitions = turndefinitions.TurnDefinitions()165turn_definitions.add("source 1", "destination 1", 100.0)166167self.assertEqual(turn_definitions,168turndefinitions.from_connections(input_connections))169170def test_creation_with_one_destination_from_one_lane(self):171input_connections = connections.Connections()172input_connections.add("source 1", "source lane 1", "destination 1")173174turn_definitions = turndefinitions.TurnDefinitions()175turn_definitions.add("source 1", "destination 1", 100.0)176177self.assertEqual(turn_definitions,178turndefinitions.from_connections(input_connections))179180def test_creation_with_two_destinations_from_one_lane(self):181input_connections = connections.Connections()182input_connections.add("source 1", "source lane 1", "destination 1")183input_connections.add("source 1", "source lane 1", "destination 2")184185turn_definitions = turndefinitions.TurnDefinitions()186turn_definitions.add("source 1", "destination 1", 100.0 / 2)187turn_definitions.add("source 1", "destination 2", 100.0 / 2)188189self.assertEqual(turn_definitions,190turndefinitions.from_connections(input_connections))191192def test_creation_with_three_destinations_from_one_lane(self):193input_connections = connections.Connections()194input_connections.add("source 1", "source lane 1", "destination 1")195input_connections.add("source 1", "source lane 1", "destination 2")196input_connections.add("source 1", "source lane 1", "destination 3")197198turn_definitions = turndefinitions.TurnDefinitions()199turn_definitions.add("source 1", "destination 1", 100.0 / 3)200turn_definitions.add("source 1", "destination 2", 100.0 / 3)201turn_definitions.add("source 1", "destination 3", 100.0 / 3)202203self.assertEqual(turn_definitions,204turndefinitions.from_connections(input_connections))205206207class UniformDestinationWeightCalculatorTestCase(unittest.TestCase):208# pylint: disable=C,W,R,E,F209210def setUp(self):211self.calculator = connections.UniformDestinationWeightCalculator()212213def tearDown(self):214self.calculator = None215216def test_uniform_weight_spread_across_lanes(self):217# 1 lane case218self.assertAlmostEqual(219100.0, self.calculator.calculate_weight(0, 1, 1))220221# 2 lane case222self.assertAlmostEqual(50.0, self.calculator.calculate_weight(0, 2, 1))223self.assertAlmostEqual(50.0, self.calculator.calculate_weight(1, 2, 1))224225# 2 lane case226self.assertAlmostEqual(227100.0 / 3, self.calculator.calculate_weight(0, 3, 1))228self.assertAlmostEqual(229100.0 / 3, self.calculator.calculate_weight(1, 3, 1))230self.assertAlmostEqual(231100.0 / 3, self.calculator.calculate_weight(2, 3, 1))232233def test_uniform_weight_spread_across_destinations(self):234# 1 destination235self.assertAlmostEqual(236100.0, self.calculator.calculate_weight(0, 1, 1))237238# 2 destinations239self.assertAlmostEqual(240100.0 / 2, self.calculator.calculate_weight(0, 1, 2))241242# 3 destinations243self.assertAlmostEqual(244100.0 / 3, self.calculator.calculate_weight(0, 1, 3))245246247class ConnectionsTestCase(unittest.TestCase):248# pylint: disable=C,W,R,E,F249250def setUp(self):251self.connections = connections.Connections()252253def tearDown(self):254self.connections = None255256def assert_contains_source(self, source):257self.assertTrue(source in258self.connections.get_sources())259260def assert_contains_lane(self, source, lane):261self.assertTrue(lane in262self.connections.get_lanes(source))263264def assert_contains_destination(self, source, lane, destination):265self.assertTrue(destination in266self.connections.get_destinations(source, lane))267268def assert_sources_no(self, sources_no):269self.assertEqual(sources_no,270len(self.connections.get_sources()))271272def assert_lanes_no(self, source, lanes_no):273self.assertEqual(lanes_no,274len(self.connections.get_lanes(source)))275276def assert_destinations_no(self, source, lane, destinations_no):277self.assertEqual(destinations_no,278len(self.connections.get_destinations(source, lane)))279280def test_map_empty_on_init(self):281self.assert_sources_no(0)282283def test_add(self):284self.connections.add("source", "source lane", "destination")285286self.assert_sources_no(1)287self.assert_contains_source("source")288289self.assert_lanes_no("source", 1)290self.assert_contains_lane("source", "source lane")291292self.assert_destinations_no("source", "source lane", 1)293self.assert_contains_destination(294"source", "source lane", "destination")295296def test_add_different_lanes(self):297self.connections.add("source", "source lane 1", "destination")298self.connections.add("source", "source lane 2", "destination")299300self.assert_sources_no(1)301self.assert_contains_source("source")302303self.assert_lanes_no("source", 2)304self.assert_contains_lane("source", "source lane 1")305self.assert_contains_lane("source", "source lane 2")306307self.assert_destinations_no("source", "source lane 1", 1)308self.assert_contains_destination(309"source", "source lane 1", "destination")310311self.assert_destinations_no("source", "source lane 2", 1)312self.assert_contains_destination(313"source", "source lane 2", "destination")314315def test_add_different_destinations(self):316self.connections.add("source", "source lane", "destination 1")317self.connections.add("source", "source lane", "destination 2")318319self.assert_sources_no(1)320self.assert_contains_source("source")321322self.assert_lanes_no("source", 1)323self.assert_contains_lane("source", "source lane")324325self.assert_destinations_no("source", "source lane", 2)326self.assert_contains_destination(327"source", "source lane", "destination 1")328self.assert_contains_destination(329"source", "source lane", "destination 2")330331def test_readd_raises_warning(self):332collecting_handler = CollectingHandler()333self.connections.logger.addHandler(collecting_handler)334335self.connections.add("source", "source lane", "destination")336self.connections.add("source", "source lane", "destination")337338self.assert_sources_no(1)339self.assert_contains_source("source")340341self.assert_lanes_no("source", 1)342self.assert_contains_lane("source", "source lane")343344self.assert_destinations_no("source", "source lane", 1)345self.assert_contains_destination("source", "source lane", "destination")346347self.assertTrue(348"Destination for source (lane source lane) readded: destination"349in [record.getMessage() for record in collecting_handler.log_records])350351352if __name__ == "__main__":353unittest.main()354355356