From 28e3ce67ae49494d57372f27b6f91580656f77a7 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 30 Apr 2020 13:54:46 -0700 Subject: [PATCH] Convert test protocol into an enum This gives us better type safety, and will be important as we add more test methods --- mesonbuild/backend/backends.py | 30 ++++++++++++++++++++++++++---- mesonbuild/interpreter.py | 3 ++- mesonbuild/mintro.py | 2 +- mesonbuild/mtest.py | 5 +++-- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 774764d62..ecdf330b6 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -14,6 +14,7 @@ from collections import OrderedDict from functools import lru_cache +import enum import json import os import pickle @@ -28,12 +29,33 @@ from .. import dependencies from .. import mesonlib from .. import mlog from ..compilers import CompilerArgs, VisualStudioLikeCompiler -from ..interpreter import Interpreter from ..mesonlib import ( File, MachineChoice, MesonException, OrderedSet, OptionOverrideProxy, classify_unity_sources, unholder ) +if T.TYPE_CHECKING: + from ..interpreter import Interpreter + + +class TestProtocol(enum.Enum): + + EXITCODE = 0 + TAP = 1 + + @classmethod + def from_str(cls, string: str) -> 'TestProtocol': + if string == 'exitcode': + return cls.EXITCODE + elif string == 'tap': + return cls.TAP + raise MesonException('unknown test format {}'.format(string)) + + def __str__(self) -> str: + if self is self.EXITCODE: + return 'exitcode' + return 'tap' + class CleanTrees: ''' @@ -91,7 +113,7 @@ class TestSerialisation: needs_exe_wrapper: bool, is_parallel: bool, cmd_args: T.List[str], env: build.EnvironmentVariables, should_fail: bool, timeout: T.Optional[int], workdir: T.Optional[str], - extra_paths: T.List[str], protocol: str, priority: int): + extra_paths: T.List[str], protocol: TestProtocol, priority: int): self.name = name self.project_name = project self.suite = suite @@ -111,7 +133,7 @@ class TestSerialisation: self.priority = priority self.needs_exe_wrapper = needs_exe_wrapper -def get_backend_from_name(backend: str, build: T.Optional[build.Build] = None, interpreter: T.Optional[Interpreter] = None) -> T.Optional['Backend']: +def get_backend_from_name(backend: str, build: T.Optional[build.Build] = None, interpreter: T.Optional['Interpreter'] = None) -> T.Optional['Backend']: if backend == 'ninja': from . import ninjabackend return ninjabackend.NinjaBackend(build, interpreter) @@ -138,7 +160,7 @@ def get_backend_from_name(backend: str, build: T.Optional[build.Build] = None, i # This class contains the basic functionality that is needed by all backends. # Feel free to move stuff in and out of it as you see fit. class Backend: - def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Interpreter]): + def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional['Interpreter']): # Make it possible to construct a dummy backend # This is used for introspection without a build directory if build is None: diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index dd1e57bad..7b8ca63c2 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -33,6 +33,7 @@ from .interpreterbase import FeatureNew, FeatureDeprecated, FeatureNewKwargs from .interpreterbase import ObjectHolder from .modules import ModuleReturnValue from .cmake import CMakeInterpreter +from .backend.backends import TestProtocol from pathlib import Path, PurePath import os @@ -979,7 +980,7 @@ class Test(InterpreterObject): self.should_fail = should_fail self.timeout = timeout self.workdir = workdir - self.protocol = protocol + self.protocol = TestProtocol.from_str(protocol) self.priority = priority def get_exe(self): diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index d5516d454..54e302bc7 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -328,7 +328,7 @@ def get_test_list(testdata) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], to['suite'] = t.suite to['is_parallel'] = t.is_parallel to['priority'] = t.priority - to['protocol'] = t.protocol + to['protocol'] = str(t.protocol) result.append(to) return result diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index 846b474df..69da40063 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -43,6 +43,7 @@ from . import environment from . import mlog from .dependencies import ExternalProgram from .mesonlib import MesonException, get_wine_shortpath, split_args +from .backend.backends import TestProtocol if T.TYPE_CHECKING: from .backend.backends import TestSerialisation @@ -631,7 +632,7 @@ class SingleTestRunner: if not self.options.verbose: stdout = tempfile.TemporaryFile("wb+") stderr = tempfile.TemporaryFile("wb+") if self.options.split else stdout - if self.test.protocol == 'tap' and stderr is stdout: + if self.test.protocol is TestProtocol.TAP and stderr is stdout: stdout = tempfile.TemporaryFile("wb+") # Let gdb handle ^C instead of us @@ -741,7 +742,7 @@ class SingleTestRunner: if timed_out: return TestRun(self.test, self.test_env, TestResult.TIMEOUT, [], p.returncode, starttime, duration, stdo, stde, cmd) else: - if self.test.protocol == 'exitcode': + if self.test.protocol is TestProtocol.EXITCODE: return TestRun.make_exitcode(self.test, self.test_env, p.returncode, starttime, duration, stdo, stde, cmd) else: if self.options.verbose: