Skip to content

Commit 1acaa8b

Browse files
committed
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.
1 parent 8bd26f2 commit 1acaa8b

File tree

6 files changed

+81
-7
lines changed

6 files changed

+81
-7
lines changed

tests/device/libraries/BSTest/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ $(PYTHON_ENV_DIR):
1414
. $(PYTHON_ENV_DIR)/bin/activate && pip install -r requirements.txt
1515

1616
test: $(TEST_EXECUTABLE) $(PYTHON_ENV_DIR)
17-
. $(PYTHON_ENV_DIR)/bin/activate && python runner.py -e $(TEST_EXECUTABLE)
17+
. $(PYTHON_ENV_DIR)/bin/activate && python runner.py -e $(TEST_EXECUTABLE) -m test/test.py
1818

1919
$(TEST_EXECUTABLE): test/test.cpp
2020
g++ -std=c++11 -Isrc -o $@ test/test.cpp

tests/device/libraries/BSTest/mock_decorators.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,19 @@ def func_wrapper():
2626
func_env['teardown'] = func_wrapper
2727
return func_wrapper
2828
return decorator
29+
30+
def setenv(test_env, key, value):
31+
if 'env' not in test_env:
32+
test_env['env'] = []
33+
test_env['env'] += [(key, value)]
34+
35+
def request_env(test_env, key):
36+
return test_env['request_env'](key)
37+
38+
def get_all_envs(test_name):
39+
global env
40+
if test_name not in env:
41+
return None
42+
if 'env' not in env[test_name]:
43+
return None
44+
return env[test_name]['env']

tests/device/libraries/BSTest/runner.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,19 +93,27 @@ def run_tests(self):
9393
self.sp.logfile = test_output
9494
print('running test "{}"'.format(name))
9595
if should_update_env:
96-
res = self.update_env()
96+
res = self.update_env(self.env_vars)
9797
if res != BSTestRunner.SUCCESS:
9898
print('failed to set environment variables')
9999
break;
100100
should_update_env = False
101101
if name in self.mocks:
102102
debug_print('setting up mocks')
103+
self.mocks[name]['request_env'] = self.request_env
103104
self.mocks[name]['setup']()
105+
extra_env = mock_decorators.get_all_envs(name)
106+
if extra_env is not None:
107+
self.update_env(extra_env)
104108
t_start = time.time()
105109
result = self.run_test(index)
106110
if name in self.mocks:
107111
debug_print('tearing down mocks')
108-
self.mocks[name]['teardown']()
112+
try:
113+
self.mocks[name]['teardown']()
114+
except AssertionError:
115+
debug_print('teardown assert failure')
116+
result = BSTestRunner.FAIL
109117
t_stop = time.time()
110118
self.sp.logfile = None
111119
test_case.elapsed_sec = t_stop - t_start
@@ -167,12 +175,12 @@ def run_test(self, index):
167175
if timeout <= 0:
168176
return BSTestRunner.TIMEOUT
169177

170-
def update_env(self):
171-
for env_kv in self.env_vars:
178+
def update_env(self, env_to_set):
179+
for env_kv in env_to_set:
172180
self.sp.sendline('setenv "{}" "{}"'.format(env_kv[0], env_kv[1]))
173181
timeout = 10
174182
while timeout > 0:
175-
res = self.sp.expect(['>>>>>bs_test_setenv ok', EOF, TIMEOUT])
183+
res = self.sp.expect(['>>>>>bs_test_setenv', EOF, TIMEOUT])
176184
if res == 0:
177185
break
178186
time.sleep(0.1)
@@ -183,6 +191,20 @@ def update_env(self):
183191
return BSTestRunner.TIMEOUT
184192
return BSTestRunner.SUCCESS
185193

194+
def request_env(self, key):
195+
self.sp.sendline('getenv "{}"'.format(key))
196+
timeout = 10
197+
while timeout > 0:
198+
res = self.sp.expect([r'>>>>>bs_test_getenv value=\"(.+)\"', EOF, TIMEOUT])
199+
if res == 0:
200+
break
201+
time.sleep(0.1)
202+
timeout -= 0.1
203+
if res != 0:
204+
return None
205+
return self.sp.match.group(1)
206+
207+
186208
ser = None
187209

188210
def spawn_port(port_name, baudrate=115200):

tests/device/libraries/BSTest/src/BSProtocol.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,14 @@ void output_menu_end(IO& io)
4848
template<typename IO>
4949
void output_setenv_result(IO& io, const char* key, const char* value)
5050
{
51-
io.printf(BS_LINE_PREFIX "setenv ok key='%s' value='%s'\n", key, value);
51+
io.printf(BS_LINE_PREFIX "setenv key=\"%s\" value=\"%s\"\n", key, value);
52+
}
53+
54+
template<typename IO>
55+
void output_getenv_result(IO& io, const char* key, const char* value)
56+
{
57+
(void) key;
58+
io.printf(BS_LINE_PREFIX "getenv value=\"%s\"\n", value);
5259
}
5360

5461
template<typename IO>
@@ -72,6 +79,15 @@ bool input_handle(IO& io, char* line_buf, size_t line_buf_size, int& test_num)
7279
test_num = -1;
7380
return false; /* we didn't get the test number yet, so return false */
7481
}
82+
if (strcmp(argv[0], "getenv") == 0) {
83+
if (argc != 2) {
84+
return false;
85+
}
86+
const char* value = getenv(argv[1]);
87+
output_getenv_result(io, argv[1], (value != NULL) ? value : "");
88+
return false;
89+
}
90+
/* not one of the commands, try to parse as test number */
7591
char* endptr;
7692
test_num = (int) strtol(argv[0], &endptr, 10);
7793
if (endptr != argv[0] + strlen(argv[0])) {

tests/device/libraries/BSTest/test/test.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,12 @@ TEST_CASE("this test also runs successfully", "[bluesmoke]")
4949
{
5050

5151
}
52+
53+
TEST_CASE("environment variables can be set and read from python", "[bluesmoke]")
54+
{
55+
const char* res = getenv("VAR_FROM_PYTHON");
56+
REQUIRE(res != NULL);
57+
CHECK(strcmp(res, "42") == 0);
58+
setenv("VAR_FROM_TEST", "24", 1);
59+
}
60+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from mock_decorators import setup, teardown, setenv, request_env
2+
3+
@setup('environment variables can be set and read from python')
4+
def setup_envtest(e):
5+
setenv(e, 'VAR_FROM_PYTHON', '42')
6+
7+
8+
@teardown('environment variables can be set and read from python')
9+
def teardown_envtest(e):
10+
env_value = request_env(e, 'VAR_FROM_TEST')
11+
assert(env_value == '24')

0 commit comments

Comments
 (0)