Source code for spinnaker_testbase.root_test_case
# Copyright (c) 2017 The University of Manchester
#
# 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
#
# https://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 os
import sys
import time
from typing import Callable, List, Optional
import unittest
from spinnman.exceptions import SpinnmanException
from pacman.exceptions import PacmanPartitionException, PacmanValueError
from spalloc_client.job import JobDestroyedError
from spinn_front_end_common.data import FecDataView
if os.environ.get('CONTINUOUS_INTEGRATION', 'false').lower() == 'true':
MAX_TRIES = 3
else:
MAX_TRIES = 1
[docs]
class RootTestCase(unittest.TestCase):
"""
This holds the code shared by the all test and script checkers
"""
def _setup(self, script: str) -> None:
# Remove random effect for testing
# Set test_seed to None to allow random
# pylint: disable=attribute-defined-outside-init
self._test_seed = 1
path = os.path.dirname(script)
os.chdir(path)
[docs]
@staticmethod
def assert_not_spin_three() -> None:
"""
Will raise a SkipTest if run on a none virtual 4 chip board
:raises SkipTest: If we're on the wrong sort of board
"""
version = FecDataView.get_machine_version().number
if version != 5:
raise unittest.SkipTest(
f"This test will not run on a spinn-{version} board")
[docs]
def report(self, message: str, file_name: str) -> None:
"""
Writes some text to the specified file
The file will be written in the env GLOBAL_REPORTS directory.
If no GLOBAL_REPORTS is defined the timestamp directory
holding the run data is used.
:param message:
:param file_name: local file name.
"""
if not message.endswith("\n"):
message += "\n"
report_path = os.path.join(
FecDataView.get_global_reports_dir(), file_name)
with open(report_path, "a", encoding="utf-8") as report_file:
report_file.write(message)
[docs]
def runsafe(self, method: Callable, retry_delay: float = 3.0,
skip_exceptions: Optional[List[type]] = None) -> None:
"""
Will run the method possibly a few times
:param method:
:param retry_delay:
:param skip_exceptions:
list of exception classes to convert in SkipTest
"""
if skip_exceptions is None:
skip_exceptions = []
retries = 0
while True:
try:
method()
break
except (JobDestroyedError, SpinnmanException) as ex:
for skip_exception in skip_exceptions:
if isinstance(ex, skip_exception):
FecDataView.raise_skiptest(
f"{ex} Still not fixed!", ex)
class_file = sys.modules[self.__module__].__file__
assert class_file is not None
with open(FecDataView.get_error_file(), "a",
encoding="utf-8") as error_file:
error_file.write(class_file)
error_file.write("\n")
error_file.write(str(ex))
error_file.write("\n")
transceiver = FecDataView.get_transceiver()
error_file.write(f"{transceiver=}\n")
retries += 1
if retries >= MAX_TRIES:
raise ex
except (PacmanValueError, PacmanPartitionException) as ex:
# skip out if on a spin three
self.assert_not_spin_three()
for skip_exception in skip_exceptions:
if isinstance(ex, skip_exception):
FecDataView.raise_skiptest(
f"{ex} Still not fixed!", ex)
raise ex
print("")
print("==========================================================")
print(f" Will run {method} again in {retry_delay} seconds")
print(f" retry: {retries}")
print("==========================================================")
print("")
time.sleep(retry_delay)
[docs]
def check_binary_used(self, binary: str) -> None:
"""
Checks if the binary is used since the last call to start
:param binary: Name of the file (no path) to check
:raises AssertionError: If the binary is not used
"""
self.check_binaries_used([binary])
[docs]
def check_binaries_used(self, binaries: List[str]) -> None:
"""
Checks if the binaries are used since the last call to start
:param binaries: List of names of the file (no path) to check
:raises AssertionError: If any binary is not used
"""
targets = FecDataView.get_executable_targets()
files = set()
for target in targets.binaries:
_, file = os.path.split(target)
files.add(file)
for binary in binaries:
if not binary.endswith(".aplx"):
binary = binary + ".aplx"
self.assertIn(binary, files)
print(files)