blob: 2305900d5a1435673e19711dad3a8bb1f3a480f2 [file] [log] [blame]
#
# Copyright (c) 2023 Project CHIP Authors
#
# Licensed under the Apache License, Version 2.0 (the 'License');
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an 'AS IS' BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import copy
import time
from dataclasses import dataclass, field
from .hooks import TestParserHooks
from .parser import TestParser, TestParserConfig
@dataclass
class TestParserBuilderOptions:
"""
TestParserBuilderOptions allows configuring the behavior of a
TestParserBuilder instance.
stop_on_error: If set to False the parser will continue parsing
the next test instead of aborting if an error is
encountered while parsing a particular test file.
"""
stop_on_error: bool = True
@dataclass
class TestParserBuilderConfig:
"""
TestParserBuilderConfig defines a set of common properties that will be used
by a TestParserBuilder instance for parsing the given list of tests.
tests: A list of YAML tests to be parsed.
parser_config: A common configuration for the tests to be parsed.
options: A common set of options for the tests to be parsed.
hooks: A configurable set of hooks to be called at various steps during
parsing. It may may allow the callers to gain insights about the
current parsing state.
"""
tests: list[str] = field(default_factory=list)
parser_config: TestParserConfig = field(default_factory=TestParserConfig)
hooks: TestParserHooks = TestParserHooks()
options: TestParserBuilderOptions = field(
default_factory=TestParserBuilderOptions)
class TestParserBuilder:
"""
TestParserBuilder is an iterator over a set of tests using a common configuration.
"""
def __init__(self, config: TestParserBuilderConfig = TestParserBuilderConfig()):
self.__tests = copy.copy(config.tests)
self.__config = config
self.__duration = 0
self.done = False
def __iter__(self):
self.__config.hooks.start(len(self.__tests))
return self
def __next__(self):
if len(self.__tests):
return self.__get_test_parser(self.__tests.pop(0))
if not self.done:
self.__config.hooks.stop(round(self.__duration))
self.done = True
raise StopIteration
def __get_test_parser(self, test_file: str) -> TestParser:
start = time.time()
parser = None
exception = None
try:
self.__config.hooks.test_start(test_file)
parser = TestParser(test_file, self.__config.parser_config)
except Exception as e:
exception = e
duration = round((time.time() - start) * 1000, 0)
self.__duration += duration
if exception:
self.__config.hooks.test_failure(exception, duration)
if self.__config.options.stop_on_error:
raise StopIteration
return None
self.__config.hooks.test_success(duration)
return parser