class TestNetworkTriggers(TestCase): def setUp(self) -> None: os.environ['PATH'] = os.path.join(gettempdir(), 'temp_data') + ';' + os.environ['PATH'] self.proj_path = os.path.join(gettempdir(), f'aeq_{uuid.uuid4().hex}') copytree(siouxfalls_project, self.proj_path) self.siouxfalls = Project() self.siouxfalls.open(self.proj_path) remove_triggers(self.siouxfalls.conn) add_triggers(self.siouxfalls.conn) def tearDown(self) -> None: self.siouxfalls.close() def test_delete_links_delete_nodes(self): items = self.siouxfalls.network.count_nodes() self.assertEqual(24, items, 'Wrong number of nodes found') links = self.siouxfalls.network.links nodes = self.siouxfalls.network.nodes node = nodes.get(1) node.is_centroid = 0 node.save() # We have completely disconnected 2 nodes (1 and 2) for i in [1, 2, 3, 4, 5, 14]: link = links.get(i) link.delete() # Since node 1 is no longer a centroid, we should have only 23 nodes in the network items = self.siouxfalls.network.count_nodes() self.assertEqual(23, items, 'Wrong number of nodes found') def test_add_regular_link(self): # Add a regular link to see if it fails when creating it # It happened at some point curr = self.siouxfalls.conn.cursor() data = [123456, 'c', 'default', LineString([Point(0, 0), Point(1, 1)]).wkb] sql = 'insert into links (link_id, modes, link_type, geometry) Values(?,?,?,GeomFromWKB(?, 4326));' curr.execute(sql, data) self.siouxfalls.conn.commit() def test_add_regular_node_change_centroid_id(self): # Add a regular link to see if it fails when creating it # It happened at some point curr = self.siouxfalls.conn.cursor() network = self.siouxfalls.network nodes = network.count_nodes() data = [987654, 1, Point(0, 0).wkb] sql = 'insert into nodes (node_id, is_centroid, geometry) Values(?,?,GeomFromWKB(?, 4326));' curr.execute(sql, data) self.siouxfalls.conn.commit() self.assertEqual(nodes + 1, network.count_nodes(), 'Failed to insert node') curr.execute('Update nodes set is_centroid=0 where node_id=?', data[:1]) self.siouxfalls.conn.commit() self.assertEqual(nodes, network.count_nodes(), 'Failed to delete node when changing centroid flag')
class TestLinkType(TestCase): def setUp(self) -> None: self.temp_proj_folder = os.path.join(tempfile.gettempdir(), uuid.uuid4().hex) copytree(no_triggers_project, self.temp_proj_folder) self.proj = Project() self.proj.open(self.temp_proj_folder) self.curr = self.proj.conn.cursor() letters = [ random.choice(string.ascii_letters + '_') for x in range(20) ] self.random_string = ''.join(letters) def tearDown(self) -> None: self.proj.close() def test_changing_link_type_id(self): ltypes = self.proj.network.link_types lt = random.choice([x for x in ltypes.all_types().values()]) with self.assertRaises(ValueError): lt.link_type_id = 'test my description' with self.assertRaises(ValueError): lt.link_type_id = 'K' def test_empty(self): ltypes = self.proj.network.link_types newt = ltypes.new('Z') # a.link_type = 'just a_test' with self.assertRaises(IntegrityError): newt.save() def test_save(self): ltypes = self.proj.network.link_types newt = ltypes.new('Z') newt.link_type = self.random_string newt.description = self.random_string[::-1] newt.save() self.curr.execute( 'select description, link_type from link_types where link_type_id="Z"' ) desc, mname = self.curr.fetchone() self.assertEqual(desc, self.random_string[::-1], "Didn't save the mode description correctly") self.assertEqual(mname, self.random_string, "Didn't save the mode name correctly")
def test_connection_with_new_project(self): temp_proj_folder = os.path.join(tempfile.gettempdir(), uuid.uuid4().hex) proj = Project() proj.new(temp_proj_folder) proj.close() proj = Project() proj.open(temp_proj_folder) conn = database_connection() cursor = conn.cursor() cursor.execute('select count(*) from links') self.assertEqual(cursor.fetchone()[0], 0, "Returned more links thant it should have") proj.close()
class TestLog(TestCase): def setUp(self) -> None: os.environ['PATH'] = os.path.join(gettempdir(), 'temp_data') + ';' + os.environ['PATH'] self.proj_dir = os.path.join(gettempdir(), uuid.uuid4().hex) copytree(siouxfalls_project, self.proj_dir) self.project = Project() self.project.open(self.proj_dir) def tearDown(self) -> None: self.project.close() def test_contents(self): log = self.project.log() cont = log.contents() self.assertEqual(len(cont), 4, 'Returned the wrong amount of data from the log') def test_clear(self): log = self.project.log() log.clear() with open(os.path.join(self.proj_dir, "aequilibrae.log"), 'r') as file: q = file.readlines() self.assertEqual(len(q), 0, 'Failed to clear the log file')
class TestProject(TestCase): def setUp(self) -> None: self.temp_proj_folder = os.path.join(tempfile.gettempdir(), uuid.uuid4().hex) self.proj = Project() self.proj.new(self.temp_proj_folder) def tearDown(self) -> None: self.proj.close() def test_opening_wrong_folder(self): temp_proj_folder = os.path.join(tempfile.gettempdir(), uuid.uuid4().hex) self.proj.close() with self.assertRaises(FileNotFoundError): proj = Project() proj.open(temp_proj_folder) self.proj.open(self.temp_proj_folder) def test_create_when_already_exists(self): with self.assertRaises(Exception): q = Project() q.new(os.path.join(tempfile.gettempdir(), uuid.uuid4().hex)) with self.assertRaises(Exception): q = Project() q.open(os.path.join(tempfile.gettempdir(), uuid.uuid4().hex)) def test_creation(self): curr = self.proj.conn.cursor() curr.execute("""PRAGMA table_info(links);""") fields = curr.fetchall() fields = [x[1] for x in fields] if 'distance' not in fields: self.fail("Table LINKS was not created correctly") curr = self.proj.conn.cursor() curr.execute("""PRAGMA table_info(nodes);""") nfields = curr.fetchall() nfields = [x[1] for x in nfields] if 'is_centroid' not in nfields: self.fail('Table NODES was not created correctly') def test_close(self): _ = database_connection() self.proj.close() with self.assertRaises(FileExistsError): _ = database_connection()
class TestNetwork_skimming(TestCase): def setUp(self) -> None: os.environ['PATH'] = os.path.join( gettempdir(), 'temp_data') + ';' + os.environ['PATH'] self.proj_dir = os.path.join(gettempdir(), uuid.uuid4().hex) copytree(siouxfalls_project, self.proj_dir) self.project = Project() self.project.open(self.proj_dir) self.network = self.project.network self.curr = self.project.conn.cursor() def tearDown(self) -> None: self.project.close() del self.curr try: rmtree(self.proj_dir) except Exception as e: print(f'Failed to remove at {e.args}') def test_network_skimming(self): self.network.build_graphs() graph = self.network.graphs['c'] graph.set_graph(cost_field="distance") graph.set_skimming("distance") # skimming results res = SkimResults() res.prepare(graph) aux_res = MultiThreadedNetworkSkimming() aux_res.prepare(graph, res) _ = skimming_single_origin(12, graph, res, aux_res, 0) skm = NetworkSkimming(graph) skm.execute() tot = np.nanmax(skm.results.skims.distance[:, :]) if tot > np.sum(graph.cost): self.fail( "Skimming was not successful. At least one np.inf returned.") if skm.report: self.fail("Skimming returned an error:" + str(skm.report)) skm.save_to_project('tEst_Skimming') if not os.path.isfile( os.path.join(self.proj_dir, 'matrices', 'test_skimming.omx')): self.fail('Did not save project to project') matrices = self.project.matrices mat = matrices.get_record('TEsT_Skimming') self.assertEqual(mat.name, 'tEst_Skimming', 'Matrix record name saved wrong') self.assertEqual(mat.file_name, 'tEst_Skimming.omx', 'matrix file_name saved wrong') self.assertEqual(mat.cores, 1, 'matrix saved number of matrix cores wrong') self.assertEqual(mat.procedure, 'Network skimming', 'Matrix saved wrong procedure name') self.assertEqual(mat.procedure_id, skm.procedure_id, 'Procedure ID saved wrong') self.assertEqual(mat.timestamp, skm.procedure_date, 'Procedure ID saved wrong')
class TestLinkTypes(TestCase): def setUp(self) -> None: self.temp_proj_folder = os.path.join(tempfile.gettempdir(), uuid.uuid4().hex) copytree(no_triggers_project, self.temp_proj_folder) self.proj = Project() self.proj.open(self.temp_proj_folder) self.curr = self.proj.conn.cursor() letters = [ random.choice(string.ascii_letters + '_') for x in range(20) ] self.random_string = ''.join(letters) def tearDown(self) -> None: self.proj.close() def test_add(self): lt = self.proj.network.link_types existing = list(lt.all_types().keys()) newlt = lt.new('G') newlt.link_type = 'unique_link_type' newlt.save() nowexisting = list(lt.all_types().keys()) n = [x for x in nowexisting if x not in existing][0] self.assertEqual('G', n, 'Failed to add link type') def test_delete(self): lt = self.proj.network.link_types existing = list(lt.all_types().keys()) deleted = random.choice(existing) lt.delete(deleted) remaining = list(lt.all_types().keys()) difference = [x for x in existing if x not in remaining] self.assertEqual(deleted, difference[0], 'Failed to delete link type') def test_get_and_get_by_name(self): lt = self.proj.network.link_types ltget = lt.get('y') ltgetbn = lt.get_by_name('default') self.assertEqual(ltget.link_type_id, ltgetbn.link_type_id, 'Get methods returned different things') self.assertEqual(ltget.link_type, ltgetbn.link_type, 'Get methods returned different things') self.assertEqual(ltget.description, ltgetbn.description, 'Get methods returned different things') self.assertEqual(ltget.lanes, ltgetbn.lanes, 'Get methods returned different things') self.assertEqual(ltget.lane_capacity, ltgetbn.lane_capacity, 'Get methods returned different things') self.assertEqual(ltget.link_type, 'default', 'Get methods returned different things') def test_all_types(self): lt = self.proj.network.link_types all_lts = set([x for x in lt.all_types().keys()]) c = self.proj.conn.cursor() c.execute('select link_type_id from link_types') reallts = set([x[0] for x in c.fetchall()]) diff = all_lts.symmetric_difference(reallts) self.assertEqual(diff, set(), 'Getting all link_types failed')
class TestNetwork(TestCase): def setUp(self) -> None: os.environ['PATH'] = os.path.join( gettempdir(), 'temp_data') + ';' + os.environ['PATH'] self.proj_path = os.path.join(gettempdir(), uuid.uuid4().hex) copytree(siouxfalls_project, self.proj_path) self.siouxfalls = Project() self.siouxfalls.open(self.proj_path) self.proj_path2 = os.path.join(gettempdir(), uuid.uuid4().hex) def tearDown(self) -> None: self.siouxfalls.close() def test_create_from_osm(self): thresh = 0.05 if os.environ.get('GITHUB_WORKFLOW', 'ERROR') == 'Code coverage': thresh = 1.01 if random() < thresh: self.siouxfalls.close() self.project = Project() self.project.new(self.proj_path2) # self.network.create_from_osm(west=153.1136245, south=-27.5095487, east=153.115, north=-27.5085, modes=["car"]) self.project.network.create_from_osm(west=-112.185, south=36.59, east=-112.179, north=36.60) curr = self.project.conn.cursor() curr.execute("""select count(*) from links""") lks = curr.fetchone()[0] curr.execute("""select count(distinct osm_id) from links""") osmids = curr.fetchone()[0] if osmids == 0: warn('COULD NOT RETRIEVE DATA FROM OSM') return if osmids >= lks: self.fail("OSM links not broken down properly") curr.execute("""select count(*) from nodes""") nds = curr.fetchone()[0] if lks > nds: self.fail( "We imported more links than nodes. Something wrong here") self.project.close() self.siouxfalls.open(self.proj_path) else: print('Skipped check to not load OSM servers') def test_count_centroids(self): items = self.siouxfalls.network.count_centroids() self.assertEqual(24, items, 'Wrong number of centroids found') nodes = self.siouxfalls.network.nodes node = nodes.get(1) node.is_centroid = 0 node.save() items = self.siouxfalls.network.count_centroids() self.assertEqual(23, items, 'Wrong number of centroids found') def test_count_links(self): items = self.siouxfalls.network.count_links() self.assertEqual(76, items, 'Wrong number of links found') def test_count_nodes(self): items = self.siouxfalls.network.count_nodes() self.assertEqual(24, items, 'Wrong number of nodes found')
class TestNode(TestCase): def setUp(self) -> None: os.environ["PATH"] = os.path.join(gettempdir(), "temp_data") + ";" + os.environ["PATH"] self.proj_dir = os.path.join(gettempdir(), uuid.uuid4().hex) copytree(siouxfalls_project, self.proj_dir) self.project = Project() self.project.open(self.proj_dir) self.network = self.project.network self.curr = self.project.conn.cursor() def tearDown(self) -> None: self.curr.close() self.project.close() try: rmtree(self.proj_dir) except Exception as e: print(f"Failed to remove at {e.args}") def test_save_and_assignment(self): nodes = self.network.nodes nd = randint(1, 24) node = nodes.get(nd) with self.assertRaises(AttributeError): node.modes = "abc" with self.assertRaises(AttributeError): node.link_types = "default" with self.assertRaises(AttributeError): node.node_id = 2 with self.assertRaises(ValueError): node.is_centroid = 2 node.is_centroid = 0 self.assertEqual(0, node.is_centroid, "Assignment of is_centroid did not work") x = node.geometry.x + random() y = node.geometry.y + random() node.geometry = Point([x, y]) node.save() self.curr.execute("Select is_centroid, asBinary(geometry) from nodes where node_id=?;", [nd]) flag, wkb = self.curr.fetchone() self.assertEqual(flag, 0, "Saving of is_centroid failed") geo = shapely.wkb.loads(wkb) self.assertEqual(geo.x, x, "Geometry X saved wrong") self.assertEqual(geo.y, y, "Geometry Y saved wrong") self.curr.execute("Select asBinary(geometry) from links where a_node=?;", [nd]) wkb = self.curr.fetchone()[0] geo2 = shapely.wkb.loads(wkb) self.assertEqual(geo2.xy[0][0], x, "Saving node geometry broke underlying network") self.assertEqual(geo2.xy[1][0], y, "Saving node geometry broke underlying network") def test_data_fields(self): nodes = self.network.nodes node1 = nodes.get(randint(1, 24)) node2 = nodes.get(randint(1, 24)) self.assertEqual(node1.data_fields(), node2.data_fields(), "Different nodes have different data fields") fields = sorted(node1.data_fields()) self.curr.execute("pragma table_info(nodes)") dt = self.curr.fetchall() actual_fields = sorted([x[1] for x in dt if x[1] != "ogc_fid"]) self.assertEqual(fields, actual_fields, "Node has unexpected set of fields") def test_renumber(self): nodes = self.network.nodes node = nodes.get(randint(2, 24)) x = node.geometry.x y = node.geometry.y with self.assertRaises(IntegrityError): node.renumber(1) num = randint(25, 2000) node.renumber(num) self.curr.execute("Select asBinary(geometry) from nodes where node_id=?;", [num]) wkb = self.curr.fetchone()[0] geo = shapely.wkb.loads(wkb) self.assertEqual(geo.x, x, "Renumbering failed") self.assertEqual(geo.y, y, "Renumbering failed")
class TestGraph(TestCase): def setUp(self) -> None: os.environ["PATH"] = os.path.join( tempfile.gettempdir(), "temp_data") + ";" + os.environ["PATH"] self.temp_proj_folder = os.path.join(tempfile.gettempdir(), uuid4().hex) copytree(siouxfalls_project, self.temp_proj_folder) self.project = Project() self.project.open(self.temp_proj_folder) self.project.network.build_graphs() self.graph = self.project.network.graphs["c"] def tearDown(self) -> None: self.project.close() def test_prepare_graph(self): graph = self.project.network.graphs["c"] graph.prepare_graph(np.arange(5) + 1) def test_set_graph(self): self.graph.set_graph(cost_field="distance") self.graph.set_blocked_centroid_flows(block_centroid_flows=True) self.assertEqual(self.graph.num_zones, 24, "Number of centroids not properly set") self.assertEqual(self.graph.num_links, 76, "Number of links not properly set") self.assertEqual( self.graph.num_nodes, 24, "Number of nodes not properly set - " + str(self.graph.num_nodes)) def test_save_to_disk(self): self.graph.save_to_disk(join(path_test, "aequilibrae_test_graph.aeg")) self.graph_id = self.graph.__id__ self.graph_version = self.graph.__version__ def test_load_from_disk(self): self.test_save_to_disk() reference_graph = Graph() reference_graph.load_from_disk(test_graph) reference_graph.__version__ = binary_version new_graph = Graph() new_graph.load_from_disk(join(path_test, "aequilibrae_test_graph.aeg")) def test_available_skims(self): self.graph.prepare_graph(np.arange(5) + 1) avail = self.graph.available_skims() data_fields = [ "distance", "name", "lanes", "capacity", "speed", "b", "free_flow_time", "power", "colum", "volume", "modes", ] for i in data_fields: if i not in avail: self.fail("Skim availability with problems") def test_exclude_links(self): # excludes a link before any setting or preparation self.graph.set_blocked_centroid_flows(False) self.graph.set_graph("distance") r1 = PathResults() r1.prepare(self.graph) r1.compute_path(20, 21) self.assertEqual(list(r1.path), [62]) r1 = PathResults() self.graph.exclude_links([62]) r1.prepare(self.graph) r1.compute_path(20, 21) self.assertEqual(list(r1.path), [63, 69])
class TestProject(TestCase): def setUp(self) -> None: self.temp_proj_folder = os.path.join(tempfile.gettempdir(), uuid.uuid4().hex) copytree(no_triggers_project, self.temp_proj_folder) self.proj = Project() self.proj.open(self.temp_proj_folder) self.curr = self.proj.conn.cursor() # Modes to add sql = 'INSERT INTO modes (mode_name, mode_id) VALUES (?, ?);' for mid in ['p', 'l', 'g', 'x', 'y', 'd', 'k', 'a', 'r', 'n', 'm']: self.curr.execute(sql, [f'mode_{mid}', mid]) self.proj.conn.commit() root = os.path.dirname(os.path.realpath(__file__)).replace('tests', '') qry_file = os.path.join( root, "database_specification/triggers/link_type_table_triggers.sql") with open(qry_file, "r") as sql_file: self.queries = sql_file.read() self.queries = [cmd for cmd in self.queries.split("#")] curr = self.proj.conn.cursor() self.rtree = True try: curr.execute("SELECT rtreecheck('idx_nodes_geometry');") except Exception as e: self.rtree = False warn(f'RTREE not available --> {e.args}') def tearDown(self) -> None: self.proj.close() def __get_query(self, qry: str) -> str: for query in self.queries: if qry in query: return query raise FileNotFoundError('QUERY DOES NOT EXIST') def test_all_tests_considered(self): tests_added = list(self.__dir__()) tests_added = [x[5:] for x in tests_added if x[:5] == 'test_'] for trigger in self.queries: if 'TRIGGER' in trigger.upper(): found = [x for x in tests_added if x in trigger] if not found: self.fail(f'Trigger not tested. {trigger}') def test_link_type_single_letter_update(self): cmd = self.__get_query('link_type_single_letter_update') sql = "UPDATE 'link_types' SET link_type_id= 'ttt' where link_type_id='t'" self.curr.execute(sql) self.curr.execute(cmd) sql = "UPDATE 'link_types' SET link_type_id= 'ww' where link_type_id='w'" with self.assertRaises(sqlite3.IntegrityError): self.curr.execute(sql) def test_link_type_single_letter_insert(self): cmd = self.__get_query('link_type_single_letter_insert') sql = "INSERT INTO 'link_types' (link_type, link_type_id) VALUES(?, ?)" self.curr.execute(sql, ['test1a', 'more_than_one']) self.curr.execute(cmd) with self.assertRaises(sqlite3.IntegrityError): self.curr.execute(sql, ['test1b', 'mm']) def test_link_type_keep_if_in_use_updating(self): cmd = self.__get_query('link_type_keep_if_in_use_updating') sql = "UPDATE 'link_types' SET link_type= 'ttt' where link_type='test'" self.curr.execute(sql) self.curr.execute(cmd) sql = "UPDATE 'link_types' SET link_type= 'QQQ' where link_type='test2'" with self.assertRaises(sqlite3.IntegrityError): self.curr.execute(sql) def test_link_type_keep_if_in_use_deleting(self): cmd = self.__get_query('link_type_keep_if_in_use_deleting') sql = "DELETE FROM 'link_types' where link_type='test3'" self.curr.execute(sql) self.curr.execute(cmd) sql = "DELETE FROM 'link_types' where link_type='test4'" with self.assertRaises(sqlite3.IntegrityError): self.curr.execute(sql) def test_link_type_on_links_update(self): cmd = self.__get_query('link_type_on_links_update') sql = "UPDATE 'links' SET link_type= 'rrr' where link_type='test3'" self.curr.execute(sql) self.curr.execute(cmd) sql = "UPDATE 'links' SET link_type= 'not_valid_type' where link_type='test4'" with self.assertRaises(sqlite3.IntegrityError): self.curr.execute(sql) def test_link_type_on_links_insert(self): cmd = self.__get_query('link_type_on_links_insert') if self.rtree: self.curr.execute('pragma table_info(links)') f = self.curr.fetchall() fields = {x[1]: x[0] for x in f} sql = 'select * from links where link_id=70' self.curr.execute(sql) a = [x for x in self.curr.fetchone()] a[fields['link_type']] = 'something indeed silly123' a[fields['link_id']] = 456789 a[fields['a_node']] = 777 a[fields['b_node']] = 999 a[0] = 456789 idx = ','.join(['?'] * len(a)) self.curr.execute(f'insert into links values ({idx})', a) self.curr.execute('delete from links where link_id=456789') self.curr.execute(cmd) with self.assertRaises(sqlite3.IntegrityError): self.curr.execute(f'insert into links values ({idx})', a) self.curr.execute('select link_type from link_types;') a[fields['link_type']] = self.curr.fetchone()[0] self.curr.execute(f'insert into links values ({idx})', a) def test_link_type_on_links_delete_protected_link_type(self): cmd = self.__get_query('link_type_on_links_delete_protected_link_type') self.curr.execute(cmd) with self.assertRaises(sqlite3.IntegrityError): self.curr.execute('delete from link_types where link_type_id="z"') with self.assertRaises(sqlite3.IntegrityError): self.curr.execute('delete from link_types where link_type_id="y"') def test_link_type_id_keep_if_protected_type(self): cmd = self.__get_query('link_type_id_keep_if_protected_type') self.curr.execute(cmd) with self.assertRaises(sqlite3.IntegrityError): self.curr.execute( 'update link_types set link_type_id="x" where link_type_id="y"' ) with self.assertRaises(sqlite3.IntegrityError): self.curr.execute( 'update link_types set link_type_id="x" where link_type_id="z"' ) def test_link_type_keep_if_protected_type(self): cmd = self.__get_query('link_type_keep_if_protected_type') self.curr.execute(cmd) with self.assertRaises(sqlite3.IntegrityError): self.curr.execute( 'update link_types set link_type="xsdfg" where link_type_id="z"' ) with self.assertRaises(sqlite3.IntegrityError): self.curr.execute( 'update link_types set link_type="xsdfg" where link_type_id="y"' ) def test_link_type_on_nodes_table_update_nodes_link_type(self): cmd = self.__get_query( 'link_type_on_nodes_table_update_nodes_link_type') self.curr.execute(cmd) self.curr.execute( 'update nodes set link_types="qwerrreyrtuyiuio" where node_id=1') self.curr.execute('select link_types from nodes where node_id=1') lts = self.curr.fetchone()[0] self.assertEqual( lts, 'etuw', 'link_types was allowed to be corrupted in the nodes table') def test_link_type_on_nodes_table_update_links_link_type(self): cmd = self.__get_query( 'link_type_on_nodes_table_update_links_link_type') self.curr.execute(cmd) self.curr.execute('update links set link_type="test" where link_id=15') self.curr.execute('select link_types from nodes where node_id=6') lts = self.curr.fetchone()[0] self.assertEqual( lts, 'rtw', 'link_types on nodes table not updated with new link type in the links' ) self.curr.execute('select link_types from nodes where node_id=5') lts = self.curr.fetchone()[0] self.assertEqual( lts, 'ertw', 'link_types was allowed to be corrupted in the nodes table') def test_link_type_on_nodes_table_update_links_a_node(self): cmd = self.__get_query('link_type_on_nodes_table_update_links_a_node') self.curr.execute(cmd) self.curr.execute('update links set a_node=1 where link_id=15') self.curr.execute('select link_types from nodes where node_id=1') lts = self.curr.fetchone()[0] self.assertEqual( lts, 'etuw', 'link_types on nodes table not updated with new link type in the links' ) self.curr.execute('select link_types from nodes where node_id=6') lts = self.curr.fetchone()[0] self.assertEqual( lts, 'rw', 'link_types was allowed to be corrupted in the nodes table') def test_link_type_on_nodes_table_update_links_b_node(self): cmd = self.__get_query('link_type_on_nodes_table_update_links_b_node') self.curr.execute(cmd) self.curr.execute('update links set b_node=1 where link_id=15') self.curr.execute('select link_types from nodes where node_id=1') lts = self.curr.fetchone()[0] self.assertEqual( lts, 'etuw', 'link_types on nodes table not updated with new link type in the links' ) self.curr.execute('select link_types from nodes where node_id=5') lts = self.curr.fetchone()[0] self.assertEqual( lts, 'ertw', 'link_types was allowed to be corrupted in the nodes table')
class TestMode(TestCase): def setUp(self) -> None: os.environ['PATH'] = os.path.join( tempfile.gettempdir(), 'temp_data') + ';' + os.environ['PATH'] self.temp_proj_folder = os.path.join(tempfile.gettempdir(), uuid.uuid4().hex) copytree(no_triggers_project, self.temp_proj_folder) self.proj = Project() self.proj.open(self.temp_proj_folder) self.curr = self.proj.conn.cursor() letters = [ random.choice(string.ascii_letters + '_') for x in range(20) ] self.random_string = ''.join(letters) def tearDown(self) -> None: self.proj.close() def test_build(self): for val in ['1', 'ab', '', None]: with self.assertRaises(ValueError): m = Mode(val) for letter in range(10): letter = random.choice(string.ascii_letters) m = Mode(letter) del m def test_changing_mode_id(self): m = Mode('c') with self.assertRaises(ValueError): m.mode_id = 'test my description' def test_save(self): self.curr.execute("select mode_id from 'modes'") letter = random.choice([x[0] for x in self.curr.fetchall()]) m = Mode(letter) m.mode_name = self.random_string m.description = self.random_string[::-1] m.save() self.curr.execute( f'select description, mode_name from modes where mode_id="{letter}"' ) desc, mname = self.curr.fetchone() self.assertEqual(desc, self.random_string[::-1], "Didn't save the mode description correctly") self.assertEqual(mname, self.random_string, "Didn't save the mode name correctly") def test_empty(self): a = Mode('k') a.mode_name = 'just a_test' with self.assertRaises(ValueError): a.save() a = Mode('l') a.mode_name = 'just_a_test_test_with_l' with self.assertRaises(ValueError): a.save()
class TestLinks(TestCase): def setUp(self) -> None: os.environ['PATH'] = os.path.join( gettempdir(), 'temp_data') + ';' + os.environ['PATH'] self.proj_dir = os.path.join(gettempdir(), uuid.uuid4().hex) copytree(siouxfalls_project, self.proj_dir) self.project = Project() self.project.open(self.proj_dir) self.network = self.project.network self.curr = self.project.conn.cursor() def tearDown(self) -> None: self.project.close() del self.curr try: rmtree(self.proj_dir) except Exception as e: print(f'Failed to remove at {e.args}') def test_get(self): links = self.network.links with self.assertRaises(ValueError): _ = links.get(123456) link = links.get(1) self.assertEqual(link.capacity_ab, 25900.20064, 'Did not populate link correctly') def test_new(self): links = self.network.links new_link = links.new() self.curr.execute('Select max(link_id) + 1 from Links') id = self.curr.fetchone()[0] self.assertEqual(new_link.link_id, id, 'Did not populate new link ID properly') self.assertEqual(new_link.geometry, None, 'Did not populate new geometry properly') def test_copy_link(self): links = self.network.links with self.assertRaises(ValueError): _ = links.copy_link(11111) new_link = links.copy_link(11) old_link = links.get(11) self.assertEqual(new_link.geometry, old_link.geometry) self.assertEqual(new_link.a_node, old_link.a_node) self.assertEqual(new_link.b_node, old_link.b_node) self.assertEqual(new_link.direction, old_link.direction) self.assertEqual(new_link.distance, old_link.distance) self.assertEqual(new_link.modes, old_link.modes) self.assertEqual(new_link.link_type, old_link.link_type) new_link.save() def test_delete(self): links = self.network.links _ = links.get(10) self.curr.execute('Select count(*) from Links') tot = self.curr.fetchone()[0] links.delete(10) links.delete(11) self.curr.execute('Select count(*) from Links') tot2 = self.curr.fetchone()[0] self.assertEqual(tot, tot2 + 2, 'Did not delete the link properly') with self.assertRaises(ValueError): links.delete(123456) with self.assertRaises(ValueError): _ = links.get(10) def test_fields(self): links = self.network.links f_editor = links.fields() fields = sorted(f_editor.all_fields()) self.curr.execute('pragma table_info(links)') dt = self.curr.fetchall() actual_fields = set([ x[1].replace('_ab', '').replace('_ba', '') for x in dt if x[1] != 'ogc_fid' ]) actual_fields = sorted(list(actual_fields)) self.assertEqual(fields, actual_fields, 'Table editor is weird for table links') def test_refresh(self): links = self.network.links link1 = links.get(1) val = randint(1, 99999999) original_value = link1.capacity_ba link1.capacity_ba = val link1_again = links.get(1) self.assertEqual(link1_again.capacity_ba, val, 'Did not preserve correctly') links.refresh() link1 = links.get(1) self.assertEqual(link1.capacity_ba, original_value, 'Did not reset correctly') def test_copy(self): nodes = self.network.nodes with self.assertRaises(Exception): _ = copy(nodes) with self.assertRaises(Exception): _ = deepcopy(nodes)
class TestNodes(TestCase): def setUp(self) -> None: os.environ['PATH'] = os.path.join( gettempdir(), 'temp_data') + ';' + os.environ['PATH'] self.proj_dir = os.path.join(gettempdir(), uuid.uuid4().hex) copytree(siouxfalls_project, self.proj_dir) self.project = Project() self.project.open(self.proj_dir) self.network = self.project.network self.curr = self.project.conn.cursor() def tearDown(self) -> None: self.project.close() del self.curr try: rmtree(self.proj_dir) except Exception as e: print(f'Failed to remove at {e.args}') def test_get(self): nodes = self.network.nodes nd = randint(1, 24) node = nodes.get(nd) self.assertEqual(node.node_id, nd, 'get node returned wrong object') # Make sure that if we renumber itg we would not get it again node.renumber(200) with self.assertRaises(ValueError): node = nodes.get(nd) def test_save(self): nodes = self.network.nodes chosen = [randint(1, 24) for _ in range(5)] while len(chosen) != len(set(chosen)): chosen = [randint(1, 24) for _ in range(5)] coords = [] for nd in chosen: node = nodes.get(nd) node.is_centroid = 0 x = node.geometry.x + random() y = node.geometry.y + random() coords.append([x, y]) node.geometry = Point([x, y]) nodes.save() for nd, coords in zip(chosen, coords): x, y = coords self.curr.execute( 'Select is_centroid, asBinary(geometry) from nodes where node_id=?;', [nd]) flag, wkb = self.curr.fetchone() self.assertEqual(flag, 0, 'Saving of is_centroid failed') geo = shapely.wkb.loads(wkb) self.assertEqual(geo.x, x, 'Geometry X saved wrong') self.assertEqual(geo.y, y, 'Geometry Y saved wrong') def test_fields(self): nodes = self.network.nodes f_editor = nodes.fields() fields = sorted(f_editor.all_fields()) self.curr.execute('pragma table_info(nodes)') dt = self.curr.fetchall() actual_fields = set([x[1] for x in dt if x[1] != 'ogc_fid']) actual_fields = sorted(list(actual_fields)) self.assertEqual(fields, actual_fields, 'Table editor is weird for table nodes') def test_copy(self): nodes = self.network.nodes with self.assertRaises(Exception): _ = copy(nodes) with self.assertRaises(Exception): _ = deepcopy(nodes) def test_new_centroid(self): nodes = self.network.nodes with self.assertRaises(Exception): node = nodes.new_centroid(1) tot_prev_centr = self.network.count_centroids() tot_prev_nodes = self.network.count_nodes() node = nodes.new_centroid(100) self.assertEqual( 1, node.is_centroid, 'Creating new centroid returned wrong is_centroid value') node.geometry = Point(1, 1) node.save() self.assertEqual(tot_prev_centr + 1, self.network.count_centroids(), 'Failed to add centroids') self.assertEqual(tot_prev_nodes + 1, self.network.count_nodes(), 'Failed to add centroids')
class TestProject(TestCase): def setUp(self) -> None: os.environ['PATH'] = os.path.join( tempfile.gettempdir(), 'temp_data') + ';' + os.environ['PATH'] self.temp_proj_folder = os.path.join(tempfile.gettempdir(), uuid.uuid4().hex) copytree(no_triggers_project, self.temp_proj_folder) self.proj = Project() self.proj.open(self.temp_proj_folder) self.curr = self.proj.conn.cursor() # Modes to add sql = 'INSERT INTO modes (mode_name, mode_id) VALUES (?, ?);' for mid in ['p', 'l', 'g', 'x', 'y', 'd', 'k', 'a', 'r', 'n', 'm']: self.curr.execute(sql, [f'mode_{mid}', mid]) self.proj.conn.commit() curr = self.proj.conn.cursor() self.rtree = True try: curr.execute("SELECT rtreecheck('idx_nodes_geometry');") except Exception as e: self.rtree = False warn(f'RTREE not available --> {e.args}') root = os.path.dirname(os.path.realpath(__file__)).replace('tests', '') qry_file = os.path.join( root, "database_specification/triggers/modes_table_triggers.sql") with open(qry_file, "r") as sql_file: self.queries = sql_file.read() self.queries = [cmd for cmd in self.queries.split("#")] def tearDown(self) -> None: self.proj.close() def __get_query(self, qry: str) -> str: for query in self.queries: if qry in query: return query raise FileNotFoundError('QUERY DOES NOT EXIST') def test_all_tests_considered(self): tests_added = list(self.__dir__()) tests_added = [x[5:] for x in tests_added if x[:5] == 'test_'] for trigger in self.queries: if 'TRIGGER' in trigger.upper(): found = [x for x in tests_added if x in trigger] if not found: self.fail(f'Trigger not tested. {trigger}') def test_mode_single_letter_update(self): cmd = self.__get_query('mode_single_letter_update') sql = "UPDATE 'modes' SET mode_id= 'ttt' where mode_id='b'" self.curr.execute(sql) self.curr.execute(cmd) with self.assertRaises(sqlite3.IntegrityError): sql = "UPDATE 'modes' SET mode_id= 'gg' where mode_id='w'" self.curr.execute(sql) def test_mode_single_letter_insert(self): cmd = self.__get_query('mode_single_letter_insert') sql = "INSERT INTO 'modes' (mode_name, mode_id) VALUES(?, ?)" self.curr.execute(sql, ['testasdasd', 'pp']) self.curr.execute(cmd) with self.assertRaises(sqlite3.IntegrityError): self.curr.execute(sql, ['test1b', 'mm']) def test_mode_keep_if_in_use_updating(self): cmd = self.__get_query('mode_keep_if_in_use_updating') sql = "UPDATE 'modes' SET mode_id= 'h' where mode_id='g'" self.curr.execute(sql) self.curr.execute(cmd) sql = "UPDATE 'modes' SET mode_id= 'j' where mode_id='l'" with self.assertRaises(sqlite3.IntegrityError): self.curr.execute(sql) def test_mode_keep_if_in_use_deleting(self): cmd = self.__get_query('mode_keep_if_in_use_deleting') sql = "DELETE FROM 'modes' where mode_id='p'" self.curr.execute(sql) self.curr.execute(cmd) sql = "DELETE FROM 'modes' where mode_id='c'" with self.assertRaises(sqlite3.IntegrityError): self.curr.execute(sql) def test_modes_on_links_update(self): cmd = self.__get_query('modes_on_links_update') sql = "UPDATE 'links' SET modes= 'qwerty' where link_id=55" self.curr.execute(sql) self.curr.execute(cmd) sql = "UPDATE 'links' SET modes= 'azerty' where link_id=56" with self.assertRaises(sqlite3.IntegrityError): self.curr.execute(sql) def test_modes_length_on_links_update(self): cmd = self.__get_query('modes_length_on_links_update') sql = "UPDATE 'links' SET modes= '' where modes='wb'" self.curr.execute(sql) self.curr.execute(cmd) sql = "UPDATE 'links' SET modes= '' where modes='bw'" with self.assertRaises(sqlite3.IntegrityError): self.curr.execute(sql) def test_modes_on_nodes_table_update_a_node(self): cmd = self.__get_query('modes_on_nodes_table_update_a_node') sql = "UPDATE 'links' SET a_node= 1 where a_node=3" self.curr.execute(sql) sql = "SELECT modes from nodes where node_id=1" self.curr.execute(sql) i = self.curr.fetchone()[0] self.assertEqual(i, 'ct') self.curr.execute(cmd) k = '' for n in [2, 5]: for f in ['a_node', 'b_node']: self.curr.execute(f"SELECT modes from links where {f}={n}") k += self.curr.fetchone()[0] existing = set(k) sql = "UPDATE 'links' SET a_node= 2 where a_node=5" self.curr.execute(sql) sql = "SELECT modes from nodes where node_id=2" self.curr.execute(sql) i = set(self.curr.fetchone()[0]) self.assertEqual(i, existing) def test_modes_on_nodes_table_update_b_node(self): cmd = self.__get_query('modes_on_nodes_table_update_b_node') sql = "UPDATE 'links' SET b_node= 1 where b_node=3" self.curr.execute(sql) sql = "SELECT modes from nodes where node_id=1" self.curr.execute(sql) i = self.curr.fetchone()[0] self.assertEqual(i, 'ct') self.curr.execute(cmd) sql = "UPDATE 'links' SET b_node= 2 where b_node=4" self.curr.execute(sql) sql = "SELECT modes from nodes where node_id=2" self.curr.execute(sql) i = self.curr.fetchone()[0] self.assertEqual(i, 'ctw') def test_modes_on_nodes_table_update_links_modes(self): cmd = self.__get_query('modes_on_nodes_table_update_links_modes') sql = "UPDATE 'links' SET modes= 'x' where a_node=24" self.curr.execute(sql) sql = "SELECT modes from nodes where node_id=24" self.curr.execute(sql) i = self.curr.fetchone()[0] self.assertEqual(i, 'c') self.curr.execute(cmd) sql = "UPDATE 'links' SET 'modes'= 'y' where a_node=24" self.curr.execute(sql) sql = "SELECT modes from nodes where node_id=24" self.curr.execute(sql) i = self.curr.fetchone()[0] self.assertIn('c', i) self.assertIn('y', i) sql = "UPDATE 'links' SET 'modes'= 'r' where b_node=24" self.curr.execute(sql) sql = "SELECT modes from nodes where node_id=24" self.curr.execute(sql) i = self.curr.fetchone()[0] self.assertIn('r', i) self.assertIn('y', i) def test_modes_on_links_insert(self): cmd = self.__get_query('modes_on_links_insert') if self.rtree: self.curr.execute('pragma table_info(links)') f = self.curr.fetchall() fields = {x[1]: x[0] for x in f} sql = 'select * from links where link_id=10' self.curr.execute(sql) a = [x for x in self.curr.fetchone()] a[fields['modes']] = 'as12' a[fields['link_id']] = 1234 a[fields['a_node']] = 999 a[fields['b_node']] = 888 a[0] = 1234 idx = ','.join(['?'] * len(a)) self.curr.execute(f'insert into links values ({idx})', a) self.curr.execute('delete from links where link_id=1234') self.curr.execute(cmd) with self.assertRaises(sqlite3.IntegrityError): self.curr.execute(f'insert into links values ({idx})', a) def test_modes_length_on_links_insert(self): cmd = self.__get_query('modes_length_on_links_insert') if self.rtree: self.curr.execute('pragma table_info(links)') f = self.curr.fetchall() fields = {x[1]: x[0] for x in f} sql = 'select * from links where link_id=70' self.curr.execute(sql) a = [x for x in self.curr.fetchone()] a[fields['modes']] = '' a[fields['link_id']] = 4321 a[fields['a_node']] = 888 a[fields['b_node']] = 999 a[0] = 4321 idx = ','.join(['?'] * len(a)) self.curr.execute(f'insert into links values ({idx})', a) self.curr.execute('delete from links where link_id=4321') self.curr.execute(cmd) with self.assertRaises(sqlite3.IntegrityError): self.curr.execute(f'insert into links values ({idx})', a) def test_keep_at_least_one(self): cmd = self.__get_query('mode_keep_at_least_one') self.curr.execute('Delete from modes;') self.curr.execute('select count(*) from modes;') self.assertEqual( self.curr.fetchone()[0], 0, 'We were not able to clear the m odes table as expected') self.curr.execute( 'insert into modes(mode_id, mode_name) VALUES("k", "some_name")') self.curr.execute(cmd) with self.assertRaises(sqlite3.IntegrityError): self.curr.execute('Delete from modes;') def test_modes_on_nodes_table_update_nodes_modes(self): cmd = self.__get_query('modes_on_nodes_table_update_nodes_modes') self.curr.execute( 'select node_id, modes from nodes where length(modes)>0') dt = self.curr.fetchall() x = choice(dt) self.curr.execute( f'update nodes set modes="abcdefgq" where node_id={x[0]}') self.curr.execute( f'select node_id, modes from nodes where node_id={x[0]}') z = self.curr.fetchone() if z == x: self.fail( 'Modes field on nodes layer is being preserved by unknown mechanism' ) self.curr.execute(cmd) y = choice(dt) while y == x: y = choice(dt) # We try to force the change to make sure it was correctly filled to begin with self.curr.execute( f'update nodes set modes="hgfedcba" where node_id={y[0]}') self.curr.execute( f'select node_id, modes from nodes where node_id={y[0]}') k = self.curr.fetchone() self.curr.execute( f'update nodes set modes="abcdefgq" where node_id={y[0]}') self.curr.execute( f'select node_id, modes from nodes where node_id={y[0]}') z = self.curr.fetchone() self.assertEqual( z, k, 'Failed to preserve the information on modes for the nodes')
class TestMatrices(TestCase): def setUp(self) -> None: proj_dir = os.path.join(gettempdir(), uuid.uuid4().hex) copytree(siouxfalls_project, proj_dir) self.project = Project() self.project.open(proj_dir) self.matrices = self.project.matrices self.matrices.reload() self.curr = self.project.conn.cursor() def tearDown(self) -> None: self.project.close() del self.project del self.matrices def randomword(self, length): allowed_characters = string.ascii_letters + '_123456789@!()[]{};:" -' val = "".join(choice(allowed_characters) for i in range(length)) if val[0] == "_" or val[-1] == "_": return self.randomword(length) return val def test_set_record(self): rec = self.matrices.get_record("omx2") with self.assertRaises(ValueError): rec.name = "omx" with self.assertRaises(ValueError): rec.file_name = "sfalls_skims.omx" rec.file_name = "SiouxFalls.omx" self.assertEqual( rec.cores, 1, "Setting a file that exists did not correct the number of cores") def test_clear_database(self): self.__mat_count(3, "The test data started wrong") self.matrices.clear_database() self.__mat_count(2, "Did not clear the database appropriately") def test_update_database(self): self.__mat_count(3, "The test data started wrong") self.matrices.update_database() self.__mat_count(4, "Did not add to the database appropriately") rec = self.matrices.get_record("omx") existing = join(rec.fldr, rec.file_name) new_name = "test_name.omx" new_name1 = "test_name1.omx" copyfile(existing, join(rec.fldr, new_name)) record = self.matrices.new_record("test_name1.omx", new_name) record.save() copyfile(existing, join(rec.fldr, new_name1)) self.matrices.update_database() def test_get_matrix(self): with self.assertRaises(Exception): _ = self.matrices.get_matrix("omxq") mat = self.matrices.get_matrix("oMx") mat.computational_view() self.assertEqual(floor(mat.matrix_view.sum()), 20309, "Matrix loaded incorrectly") def test_get_record(self): rec = self.matrices.get_record("omx") self.assertEqual(rec.cores, 4, "record populated wrong. Number of cores") self.assertEqual(rec.description, None, "record populated wrong. Description") def test_record_update_cores(self): rec = self.matrices.get_record("omx") rec.update_cores() self.assertEqual(rec.cores, 2, "Cores update did not work") def test_save_record(self): rec = self.matrices.get_record("omx") text = self.randomword(randint(30, 100)) rec.description = text rec.save() self.curr.execute('select description from matrices where name="omx";') self.assertEqual(text, self.curr.fetchone()[0], "Saving matrix record description failed") def test_delete(self): self.matrices.delete_record("omx") self.curr.execute('select count(*) from matrices where name="omx";') self.assertEqual(0, self.curr.fetchone()[0], " Deleting matrix record failed") with self.assertRaises(Exception): self.matrices.get_record("omx") def test_list(self): df = self.matrices.list() self.curr.execute("select count(*) from Matrices") self.assertEqual( df.shape[0], self.curr.fetchone()[0], "Returned the wrong number of matrices in the database") self.assertEqual(df[df.status == "file missing"].shape[0], 1, "Wrong # of records for missing matrix files") def __mat_count(self, should_have: int, error_message: str) -> None: self.curr.execute("Select count(*) from Matrices;") self.assertEqual(self.curr.fetchone()[0], should_have, error_message)
class TestLink(TestCase): def setUp(self) -> None: os.environ['PATH'] = os.path.join( gettempdir(), '../../temp_data') + ';' + os.environ['PATH'] self.proj_dir = os.path.join(gettempdir(), uuid.uuid4().hex) copytree(siouxfalls_project, self.proj_dir) self.project = Project() self.project.open(self.proj_dir) self.network = self.project.network self.curr = self.project.conn.cursor() self.links = self.network.links self.modes = self.network.modes self.links = self.network.links self.lid = randint(1, 24) self.link = self.links.get(self.lid) def tearDown(self) -> None: self.project.close() del self.curr try: rmtree(self.proj_dir) except Exception as e: print(f'Failed to remove at {e.args}') def test_delete(self): self.link.delete() with self.assertRaises(Exception): _ = self.links.get(self.lid) self.curr.execute('Select count(*) from links where link_id=?', [self.lid]) self.assertEqual(0, self.curr.fetchone()[0], f'Failed to delete link {self.lid}') def test_save(self): self.link.save() extension = random() name = 'just a non-important value' geo = substring(self.link.geometry, 0, extension, normalized=True) self.link.name = name self.link.geometry = geo self.link.save() self.links.refresh() link2 = self.links.get(self.lid) self.assertEqual(link2.name, name, 'Failed to save the link name') self.assertAlmostEqual(link2.geometry, geo, 3, 'Failed to save the link geometry') tot_prev = self.network.count_links() lnk = self.links.new() lnk.geometry = substring(self.link.geometry, 0, 0.88, normalized=True) lnk.modes = 'c' lnk.save() self.assertEqual(tot_prev + 1, self.network.count_links(), 'Failed to save new link') def test_set_modes(self): self.link.set_modes('cbt') self.assertEqual(self.link.modes, 'cbt', 'Did not set modes correctly') self.link.save() self.assertEqual(self.__check_mode(), 'cbt') def test_add_mode(self): for mode in [1, ['cbt']]: with self.assertRaises(TypeError): self.link.add_mode(mode) with self.assertRaises(ValueError): self.link.add_mode('bt') self.link.add_mode('b') self.link.save() self.assertEqual(self.__check_mode(), 'cb') mode = self.modes.get('t') self.link.add_mode(mode) self.link.save() self.assertEqual(self.__check_mode(), 'cbt') def test_drop_mode(self): self.link.set_modes('cbt') self.link.save() self.assertEqual(self.__check_mode(), 'cbt') self.link.drop_mode('t') self.link.save() self.assertEqual(self.__check_mode(), 'cb') mode = self.modes.get('b') self.link.drop_mode(mode) self.link.save() self.assertEqual(self.__check_mode(), 'c') def test_data_fields(self): link2 = self.links.get(randint(1, 24)) while link2.link_id == self.link.link_id: link2 = self.links.get(randint(1, 24)) self.assertEqual(link2.data_fields(), self.link.data_fields(), 'Different links have different data fields') fields = sorted(link2.data_fields()) self.curr.execute('pragma table_info(links)') dt = self.curr.fetchall() data_fields = sorted([x[1] for x in dt if x[1] != 'ogc_fid']) self.assertEqual(sorted(fields), sorted(data_fields), 'Link has unexpected set of fields') def __check_mode(self): sql = 'Select modes from links where link_id=?' self.curr.execute(sql, [self.lid]) return self.curr.fetchone()[0]