Skip to content
This repository was archived by the owner on Jan 15, 2021. It is now read-only.

Commit a754daf

Browse files
committed
Merge pull request #291 from autopulated/fix-286
fail gracefully (and with non-zero exit status) if the test output filter command is not found
2 parents 0069bb8 + 6435409 commit a754daf

File tree

3 files changed

+185
-4
lines changed

3 files changed

+185
-4
lines changed

yotta/lib/target.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -550,12 +550,18 @@ def test(self, builddir, program, filter_command, forward_args):
550550
] + forward_args
551551
logger.debug('running test: %s', cmd)
552552
if filter_command:
553+
logger.debug('using output filter command: %s', filter_command)
553554
test_child = subprocess.Popen(
554555
cmd, cwd = builddir, stdout = subprocess.PIPE
555556
)
556-
test_filter = subprocess.Popen(
557-
filter_command, cwd = builddir, stdin = test_child.stdout
558-
)
557+
try:
558+
test_filter = subprocess.Popen(
559+
filter_command, cwd = builddir, stdin = test_child.stdout
560+
)
561+
except OSError as e:
562+
logger.error('error starting test output filter "%s": %s', filter_command, e)
563+
test_child.terminate()
564+
return 1
559565
test_filter.communicate()
560566
test_child.terminate()
561567
test_child.stdout.close()

