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()