# Copyright 2014-2015, Tresys Technology, LLC # # SPDX-License-Identifier: GPL-2.0-only # import os import unittest from setools import DomainTransitionAnalysis from setools import TERuletype as TERT from setools.exception import InvalidType from setools.policyrep import Type from . import mixins from .policyrep.util import compile_policy class DomainTransitionAnalysisTest(mixins.ValidateRule, unittest.TestCase): @classmethod def setUpClass(cls): cls.p = compile_policy("tests/dta.conf") cls.a = DomainTransitionAnalysis(cls.p) cls.a._build_graph() @classmethod def tearDownClass(cls): os.unlink(cls.p.path) def test_000_graph_structure(self): """DTA: verify graph structure.""" # don't check node list since the disconnected nodes are not # removed after removing invalid domain transitions start = self.p.lookup_type("start") trans1 = self.p.lookup_type("trans1") trans2 = self.p.lookup_type("trans2") trans3 = self.p.lookup_type("trans3") trans5 = self.p.lookup_type("trans5") dyntrans100 = self.p.lookup_type("dyntrans100") bothtrans200 = self.p.lookup_type("bothtrans200") edges = set(self.a.G.out_edges()) self.assertSetEqual(set([(dyntrans100, bothtrans200), (start, dyntrans100), (start, trans1), (trans1, trans2), (trans2, trans3), (trans3, trans5)]), edges) def test_001_bothtrans(self): """DTA: type_transition, setexeccon(), and setcon() transitions.""" s = self.p.lookup_type("dyntrans100") t = self.p.lookup_type("bothtrans200") e = self.p.lookup_type("bothtrans200_exec") # regular transition r = self.a.G.edges[s, t]["transition"] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, t, "process", set(["transition", "dyntransition"])) # setexec perms r = self.a.G.edges[s, t]["setexec"] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, s, "process", set(["setexec", "setcurrent"])) # exec perms k = sorted(self.a.G.edges[s, t]["execute"].keys()) self.assertEqual(k, [e]) r = self.a.G.edges[s, t]["execute"][e] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, e, "file", set(["execute"])) # entrypoint perms k = sorted(self.a.G.edges[s, t]["entrypoint"].keys()) self.assertEqual(k, [e]) r = self.a.G.edges[s, t]["entrypoint"][e] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, t, e, "file", set(["entrypoint"])) # type_transition k = sorted(self.a.G.edges[s, t]["type_transition"].keys()) self.assertEqual(k, [e]) r = self.a.G.edges[s, t]["type_transition"][e] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.type_transition, s, e, "process", t) # dynamic transition r = self.a.G.edges[s, t]["dyntransition"] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, t, "process", set(["transition", "dyntransition"])) # setcurrent r = self.a.G.edges[s, t]["setcurrent"] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, s, "process", set(["setexec", "setcurrent"])) def test_010_dyntrans(self): """DTA: setcon() transition.""" s = self.p.lookup_type("start") t = self.p.lookup_type("dyntrans100") # regular transition r = self.a.G.edges[s, t]["transition"] self.assertEqual(len(r), 0) # setexec perms r = self.a.G.edges[s, t]["setexec"] self.assertEqual(len(r), 0) # exec perms k = sorted(self.a.G.edges[s, t]["execute"].keys()) self.assertEqual(len(k), 0) # entrypoint perms k = sorted(self.a.G.edges[s, t]["entrypoint"].keys()) self.assertEqual(len(k), 0) # type_transition k = sorted(self.a.G.edges[s, t]["type_transition"].keys()) self.assertEqual(len(k), 0) # dynamic transition r = self.a.G.edges[s, t]["dyntransition"] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, t, "process", set(["dyntransition"])) # setcurrent r = self.a.G.edges[s, t]["setcurrent"] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, s, "process", set(["setcurrent"])) def test_020_trans(self): """DTA: type_transition transition.""" s = self.p.lookup_type("start") t = self.p.lookup_type("trans1") e = self.p.lookup_type("trans1_exec") # regular transition r = self.a.G.edges[s, t]["transition"] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, t, "process", set(["transition"])) # setexec perms r = self.a.G.edges[s, t]["setexec"] self.assertEqual(len(r), 0) # exec perms k = sorted(self.a.G.edges[s, t]["execute"].keys()) self.assertEqual(k, [e]) r = self.a.G.edges[s, t]["execute"][e] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, e, "file", set(["execute"])) # entrypoint perms k = sorted(self.a.G.edges[s, t]["entrypoint"].keys()) self.assertEqual(k, [e]) r = self.a.G.edges[s, t]["entrypoint"][e] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, t, e, "file", set(["entrypoint"])) # type_transition k = sorted(self.a.G.edges[s, t]["type_transition"].keys()) self.assertEqual(k, [e]) r = self.a.G.edges[s, t]["type_transition"][e] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.type_transition, s, e, "process", t) # dynamic transition r = self.a.G.edges[s, t]["dyntransition"] self.assertEqual(len(r), 0) # setcurrent r = self.a.G.edges[s, t]["setcurrent"] self.assertEqual(len(r), 0) def test_030_setexec(self): """DTA: setexec() transition.""" s = self.p.lookup_type("trans1") t = self.p.lookup_type("trans2") e = self.p.lookup_type("trans2_exec") # regular transition r = self.a.G.edges[s, t]["transition"] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, t, "process", set(["transition"])) # setexec perms r = self.a.G.edges[s, t]["setexec"] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, s, "process", set(["setexec"])) # exec perms k = sorted(self.a.G.edges[s, t]["execute"].keys()) self.assertEqual(k, [e]) r = self.a.G.edges[s, t]["execute"][e] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, e, "file", set(["execute"])) # entrypoint perms k = sorted(self.a.G.edges[s, t]["entrypoint"].keys()) self.assertEqual(k, [e]) r = self.a.G.edges[s, t]["entrypoint"][e] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, t, e, "file", set(["entrypoint"])) # type_transition k = sorted(self.a.G.edges[s, t]["type_transition"].keys()) self.assertEqual(len(k), 0) # dynamic transition r = self.a.G.edges[s, t]["dyntransition"] self.assertEqual(len(r), 0) # setcurrent r = self.a.G.edges[s, t]["setcurrent"] self.assertEqual(len(r), 0) def test_040_two_entrypoint(self): """DTA: 2 entrypoints, only one by type_transition.""" s = self.p.lookup_type("trans2") t = self.p.lookup_type("trans3") e = [self.p.lookup_type("trans3_exec1"), self.p.lookup_type("trans3_exec2")] # regular transition r = self.a.G.edges[s, t]["transition"] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, t, "process", set(["transition"])) # setexec perms r = self.a.G.edges[s, t]["setexec"] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, s, "process", set(["setexec"])) # exec perms k = sorted(self.a.G.edges[s, t]["execute"].keys()) self.assertEqual(k, e) r = self.a.G.edges[s, t]["execute"][e[0]] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, e[0], "file", set(["execute"])) r = self.a.G.edges[s, t]["execute"][e[1]] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, e[1], "file", set(["execute"])) # entrypoint perms k = sorted(self.a.G.edges[s, t]["entrypoint"].keys()) self.assertEqual(k, e) r = self.a.G.edges[s, t]["entrypoint"][e[0]] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, t, e[0], "file", set(["entrypoint"])) r = self.a.G.edges[s, t]["entrypoint"][e[1]] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, t, e[1], "file", set(["entrypoint"])) # type_transition k = sorted(self.a.G.edges[s, t]["type_transition"].keys()) self.assertEqual(k, [e[0]]) r = self.a.G.edges[s, t]["type_transition"][e[0]] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.type_transition, s, e[0], "process", t) # dynamic transition r = self.a.G.edges[s, t]["dyntransition"] self.assertEqual(len(r), 0) # setcurrent r = self.a.G.edges[s, t]["setcurrent"] self.assertEqual(len(r), 0) def test_050_cond_type_trans(self): """DTA: conditional type_transition.""" s = self.p.lookup_type("trans3") t = self.p.lookup_type("trans5") e = self.p.lookup_type("trans5_exec") # regular transition r = self.a.G.edges[s, t]["transition"] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, t, "process", set(["transition"])) # setexec perms r = self.a.G.edges[s, t]["setexec"] self.assertEqual(len(r), 0) # exec perms k = sorted(self.a.G.edges[s, t]["execute"].keys()) self.assertEqual(k, [e]) r = self.a.G.edges[s, t]["execute"][e] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, s, e, "file", set(["execute"])) # entrypoint perms k = sorted(self.a.G.edges[s, t]["entrypoint"].keys()) self.assertEqual(k, [e]) r = self.a.G.edges[s, t]["entrypoint"][e] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.allow, t, e, "file", set(["entrypoint"])) # type_transition k = sorted(self.a.G.edges[s, t]["type_transition"].keys()) self.assertEqual(k, [e]) r = self.a.G.edges[s, t]["type_transition"][e] self.assertEqual(len(r), 1) self.validate_rule(r[0], TERT.type_transition, s, e, "process", t, cond="trans5") # dynamic transition r = self.a.G.edges[s, t]["dyntransition"] self.assertEqual(len(r), 0) # setcurrent r = self.a.G.edges[s, t]["setcurrent"] self.assertEqual(len(r), 0) def test_100_forward_subgraph_structure(self): """DTA: verify forward subgraph structure.""" # The purpose is to ensure the subgraph is reversed # only when the reverse option is set, not that # graph reversal is correct (assumed that NetworkX # does it correctly). # Don't check node list since the disconnected nodes are not # removed after removing invalid domain transitions self.a.reverse = False self.a._build_subgraph() start = self.p.lookup_type("start") trans1 = self.p.lookup_type("trans1") trans2 = self.p.lookup_type("trans2") trans3 = self.p.lookup_type("trans3") trans5 = self.p.lookup_type("trans5") dyntrans100 = self.p.lookup_type("dyntrans100") bothtrans200 = self.p.lookup_type("bothtrans200") edges = set(self.a.subG.out_edges()) self.assertSetEqual(set([(dyntrans100, bothtrans200), (start, dyntrans100), (start, trans1), (trans1, trans2), (trans2, trans3), (trans3, trans5)]), edges) def test_101_reverse_subgraph_structure(self): """DTA: verify reverse subgraph structure.""" # The purpose is to ensure the subgraph is reversed # only when the reverse option is set, not that # graph reversal is correct (assumed that NetworkX # does it correctly). # Don't check node list since the disconnected nodes are not # removed after removing invalid domain transitions self.a.reverse = True self.a._build_subgraph() start = self.p.lookup_type("start") trans1 = self.p.lookup_type("trans1") trans2 = self.p.lookup_type("trans2") trans3 = self.p.lookup_type("trans3") trans5 = self.p.lookup_type("trans5") dyntrans100 = self.p.lookup_type("dyntrans100") bothtrans200 = self.p.lookup_type("bothtrans200") edges = set(self.a.subG.out_edges()) self.assertSetEqual(set([(bothtrans200, dyntrans100), (dyntrans100, start), (trans1, start), (trans2, trans1), (trans3, trans2), (trans5, trans3)]), edges) def test_200_exclude_domain(self): """DTA: exclude domain type.""" # Don't check node list since the disconnected nodes are not # removed after removing invalid domain transitions self.a.reverse = False self.a.exclude = ["trans1"] self.a._build_subgraph() start = self.p.lookup_type("start") trans2 = self.p.lookup_type("trans2") trans3 = self.p.lookup_type("trans3") trans5 = self.p.lookup_type("trans5") dyntrans100 = self.p.lookup_type("dyntrans100") bothtrans200 = self.p.lookup_type("bothtrans200") edges = set(self.a.subG.out_edges()) self.assertSetEqual(set([(dyntrans100, bothtrans200), (start, dyntrans100), (trans2, trans3), (trans3, trans5)]), edges) def test_201_exclude_entryoint_with_2entrypoints(self): """DTA: exclude entrypoint type without transition deletion (other entrypoints).""" # Don't check node list since the disconnected nodes are not # removed after removing invalid domain transitions self.a.reverse = False self.a.exclude = ["trans3_exec1"] self.a._build_subgraph() start = self.p.lookup_type("start") trans1 = self.p.lookup_type("trans1") trans2 = self.p.lookup_type("trans2") trans3 = self.p.lookup_type("trans3") trans5 = self.p.lookup_type("trans5") dyntrans100 = self.p.lookup_type("dyntrans100") bothtrans200 = self.p.lookup_type("bothtrans200") edges = set(self.a.subG.out_edges()) self.assertSetEqual(set([(dyntrans100, bothtrans200), (start, dyntrans100), (start, trans1), (trans1, trans2), (trans2, trans3), (trans3, trans5)]), edges) def test_202_exclude_entryoint_with_dyntrans(self): """DTA: exclude entrypoint type without transition deletion (dyntrans).""" # Don't check node list since the disconnected nodes are not # removed after removing invalid domain transitions self.a.reverse = False self.a.exclude = ["bothtrans200_exec"] self.a._build_subgraph() start = self.p.lookup_type("start") trans1 = self.p.lookup_type("trans1") trans2 = self.p.lookup_type("trans2") trans3 = self.p.lookup_type("trans3") trans5 = self.p.lookup_type("trans5") dyntrans100 = self.p.lookup_type("dyntrans100") bothtrans200 = self.p.lookup_type("bothtrans200") edges = set(self.a.subG.out_edges()) self.assertSetEqual(set([(dyntrans100, bothtrans200), (start, dyntrans100), (start, trans1), (trans1, trans2), (trans2, trans3), (trans3, trans5)]), edges) def test_203_exclude_entryoint_delete_transition(self): """DTA: exclude entrypoint type with transition deletion.""" # Don't check node list since the disconnected nodes are not # removed after removing invalid domain transitions self.a.reverse = False self.a.exclude = ["trans2_exec"] self.a._build_subgraph() start = self.p.lookup_type("start") trans1 = self.p.lookup_type("trans1") trans2 = self.p.lookup_type("trans2") trans3 = self.p.lookup_type("trans3") trans5 = self.p.lookup_type("trans5") dyntrans100 = self.p.lookup_type("dyntrans100") bothtrans200 = self.p.lookup_type("bothtrans200") edges = set(self.a.subG.out_edges()) self.assertSetEqual(set([(dyntrans100, bothtrans200), (start, dyntrans100), (start, trans1), (trans2, trans3), (trans3, trans5)]), edges) def test_300_all_paths(self): """DTA: all paths output""" self.a.reverse = False self.a.exclude = None expected_path = ["start", "dyntrans100", "bothtrans200"] paths = list(self.a.all_paths("start", "bothtrans200", 3)) self.assertEqual(1, len(paths)) for path in paths: for stepnum, step in enumerate(path): self.assertIsInstance(step.source, Type) self.assertIsInstance(step.target, Type) self.assertEqual(expected_path[stepnum], step.source) self.assertEqual(expected_path[stepnum + 1], step.target) for r in step.transition: self.assertIn("transition", r.perms) for e in step.entrypoints: self.assertIsInstance(e.name, Type) for r in e.entrypoint: self.assertIn("entrypoint", r.perms) for r in e.execute: self.assertIn("execute", r.perms) for r in e.type_transition: self.assertEqual(TERT.type_transition, r.ruletype) for r in step.setexec: self.assertIn("setexec", r.perms) for r in step.dyntransition: self.assertIn("dyntransition", r.perms) for r in step.setcurrent: self.assertIn("setcurrent", r.perms) def test_301_all_shortest_paths(self): """DTA: all shortest paths output""" self.a.reverse = False self.a.exclude = None expected_path = ["start", "dyntrans100", "bothtrans200"] paths = list(self.a.all_shortest_paths("start", "bothtrans200")) self.assertEqual(1, len(paths)) for path in paths: for stepnum, step in enumerate(path): self.assertIsInstance(step.source, Type) self.assertIsInstance(step.target, Type) self.assertEqual(expected_path[stepnum], step.source) self.assertEqual(expected_path[stepnum + 1], step.target) for r in step.transition: self.assertIn("transition", r.perms) for e in step.entrypoints: self.assertIsInstance(e.name, Type) for r in e.entrypoint: self.assertIn("entrypoint", r.perms) for r in e.execute: self.assertIn("execute", r.perms) for r in e.type_transition: self.assertEqual(TERT.type_transition, r.ruletype) for r in step.setexec: self.assertIn("setexec", r.perms) for r in step.dyntransition: self.assertIn("dyntransition", r.perms) for r in step.setcurrent: self.assertIn("setcurrent", r.perms) def test_302_shortest_path(self): """DTA: shortest path output""" self.a.reverse = False self.a.exclude = None expected_path = ["start", "dyntrans100", "bothtrans200"] paths = list(self.a.shortest_path("start", "bothtrans200")) self.assertEqual(1, len(paths)) for path in paths: for stepnum, step in enumerate(path): self.assertIsInstance(step.source, Type) self.assertIsInstance(step.target, Type) self.assertEqual(expected_path[stepnum], step.source) self.assertEqual(expected_path[stepnum + 1], step.target) for r in step.transition: self.assertIn("transition", r.perms) for e in step.entrypoints: self.assertIsInstance(e.name, Type) for r in e.entrypoint: self.assertIn("entrypoint", r.perms) for r in e.execute: self.assertIn("execute", r.perms) for r in e.type_transition: self.assertEqual(TERT.type_transition, r.ruletype) for r in step.setexec: self.assertIn("setexec", r.perms) for r in step.dyntransition: self.assertIn("dyntransition", r.perms) for r in step.setcurrent: self.assertIn("setcurrent", r.perms) def test_303_transitions(self): """DTA: transitions output""" self.a.reverse = False self.a.exclude = None transitions = list(self.a.transitions("start")) self.assertEqual(2, len(transitions)) for step in transitions: self.assertIsInstance(step.source, Type) self.assertIsInstance(step.target, Type) self.assertEqual("start", step.source) for r in step.transition: self.assertIn("transition", r.perms) for e in step.entrypoints: self.assertIsInstance(e.name, Type) for r in e.entrypoint: self.assertIn("entrypoint", r.perms) for r in e.execute: self.assertIn("execute", r.perms) for r in e.type_transition: self.assertEqual(TERT.type_transition, r.ruletype) for r in step.setexec: self.assertIn("setexec", r.perms) for r in step.dyntransition: self.assertIn("dyntransition", r.perms) for r in step.setcurrent: self.assertIn("setcurrent", r.perms) def test_310_all_paths_reversed(self): """DTA: all paths output reverse DTA""" self.a.reverse = True self.a.exclude = None expected_path = ["bothtrans200", "dyntrans100", "start"] paths = list(self.a.all_paths("bothtrans200", "start", 3)) self.assertEqual(1, len(paths)) for path in paths: for stepnum, step in enumerate(path): self.assertIsInstance(step.source, Type) self.assertIsInstance(step.target, Type) self.assertEqual(step.source, expected_path[stepnum + 1]) self.assertEqual(step.target, expected_path[stepnum]) for r in step.transition: self.assertIn("transition", r.perms) for e in step.entrypoints: self.assertIsInstance(e.name, Type) for r in e.entrypoint: self.assertIn("entrypoint", r.perms) for r in e.execute: self.assertIn("execute", r.perms) for r in e.type_transition: self.assertEqual(TERT.type_transition, r.ruletype) for r in step.setexec: self.assertIn("setexec", r.perms) for r in step.dyntransition: self.assertIn("dyntransition", r.perms) for r in step.setcurrent: self.assertIn("setcurrent", r.perms) def test_311_all_shortest_paths_reversed(self): """DTA: all shortest paths output reverse DTA""" self.a.reverse = True self.a.exclude = None expected_path = ["bothtrans200", "dyntrans100", "start"] paths = list(self.a.all_shortest_paths("bothtrans200", "start")) self.assertEqual(1, len(paths)) for path in paths: for stepnum, step in enumerate(path): self.assertIsInstance(step.source, Type) self.assertIsInstance(step.target, Type) self.assertEqual(step.source, expected_path[stepnum + 1]) self.assertEqual(step.target, expected_path[stepnum]) for r in step.transition: self.assertIn("transition", r.perms) for e in step.entrypoints: self.assertIsInstance(e.name, Type) for r in e.entrypoint: self.assertIn("entrypoint", r.perms) for r in e.execute: self.assertIn("execute", r.perms) for r in e.type_transition: self.assertEqual(TERT.type_transition, r.ruletype) for r in step.setexec: self.assertIn("setexec", r.perms) for r in step.dyntransition: self.assertIn("dyntransition", r.perms) for r in step.setcurrent: self.assertIn("setcurrent", r.perms) def test_312_shortest_path_reversed(self): """DTA: shortest path output reverse DTA""" self.a.reverse = True self.a.exclude = None expected_path = ["bothtrans200", "dyntrans100", "start"] paths = list(self.a.shortest_path("bothtrans200", "start")) self.assertEqual(1, len(paths)) for path in paths: for stepnum, step in enumerate(path): self.assertIsInstance(step.source, Type) self.assertIsInstance(step.target, Type) self.assertEqual(expected_path[stepnum + 1], step.source) self.assertEqual(expected_path[stepnum], step.target) for r in step.transition: self.assertIn("transition", r.perms) for e in step.entrypoints: self.assertIsInstance(e.name, Type) for r in e.entrypoint: self.assertIn("entrypoint", r.perms) for r in e.execute: self.assertIn("execute", r.perms) for r in e.type_transition: self.assertEqual(TERT.type_transition, r.ruletype) for r in step.setexec: self.assertIn("setexec", r.perms) for r in step.dyntransition: self.assertIn("dyntransition", r.perms) for r in step.setcurrent: self.assertIn("setcurrent", r.perms) def test_313_transitions_reversed(self): """DTA: transitions output reverse DTA""" self.a.reverse = True self.a.exclude = None transitions = list(self.a.transitions("bothtrans200")) self.assertEqual(1, len(transitions)) for step in transitions: self.assertIsInstance(step.source, Type) self.assertIsInstance(step.target, Type) self.assertEqual("bothtrans200", step.target) for r in step.transition: self.assertIn("transition", r.perms) for e in step.entrypoints: self.assertIsInstance(e.name, Type) for r in e.entrypoint: self.assertIn("entrypoint", r.perms) for r in e.execute: self.assertIn("execute", r.perms) for r in e.type_transition: self.assertEqual(TERT.type_transition, r.ruletype) for r in step.setexec: self.assertIn("setexec", r.perms) for r in step.dyntransition: self.assertIn("dyntransition", r.perms) for r in step.setcurrent: self.assertIn("setcurrent", r.perms) def test_900_set_exclude_invalid_type(self): """DTA: set invalid excluded type.""" self.a.reverse = False self.a.exclude = None with self.assertRaises(InvalidType): self.a.exclude = ["trans1", "invalid_type"] def test_910_all_paths_invalid_source(self): """DTA: all paths with invalid source type.""" self.a.reverse = False self.a.exclude = None with self.assertRaises(InvalidType): list(self.a.all_paths("invalid_type", "trans1")) def test_911_all_paths_invalid_target(self): """DTA: all paths with invalid target type.""" self.a.reverse = False self.a.exclude = None with self.assertRaises(InvalidType): list(self.a.all_paths("trans1", "invalid_type")) def test_912_all_paths_invalid_maxlen(self): """DTA: all paths with invalid max path length.""" self.a.reverse = False self.a.exclude = None with self.assertRaises(ValueError): list(self.a.all_paths("trans1", "trans2", maxlen=-2)) def test_913_all_paths_source_excluded(self): """DTA: all paths with excluded source type.""" self.a.reverse = False self.a.exclude = ["trans1"] paths = list(self.a.all_paths("trans1", "trans2")) self.assertEqual(0, len(paths)) def test_914_all_paths_target_excluded(self): """DTA: all paths with excluded target type.""" self.a.reverse = False self.a.exclude = ["trans2"] paths = list(self.a.all_paths("trans1", "trans2")) self.assertEqual(0, len(paths)) def test_915_all_paths_source_disconnected(self): """DTA: all paths with disconnected source type.""" self.a.reverse = False self.a.exclude = None paths = list(self.a.all_paths("trans5", "trans2")) self.assertEqual(0, len(paths)) def test_916_all_paths_target_disconnected(self): """DTA: all paths with disconnected target type.""" self.a.reverse = False self.a.exclude = ["trans3"] paths = list(self.a.all_paths("trans2", "trans5")) self.assertEqual(0, len(paths)) def test_920_shortest_path_invalid_source(self): """DTA: shortest path with invalid source type.""" self.a.reverse = False self.a.exclude = None with self.assertRaises(InvalidType): list(self.a.shortest_path("invalid_type", "trans1")) def test_921_shortest_path_invalid_target(self): """DTA: shortest path with invalid target type.""" self.a.reverse = False self.a.exclude = None with self.assertRaises(InvalidType): list(self.a.shortest_path("trans1", "invalid_type")) def test_922_shortest_path_source_excluded(self): """DTA: shortest path with excluded source type.""" self.a.reverse = False self.a.exclude = ["trans1"] paths = list(self.a.shortest_path("trans1", "trans2")) self.assertEqual(0, len(paths)) def test_923_shortest_path_target_excluded(self): """DTA: shortest path with excluded target type.""" self.a.reverse = False self.a.exclude = ["trans2"] paths = list(self.a.shortest_path("trans1", "trans2")) self.assertEqual(0, len(paths)) def test_924_shortest_path_source_disconnected(self): """DTA: shortest path with disconnected source type.""" self.a.reverse = False self.a.exclude = None paths = list(self.a.shortest_path("trans5", "trans2")) self.assertEqual(0, len(paths)) def test_925_shortest_path_target_disconnected(self): """DTA: shortest path with disconnected target type.""" self.a.reverse = False self.a.exclude = ["trans3"] paths = list(self.a.shortest_path("trans2", "trans5")) self.assertEqual(0, len(paths)) def test_930_all_shortest_paths_invalid_source(self): """DTA: all shortest paths with invalid source type.""" self.a.reverse = False self.a.exclude = None with self.assertRaises(InvalidType): list(self.a.all_shortest_paths("invalid_type", "trans1")) def test_931_all_shortest_paths_invalid_target(self): """DTA: all shortest paths with invalid target type.""" self.a.reverse = False self.a.exclude = None with self.assertRaises(InvalidType): list(self.a.all_shortest_paths("trans1", "invalid_type")) def test_932_all_shortest_paths_source_excluded(self): """DTA: all shortest paths with excluded source type.""" self.a.reverse = False self.a.exclude = ["trans1"] paths = list(self.a.all_shortest_paths("trans1", "trans2")) self.assertEqual(0, len(paths)) def test_933_all_shortest_paths_target_excluded(self): """DTA: all shortest paths with excluded target type.""" self.a.reverse = False self.a.exclude = ["trans2"] paths = list(self.a.all_shortest_paths("trans1", "trans2")) self.assertEqual(0, len(paths)) def test_934_all_shortest_paths_source_disconnected(self): """DTA: all shortest paths with disconnected source type.""" self.a.reverse = False self.a.exclude = None paths = list(self.a.all_shortest_paths("trans5", "trans2")) self.assertEqual(0, len(paths)) def test_935_all_shortest_paths_target_disconnected(self): """DTA: all shortest paths with disconnected target type.""" self.a.reverse = False self.a.exclude = ["trans3"] paths = list(self.a.all_shortest_paths("trans2", "trans5")) self.assertEqual(0, len(paths)) def test_940_transitions_invalid_source(self): """DTA: transitions with invalid source type.""" self.a.reverse = False self.a.exclude = None with self.assertRaises(InvalidType): list(self.a.transitions("invalid_type")) def test_941_transitions_source_excluded(self): """DTA: transitions with excluded source type.""" self.a.reverse = False self.a.exclude = ["trans1"] paths = list(self.a.transitions("trans1")) self.assertEqual(0, len(paths)) def test_942_transitions_source_disconnected(self): """DTA: transitions with disconnected source type.""" self.a.reverse = False self.a.exclude = ["trans3"] paths = list(self.a.transitions("trans5")) self.assertEqual(0, len(paths))