commit 69053634be3c3d8af05cc2b5648fe8bd375136ae Author: Nils Pukropp Date: Thu Mar 20 22:16:19 2025 +0100 init diff --git a/test14.py b/test14.py new file mode 100644 index 0000000..4d6c526 --- /dev/null +++ b/test14.py @@ -0,0 +1,964 @@ +from dataclasses import dataclass, field, fields, is_dataclass, InitVar +from types import NoneType, FunctionType, GenericAlias +from typing import get_args, Callable, Iterable, Iterator, Type, Optional, TypeAliasType, ForwardRef, Any, Literal +from enum import Enum +import unittest +from unittest import mock +from unittest.mock import patch +from functools import wraps +import signal +import io +import importlib +import importlib.util +import sys +import subprocess +import os +import shutil +import re +import math +import inspect +import json +import ast +import copy +import functools +import itertools + +output = "" + + +class TimeoutException(Exception): + pass + + +class Timeout: + def __init__(self, seconds, msg=None) -> None: + if msg is None: + msg = f"Test timed out after {seconds} seconds." + self.seconds = seconds + self.msg = msg + + def handle_timeout(self, signal, frame): + raise TimeoutException(self.msg) + + def __enter__(self): + signal.signal(signal.SIGALRM, self.handle_timeout) + signal.alarm(self.seconds) + + def __exit__(self, exc_type, exc_val, exc_tb): + signal.alarm(0) + +class IterablePure: + def __init__(self, i: Optional[Iterable] = None, repeat: bool = False): + if i is not None: + self.i = i + else: + def endless(): + c = 0 + while True: + yield c + c += 1 + self.i = endless() + + self.repeat = repeat + + def __iter__(self): + if self.repeat: + while True: + yield from self.i + else: + yield from self.i + + +def resolve_type_alias(t: Type) -> Type: + while isinstance(t, TypeAliasType | GenericAlias) and hasattr(t, "__value__"): + if isinstance(t, TypeAliasType): + t = t.__value__ + elif isinstance(t, GenericAlias): + t = t.__value__[*t.__args__] + return t + + +def check_annot(function: Callable, expected: list[Type], ret=None): + actual = function.__annotations__ + if "self" in actual: + del actual["self"] + return_type = actual["return"] if "return" in actual else None + actual = list(actual.values())[:-1] if "return" in actual else list(actual.values()) + for a, e in zip(actual, expected): + a = resolve_type_alias(a) + e = resolve_type_alias(e) + if a != e: + return False + return resolve_type_alias(ret) == resolve_type_alias(return_type) + + +def check_lambda_annotations(module, f_name: str, param_types: list[object], return_type: object = None) -> bool: + annotation = module.__annotations__[f_name] + if annotation.__name__ != 'Callable': + return False + + all_types = annotation.__args__ + types, ret_type = all_types[:-1], all_types[-1] + if ret_type != return_type: + return False + + for param, param_type in zip(types, param_types): + while isinstance(param, TypeAliasType): + param = param.__value__ + while isinstance(param_type, TypeAliasType): + param_type = param_type.__value__ + if param != param_type: + return False + return True + + +def check_attributes(o: object, inherited_attr: list[str], new_attr: list[str]) -> bool: + attr = [f.name for f in fields(o)] + if attr != inherited_attr + new_attr: + return False + + for attr in inherited_attr: + if attr in o.__annotations__: + return False + return True + + +def check_no_if_used(f: Callable) -> bool: + tree = ast.parse(inspect.getsource(f)) + for node in ast.walk(tree): + if isinstance(node, ast.If): + return False + return True + +def check_comprehension_used(f: Callable) -> bool: + source = inspect.getsource(f) + tree = ast.parse(source) + + for node in ast.walk(tree): + if isinstance(node, (ast.ListComp, ast.SetComp, ast.DictComp, ast.GeneratorExp)): + return True + return False + + +def check_no_sideeffects(f: Callable, *args) -> bool: + args_copy = tuple(copy.deepcopy(a) for a in args) + f(*args) + return args == args_copy + + +def check_function_used(f: Callable, name: str) -> bool: + source = inspect.getsource(f) + if source.startswith(4 * " "): + source = "\n".join(l[4:] for l in source.split("\n")) + return name in [c.func.id for c in ast.walk(ast.parse(source)) if isinstance(c, ast.Call) and isinstance(c.func, ast.Name)] + + +def check_function_not_used(f: Callable, name: str) -> bool: + source = inspect.getsource(f) + if source.startswith(4 * " "): + source = "\n".join(l[4:] for l in source.split("\n")) + return name not in [c.func.id for c in ast.walk(ast.parse(source)) if isinstance(c, ast.Call) and isinstance(c.func, ast.Name)] + + +def check_pattern_matching_used(f: Callable) -> bool: + source = inspect.getsource(f) + tree = ast.parse(source) + return any(isinstance(node, ast.Match) for node in ast.walk(tree)) + + +def check_gen(g: Iterator, res: Iterable, check_end: bool = True, max: int = 100) -> bool: + if not isinstance(g, Iterator): + return False + for i, x in enumerate(res): + el = next(g) + if el != x: + return False + if i >= max: + break + if check_end: + try: + next(g) + except StopIteration: + return True + return False + return True + + +def check_only_one_line(f: Callable) -> bool: + if f.__name__ == '': + return True + inspect.getsource(f) + lines = [line for line in inspect.getsource(f).split('\n') if not line.strip().startswith('#') and line.strip() != ''] + return len(lines) == 2 + + +def mock_print(*args, sep=None, end=None, **_kwargs): + global output + if sep is None: + sep = " " + if end is None: + end = "\n" + args = [str(a) for a in args] + output += str(sep.join(args)) + end + + +def mock_input(*arg: str): + inputs = [s for s in arg] + + def input_function(arg=None): + if arg is None: + arg = "" + nonlocal inputs + if len(inputs) == 0: + raise Exception("More input asked than given") + p = inputs[0] + inputs = inputs[1:] + mock_print(arg, p, sep="") + return p + return input_function + + +def input_error(*arg): + raise Exception("Input is not allowed here") + + +@patch("builtins.print", mock_print) +@patch("builtins.input", input_error) +def check_global_statements(unit: unittest.TestCase, module_name: str): + global output + output = "" + with Timeout(2): + if module_name in sys.modules.keys(): + del sys.modules[module_name] + module = importlib.import_module(module_name) + unit.assertEqual(output, "") + has_global_asserts = any(isinstance(node, ast.Assert) + for node in ast.iter_child_nodes(ast.parse(inspect.getsource(module)))) + unit.assertFalse(has_global_asserts) + + +def no_input_test(test_function: Callable) -> Callable: + @wraps(test_function) + @patch("builtins.print", mock_print) + @patch("builtins.input", input_error) + def inner(self): + global output + output = "" + with Timeout(2): + test_function(self) + return inner + + +class Ex1_sequences(unittest.TestCase): + def test1_global_statements(self): + check_global_statements(self, "ex1_sequences") + + @no_input_test + def test1_annot(self): + global output + output = "" + with Timeout(2): + import ex1_sequences + self.assertTrue(check_annot(ex1_sequences.count_iterations, [int, int], int)) + + @no_input_test + def test1_count_iterations(self): + global output + output = "" + with Timeout(2): + import ex1_sequences + self.assertEqual(ex1_sequences.count_iterations(10, 6), 1) + self.assertEqual(ex1_sequences.count_iterations(7, 6), 3) + self.assertEqual(ex1_sequences.count_iterations(4, 2), 1) + self.assertEqual(ex1_sequences.count_iterations(70, 2), 204) + self.assertEqual(ex1_sequences.count_iterations(3, 2), 3) + self.assertEqual(ex1_sequences.count_iterations(7, 4), 11) + self.assertEqual(ex1_sequences.count_iterations(37, 20), 6) + self.assertEqual(ex1_sequences.count_iterations(14, 4), 23) + self.assertEqual(ex1_sequences.count_iterations(8, 2), 2) + self.assertEqual(ex1_sequences.count_iterations(4, 3), 1) + + +class Ex2_dicts(unittest.TestCase): + def test2_global_statements(self): + check_global_statements(self, "ex2_dicts") + + @no_input_test + def test2_annot(self): + global output + output = "" + with Timeout(2): + import ex2_dicts + self.assertTrue(check_annot(ex2_dicts.lines, [dict[int, set[str]], str], set[int])) + self.assertTrue(check_annot(ex2_dicts.invert, [dict[int, set[str]]], dict[str, set[int]])) + self.assertTrue(check_annot(ex2_dicts.add_line, [dict[int, set[str]], set[str]], None)) + + @no_input_test + def test2_lines(self): + global output + output = "" + with Timeout(2): + import ex2_dicts + example1 = { + 1: {"Hauptbahnhof", "Paduaallee", "Stadttheater"}, + 2: {"Hauptbahnhof", "Stadttheater", "Hornusstraße", "Johanneskirche"}, + 3: {"Am Lindenwäldle", "Hauptbahnhof", "Stadttheater", "Johanneskirche"}, + 5: {"Europaplatz", "Stadttheater", "Am Lindenwäldle"}, + } + example2 = { + 1: {"stat1", "stat2", "stat3"}, + 3: {"stat3", "stat4"}, + 19: {"stat1", "stat2", "stat3", "stat4"} + } + self.assertEqual(ex2_dicts.lines(example1, "Hauptbahnhof"), {1, 2, 3}) + self.assertEqual(ex2_dicts.lines(example1, "Paduaallee"), {1}) + self.assertEqual(ex2_dicts.lines(example1, "Stadttheater"), {1, 2, 3, 5}) + self.assertEqual(ex2_dicts.lines(example1, "Stadttheater"), {1, 2, 3, 5}) + self.assertEqual(ex2_dicts.lines(example1, "Johanneskirche"), {2, 3}) + self.assertEqual(ex2_dicts.lines(example1, "Hornusstraße"), {2}) + self.assertEqual(ex2_dicts.lines(example1, "Am Lindenwäldle"), {3, 5}) + self.assertEqual(ex2_dicts.lines(example1, "Europaplatz"), {5}) + self.assertEqual(ex2_dicts.lines(example2, "stat1"), {1, 19}) + self.assertEqual(ex2_dicts.lines(example2, "stat2"), {1, 19}) + self.assertEqual(ex2_dicts.lines(example2, "stat3"), {1, 3, 19}) + self.assertEqual(ex2_dicts.lines(example2, "stat4"), {3, 19}) + + self.assertEqual(ex2_dicts.lines(example1, "Anywhere"), set()) + self.assertEqual(ex2_dicts.lines(example2, "Hauptbahnhof"), set()) + + self.assertEqual(ex2_dicts.lines({}, "Hauptbahnhof"), set()) + self.assertEqual(ex2_dicts.lines({}, "Anywhere"), set()) + + self.assertTrue(check_no_sideeffects(ex2_dicts.lines, example1, "Hauptbahnhof")) + + @no_input_test + def test2_invert(self): + global output + output = "" + with Timeout(2): + import ex2_dicts + example1 = { + 1: {"Hauptbahnhof", "Paduaallee", "Stadttheater"}, + 2: {"Hauptbahnhof", "Stadttheater", "Hornusstraße", "Johanneskirche"}, + 3: {"Am Lindenwäldle", "Hauptbahnhof", "Stadttheater", "Johanneskirche"}, + 5: {"Europaplatz", "Stadttheater", "Am Lindenwäldle"}, + } + example2 = { + 1: {"stat1", "stat2", "stat3"}, + 3: {"stat3", "stat4"}, + 19: {"stat1", "stat2", "stat3", "stat4"} + } + self.assertDictEqual(ex2_dicts.invert(example1),{ + 'Stadttheater': {1, 2, 3, 5}, + 'Hauptbahnhof': {1, 2, 3}, + 'Paduaallee': {1}, + 'Johanneskirche': {2, 3}, + 'Hornusstraße': {2}, + 'Am Lindenwäldle': {3, 5}, + 'Europaplatz': {5} + }) + self.assertDictEqual(ex2_dicts.invert(example2), { + 'stat1': {1, 19}, + 'stat2': {1, 19}, + 'stat3': {1, 3, 19}, + 'stat4': {3, 19} + }) + self.assertEqual(ex2_dicts.invert({}), {}) + self.assertTrue(check_no_sideeffects(ex2_dicts.invert, example1)) + + @no_input_test + def test2_add_line(self): + global output + output = "" + with Timeout(2): + import ex2_dicts + example1 = { + 1: {"Hauptbahnhof", "Paduaallee", "Stadttheater"}, + 2: {"Hauptbahnhof", "Stadttheater", "Hornusstraße", "Johanneskirche"}, + 3: {"Am Lindenwäldle", "Hauptbahnhof", "Stadttheater", "Johanneskirche"}, + 5: {"Europaplatz", "Stadttheater", "Am Lindenwäldle"}, + } + example2 = { + 1: {"stat1", "stat2", "stat3"}, + 3: {"stat3", "stat4"}, + 19: {"stat1", "stat2", "stat3", "stat4"} + } + ex2_dicts.add_line( + example1, + { + "Technische Fakultät", + "Hauptbahnhof", + "Stadttheater", + "Europaplatz", + "Hornusstraße", + }, + ) + self.assertDictEqual(example1, { + 1: {"Hauptbahnhof", "Paduaallee", "Stadttheater"}, + 2: {"Hauptbahnhof", "Stadttheater", "Hornusstraße", "Johanneskirche"}, + 3: {"Am Lindenwäldle", "Hauptbahnhof", "Stadttheater", "Johanneskirche"}, + 4: {"Technische Fakultät", "Hauptbahnhof", "Stadttheater", "Europaplatz", "Hornusstraße"}, + 5: {"Europaplatz", "Stadttheater", "Am Lindenwäldle"} + }) + + ex2_dicts.add_line(example2, {"stat1", "stat2", "stat3"}) + self.assertDictEqual(example2, { + 1: {"stat1", "stat2", "stat3"}, + 2: {"stat1", "stat2", "stat3"}, + 3: {"stat3", "stat4"}, + 19: {"stat1", "stat2", "stat3", "stat4"} + }) + + ex2_dicts.add_line(example2, {"foo", "bar"}) + self.assertDictEqual(example2, { + 1: {"stat1", "stat2", "stat3"}, + 2: {"stat1", "stat2", "stat3"}, + 3: {"stat3", "stat4"}, + 4: {"foo", "bar"}, + 19: {"stat1", "stat2", "stat3", "stat4"} + }) + + example3 = {} + for i in range(1, 100): + ex2_dicts.add_line(example3, {f"stat{i}"}) + for j in range(1, i + 1): + self.assertEqual(example3[j], {f"stat{j}"}) + self.assertIsNone(ex2_dicts.add_line({}, {"foo"})) + + +class Ex3_strings(unittest.TestCase): + def test3_global_statements(self): + check_global_statements(self, "ex3_strings") + + @no_input_test + def test3_annot(self): + global output + output = "" + with Timeout(2): + import ex3_strings + self.assertTrue(check_annot(ex3_strings.s2_in_s1, [str, str], bool)) + self.assertTrue(check_annot(ex3_strings.split_text, [str], list[str])) + + @no_input_test + def test3_s2_in_s1(self): + global output + output = "" + with Timeout(2): + import ex3_strings + self.assertTrue(ex3_strings.s2_in_s1("function", "fn") is True) + self.assertTrue(ex3_strings.s2_in_s1("function", "ufnction") is False) + self.assertTrue(ex3_strings.s2_in_s1("function", "fnn") is True) + self.assertTrue(ex3_strings.s2_in_s1("function", "fcc") is False) + self.assertTrue(ex3_strings.s2_in_s1("teststring", "tssr") is True) + self.assertTrue(ex3_strings.s2_in_s1("test", "test") is True) + self.assertTrue(ex3_strings.s2_in_s1("cons", "cs") is True) + self.assertTrue(ex3_strings.s2_in_s1("co", "oc") is False) + self.assertTrue(ex3_strings.s2_in_s1("false", "flase") is False) + + self.assertTrue(ex3_strings.s2_in_s1("foo", "") is True) + self.assertTrue(ex3_strings.s2_in_s1("", "bar") is False) + + @no_input_test + def test3_split_text(self): + global output + output = "" + with Timeout(2): + import ex3_strings + self.assertListEqual(ex3_strings.split_text("You're a lizard, Harry!"), [ + 'You', "'", 're', ' ', 'a', ' ', 'lizard', ', ', 'Harry', '!' + ]) + self.assertListEqual(ex3_strings.split_text("Luke! I'm your father!!"), [ + 'Luke', '! ', 'I', "'", 'm', ' ', 'your', ' ', 'father', '!!' + ]) + self.assertListEqual(ex3_strings.split_text("*Stay away from her, you $!#@!*"), [ + '*', 'Stay', ' ', 'away', ' ', 'from', ' ', 'her', ', ', 'you', ' $!#@!*' + ]) + self.assertListEqual(ex3_strings.split_text("hello world"), ["hello", " ", "world"]) + self.assertListEqual(ex3_strings.split_text("test$$case"), ["test", "$$", "case"]) + self.assertListEqual(ex3_strings.split_text(""), []) + self.assertListEqual(ex3_strings.split_text("word"), ["word"]) + self.assertListEqual(ex3_strings.split_text("138904642&(/%$)(=)"), ["138904642&(/%$)(=)"]) + + +class Ex4_dataclasses(unittest.TestCase): + def test4_global_statements(self): + check_global_statements(self, "ex5_dataclasses") + + @no_input_test + def test4_annot(self): + global output + output = "" + with Timeout(2): + import ex5_dataclasses + self.assertTrue(is_dataclass(ex5_dataclasses.Vehicle)) + self.assertTrue(check_attributes(ex5_dataclasses.Vehicle, [], ["seats", "hp", "ccm", "weight"])) + self.assertDictEqual(ex5_dataclasses.Vehicle.__annotations__, { + "seats": int, + "hp": int, + "ccm": int, + "weight": int + }) + + @no_input_test + def test4_Vehicle(self): + global output + output = "" + with Timeout(2): + import ex5_dataclasses + # seats + self.assertRaises(BaseException, ex5_dataclasses.Vehicle.__init__, 0, 5, 5, 5) + self.assertRaises(BaseException, ex5_dataclasses.Vehicle.__init__, -5, 5, 5, 5) + self.assertRaises(BaseException, ex5_dataclasses.Vehicle.__init__, 10, 5, 5, 5) + self.assertRaises(BaseException, ex5_dataclasses.Vehicle.__init__, 165, 5, 5, 5) + ex5_dataclasses.Vehicle(1, 5, 5, 5) + ex5_dataclasses.Vehicle(5, 5, 5, 5) + ex5_dataclasses.Vehicle(9, 5, 5, 5) + + # hp + self.assertRaises(BaseException, ex5_dataclasses.Vehicle.__init__, 5, 0, 5, 5) + self.assertRaises(BaseException, ex5_dataclasses.Vehicle.__init__, 5, -5, 5, 5) + ex5_dataclasses.Vehicle(5, 1, 5, 5) + ex5_dataclasses.Vehicle(5, 5, 5, 5) + ex5_dataclasses.Vehicle(5, 9, 5, 5) + + # ccm + self.assertRaises(BaseException, ex5_dataclasses.Vehicle.__init__, 5, 5, 0, 5) + self.assertRaises(BaseException, ex5_dataclasses.Vehicle.__init__, 5, 5, -5, 5) + ex5_dataclasses.Vehicle(5, 5, 1, 5) + ex5_dataclasses.Vehicle(5, 5, 5, 5) + ex5_dataclasses.Vehicle(5, 5, 9, 5) + + # weight + self.assertRaises(BaseException, ex5_dataclasses.Vehicle.__init__, 5, 5, 5, 0) + self.assertRaises(BaseException, ex5_dataclasses.Vehicle.__init__, 5, 5, 5, -5) + ex5_dataclasses.Vehicle(5, 5, 5, 1) + ex5_dataclasses.Vehicle(5, 5, 5, 5) + ex5_dataclasses.Vehicle(5, 5, 5, 9) + + @no_input_test + def test4_Vehicle_fun_factor(self): + global output + output = "" + with Timeout(2): + import ex5_dataclasses + v1 = ex5_dataclasses.Vehicle(1, 1, 1, 1) + v2 = ex5_dataclasses.Vehicle(2, 1, 4, 2) + v3 = ex5_dataclasses.Vehicle(1, 4, 5, 2) + v4 = ex5_dataclasses.Vehicle(5, 6, 3, 9) + v5 = ex5_dataclasses.Vehicle(3, 1, 6, 2) + v6 = ex5_dataclasses.Vehicle(4, 2, 7, 1) + + self.assertEqual(v1.fun_factor(), 11) + self.assertEqual(v2.fun_factor(), 7) + self.assertEqual(v3.fun_factor(), 22.5) + self.assertEqual(v4.fun_factor(), 7) + self.assertEqual(v5.fun_factor(), 8) + self.assertEqual(v6.fun_factor(), 27) + + @no_input_test + def test4_Vehicle_gt(self): + global output + output = "" + with Timeout(2): + import ex5_dataclasses + v1 = ex5_dataclasses.Vehicle(1, 1, 1, 1) + v2 = ex5_dataclasses.Vehicle(2, 1, 4, 2) + v3 = ex5_dataclasses.Vehicle(1, 4, 5, 2) + v4 = ex5_dataclasses.Vehicle(5, 6, 3, 9) + v5 = ex5_dataclasses.Vehicle(3, 1, 6, 2) + v6 = ex5_dataclasses.Vehicle(4, 2, 7, 1) + + self.assertTrue(v1 > v2) + self.assertTrue(v3 > v2) + self.assertTrue(v6 > v3) + self.assertTrue(v5 > v4) + self.assertTrue(v5 > v2) + + @no_input_test + def test4_Car(self): + global output + output = "" + with Timeout(2): + import ex5_dataclasses + self.assertTrue(is_dataclass(ex5_dataclasses.Car)) + self.assertTrue(issubclass(ex5_dataclasses.Car, ex5_dataclasses.Vehicle)) + self.assertTrue(check_attributes(ex5_dataclasses.Car, ["seats", "hp", "ccm", "weight"], ["spoiler"])) + self.assertDictEqual(ex5_dataclasses.Car.__annotations__, {"spoiler": bool}) + self.assertTrue(ex5_dataclasses.Car.__post_init__ is ex5_dataclasses.Vehicle.__post_init__) + self.assertTrue(check_function_used(ex5_dataclasses.Car.fun_factor, "super")) + c1 = ex5_dataclasses.Car(5, 5, 5, 5, True) + c2 = ex5_dataclasses.Car(5, 5, 5, 5, False) + with patch.object(ex5_dataclasses.Vehicle, "fun_factor", return_value=1337): + self.assertEqual(c1.fun_factor(), 1337.2) + self.assertEqual(c2.fun_factor(), 1337) + + @no_input_test + def test4_Motorcycle(self): + global output + output = "" + with Timeout(2): + import ex5_dataclasses + self.assertTrue(is_dataclass(ex5_dataclasses.Motorcycle)) + self.assertTrue(issubclass(ex5_dataclasses.Motorcycle, ex5_dataclasses.Vehicle)) + self.assertTrue(check_attributes(ex5_dataclasses.Motorcycle, ["seats", "hp", "ccm", "weight"], ["sidecar"])) + self.assertDictEqual(ex5_dataclasses.Motorcycle.__annotations__, {"sidecar": bool}) + self.assertTrue(check_function_used(ex5_dataclasses.Motorcycle.fun_factor, "super")) + with patch("ex5_dataclasses.Vehicle.__post_init__") as vehicle_post_init: + ex5_dataclasses.Motorcycle(3, 1, 1, 1, True) + vehicle_post_init.assert_called_once() + self.assertRaises(BaseException, ex5_dataclasses.Motorcycle.__init__, 3, 1, 1, 1, False) + self.assertRaises(BaseException, ex5_dataclasses.Motorcycle.__init__, 6, 1, 1, 1, False) + self.assertRaises(BaseException, ex5_dataclasses.Motorcycle.__init__, 1, 1, 1, 1, True) + self.assertRaises(BaseException, ex5_dataclasses.Motorcycle.__init__, 4, 1, 1, 1, True) + with patch.object(ex5_dataclasses.Vehicle, "fun_factor", return_value=1337): + m1 = ex5_dataclasses.Motorcycle(3, 5, 5, 5, True) + m2 = ex5_dataclasses.Motorcycle(2, 5, 5, 5, False) + self.assertAlmostEqual(m1.fun_factor(), 3208.8) + self.assertAlmostEqual(m2.fun_factor(), 668.5) + + +class Ex5_automaton(unittest.TestCase): + def test5_global_statements(self): + check_global_statements(self, "ex4_automaton") + + @no_input_test + def test5_State(self): + global output + output = "" + with Timeout(2): + import ex4_automaton + self.assertTrue(issubclass(ex4_automaton.State, Enum)) + self.assertFalse(is_dataclass(ex4_automaton.State)) + states = ex4_automaton.State._member_names_ + self.assertTrue(states == ["q0", "q1", "q2", "qe"] or states == ["Q0", "Q1", "Q2", "QE"]) + + @no_input_test + def test5_delta_annot(self): + global output + output = "" + with Timeout(2): + from ex4_automaton import delta, Alphabet, State + self.assertTrue(check_annot(delta, [State, Alphabet], ret=State)) + + @no_input_test + def test5_delta_match(self): + global output + output = "" + with Timeout(2): + import ex4_automaton + self.assertTrue(check_pattern_matching_used(ex4_automaton.delta)) + + @no_input_test + def test5_delta(self): + global output + output = "" + with Timeout(2): + import ex4_automaton + q0 = ex4_automaton.State.q0 if "q0" in ex4_automaton.State._member_names_ else ex4_automaton.State.Q0 + q1 = ex4_automaton.State.q1 if "q1" in ex4_automaton.State._member_names_ else ex4_automaton.State.Q1 + q2 = ex4_automaton.State.q2 if "q2" in ex4_automaton.State._member_names_ else ex4_automaton.State.Q2 + qe = ex4_automaton.State.qe if "qe" in ex4_automaton.State._member_names_ else ex4_automaton.State.QE + self.assertEqual(ex4_automaton.delta(q0, "a"), q1) + self.assertEqual(ex4_automaton.delta(q1, "a"), q0) + self.assertEqual(ex4_automaton.delta(q1, "b"), q1) + self.assertEqual(ex4_automaton.delta(q0, "b"), q2) + self.assertEqual(ex4_automaton.delta(q2, "a"), q2) + self.assertEqual(ex4_automaton.delta(q2, "c"), q1) + self.assertEqual(ex4_automaton.delta(q2, "b"), qe) + + @no_input_test + def test5_automaton(self): + global output + output = "" + with Timeout(2): + import ex4_automaton + M = ex4_automaton.automaton() + self.assertEqual(resolve_type_alias(ex4_automaton.Alphabet), resolve_type_alias(Literal["a", "b", "c"])) + self.assertEqual(M.delta, ex4_automaton.delta) + self.assertEqual(M.start, ex4_automaton.State.q0 if "q0" in ex4_automaton.State._member_names_ else ex4_automaton.State.Q0) + self.assertEqual(M.finals, frozenset({ex4_automaton.State.q0 if "q0" in ex4_automaton.State._member_names_ else ex4_automaton.State.Q0})) + self.assertTrue(check_annot(ex4_automaton.automaton, [], ex4_automaton.Automaton[ex4_automaton.State, ex4_automaton.Alphabet])) + + +class Ex6_recursion(unittest.TestCase): + def test6_global_statements(self): + check_global_statements(self, "ex6_recursion") + + @no_input_test + def test6_annot(self): + global output + output = "" + with Timeout(2): + import ex6_recursion + type_params = ex6_recursion.filter_tree.__type_params__ + self.assertEqual(len(type_params), 1) + T = type_params[0] + self.assertTrue(check_annot(ex6_recursion.filter_tree, [Callable[[T], bool], ex6_recursion.Tree[T]], list[T])) + self.assertTrue(check_annot(ex6_recursion.mirror_tree, [ex6_recursion.Tree[Any]], None)) + + @no_input_test + def test6_filter_tree(self): + global output + output = "" + with Timeout(2): + import ex6_recursion + Node = ex6_recursion.Node + example_node1 = Node("zero", Node("one"), Node("two", Node("three"), Node("four"))) + example_node2 = Node(0, Node(5, Node(3)), Node(1)) + example_node3 = None + example_node4 = Node(0) + example_node5 = Node(1, Node(2), Node(3)) + self.assertListEqual(ex6_recursion.filter_tree(lambda x: 'e' in x, example_node1), ['zero', 'one', 'three']) + self.assertListEqual(ex6_recursion.filter_tree(lambda x: 'o' in x, example_node1), ['zero', 'one', 'two', 'four']) + self.assertListEqual(ex6_recursion.filter_tree(lambda _: False, example_node1), []) + self.assertListEqual(ex6_recursion.filter_tree(lambda _: True, None), []) + self.assertListEqual(ex6_recursion.filter_tree(lambda x: x % 2 == 0, example_node5), [2]) + self.assertListEqual(ex6_recursion.filter_tree(lambda x: x < 0, example_node4), []) + self.assertListEqual(ex6_recursion.filter_tree(lambda x: True, example_node3), []) + self.assertTrue(check_no_sideeffects(ex6_recursion.filter_tree, lambda x: len(x) == 3, example_node1)) + + @no_input_test + def test6_mirror_tree(self): + global output + output = "" + with Timeout(2): + import ex6_recursion + Node = ex6_recursion.Node + example_node1 = Node("zero", Node("one"), Node("two", Node("three"), Node("four"))) + example_node2 = Node(0, Node(5, Node(3)), Node(1)) + example_node3 = None + example_node4 = Node(0) + example_node5 = Node(1, Node(2), Node(3)) + self.assertIsNone(ex6_recursion.mirror_tree(example_node1)) + example_node1 = Node("zero", Node("one"), Node("two", Node("three"), Node("four"))) + + ex6_recursion.mirror_tree(example_node2) + self.assertEqual(example_node2, Node(0, Node(1), Node(5, None, Node(3)))) + ex6_recursion.mirror_tree(example_node2) + self.assertEqual(example_node2, Node(0, Node(5, Node(3)), Node(1))) + ex6_recursion.mirror_tree(example_node1) + self.assertEqual(example_node1, Node("zero", Node("two", Node("four"), Node("three")), Node("one"))) + x = None + ex6_recursion.mirror_tree(x) + self.assertIsNone(x) + + # mirror twice + ex6_recursion.mirror_tree(example_node5) + ex6_recursion.mirror_tree(example_node5) + self.assertEqual(example_node5, Node(1, Node(2), Node(3))) + + +class Ex7_generators(unittest.TestCase): + def test7_global_statements(self): + check_global_statements(self, "ex7_generators") + + @no_input_test + def test7_annot(self): + global output + output = "" + with Timeout(2): + import ex7_generators + type_params = ex7_generators.drop.__type_params__ + self.assertEqual(len(type_params), 1) + T = type_params[0] + self.assertTrue(check_annot(ex7_generators.drop, [Iterable[T], int], Iterator[T])) + + type_params = ex7_generators.split.__type_params__ + self.assertEqual(len(type_params), 1) + T = type_params[0] + self.assertTrue(check_annot(ex7_generators.split, [Iterable[T], T], Iterator[list[T]])) + + type_params = ex7_generators.apply_pairs.__type_params__ + self.assertEqual(len(type_params), 2) + T, R = type_params + self.assertTrue(check_annot(ex7_generators.apply_pairs, [Iterable[T], Callable[[T, T], R]], Iterator[R])) + + @no_input_test + def test7_drop(self): + global output + output = "" + with Timeout(2): + import ex7_generators + self.assertTrue(check_function_not_used(ex7_generators.drop, "list")) + self.assertTrue(check_gen(ex7_generators.drop(IterablePure([2, 4, 6, 8, 10, 12]), 3), [8, 10, 12])) + self.assertTrue(check_gen(ex7_generators.drop(IterablePure([True, False, False]), 0), [True, False, False])) + self.assertTrue(check_gen(ex7_generators.drop(IterablePure(["a", "b", "c", "d"]), 8), [])) + self.assertTrue(check_gen(ex7_generators.drop(IterablePure(range(1, 4)), 1), [2, 3])) + self.assertTrue(check_gen(ex7_generators.drop(IterablePure([1, 1, 1, 1]), 0), [1, 1, 1, 1])) + self.assertTrue(check_gen(ex7_generators.drop(IterablePure([]), 0), [])) + self.assertTrue(check_gen(ex7_generators.drop(IterablePure(), 178), range(178, 1000), False, 1000)) + + @no_input_test + def test7_split(self): + global output + output = "" + with Timeout(2): + import ex7_generators + g1 = ex7_generators.split(IterablePure([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), 5) + self.assertTrue(check_gen(g1, [list(range(1, 5)), list(range(6, 11))])) + g2 = ex7_generators.split(IterablePure("abcdefghij", True), "e") + self.assertTrue(check_gen(g2, [list("abcd")] + [list("fghijabcd")] * 999, False, 1000)) + g3 = ex7_generators.split(IterablePure("mississippiXXX", False), "i") + self.assertTrue(check_gen(g3, [list("m"), list("ss"), list("ss"), list("pp"), list("XXX")])) + g4 = ex7_generators.split(IterablePure(("Hallo", "Welt", "asdfa", "?", "asdfa", "wsgd", "Nöö", "asdfa", "Nix da"), False), "asdfa") + self.assertTrue(check_gen(g4, [["Hallo", "Welt"], ["?"], ["wsgd", "Nöö"], ["Nix da"]])) + g5 = ex7_generators.split(IterablePure("abcdefghij", True), "a") + self.assertTrue(check_gen(g5, [[]] + [list("bcdefghij")] * 999, False, 1000)) + + g1 = ex7_generators.split(IterablePure([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), 10) + self.assertTrue(check_gen(g1, [list(range(1, 10)), []])) + g2 = ex7_generators.split(IterablePure("abcdjjefjjghi"), "j") + self.assertTrue(check_gen(g2, [list("abcd"), [], list("ef"), [], list("ghi")])) + + @no_input_test + def test7_apply_pairs(self): + global output + output = "" + with Timeout(2): + import ex7_generators + check_function_not_used(ex7_generators.apply_pairs, "list") + + sub = lambda x, y: x - y + eq = lambda x, y: x == y + add_1 = lambda x, y: x + y + 1 + + g1 = ex7_generators.apply_pairs(IterablePure([5, 2, 7, 9, 1]), sub) + self.assertTrue(check_gen(g1, [3, -5, -2, 8])) + g2 = ex7_generators.apply_pairs(IterablePure("abaabbc", repeat=True), eq) + self.assertTrue(check_gen(g2, [False, False, True, False, True, False, False] * 100, False, 700)) + g3 = ex7_generators.apply_pairs(IterablePure([1]), sub) + self.assertTrue(check_gen(g3, [])) + g4 = ex7_generators.apply_pairs(IterablePure([None, None, "", None]), eq) + self.assertTrue(check_gen(g4, [True, False, False])) + g5 = ex7_generators.apply_pairs(IterablePure([0, 1, 1, 0, 1]), lambda x, y: (x + y) % 2) + self.assertTrue(check_gen(g5, [1, 0, 1, 1])) + g6 = ex7_generators.apply_pairs(IterablePure([0, 1, 1, 0, 1]), lambda x, y: x * y) + self.assertTrue(check_gen(g6, [0, 1, 0, 0])) + g7 = ex7_generators.apply_pairs(IterablePure([1, 0]), sub) + self.assertTrue(check_gen(g7, [1])) + g8 = ex7_generators.apply_pairs(IterablePure([1, 0], True), add_1) + self.assertTrue(check_gen(g8, [2, 2] * 1000, False, 1000)) + + +class Ex8_fp(unittest.TestCase): + def test8_global_statements(self): + check_global_statements(self, "ex8_fp") + + @no_input_test + def test8_annot(self): + global output + output = "" + with Timeout(2): + import ex8_fp + if ex8_fp.sum_0.__name__ == '': + self.assertTrue(check_lambda_annotations(ex8_fp, 'sum_0', [list[Callable[[float], float]]], float)) + else: + self.assertTrue(check_annot(ex8_fp.sum_0, [list[Callable[[float], float]]], float)) + + type_params = ex8_fp.extensionally_equal.__type_params__ + self.assertEqual(len(type_params), 2) + T, R = type_params + self.assertTrue(check_annot(ex8_fp.extensionally_equal, [Callable[[T], R], Callable[[T], R], list[T]], bool)) + + if ex8_fp.map_matrix.__name__ == '': + self.assertTrue(check_lambda_annotations(ex8_fp, 'map_matrix', [Callable[[float], float], list[list[float]]], list[list[float]])) + else: + self.assertTrue(check_annot(ex8_fp.map_matrix, [Callable[[float], float], list[list[float]]], list[list[float]])) + + @no_input_test + def test8_sum_0(self): + global output + output = "" + with Timeout(2): + import ex8_fp + self.assertTrue(check_only_one_line(ex8_fp.sum_0)) + f = lambda x: x + 1 + self.assertEqual(ex8_fp.sum_0([f]), 1) + self.assertEqual(ex8_fp.sum_0([f, f, f]), 3) + + f = lambda x: x + 1 + g = lambda x: x**2 + self.assertEqual(ex8_fp.sum_0([f, g]), 1) + + f = lambda x: x % 12 + g = lambda x: x**x + h = lambda _: 1337.333 + self.assertTrue(math.isclose(ex8_fp.sum_0([f, g, h]), 1338.333)) + + self.assertEqual(ex8_fp.sum_0([]), 0) + + @no_input_test + def test8_extensionally_equal(self): + global output + output = "" + with Timeout(2): + import ex8_fp + self.assertTrue(check_only_one_line(ex8_fp.extensionally_equal)) + f = lambda x: x * 2 - 1 + g = lambda y: y * (4 / 2) - 1 + self.assertTrue(ex8_fp.extensionally_equal(f, g, [1, 2, 3, 4, 5])) + h = lambda x: x ** 2 - 4 + k = lambda x: (x - 2) * (x + 2) + self.assertTrue(ex8_fp.extensionally_equal(h, k, [1, 5, 3, 7, 3])) + l = lambda y: y < 4 + le = lambda x: x <= 4 + self.assertTrue(ex8_fp.extensionally_equal(l, le, [1, 2, 3])) + + g = lambda y: y * (4 / 2) - 1 + k = lambda x: (x - 2) * (x + 2) + self.assertFalse(ex8_fp.extensionally_equal(g, k, [1])) + self.assertFalse(ex8_fp.extensionally_equal(g, k, [0])) + self.assertFalse(ex8_fp.extensionally_equal(g, k, [1, 3])) + l = lambda y: y < 4 + le = lambda x: x <= 4 + self.assertFalse(ex8_fp.extensionally_equal(l, le, [1, 2, 3, 4])) + + @no_input_test + def test8_map_matrix(self): + global output + output = "" + with Timeout(2): + import ex8_fp + self.assertTrue(check_only_one_line(ex8_fp.map_matrix)) + self.assertFalse(check_comprehension_used(ex8_fp.map_matrix)) + self.assertTrue(check_function_used(ex8_fp.map_matrix, "map")) + self.assertTrue(check_function_used(ex8_fp.map_matrix, "list")) + + example = [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]] + self.assertListEqual(ex8_fp.map_matrix(lambda x: x * 2, example), [[2, 4, 6], [8, 10, 12]]) + example2 = [[2, 5], [5, 6]] + self.assertListEqual(ex8_fp.map_matrix(lambda x: x ** 2, example2), [[4, 25], [25, 36]]) + self.assertListEqual(ex8_fp.map_matrix(lambda y: y < 5, example2), [[True, False], [False, False]]) + self.assertListEqual(ex8_fp.map_matrix(lambda x: x, []), []) + + +def get_results(): + result_data = {} + output = io.StringIO("") + test_classes = [(name, cls) for name, cls in inspect.getmembers(sys.modules[__name__], lambda x: inspect.isclass( + x) and (x.__module__ == __name__)) if unittest.TestCase in cls.__mro__] + suite = unittest.TestLoader().loadTestsFromTestCase(test_classes[0][1]) + for other in test_classes[1:]: + suite.addTest(unittest.TestLoader().loadTestsFromTestCase(other[1])) + testResult = unittest.TextTestRunner(stream=output, verbosity=2).run(suite) + result_data["tests"] = [str(test_method) for test in test_classes + for test_method in unittest.TestLoader().loadTestsFromTestCase(test[1])] + result_data["failure"] = not testResult.wasSuccessful() + result_data["tests_run"] = testResult.testsRun + result_data["failures"] = [(str(func), str(err)) + for func, err in testResult.failures] + result_data["errors"] = [(str(func), str(err)) + for func, err in testResult.errors] + return result_data + + +if __name__ == "__main__": + docker_run = True + try: + with open("/output/output.json", "w", encoding="utf-8") as f: + result = get_results() + json.dump(result, f) + except FileNotFoundError: + docker_run = False + if not docker_run: + unittest.main()