From 885757f7520c260c17f6eb11df149e2d72cca056 Mon Sep 17 00:00:00 2001 From: SAVELIY BAKTURIN <96750568+zavierwaffle@users.noreply.github.com> Date: Sun, 8 Mar 2026 18:08:25 +0000 Subject: [PATCH] + Fixed Floating test suite. --- README.md | 7 ++- main.py | 3 +- testsuites/fixed_floating.py | 110 +++++++++++++++++++++++++++++++++++ testsuites/suite.py | 23 ++++---- 4 files changed, 129 insertions(+), 14 deletions(-) create mode 100644 testsuites/fixed_floating.py diff --git a/README.md b/README.md index af4f4a2..eaf43ab 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,10 @@ Ниже представлена таблица доступных для тестирования (как локально, так и автоматически в репозиториях) лабораторных работ с названием набора тестов для тестера (`suite`). -| № | Лабораторная работа | Набор тестов | -|:--:|:--------------------|:-------------| -| 0 | Интро | `intro` | +| № | Лабораторная работа | Набор тестов | +|:--:|:--------------------|:-----------------| +| 0 | Интро | `intro` | +| 1 | Представление чисел | `fixed_floating` | ## Скрипт запуска diff --git a/main.py b/main.py index d5beca2..803074d 100755 --- a/main.py +++ b/main.py @@ -4,12 +4,13 @@ import argparse import platform import testsuites.intro as intro +import testsuites.fixed_floating as fixed_floating from testsuites import Testsuite, DynamicWrapper from typing import Dict, Any, List __TESTSUITES: List[Testsuite] = [ - intro.instance + intro.instance, fixed_floating.instance ] __SUITENAMES: List[str] = [t.name() for t in __TESTSUITES] diff --git a/testsuites/fixed_floating.py b/testsuites/fixed_floating.py new file mode 100644 index 0000000..2915ea8 --- /dev/null +++ b/testsuites/fixed_floating.py @@ -0,0 +1,110 @@ +from .suite import Run, Runned, Verdict +from testsuites import * +from enum import Enum + +class __FixedFloating(Testsuite): + __SUITE_NAME = "fixed_floating" + __TIMEOUT = 1 + __CATEGORIES_TO_ENVNAMES = {"fixed": "FIXED", "floating": "FLOATING"} + + def __init__(self): + super().__init__(self.__SUITE_NAME, PREFIX_ENVIRONMENT_NAME, self.__CATEGORIES_TO_ENVNAMES) + + def get_tester(self) -> Tester: + tester = Tester(self.name()) + + class Policy(Enum): + FIXED = 1 + FLOATING = 2 + + class __Expected(Expected): + def __init__(self, ref: str, policy: Policy): + super().__init__() + + self.__ref = ref + self.__policy = policy + + def test(self, run: Run, runned: Runned) -> Verdict: + output = runned.get_stdout() + if not output.endswith("\n"): + return Verdict(VerdictErrno.ERROR_INVALID_FORMAT, f"newline at stdout's end expected") + + lines = output.splitlines() + if len(lines) != 1: + return Verdict(VerdictErrno.ERROR_INVALID_FORMAT, f"single line expected") + + line = lines[0] + if line != line.lstrip() or line != line.rstrip(): + return Verdict(VerdictErrno.ERROR_INVALID_FORMAT, f"found unexpected space characters in stdout") + + actuals = line.split(" ") + if len(actuals) != self.__policy.value: + return Verdict(VerdictErrno.ERROR_INVALID_FORMAT, f"expected {self.__policy.value} elements on single line, but found {len(actuals)}") + + expecteds = self.__ref.split(" ") + + if any(a != e for a, e in zip(actuals, expecteds)): + return Verdict(VerdictErrno.ERROR_ASSERTION, f"expected '{self.__ref}', but actual is '{line}'") + + return ok() + + def __single_test(args: str, ref: str, policy: Policy) -> SingleTest: + run = Run(c_timeout = self.__TIMEOUT, c_stdin = None, c_args = args.split(" "), t_returncode_policy = ReturnCodePolicy.ShouldBeZero) + expected = __Expected(ref, policy) + return (run, expected) + + def __sequence(args: str, ref: str, policy: Policy) -> List[SingleTest]: + return [__single_test(args, ref, policy)] + + def __test(name: str, categories: List[str], args: str, ref: str, policy: Policy) -> Test: + return Test(name, categories, __sequence(args, ref, policy)) + + def __t(name: str, categories: List[str], args: str, ref: str, policy: Policy): + tester.add(__test(name, categories, args, ref, policy)) + + def fixed(name: str, argv: str, ref: str): + categories = ["fixed"] + __t(name, categories, argv, ref, Policy.FIXED) + + def floating(name: str, argv: str, ref: str): + categories = ["floating"] + __t(name, categories, argv, ref, Policy.FLOATING) + + fixed(name = "print with rounding A 0", argv = "16.12 0 0x17360", ref = "23.210") + fixed(name = "print with rounding A 1", argv = "16.12 1 0x17360", ref = "23.211") + fixed(name = "print with rounding A 2", argv = "16.12 2 0x17360", ref = "23.211") + fixed(name = "print with rounding A 3", argv = "16.12 3 0x17360", ref = "23.210") + + fixed(name = "print with rounding B 0", argv = "8.8 0 0x9c9f", ref = "-99.378") + fixed(name = "print with rounding B 1", argv = "8.8 1 0x9c9F", ref = "-99.379") + fixed(name = "print with rounding B 2", argv = "8.8 2 0x9C9f", ref = "-99.378") + fixed(name = "print with rounding B 3", argv = "8.8 3 0x9c9f", ref = "-99.379") + + fixed(name = "+ with rounding 0", argv = "8.8 0 + 0xdc9f 0xD736", ref = "-76.167") + fixed(name = "+ with rounding 1", argv = "8.8 1 + 0xDc9f 0xd736", ref = "-76.168") + fixed(name = "+ with rounding 2", argv = "8.8 2 + 0xdC9f 0xd736", ref = "-76.167") + fixed(name = "+ with rounding 3", argv = "8.8 3 + 0xdc9F 0xd736", ref = "-76.168") + + floating(name = "single pres.: print with rounding 0", argv = "s 0 0xB9CD542", ref = "0x1.39aa84p-104 0x0B9CD542") + floating(name = "single pres.: print with rounding 1", argv = "s 1 0xB9Cd542", ref = "0x1.39aa84p-104 0x0B9CD542") + floating(name = "single pres.: print with rounding 2", argv = "s 2 0xb9CD542", ref = "0x1.39aa84p-104 0x0B9CD542") + floating(name = "single pres.: print with rounding 3", argv = "s 3 0xB9cD542", ref = "0x1.39aa84p-104 0x0B9CD542") + + floating(name = "half pres.: * with rounding 0", argv = "h 0 * 0x4145 0x142EB", ref = "0x1.238p+3 0x488E") + floating(name = "half pres.: * with rounding 1", argv = "h 1 * 0x4145 0x142eB", ref = "0x1.23cp+3 0x488F") + floating(name = "half pres.: * with rounding 2", argv = "h 2 * 0x4145 0x142eb", ref = "0x1.23cp+3 0x488F") + floating(name = "half pres.: * with rounding 3", argv = "h 3 * 0x4145 0x142Eb", ref = "0x1.238p+3 0x488E") + + floating(name = "half pres.: special with rounding 0", argv = "h 0 / 0x1 0x0", ref = "inf 0x7C00") + floating(name = "single pres.: special with rounding 1", argv = "s 1 + 0xFFC10000 0x7F800001", ref = "nan 0xFFC10000") + floating(name = "single pres.: special with rounding 2", argv = "s 2 / 0x1 0x0", ref = "inf 0x7F800000") + floating(name = "half pres.: special with rounding 3", argv = "h 3 + 0xFF10 0x7F01", ref = "nan 0xFF10") + + floating(name = "low pres.: fp4 with rounding 0", argv = "e2m1 0 0xf", ref = "-0x1.8p+2 0xF") + floating(name = "low pres.: fp4 with rounding 1", argv = "e2m1 0 0xf", ref = "-0x1.8p+2 0xF") + floating(name = "low pres.: fp4 with rounding 2", argv = "e2m1 0 0xf", ref = "-0x1.8p+2 0xF") + floating(name = "low pres.: fp4 with rounding 3", argv = "e2m1 0 0xf", ref = "-0x1.8p+2 0xF") + + return tester + +instance = __FixedFloating() diff --git a/testsuites/suite.py b/testsuites/suite.py index e2c359e..e738a51 100644 --- a/testsuites/suite.py +++ b/testsuites/suite.py @@ -6,6 +6,7 @@ import enum import signal from typing import List, Optional, Tuple, Union, Callable, TypeVar, Any, Dict, Set, Iterable +from decimal import Decimal from abc import abstractmethod, ABC T = TypeVar('T') @@ -398,31 +399,33 @@ class Result: def __get_total_by_category(self, category: str) -> int: total = 0 - for test, verdict in zip(self.__tests, self.__verdicts): + for test, _ in zip(self.__tests, self.__verdicts): if category in test.categories(): total += 1 return total - def __get_result_by_category(self, category: str) -> float: + def __get_result_by_category(self, category: str) -> Decimal: total = self.__get_total_by_category(category) passed = self.__get_passed_by_category(category) - return passed / total + if total == 0: + return Decimal(0.0) + return Decimal(passed) / Decimal(total) - def __calculate_total(self, coefficients: Dict[str, float]) -> float: - total = 0.0 + def __calculate_total(self, coefficients: Dict[str, float]) -> Decimal: + total = Decimal(0.0) for category, coefficient in coefficients.items(): result = self.__get_result_by_category(category) - total += result * coefficient + total += result * Decimal(coefficient) return total - def __get_results_by_categories(self, categories: Iterable[str]) -> Dict[str, float]: - results: Dict[str, float] = {} + def __get_results_by_categories(self, categories: Iterable[str]) -> Dict[str, str]: + results: Dict[str, str] = {} for category in categories: - results[category] = self.__get_result_by_category(category) + results[category] = str(self.__get_result_by_category(category)) return results @@ -464,7 +467,7 @@ class Result: j: Dict[str, Any] = {} - j["result"] = self.__calculate_total(coefficients) + j["result"] = str(self.__calculate_total(coefficients)) j["categories"] = self.__get_results_by_categories(categories) j["tests"] = self.__get_results()