|
| 1 | +import unittest |
| 2 | +import subprocess |
| 3 | +import os |
| 4 | +import json |
| 5 | +from parameterized import parameterized |
| 6 | +import time |
| 7 | +import signal |
| 8 | +from abc import ABC, abstractmethod |
| 9 | +# Configuration of each test case. |
| 10 | +TEST_CONFIGS = [ |
| 11 | + ("test1", "integration_tests/launch/test1.yaml", 10), |
| 12 | + ("test2", "integration_tests/launch/test2.yaml", 10), |
| 13 | +] |
| 14 | + |
| 15 | +import os |
| 16 | + |
| 17 | +def get_last_modified_folder(parent_path): |
| 18 | + subdirs = [entry.path for entry in os.scandir(parent_path) if entry.is_dir()] |
| 19 | + if not subdirs: |
| 20 | + return None |
| 21 | + last_modified_folder = max(subdirs, key=os.path.getmtime) |
| 22 | + return last_modified_folder |
| 23 | + |
| 24 | + |
| 25 | +class BaseLogValidator(ABC): |
| 26 | + |
| 27 | + @abstractmethod |
| 28 | + def validate(self, log_dir): |
| 29 | + """Each test case must implement this method""" |
| 30 | + pass |
| 31 | + |
| 32 | +class ValidateTestCase1(BaseLogValidator): |
| 33 | + def validate(self, log_dir): |
| 34 | + log_file = os.path.join(log_dir, "behavior.json") |
| 35 | + with open(log_file, "r") as file: |
| 36 | + for index, line in enumerate(file): |
| 37 | + try: |
| 38 | + record = json.loads(line) |
| 39 | + acceleration = record.get("vehicle", {}).get("data", {}).get("acceleration", 0) |
| 40 | + assert abs(acceleration) <= .11, f"Record {index} has acceleration {acceleration} > 1" |
| 41 | + except json.JSONDecodeError: |
| 42 | + raise AssertionError(f"Malformed JSON in log file at line {index}") |
| 43 | + |
| 44 | +class ValidateTestCase2(BaseLogValidator): |
| 45 | + def validate(self, log_dir): |
| 46 | + log_file = os.path.join(log_dir, "behavior.json") |
| 47 | + |
| 48 | + |
| 49 | +class IntegrationTestSuite(unittest.TestCase): |
| 50 | + VALIDATORS = { |
| 51 | + "test1": ValidateTestCase1(), |
| 52 | + "test2": ValidateTestCase2(), |
| 53 | + } |
| 54 | + def setUp(self): |
| 55 | + pass |
| 56 | + def tearDown(self): |
| 57 | + """Clean up after each test if necessary.""" |
| 58 | + pass |
| 59 | + |
| 60 | + @parameterized.expand(TEST_CONFIGS) |
| 61 | + def test_command_execution(self, name, config_path, runtime): |
| 62 | + process = subprocess.Popen(["python3", "main.py", "--variant=sim", config_path], text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| 63 | + # for line in iter(process.stdout.readline, ''): |
| 64 | + # print(line, end='') |
| 65 | + time.sleep(runtime) |
| 66 | + print("Stopping GEMStack...") |
| 67 | + os.kill(process.pid, signal.SIGINT) |
| 68 | + process.wait() |
| 69 | + |
| 70 | + # Validate logs |
| 71 | + validator = self.VALIDATORS.get(name) |
| 72 | + if validator is None: |
| 73 | + self.fail(f"no validator found for {name}") |
| 74 | + validator.validate(get_last_modified_folder('logs')) |
| 75 | + |
| 76 | + |
| 77 | + |
| 78 | +if __name__ == "__main__": |
| 79 | + unittest.main() |
0 commit comments