User | Revision | Line number | New contents of line |
switches |
0:0e018d759a2a
|
1
|
"""
|
switches |
0:0e018d759a2a
|
2
|
mbed SDK
|
switches |
0:0e018d759a2a
|
3
|
Copyright (c) 2011-2014 ARM Limited
|
switches |
0:0e018d759a2a
|
4
|
|
switches |
0:0e018d759a2a
|
5
|
Licensed under the Apache License, Version 2.0 (the "License");
|
switches |
0:0e018d759a2a
|
6
|
you may not use this file except in compliance with the License.
|
switches |
0:0e018d759a2a
|
7
|
You may obtain a copy of the License at
|
switches |
0:0e018d759a2a
|
8
|
|
switches |
0:0e018d759a2a
|
9
|
http://www.apache.org/licenses/LICENSE-2.0
|
switches |
0:0e018d759a2a
|
10
|
|
switches |
0:0e018d759a2a
|
11
|
Unless required by applicable law or agreed to in writing, software
|
switches |
0:0e018d759a2a
|
12
|
distributed under the License is distributed on an "AS IS" BASIS,
|
switches |
0:0e018d759a2a
|
13
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
switches |
0:0e018d759a2a
|
14
|
See the License for the specific language governing permissions and
|
switches |
0:0e018d759a2a
|
15
|
limitations under the License.
|
switches |
0:0e018d759a2a
|
16
|
|
switches |
0:0e018d759a2a
|
17
|
Author: Przemyslaw Wirkus <Przemyslaw.wirkus@arm.com>
|
switches |
0:0e018d759a2a
|
18
|
"""
|
switches |
0:0e018d759a2a
|
19
|
|
switches |
0:0e018d759a2a
|
20
|
import sys
|
switches |
0:0e018d759a2a
|
21
|
import json
|
switches |
0:0e018d759a2a
|
22
|
import optparse
|
switches |
0:0e018d759a2a
|
23
|
from flask import Flask
|
switches |
0:0e018d759a2a
|
24
|
from os.path import join, abspath, dirname
|
switches |
0:0e018d759a2a
|
25
|
|
switches |
0:0e018d759a2a
|
26
|
# Be sure that the tools directory is in the search path
|
switches |
0:0e018d759a2a
|
27
|
ROOT = abspath(join(dirname(__file__), ".."))
|
switches |
0:0e018d759a2a
|
28
|
sys.path.insert(0, ROOT)
|
switches |
0:0e018d759a2a
|
29
|
|
switches |
0:0e018d759a2a
|
30
|
# Imports related to mbed build api
|
switches |
0:0e018d759a2a
|
31
|
from tools.utils import construct_enum
|
switches |
0:0e018d759a2a
|
32
|
from tools.build_api import mcu_toolchain_matrix
|
switches |
0:0e018d759a2a
|
33
|
|
switches |
0:0e018d759a2a
|
34
|
# Imports from TEST API
|
switches |
0:0e018d759a2a
|
35
|
from test_api import SingleTestRunner
|
switches |
0:0e018d759a2a
|
36
|
from test_api import SingleTestExecutor
|
switches |
0:0e018d759a2a
|
37
|
from test_api import get_json_data_from_file
|
switches |
0:0e018d759a2a
|
38
|
from test_api import print_muts_configuration_from_json
|
switches |
0:0e018d759a2a
|
39
|
from test_api import print_test_configuration_from_json
|
switches |
0:0e018d759a2a
|
40
|
from test_api import get_avail_tests_summary_table
|
switches |
0:0e018d759a2a
|
41
|
from test_api import get_default_test_options_parser
|
switches |
0:0e018d759a2a
|
42
|
|
switches |
0:0e018d759a2a
|
43
|
|
switches |
0:0e018d759a2a
|
44
|
class SingleTestRunnerWebService(SingleTestRunner):
|
switches |
0:0e018d759a2a
|
45
|
def __init__(self):
|
switches |
0:0e018d759a2a
|
46
|
super(SingleTestRunnerWebService, self).__init__()
|
switches |
0:0e018d759a2a
|
47
|
|
switches |
0:0e018d759a2a
|
48
|
# With this lock we should control access to certain resources inside this class
|
switches |
0:0e018d759a2a
|
49
|
self.resource_lock = thread.allocate_lock()
|
switches |
0:0e018d759a2a
|
50
|
|
switches |
0:0e018d759a2a
|
51
|
self.RestRequest = construct_enum(REST_MUTS='muts',
|
switches |
0:0e018d759a2a
|
52
|
REST_TEST_SPEC='test_spec',
|
switches |
0:0e018d759a2a
|
53
|
REST_TEST_RESULTS='test_results')
|
switches |
0:0e018d759a2a
|
54
|
|
switches |
0:0e018d759a2a
|
55
|
def get_rest_result_template(self, result, command, success_code):
|
switches |
0:0e018d759a2a
|
56
|
""" Returns common part of every web service request
|
switches |
0:0e018d759a2a
|
57
|
"""
|
switches |
0:0e018d759a2a
|
58
|
result = {"result" : result,
|
switches |
0:0e018d759a2a
|
59
|
"command" : command,
|
switches |
0:0e018d759a2a
|
60
|
"success_code": success_code} # 0 - OK, >0 - Error number
|
switches |
0:0e018d759a2a
|
61
|
return result
|
switches |
0:0e018d759a2a
|
62
|
|
switches |
0:0e018d759a2a
|
63
|
# REST API handlers for Flask framework
|
switches |
0:0e018d759a2a
|
64
|
def rest_api_status(self):
|
switches |
0:0e018d759a2a
|
65
|
""" Returns current test execution status. E.g. running / finished etc.
|
switches |
0:0e018d759a2a
|
66
|
"""
|
switches |
0:0e018d759a2a
|
67
|
with self.resource_lock:
|
switches |
0:0e018d759a2a
|
68
|
pass
|
switches |
0:0e018d759a2a
|
69
|
|
switches |
0:0e018d759a2a
|
70
|
def rest_api_config(self):
|
switches |
0:0e018d759a2a
|
71
|
""" Returns configuration passed to SingleTest executor
|
switches |
0:0e018d759a2a
|
72
|
"""
|
switches |
0:0e018d759a2a
|
73
|
with self.resource_lock:
|
switches |
0:0e018d759a2a
|
74
|
pass
|
switches |
0:0e018d759a2a
|
75
|
|
switches |
0:0e018d759a2a
|
76
|
def rest_api_log(self):
|
switches |
0:0e018d759a2a
|
77
|
""" Returns current test log """
|
switches |
0:0e018d759a2a
|
78
|
with self.resource_lock:
|
switches |
0:0e018d759a2a
|
79
|
pass
|
switches |
0:0e018d759a2a
|
80
|
|
switches |
0:0e018d759a2a
|
81
|
def rest_api_request_handler(self, request_type):
|
switches |
0:0e018d759a2a
|
82
|
""" Returns various data structures. Both static and mutable during test
|
switches |
0:0e018d759a2a
|
83
|
"""
|
switches |
0:0e018d759a2a
|
84
|
result = {}
|
switches |
0:0e018d759a2a
|
85
|
success_code = 0
|
switches |
0:0e018d759a2a
|
86
|
with self.resource_lock:
|
switches |
0:0e018d759a2a
|
87
|
if request_type == self.RestRequest.REST_MUTS:
|
switches |
0:0e018d759a2a
|
88
|
result = self.muts # Returns MUTs
|
switches |
0:0e018d759a2a
|
89
|
elif request_type == self.RestRequest.REST_TEST_SPEC:
|
switches |
0:0e018d759a2a
|
90
|
result = self.test_spec # Returns Test Specification
|
switches |
0:0e018d759a2a
|
91
|
elif request_type == self.RestRequest.REST_TEST_RESULTS:
|
switches |
0:0e018d759a2a
|
92
|
pass # Returns test results
|
switches |
0:0e018d759a2a
|
93
|
else:
|
switches |
0:0e018d759a2a
|
94
|
success_code = -1
|
switches |
0:0e018d759a2a
|
95
|
return json.dumps(self.get_rest_result_template(result, 'request/' + request_type, success_code), indent=4)
|
switches |
0:0e018d759a2a
|
96
|
|
switches |
0:0e018d759a2a
|
97
|
|
switches |
0:0e018d759a2a
|
98
|
def singletest_in_webservice_mode():
|
switches |
0:0e018d759a2a
|
99
|
# TODO Implement this web service functionality
|
switches |
0:0e018d759a2a
|
100
|
pass
|
switches |
0:0e018d759a2a
|
101
|
|
switches |
0:0e018d759a2a
|
102
|
|
switches |
0:0e018d759a2a
|
103
|
def get_default_test_webservice_options_parser():
|
switches |
0:0e018d759a2a
|
104
|
""" Get test script web service options used by CLI, webservices etc.
|
switches |
0:0e018d759a2a
|
105
|
"""
|
switches |
0:0e018d759a2a
|
106
|
parser = get_default_test_options_parser()
|
switches |
0:0e018d759a2a
|
107
|
|
switches |
0:0e018d759a2a
|
108
|
# Things related to web services offered by test suite scripts
|
switches |
0:0e018d759a2a
|
109
|
parser.add_argument('', '--rest-api',
|
switches |
0:0e018d759a2a
|
110
|
dest='rest_api_enabled',
|
switches |
0:0e018d759a2a
|
111
|
default=False,
|
switches |
0:0e018d759a2a
|
112
|
action="store_true",
|
switches |
0:0e018d759a2a
|
113
|
help='Enables REST API.')
|
switches |
0:0e018d759a2a
|
114
|
|
switches |
0:0e018d759a2a
|
115
|
parser.add_argument('', '--rest-api-port',
|
switches |
0:0e018d759a2a
|
116
|
dest='rest_api_port_no',
|
switches |
0:0e018d759a2a
|
117
|
type=int,
|
switches |
0:0e018d759a2a
|
118
|
help='Sets port for REST API interface')
|
switches |
0:0e018d759a2a
|
119
|
|
switches |
0:0e018d759a2a
|
120
|
return parser
|
switches |
0:0e018d759a2a
|
121
|
|
switches |
0:0e018d759a2a
|
122
|
'''
|
switches |
0:0e018d759a2a
|
123
|
if __name__ == '__main__':
|
switches |
0:0e018d759a2a
|
124
|
# Command line options
|
switches |
0:0e018d759a2a
|
125
|
parser = get_default_test_options_parser()
|
switches |
0:0e018d759a2a
|
126
|
|
switches |
0:0e018d759a2a
|
127
|
parser.description = """This script allows you to run mbed defined test cases for particular MCU(s) and corresponding toolchain(s)."""
|
switches |
0:0e018d759a2a
|
128
|
parser.epilog = """Example: singletest.py -i test_spec.json -M muts_all.json"""
|
switches |
0:0e018d759a2a
|
129
|
|
switches |
0:0e018d759a2a
|
130
|
(opts, args) = parser.parse_args()
|
switches |
0:0e018d759a2a
|
131
|
|
switches |
0:0e018d759a2a
|
132
|
# Print summary / information about automation test status
|
switches |
0:0e018d759a2a
|
133
|
if opts.test_automation_report:
|
switches |
0:0e018d759a2a
|
134
|
print get_avail_tests_summary_table()
|
switches |
0:0e018d759a2a
|
135
|
exit(0)
|
switches |
0:0e018d759a2a
|
136
|
|
switches |
0:0e018d759a2a
|
137
|
# Print summary / information about automation test status
|
switches |
0:0e018d759a2a
|
138
|
if opts.test_case_report:
|
switches |
0:0e018d759a2a
|
139
|
test_case_report_cols = ['id', 'automated', 'description', 'peripherals', 'host_test', 'duration', 'source_dir']
|
switches |
0:0e018d759a2a
|
140
|
print get_avail_tests_summary_table(cols=test_case_report_cols, result_summary=False, join_delim='\n')
|
switches |
0:0e018d759a2a
|
141
|
exit(0)
|
switches |
0:0e018d759a2a
|
142
|
|
switches |
0:0e018d759a2a
|
143
|
# Only prints matrix of supported toolchains
|
switches |
0:0e018d759a2a
|
144
|
if opts.supported_toolchains:
|
switches |
0:0e018d759a2a
|
145
|
print mcu_toolchain_matrix(platform_filter=opts.general_filter_regex)
|
switches |
0:0e018d759a2a
|
146
|
exit(0)
|
switches |
0:0e018d759a2a
|
147
|
|
switches |
0:0e018d759a2a
|
148
|
# Open file with test specification
|
switches |
0:0e018d759a2a
|
149
|
# test_spec_filename tells script which targets and their toolchain(s)
|
switches |
0:0e018d759a2a
|
150
|
# should be covered by the test scenario
|
switches |
0:0e018d759a2a
|
151
|
test_spec = get_json_data_from_file(opts.test_spec_filename) if opts.test_spec_filename else None
|
switches |
0:0e018d759a2a
|
152
|
if test_spec is None:
|
switches |
0:0e018d759a2a
|
153
|
if not opts.test_spec_filename:
|
switches |
0:0e018d759a2a
|
154
|
parser.print_help()
|
switches |
0:0e018d759a2a
|
155
|
exit(-1)
|
switches |
0:0e018d759a2a
|
156
|
|
switches |
0:0e018d759a2a
|
157
|
# Get extra MUTs if applicable
|
switches |
0:0e018d759a2a
|
158
|
MUTs = get_json_data_from_file(opts.muts_spec_filename) if opts.muts_spec_filename else None
|
switches |
0:0e018d759a2a
|
159
|
|
switches |
0:0e018d759a2a
|
160
|
if MUTs is None:
|
switches |
0:0e018d759a2a
|
161
|
if not opts.muts_spec_filename:
|
switches |
0:0e018d759a2a
|
162
|
parser.print_help()
|
switches |
0:0e018d759a2a
|
163
|
exit(-1)
|
switches |
0:0e018d759a2a
|
164
|
|
switches |
0:0e018d759a2a
|
165
|
# Only prints read MUTs configuration
|
switches |
0:0e018d759a2a
|
166
|
if MUTs and opts.verbose_test_configuration_only:
|
switches |
0:0e018d759a2a
|
167
|
print "MUTs configuration in %s:"% opts.muts_spec_filename
|
switches |
0:0e018d759a2a
|
168
|
print print_muts_configuration_from_json(MUTs)
|
switches |
0:0e018d759a2a
|
169
|
print
|
switches |
0:0e018d759a2a
|
170
|
print "Test specification in %s:"% opts.test_spec_filename
|
switches |
0:0e018d759a2a
|
171
|
print print_test_configuration_from_json(test_spec)
|
switches |
0:0e018d759a2a
|
172
|
exit(0)
|
switches |
0:0e018d759a2a
|
173
|
|
switches |
0:0e018d759a2a
|
174
|
# Verbose test specification and MUTs configuration
|
switches |
0:0e018d759a2a
|
175
|
if MUTs and opts.verbose:
|
switches |
0:0e018d759a2a
|
176
|
print print_muts_configuration_from_json(MUTs)
|
switches |
0:0e018d759a2a
|
177
|
if test_spec and opts.verbose:
|
switches |
0:0e018d759a2a
|
178
|
print print_test_configuration_from_json(test_spec)
|
switches |
0:0e018d759a2a
|
179
|
|
switches |
0:0e018d759a2a
|
180
|
if opts.only_build_tests:
|
switches |
0:0e018d759a2a
|
181
|
# We are skipping testing phase, and suppress summary
|
switches |
0:0e018d759a2a
|
182
|
opts.suppress_summary = True
|
switches |
0:0e018d759a2a
|
183
|
|
switches |
0:0e018d759a2a
|
184
|
single_test = SingleTestRunner(_global_loops_count=opts.test_global_loops_value,
|
switches |
0:0e018d759a2a
|
185
|
_test_loops_list=opts.test_loops_list,
|
switches |
0:0e018d759a2a
|
186
|
_muts=MUTs,
|
switches |
0:0e018d759a2a
|
187
|
_test_spec=test_spec,
|
switches |
0:0e018d759a2a
|
188
|
_opts_goanna_for_mbed_sdk=opts.goanna_for_mbed_sdk,
|
switches |
0:0e018d759a2a
|
189
|
_opts_goanna_for_tests=opts.goanna_for_tests,
|
switches |
0:0e018d759a2a
|
190
|
_opts_shuffle_test_order=opts.shuffle_test_order,
|
switches |
0:0e018d759a2a
|
191
|
_opts_shuffle_test_seed=opts.shuffle_test_seed,
|
switches |
0:0e018d759a2a
|
192
|
_opts_test_by_names=opts.test_by_names,
|
switches |
0:0e018d759a2a
|
193
|
_opts_test_only_peripheral=opts.test_only_peripheral,
|
switches |
0:0e018d759a2a
|
194
|
_opts_test_only_common=opts.test_only_common,
|
switches |
0:0e018d759a2a
|
195
|
_opts_verbose_skipped_tests=opts.verbose_skipped_tests,
|
switches |
0:0e018d759a2a
|
196
|
_opts_verbose_test_result_only=opts.verbose_test_result_only,
|
switches |
0:0e018d759a2a
|
197
|
_opts_verbose=opts.verbose,
|
switches |
0:0e018d759a2a
|
198
|
_opts_firmware_global_name=opts.firmware_global_name,
|
switches |
0:0e018d759a2a
|
199
|
_opts_only_build_tests=opts.only_build_tests,
|
switches |
0:0e018d759a2a
|
200
|
_opts_suppress_summary=opts.suppress_summary,
|
switches |
0:0e018d759a2a
|
201
|
_opts_test_x_toolchain_summary=opts.test_x_toolchain_summary,
|
switches |
0:0e018d759a2a
|
202
|
_opts_copy_method=opts.copy_method
|
switches |
0:0e018d759a2a
|
203
|
)
|
switches |
0:0e018d759a2a
|
204
|
|
switches |
0:0e018d759a2a
|
205
|
try:
|
switches |
0:0e018d759a2a
|
206
|
st_exec_thread = SingleTestExecutor(single_test)
|
switches |
0:0e018d759a2a
|
207
|
except KeyboardInterrupt, e:
|
switches |
0:0e018d759a2a
|
208
|
print "\n[CTRL+c] exit"
|
switches |
0:0e018d759a2a
|
209
|
st_exec_thread.start()
|
switches |
0:0e018d759a2a
|
210
|
|
switches |
0:0e018d759a2a
|
211
|
if opts.rest_api_enabled:
|
switches |
0:0e018d759a2a
|
212
|
# Enable REST API
|
switches |
0:0e018d759a2a
|
213
|
|
switches |
0:0e018d759a2a
|
214
|
app = Flask(__name__)
|
switches |
0:0e018d759a2a
|
215
|
|
switches |
0:0e018d759a2a
|
216
|
@app.route('/')
|
switches |
0:0e018d759a2a
|
217
|
def hello_world():
|
switches |
0:0e018d759a2a
|
218
|
return 'Hello World!'
|
switches |
0:0e018d759a2a
|
219
|
|
switches |
0:0e018d759a2a
|
220
|
@app.route('/status')
|
switches |
0:0e018d759a2a
|
221
|
def rest_api_status():
|
switches |
0:0e018d759a2a
|
222
|
return single_test.rest_api_status() # TODO
|
switches |
0:0e018d759a2a
|
223
|
|
switches |
0:0e018d759a2a
|
224
|
@app.route('/config')
|
switches |
0:0e018d759a2a
|
225
|
def rest_api_config():
|
switches |
0:0e018d759a2a
|
226
|
return single_test.rest_api_config() # TODO
|
switches |
0:0e018d759a2a
|
227
|
|
switches |
0:0e018d759a2a
|
228
|
@app.route('/log')
|
switches |
0:0e018d759a2a
|
229
|
def rest_api_log():
|
switches |
0:0e018d759a2a
|
230
|
return single_test.rest_api_log() # TODO
|
switches |
0:0e018d759a2a
|
231
|
|
switches |
0:0e018d759a2a
|
232
|
@app.route('/request/<request_type>') # 'muts', 'test_spec', 'test_results'
|
switches |
0:0e018d759a2a
|
233
|
def rest_api_request_handler(request_type):
|
switches |
0:0e018d759a2a
|
234
|
result = single_test.rest_api_request_handler(request_type) # TODO
|
switches |
0:0e018d759a2a
|
235
|
return result
|
switches |
0:0e018d759a2a
|
236
|
|
switches |
0:0e018d759a2a
|
237
|
rest_api_port = int(opts.rest_api_port_no) if opts.rest_api_port_no else 5555
|
switches |
0:0e018d759a2a
|
238
|
app.debug = False
|
switches |
0:0e018d759a2a
|
239
|
app.run(port=rest_api_port) # Blocking Flask REST API web service
|
switches |
0:0e018d759a2a
|
240
|
else:
|
switches |
0:0e018d759a2a
|
241
|
st_exec_thread.join()
|
switches |
0:0e018d759a2a
|
242
|
|
switches |
0:0e018d759a2a
|
243
|
'''
|