yotta/test/cli/test.py

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
#!/usr/bin/env python
2+
# Copyright 2015 ARM Limited
3+
#
4+
# Licensed under the Apache License, Version 2.0
5+
# See LICENSE file for details.
6+
7+
# standard library modules, , ,
8+
import unittest
9+
import os
10+
import tempfile
11+
import copy
12+
13+
# internal modules:
14+
from yotta.lib.fsutils import mkDirP, rmRf
15+
from yotta.lib.detect import systemDefaultTarget
16+
from . import cli
17+
18+
19+
Test_Tests = {
20+
'module.json':'''{
21+
"name": "test-tests",
22+
"version": "0.0.0",
23+
"description": "Test yotta's compilation of tests.",
24+
"author": "James Crosby <[email protected]>",
25+
"licenses": [
26+
{
27+
"url": "https://spdx.org/licenses/Apache-2.0",
28+
"type": "Apache-2.0"
29+
}
30+
]
31+
}''',
32+
'source/foo.c':'''#include "stdio.h"
33+
int foo(){
34+
printf("foo!\\n");
35+
return 7;
36+
}''',
37+
'test-tests/foo.h':'int foo();',
38+
'test/a/bar.c':'#include "test-tests/foo.h"\nint main(){ foo(); return 0; }',
39+
'test/b/a/bar.c':'#include "test-tests/foo.h"\nint bar(); int main(){ foo(); bar(); return 0; }',
40+
'test/b/b/bar.c':'#include "stdio.h"\nint bar(){ printf("bar!\\n"); return 7; }',
41+
'test/c/a/a/bar.c':'#include "test-tests/foo.h"\nint bar(); int main(){ foo(); bar(); return 0; }',
42+
'test/c/b/a/bar.c':'#include "stdio.h"\nint bar(){ printf("bar!\\n"); return 7; }',
43+
'test/d/a/a/bar.c':'#include "test-tests/foo.h"\nint bar(); int main(){ foo(); bar(); return 0; }',
44+
'test/d/a/b/bar.c':'#include "stdio.h"\nint bar(){ printf("bar!\\n"); return 7; }',
45+
'test/e/a/a/a/bar.c':'#include "test-tests/foo.h"\nint bar(); int main(){ foo(); bar(); return 0; }',
46+
'test/e/b/a/a/bar.c':'#include "stdio.h"\nint bar(){ printf("bar!\\n"); return 7; }',
47+
'test/f/a/a/a/bar.c':'#include "test-tests/foo.h"\nint bar(); int main(){ foo(); bar(); return 0; }',
48+
'test/f/a/b/a/bar.c':'#include "stdio.h"\nint bar(){ printf("bar!\\n"); return 7; }',
49+
'test/g/a/a/a/bar.c':'#include "test-tests/foo.h"\nint bar(); int main(){ foo(); bar(); return 0; }',
50+
'test/g/a/a/b/bar.c':'#include "stdio.h"\nint bar(){ printf("bar!\\n"); return 7; }'
51+
}
52+
53+
Test_Fitler_Pass = copy.copy(Test_Tests)
54+
Test_Fitler_Pass['module.json'] = '''{
55+
"name": "test-tests",
56+
"version": "0.0.0",
57+
"licenses": [
58+
{
59+
"url": "https://spdx.org/licenses/Apache-2.0",
60+
"type": "Apache-2.0"
61+
}
62+
],
63+
"scripts": {
64+
"testReporter": [
65+
"grep",
66+
"!"
67+
]
68+
}
69+
}'''
70+
71+
Test_Fitler_Fail = copy.copy(Test_Tests)
72+
Test_Fitler_Fail['module.json'] = '''{
73+
"name": "test-tests",
74+
"version": "0.0.0",
75+
"licenses": [
76+
{
77+
"url": "https://spdx.org/licenses/Apache-2.0",
78+
"type": "Apache-2.0"
79+
}
80+
],
81+
"scripts": {
82+
"testReporter": [
83+
"grep",
84+
"string that isnt in the output"
85+
]
86+
}
87+
}'''
88+
89+
Test_Fitler_NotFound = copy.copy(Test_Tests)
90+
Test_Fitler_NotFound['module.json'] = '''{
91+
"name": "test-tests",
92+
"version": "0.0.0",
93+
"licenses": [
94+
{
95+
"url": "https://spdx.org/licenses/Apache-2.0",
96+
"type": "Apache-2.0"
97+
}
98+
],
99+
"scripts": {
100+
"testReporter": [
101+
"commandthatshouldntexist"
102+
]
103+
}
104+
}'''
105+
106+
def isWindows():
107+
return os.name == 'nt'
108+
109+
class TestCLITest(unittest.TestCase):
110+
def writeTestFiles(self, files, add_space_in_path=False):
111+
test_dir = tempfile.mkdtemp()
112+
if add_space_in_path:
113+
test_dir = test_dir + ' spaces in path'
114+
115+
for path, contents in files.items():
116+
path_dir, file_name = os.path.split(path)
117+
path_dir = os.path.join(test_dir, path_dir)
118+
mkDirP(path_dir)
119+
with open(os.path.join(path_dir, file_name), 'w') as f:
120+
f.write(contents)
121+
return test_dir
122+
123+
@unittest.skipIf(isWindows(), "can't build natively on windows yet")
124+
def test_tests(self):
125+
test_dir = self.writeTestFiles(Test_Tests, True)
126+
output = self.runCheckCommand(['--target', systemDefaultTarget(), 'build'], test_dir)
127+
output = self.runCheckCommand(['--target', systemDefaultTarget(), 'test'], test_dir)
128+
self.assertIn('test-a passed', output)
129+
self.assertIn('test-c passed', output)
130+
self.assertIn('test-d passed', output)
131+
self.assertIn('test-e passed', output)
132+
self.assertIn('test-f passed', output)
133+
self.assertIn('test-g passed', output)
134+
rmRf(test_dir)
135+
136+
@unittest.skipIf(isWindows(), "can't build natively on windows yet")
137+
def test_testOutputFilterPassing(self):
138+
test_dir = self.writeTestFiles(Test_Fitler_Pass, True)
139+
stdout = self.runCheckCommand(['--target', systemDefaultTarget(), 'test'], test_dir)
140+
rmRf(test_dir)
141+
142+
@unittest.skipIf(isWindows(), "can't build natively on windows yet")
143+
def test_testOutputFilterFailing(self):
144+
test_dir = self.writeTestFiles(Test_Fitler_Fail, True)
145+
stdout, stderr, statuscode = cli.run(['--target', systemDefaultTarget(), 'test'], cwd=test_dir)
146+
if statuscode == 0:
147+
print(stdout)
148+
print(stderr)
149+
self.assertIn('test-a failed', '%s %s' % (stdout, stderr))
150+
self.assertIn('test-c failed', '%s %s' % (stdout, stderr))
151+
self.assertIn('test-d failed', '%s %s' % (stdout, stderr))
152+
self.assertIn('test-e failed', '%s %s' % (stdout, stderr))
153+
self.assertIn('test-f failed', '%s %s' % (stdout, stderr))
154+
self.assertIn('test-g failed', '%s %s' % (stdout, stderr))
155+
self.assertNotEqual(statuscode, 0)
156+
rmRf(test_dir)
157+
158+
@unittest.skipIf(isWindows(), "can't build natively on windows yet")
159+
def test_testOutputFilterNotFound(self):
160+
test_dir = self.writeTestFiles(Test_Fitler_NotFound, True)
161+
stdout, stderr, statuscode = cli.run(['--target', systemDefaultTarget(), 'test'], cwd=test_dir)
162+
if statuscode == 0:
163+
print(stdout)
164+
print(stderr)
165+
self.assertNotEqual(statuscode, 0)
166+
rmRf(test_dir)
167+
168+
def runCheckCommand(self, args, test_dir):
169+
stdout, stderr, statuscode = cli.run(args, cwd=test_dir)
170+
if statuscode != 0:
171+
print('command failed with status %s' % statuscode)
172+
print(stdout)
173+
print(stderr)
174+
self.assertEqual(statuscode, 0)
175+
return '%s %s' % (stdout, stderr)

yotta/test/test_subcommand.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ def test_moduleFromDirname(self):
2020
self.assertTrue(test_subcommand.moduleFromDirname('ym/e/d', {'b':'b', 'c':'c'}, 'a') == 'a')
2121
self.assertTrue(test_subcommand.moduleFromDirname('ym/e/d', {'b':'b', 'c':'c', 'e':'e'}, 'a') == 'e')
2222

23-
23+
# see also yotta/test/cli/test.py for cli-driven testing
2424

2525

0 commit comments

Comments
 (0)