1import os 2import json 3import pathlib 4import subprocess 5import tempfile 6import unittest.mock 7 8from oeqa.selftest.case import OESelftestTestCase 9from oeqa.core.decorator import OETestTag 10 11runfvp = pathlib.Path(__file__).parents[5] / "scripts" / "runfvp" 12testdir = pathlib.Path(__file__).parent / "tests" 13 14@OETestTag("meta-arm") 15class RunFVPTests(OESelftestTestCase): 16 def setUpLocal(self): 17 self.assertTrue(runfvp.exists()) 18 19 def run_fvp(self, *args, env=None, should_succeed=True): 20 """ 21 Call runfvp passing any arguments. If check is True verify return stdout 22 on exit code 0 or fail the test, otherwise return the CompletedProcess 23 instance. 24 """ 25 cli = [runfvp,] + list(args) 26 print(f"Calling {cli}") 27 # Set cwd to testdir so that any mock FVPs are found 28 ret = subprocess.run(cli, cwd=testdir, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) 29 if should_succeed: 30 self.assertEqual(ret.returncode, 0, f"runfvp exit {ret.returncode}, output: {ret.stdout}") 31 return ret.stdout 32 else: 33 self.assertNotEqual(ret.returncode, 0, f"runfvp exit {ret.returncode}, output: {ret.stdout}") 34 return ret.stdout 35 36 def test_help(self): 37 output = self.run_fvp("--help") 38 self.assertIn("Run images in a FVP", output) 39 40 def test_bad_options(self): 41 self.run_fvp("--this-is-an-invalid-option", should_succeed=False) 42 43 def test_run_auto_tests(self): 44 cases = list(testdir.glob("auto-*.json")) 45 if not cases: 46 self.fail("No tests found") 47 for case in cases: 48 with self.subTest(case=case.stem): 49 self.run_fvp(case) 50 51 def test_fvp_options(self): 52 # test-parameter sets one argument, add another manually 53 self.run_fvp(testdir / "test-parameter.json", "--", "--parameter", "board.dog=woof") 54 55 def test_fvp_environment(self): 56 output = self.run_fvp(testdir / "test-environment.json", env={"DISPLAY": "test_fvp_environment:42"}) 57 self.assertEqual(output.strip(), "Found expected DISPLAY") 58 59@OETestTag("meta-arm") 60class ConfFileTests(OESelftestTestCase): 61 def test_no_exe(self): 62 from fvp import conffile 63 with tempfile.NamedTemporaryFile('w') as tf: 64 tf.write('{}') 65 tf.flush() 66 67 with self.assertRaises(ValueError): 68 conffile.load(tf.name) 69 70 def test_minimal(self): 71 from fvp import conffile 72 with tempfile.NamedTemporaryFile('w') as tf: 73 tf.write('{"exe": "FVP_Binary"}') 74 tf.flush() 75 76 conf = conffile.load(tf.name) 77 self.assertTrue('fvp-bindir' in conf) 78 self.assertTrue('fvp-bindir' in conf) 79 self.assertTrue("exe" in conf) 80 self.assertTrue("parameters" in conf) 81 self.assertTrue("data" in conf) 82 self.assertTrue("applications" in conf) 83 self.assertTrue("terminals" in conf) 84 self.assertTrue("args" in conf) 85 self.assertTrue("consoles" in conf) 86 self.assertTrue("env" in conf) 87 88 89@OETestTag("meta-arm") 90class RunnerTests(OESelftestTestCase): 91 def create_mock(self): 92 return unittest.mock.patch("subprocess.Popen") 93 94 @unittest.mock.patch.dict(os.environ, {"PATH": "/path-42:/usr/sbin:/usr/bin:/sbin:/bin"}) 95 def test_start(self): 96 from fvp import runner 97 with self.create_mock() as m: 98 fvp = runner.FVPRunner(self.logger) 99 config = {"fvp-bindir": "/usr/bin", 100 "exe": "FVP_Binary", 101 "parameters": {'foo': 'bar'}, 102 "data": ['data1'], 103 "applications": {'a1': 'file'}, 104 "terminals": {}, 105 "args": ['--extra-arg'], 106 "env": {"FOO": "BAR"} 107 } 108 109 with tempfile.NamedTemporaryFile('w') as fvpconf: 110 json.dump(config, fvpconf) 111 fvpconf.flush() 112 cwd_mock = os.path.dirname(fvpconf.name) 113 fvp.start(fvpconf.name) 114 115 m.assert_called_once_with(['/usr/bin/FVP_Binary', 116 '--parameter', 'foo=bar', 117 '--data', 'data1', 118 '--application', 'a1=file', 119 '--extra-arg'], 120 stdin=unittest.mock.ANY, 121 stdout=unittest.mock.ANY, 122 stderr=unittest.mock.ANY, 123 env={"FOO":"BAR", "PATH": "/path-42:/usr/sbin:/usr/bin:/sbin:/bin"}, 124 cwd=cwd_mock) 125 126 @unittest.mock.patch.dict(os.environ, {"DISPLAY": ":42", "WAYLAND_DISPLAY": "wayland-42", "PATH": "/path-42:/usr/sbin:/usr/bin:/sbin:/bin"}) 127 def test_env_passthrough(self): 128 from fvp import runner 129 with self.create_mock() as m: 130 fvp = runner.FVPRunner(self.logger) 131 config = {"fvp-bindir": "/usr/bin", 132 "exe": "FVP_Binary", 133 "parameters": {}, 134 "data": [], 135 "applications": {}, 136 "terminals": {}, 137 "args": [], 138 "env": {"FOO": "BAR"} 139 } 140 141 with tempfile.NamedTemporaryFile('w') as fvpconf: 142 json.dump(config, fvpconf) 143 fvpconf.flush() 144 cwd_mock = os.path.dirname(fvpconf.name) 145 fvp.start(fvpconf.name) 146 147 m.assert_called_once_with(['/usr/bin/FVP_Binary'], 148 stdin=unittest.mock.ANY, 149 stdout=unittest.mock.ANY, 150 stderr=unittest.mock.ANY, 151 env={"DISPLAY":":42", "FOO": "BAR", "WAYLAND_DISPLAY": "wayland-42", "PATH": "/path-42:/usr/sbin:/usr/bin:/sbin:/bin"}, 152 cwd=cwd_mock) 153