#!/usr/bin/env python3 # -*- coding: utf-8 -*- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # IMPORTS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ import pytest; from pytest import mark; from pytest import fixture; from pytest import lazy_fixture; from unittest import TestCase; from unittest.mock import patch; from src.thirdparty.types import *; from src.models.graphs import *; from src.algorithms.tarjan import *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # FIXTURES # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @fixture(scope='module') def graph1() -> Graph: return Graph( nodes=[1,2,3,4], edges=[(1,2), (2,4), (4,2)], ); @fixture(scope='module') def graph2() -> Graph: return Graph( nodes=[1,2,3,4,5,6,7], edges=[(1,2), (1,3), (2,3), (3,4), (4,5), (5,2), (5,6), (5,7), (6,7)], ); @fixture(scope='module') def graph3() -> Graph: return Graph( nodes=[1,2,3,4,5,6,7,8], edges=[ (1,2), (1,3), (2,4), (2,5), (3,5), (3,6), (3,8), (4,5), (4,7), (5,1), (5,8), (6,8), (7,8), (8,6), ], ); # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Test Tarjan-Algorithm # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @mark.parametrize( ('G', 'expected'), [ (lazy_fixture('graph1'), [[1], [3], [2,4]]), (lazy_fixture('graph2'), [[1], [6], [7], [2,3,4,5]]), (lazy_fixture('graph3'), [[1,2,3,4,5], [7], [6,8]]), ], ) @mark.usefixtures('test') def test_tarjan(test, G, expected): components = tarjan_algorithm(G, False); assert_components_eq(test, components, expected); @patch(f'{__name__}.tarjan_algorithm', lambda *_: []) @mark.parametrize(('G', 'expected'), [ (lazy_fixture('graph1'), [[1], [3], [2,4]])]) @mark.usefixtures('test') def test_failable_tarjan(test, G, expected): with pytest.raises(AssertionError): test_tarjan(test, G, expected); # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # AUXILIARY METHODS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def assert_components_eq(test: TestCase, components1: list[list[Any]], components2: list[list[Any]]): result = check_components_eq(test, components1, components2); test.assertTrue(result); def check_components_eq(test: TestCase, components1: list[list[Any]], components2: list[list[Any]]) -> bool: if len(components1) != len(components2): return False; for component1 in components1: found = False; for component2 in components2: try: test.assertCountEqual(component1, component2); found = True; break; except: continue; if not found: return False; return True;