From 1acaa8b8f6acc1f3a3736f4a8a2506b1377a6bdf Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 10 Apr 2018 21:19:53 +0800 Subject: [PATCH] allow reading test environment from python mocks This allows requesting environment variable values set in the C++ test code, from python mock code. Use case is cross-checking test results against values expected by the host side part of the test. --- tests/device/libraries/BSTest/Makefile | 2 +- .../libraries/BSTest/mock_decorators.py | 16 ++++++++++ tests/device/libraries/BSTest/runner.py | 32 ++++++++++++++++--- .../device/libraries/BSTest/src/BSProtocol.h | 18 ++++++++++- tests/device/libraries/BSTest/test/test.cpp | 9 ++++++ tests/device/libraries/BSTest/test/test.py | 11 +++++++ 6 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 tests/device/libraries/BSTest/test/test.py diff --git a/tests/device/libraries/BSTest/Makefile b/tests/device/libraries/BSTest/Makefile index c4216d9eb..2df59d115 100644 --- a/tests/device/libraries/BSTest/Makefile +++ b/tests/device/libraries/BSTest/Makefile @@ -14,7 +14,7 @@ $(PYTHON_ENV_DIR): . $(PYTHON_ENV_DIR)/bin/activate && pip install -r requirements.txt test: $(TEST_EXECUTABLE) $(PYTHON_ENV_DIR) - . $(PYTHON_ENV_DIR)/bin/activate && python runner.py -e $(TEST_EXECUTABLE) + . $(PYTHON_ENV_DIR)/bin/activate && python runner.py -e $(TEST_EXECUTABLE) -m test/test.py $(TEST_EXECUTABLE): test/test.cpp g++ -std=c++11 -Isrc -o $@ test/test.cpp diff --git a/tests/device/libraries/BSTest/mock_decorators.py b/tests/device/libraries/BSTest/mock_decorators.py index 5dc3f0347..068448eda 100644 --- a/tests/device/libraries/BSTest/mock_decorators.py +++ b/tests/device/libraries/BSTest/mock_decorators.py @@ -26,3 +26,19 @@ def teardown(test_name): func_env['teardown'] = func_wrapper return func_wrapper return decorator + +def setenv(test_env, key, value): + if 'env' not in test_env: + test_env['env'] = [] + test_env['env'] += [(key, value)] + +def request_env(test_env, key): + return test_env['request_env'](key) + +def get_all_envs(test_name): + global env + if test_name not in env: + return None + if 'env' not in env[test_name]: + return None + return env[test_name]['env'] diff --git a/tests/device/libraries/BSTest/runner.py b/tests/device/libraries/BSTest/runner.py index 4f964f55b..bcdc099af 100644 --- a/tests/device/libraries/BSTest/runner.py +++ b/tests/device/libraries/BSTest/runner.py @@ -93,19 +93,27 @@ class BSTestRunner(object): self.sp.logfile = test_output print('running test "{}"'.format(name)) if should_update_env: - res = self.update_env() + res = self.update_env(self.env_vars) if res != BSTestRunner.SUCCESS: print('failed to set environment variables') break; should_update_env = False if name in self.mocks: debug_print('setting up mocks') + self.mocks[name]['request_env'] = self.request_env self.mocks[name]['setup']() + extra_env = mock_decorators.get_all_envs(name) + if extra_env is not None: + self.update_env(extra_env) t_start = time.time() result = self.run_test(index) if name in self.mocks: debug_print('tearing down mocks') - self.mocks[name]['teardown']() + try: + self.mocks[name]['teardown']() + except AssertionError: + debug_print('teardown assert failure') + result = BSTestRunner.FAIL t_stop = time.time() self.sp.logfile = None test_case.elapsed_sec = t_stop - t_start @@ -167,12 +175,12 @@ class BSTestRunner(object): if timeout <= 0: return BSTestRunner.TIMEOUT - def update_env(self): - for env_kv in self.env_vars: + def update_env(self, env_to_set): + for env_kv in env_to_set: self.sp.sendline('setenv "{}" "{}"'.format(env_kv[0], env_kv[1])) timeout = 10 while timeout > 0: - res = self.sp.expect(['>>>>>bs_test_setenv ok', EOF, TIMEOUT]) + res = self.sp.expect(['>>>>>bs_test_setenv', EOF, TIMEOUT]) if res == 0: break time.sleep(0.1) @@ -183,6 +191,20 @@ class BSTestRunner(object): return BSTestRunner.TIMEOUT return BSTestRunner.SUCCESS + def request_env(self, key): + self.sp.sendline('getenv "{}"'.format(key)) + timeout = 10 + while timeout > 0: + res = self.sp.expect([r'>>>>>bs_test_getenv value=\"(.+)\"', EOF, TIMEOUT]) + if res == 0: + break + time.sleep(0.1) + timeout -= 0.1 + if res != 0: + return None + return self.sp.match.group(1) + + ser = None def spawn_port(port_name, baudrate=115200): diff --git a/tests/device/libraries/BSTest/src/BSProtocol.h b/tests/device/libraries/BSTest/src/BSProtocol.h index 0c72dd60b..f4ed73bd7 100644 --- a/tests/device/libraries/BSTest/src/BSProtocol.h +++ b/tests/device/libraries/BSTest/src/BSProtocol.h @@ -48,7 +48,14 @@ void output_menu_end(IO& io) template void output_setenv_result(IO& io, const char* key, const char* value) { - io.printf(BS_LINE_PREFIX "setenv ok key='%s' value='%s'\n", key, value); + io.printf(BS_LINE_PREFIX "setenv key=\"%s\" value=\"%s\"\n", key, value); +} + +template +void output_getenv_result(IO& io, const char* key, const char* value) +{ + (void) key; + io.printf(BS_LINE_PREFIX "getenv value=\"%s\"\n", value); } template @@ -72,6 +79,15 @@ bool input_handle(IO& io, char* line_buf, size_t line_buf_size, int& test_num) test_num = -1; return false; /* we didn't get the test number yet, so return false */ } + if (strcmp(argv[0], "getenv") == 0) { + if (argc != 2) { + return false; + } + const char* value = getenv(argv[1]); + output_getenv_result(io, argv[1], (value != NULL) ? value : ""); + return false; + } + /* not one of the commands, try to parse as test number */ char* endptr; test_num = (int) strtol(argv[0], &endptr, 10); if (endptr != argv[0] + strlen(argv[0])) { diff --git a/tests/device/libraries/BSTest/test/test.cpp b/tests/device/libraries/BSTest/test/test.cpp index c6117c8b4..863373e0d 100644 --- a/tests/device/libraries/BSTest/test/test.cpp +++ b/tests/device/libraries/BSTest/test/test.cpp @@ -49,3 +49,12 @@ TEST_CASE("this test also runs successfully", "[bluesmoke]") { } + +TEST_CASE("environment variables can be set and read from python", "[bluesmoke]") +{ + const char* res = getenv("VAR_FROM_PYTHON"); + REQUIRE(res != NULL); + CHECK(strcmp(res, "42") == 0); + setenv("VAR_FROM_TEST", "24", 1); +} + diff --git a/tests/device/libraries/BSTest/test/test.py b/tests/device/libraries/BSTest/test/test.py new file mode 100644 index 000000000..c367c96a3 --- /dev/null +++ b/tests/device/libraries/BSTest/test/test.py @@ -0,0 +1,11 @@ +from mock_decorators import setup, teardown, setenv, request_env + +@setup('environment variables can be set and read from python') +def setup_envtest(e): + setenv(e, 'VAR_FROM_PYTHON', '42') + + +@teardown('environment variables can be set and read from python') +def teardown_envtest(e): + env_value = request_env(e, 'VAR_FROM_TEST') + assert(env_value == '24')