micrOSDevToolKit 2.9.8__py3-none-any.whl → 2.9.10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of micrOSDevToolKit might be problematic. Click here for more details.
- micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json +20 -20
- micrOS/source/LM_oled_ui.py +1 -1
- micrOS/source/LM_system.py +4 -4
- micrOS/source/Notify.py +4 -0
- micrOS/source/Server.py +1 -1
- micrOS/source/Shell.py +3 -3
- micrOS/source/Tasks.py +1 -1
- micrOS/source/Time.py +7 -8
- micrOS/source/__pycache__/Common.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Logger.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Server.cpython-312.pyc +0 -0
- micrOS/source/micrOSloader.py +0 -1
- micrOS/source/urequests.py +14 -7
- {micrOSDevToolKit-2.9.8.data → micrOSDevToolKit-2.9.10.data}/scripts/devToolKit.py +10 -0
- {micrOSDevToolKit-2.9.8.dist-info → micrOSDevToolKit-2.9.10.dist-info}/METADATA +14 -4
- {micrOSDevToolKit-2.9.8.dist-info → micrOSDevToolKit-2.9.10.dist-info}/RECORD +51 -47
- {micrOSDevToolKit-2.9.8.dist-info → micrOSDevToolKit-2.9.10.dist-info}/WHEEL +1 -1
- toolkit/DevEnvUSB.py +6 -5
- toolkit/MicrOSDevEnv.py +19 -5
- toolkit/WebRepl.py +73 -0
- toolkit/dashboard_apps/BackupRestore.py +20 -35
- toolkit/dashboard_apps/CCTDemo.py +12 -17
- toolkit/dashboard_apps/CCTTest.py +20 -24
- toolkit/dashboard_apps/CamStream.py +2 -6
- toolkit/dashboard_apps/CatGame.py +14 -16
- toolkit/dashboard_apps/Dimmer.py +11 -21
- toolkit/dashboard_apps/GetVersion.py +11 -19
- toolkit/dashboard_apps/MicrophoneTest.py +1 -6
- toolkit/dashboard_apps/NeoEffectsDemo.py +28 -34
- toolkit/dashboard_apps/NeopixelTest.py +20 -25
- toolkit/dashboard_apps/PresenceTest.py +2 -8
- toolkit/dashboard_apps/RGBTest.py +20 -24
- toolkit/dashboard_apps/RoboArm.py +24 -32
- toolkit/dashboard_apps/SED_test.py +10 -14
- toolkit/dashboard_apps/SensorsTest.py +61 -0
- toolkit/dashboard_apps/SystemTest.py +151 -77
- toolkit/dashboard_apps/Template_app.py +11 -23
- toolkit/dashboard_apps/_app_base.py +34 -0
- toolkit/dashboard_apps/uLightDemo.py +15 -24
- toolkit/lib/micrOSClient.py +16 -11
- toolkit/micrOSlint.py +3 -3
- toolkit/socketClient.py +0 -1
- toolkit/workspace/precompiled/LM_oled_ui.mpy +0 -0
- toolkit/workspace/precompiled/LM_system.mpy +0 -0
- toolkit/workspace/precompiled/Notify.mpy +0 -0
- toolkit/workspace/precompiled/Shell.mpy +0 -0
- toolkit/workspace/precompiled/Time.mpy +0 -0
- toolkit/workspace/precompiled/micrOSloader.mpy +0 -0
- toolkit/workspace/precompiled/urequests.mpy +0 -0
- toolkit/dashboard_apps/AirQualityBME280.py +0 -36
- toolkit/dashboard_apps/AirQualityDHT22_CO2.py +0 -36
- {micrOSDevToolKit-2.9.8.dist-info → micrOSDevToolKit-2.9.10.dist-info}/LICENSE +0 -0
- {micrOSDevToolKit-2.9.8.dist-info → micrOSDevToolKit-2.9.10.dist-info}/top_level.txt +0 -0
|
@@ -5,34 +5,79 @@ import sys
|
|
|
5
5
|
import time
|
|
6
6
|
import socket
|
|
7
7
|
import ast
|
|
8
|
+
from pprint import pprint
|
|
9
|
+
try:
|
|
10
|
+
from ._app_base import AppBase
|
|
11
|
+
except:
|
|
12
|
+
from _app_base import AppBase
|
|
13
|
+
|
|
8
14
|
MYPATH = os.path.dirname(os.path.abspath(__file__))
|
|
9
|
-
|
|
10
|
-
import socketClient
|
|
15
|
+
REPORT_OUTPUT_PATH = os.path.join(MYPATH, '../../micrOS/release_info/micrOS_ReleaseInfo/devices_system_metrics.json')
|
|
11
16
|
sys.path.append(os.path.join(MYPATH, '../lib/'))
|
|
12
17
|
from TerminalColors import Colors
|
|
13
18
|
import requests
|
|
14
19
|
|
|
15
|
-
|
|
16
|
-
DEVICE = '__simulator__'
|
|
17
|
-
PASSWD = None
|
|
20
|
+
CLIENT = None
|
|
18
21
|
TIMEOUT_SEC = 5
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
# COLLECT AND SAVE SYSTEM TEST METRICS
|
|
24
|
+
ENABLE_DATA_COLLECTION = os.environ.get("ENABLE_DATA_COLLECTION", False)
|
|
25
|
+
REPORT_DICT = {}
|
|
26
|
+
METRICS = {}
|
|
27
|
+
|
|
28
|
+
#####################################
|
|
29
|
+
# METRICS #
|
|
30
|
+
#####################################
|
|
31
|
+
def load_reports():
|
|
32
|
+
global REPORT_DICT
|
|
33
|
+
previous_reports = {}
|
|
34
|
+
try:
|
|
35
|
+
with open(REPORT_OUTPUT_PATH, 'r') as f:
|
|
36
|
+
previous_reports = json.loads(f.read())
|
|
37
|
+
except FileNotFoundError:
|
|
38
|
+
pass
|
|
39
|
+
finally:
|
|
40
|
+
REPORT_DICT = previous_reports
|
|
41
|
+
|
|
42
|
+
def create_report(device_name:str, metrics:dict) -> None:
|
|
43
|
+
global REPORT_DICT
|
|
44
|
+
|
|
45
|
+
if not ENABLE_DATA_COLLECTION:
|
|
46
|
+
print(f"[SKIP] system test metrics export, ENABLE_DATA_COLLECTION={ENABLE_DATA_COLLECTION}")
|
|
47
|
+
pprint(metrics)
|
|
48
|
+
return
|
|
49
|
+
load_reports()
|
|
50
|
+
version = metrics.get('version')
|
|
51
|
+
device_type = metrics.get('board_type')
|
|
52
|
+
device_type = '???' if device_type is None else device_type.split()[-1]
|
|
53
|
+
if REPORT_DICT.get(version) is None:
|
|
54
|
+
REPORT_DICT[version] = {}
|
|
55
|
+
if REPORT_DICT.get(version).get(device_type) is None:
|
|
56
|
+
REPORT_DICT[version][device_type] = {}
|
|
57
|
+
REPORT_DICT[version][device_type][device_name] = metrics
|
|
58
|
+
# Cleanup - remove redundant elements
|
|
59
|
+
REPORT_DICT[version][device_type][device_name].pop("board_type", None)
|
|
60
|
+
REPORT_DICT[version][device_type][device_name].pop("version", None)
|
|
61
|
+
# Dump report
|
|
62
|
+
print(f"Save system test report: {REPORT_OUTPUT_PATH}")
|
|
63
|
+
pprint(metrics)
|
|
64
|
+
with open(REPORT_OUTPUT_PATH, 'w') as f:
|
|
65
|
+
f.write(json.dumps(REPORT_DICT, indent=4))
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _add_metrics(key:str, value):
|
|
69
|
+
global METRICS
|
|
70
|
+
METRICS[key] = value
|
|
71
|
+
|
|
72
|
+
#####################################
|
|
73
|
+
# TESTS #
|
|
74
|
+
#####################################
|
|
30
75
|
|
|
31
76
|
def single_cmd_exec_check():
|
|
32
77
|
info = "[ST] Run single command execution check [hello]"
|
|
33
78
|
print(info)
|
|
34
79
|
cmd_list = ['hello']
|
|
35
|
-
output = execute(cmd_list)
|
|
80
|
+
output = CLIENT.execute(cmd_list)
|
|
36
81
|
if output[0]:
|
|
37
82
|
if output[1].startswith("hello:"):
|
|
38
83
|
return True, info
|
|
@@ -42,17 +87,18 @@ def shell_cmds_check():
|
|
|
42
87
|
info = "[ST] Run built-in shell commands [modules|version|help]"
|
|
43
88
|
print(info)
|
|
44
89
|
cmd_list = ['modules']
|
|
45
|
-
output = execute(cmd_list)
|
|
90
|
+
output = CLIENT.execute(cmd_list)
|
|
46
91
|
if output[0]:
|
|
92
|
+
_add_metrics("modules", ast.literal_eval(output[1]))
|
|
47
93
|
if not (output[1].startswith("[") and output[1].endswith("]")):
|
|
48
94
|
return False, f"{info}modules: {output[1]}"
|
|
49
95
|
cmd_list = ['version']
|
|
50
|
-
output = execute(cmd_list)
|
|
96
|
+
output = CLIENT.execute(cmd_list)
|
|
51
97
|
if output[0]:
|
|
52
98
|
if not ('.' in output[1] and '-' in output[1]):
|
|
53
99
|
return False, f"{info}version: {output[1]}"
|
|
54
100
|
cmd_list = ['help']
|
|
55
|
-
output = execute(cmd_list)
|
|
101
|
+
output = CLIENT.execute(cmd_list)
|
|
56
102
|
if output[0]:
|
|
57
103
|
if not ('[MICROS]' in output[1] and '[CONF]' in output[1] and '[TASK]' in output[1] and '[EXEC]' in output[1]):
|
|
58
104
|
return False, f"{info}help: {output[1]}"
|
|
@@ -63,7 +109,7 @@ def lm_cmd_exec_check():
|
|
|
63
109
|
info = "[ST] Run Load Module command execution check [system heartbeat]"
|
|
64
110
|
print(info)
|
|
65
111
|
cmd_list = ['system heartbeat']
|
|
66
|
-
output = execute(cmd_list)
|
|
112
|
+
output = CLIENT.execute(cmd_list)
|
|
67
113
|
if output[0]:
|
|
68
114
|
if output[1].strip() == '<3 heartbeat <3':
|
|
69
115
|
return True, info
|
|
@@ -74,7 +120,7 @@ def micrOS_config_get():
|
|
|
74
120
|
info = "[ST] Run micrOS config get [conf -> socport]"
|
|
75
121
|
print(info)
|
|
76
122
|
cmd_list = ['config <a> socport']
|
|
77
|
-
output = execute(cmd_list)
|
|
123
|
+
output = CLIENT.execute(cmd_list)
|
|
78
124
|
if output[0]:
|
|
79
125
|
if output[1].strip() == '9008':
|
|
80
126
|
return True, info
|
|
@@ -88,7 +134,7 @@ def micrOS_config_set():
|
|
|
88
134
|
|
|
89
135
|
# [1] Get actual utc value
|
|
90
136
|
cmd_list = ['config <a> utc']
|
|
91
|
-
output = execute(cmd_list)
|
|
137
|
+
output = CLIENT.execute(cmd_list)
|
|
92
138
|
if output[0]:
|
|
93
139
|
try:
|
|
94
140
|
utc_bak = int(output[1].strip())
|
|
@@ -98,21 +144,21 @@ def micrOS_config_set():
|
|
|
98
144
|
# [2] Set x+1 value as expected
|
|
99
145
|
utc_expected = utc_bak+1
|
|
100
146
|
cmd_list = ['config <a> utc {}'.format(utc_expected)]
|
|
101
|
-
output = execute(cmd_list)
|
|
147
|
+
output = CLIENT.execute(cmd_list)
|
|
102
148
|
if output[0]:
|
|
103
149
|
if output[1].strip() != 'Saved':
|
|
104
150
|
return False, f"{info} + utc overwrite issue: {output[1]}"
|
|
105
151
|
|
|
106
152
|
# [3] Get modified utc value - veridy [2] step
|
|
107
153
|
cmd_list = ['config <a> utc']
|
|
108
|
-
output = execute(cmd_list)
|
|
154
|
+
output = CLIENT.execute(cmd_list)
|
|
109
155
|
if output[0]:
|
|
110
156
|
if int(output[1].strip()) != utc_expected:
|
|
111
157
|
return False, f"{info} + utc modified value error: {output[1]} != {utc_expected}"
|
|
112
158
|
|
|
113
159
|
# Restore original value
|
|
114
160
|
cmd_list = ['config <a> utc {}'.format(utc_bak)]
|
|
115
|
-
output = execute(cmd_list)
|
|
161
|
+
output = CLIENT.execute(cmd_list)
|
|
116
162
|
if output[0]:
|
|
117
163
|
if output[1].strip() != 'Saved':
|
|
118
164
|
return False, f"{info} + utc overwrite issue: {output[1]}"
|
|
@@ -126,11 +172,11 @@ def micrOS_bgjob_one_shot_check():
|
|
|
126
172
|
print(info)
|
|
127
173
|
|
|
128
174
|
# Initial task cleanup...
|
|
129
|
-
execute(['task kill system.clock'])
|
|
175
|
+
CLIENT.execute(['task kill system.clock'])
|
|
130
176
|
|
|
131
177
|
for _ in range(0, 2):
|
|
132
178
|
cmd_list = ['system clock &']
|
|
133
|
-
output = execute(cmd_list)
|
|
179
|
+
output = CLIENT.execute(cmd_list)
|
|
134
180
|
time.sleep(1)
|
|
135
181
|
if output[0]:
|
|
136
182
|
if 'Start system.clock' not in output[1].strip():
|
|
@@ -144,14 +190,14 @@ def micrOS_bgjob_loop_check():
|
|
|
144
190
|
|
|
145
191
|
# Start background task loop
|
|
146
192
|
cmd_list = ['system clock &&']
|
|
147
|
-
output = execute(cmd_list)
|
|
193
|
+
output = CLIENT.execute(cmd_list)
|
|
148
194
|
if output[0]:
|
|
149
195
|
if 'Start system.clock' not in output[1].strip():
|
|
150
196
|
return False, f'[Start Task error] {info} + not expected return: {output[1]}'
|
|
151
197
|
|
|
152
198
|
# Attempt to overload background thread
|
|
153
199
|
cmd_list = ['system clock &&']
|
|
154
|
-
output = execute(cmd_list)
|
|
200
|
+
output = CLIENT.execute(cmd_list)
|
|
155
201
|
if output[0]:
|
|
156
202
|
if 'system.clock is Busy' not in output[1].strip():
|
|
157
203
|
return False, f'[Overload task - run same] {info} + not expected return: {output[1]}'
|
|
@@ -159,14 +205,14 @@ def micrOS_bgjob_loop_check():
|
|
|
159
205
|
# Show task output by task tag
|
|
160
206
|
time.sleep(0.1) # Give time for the task to start and update buffer... (sim)
|
|
161
207
|
cmd_list = ['task show system.clock']
|
|
162
|
-
output = execute(cmd_list)
|
|
208
|
+
output = CLIENT.execute(cmd_list)
|
|
163
209
|
if output[0]:
|
|
164
210
|
if "No task found" in output[1].strip() or len(output[1].strip()) == 0:
|
|
165
211
|
return False, f'[No task output] {info} + not expected return: {output[1]}'
|
|
166
212
|
|
|
167
213
|
# Stop BgJob
|
|
168
214
|
cmd_list = ['task kill system.clock']
|
|
169
|
-
output = execute(cmd_list)
|
|
215
|
+
output = CLIENT.execute(cmd_list)
|
|
170
216
|
if output[0]:
|
|
171
217
|
if 'Kill:' in output[1].strip() or 'system.clock' in output[1].strip():
|
|
172
218
|
return True, f'[Stop task] {info}'
|
|
@@ -179,7 +225,7 @@ def micrOS_task_list_check():
|
|
|
179
225
|
print(info)
|
|
180
226
|
|
|
181
227
|
async_available_cmd_list = ['task list']
|
|
182
|
-
output = execute(async_available_cmd_list)
|
|
228
|
+
output = CLIENT.execute(async_available_cmd_list)
|
|
183
229
|
if output[0]:
|
|
184
230
|
if "---- micrOS top ----" not in output[1]:
|
|
185
231
|
return False, f"{info} - ERROR: missing response prefix {output[1]}"
|
|
@@ -187,7 +233,7 @@ def micrOS_task_list_check():
|
|
|
187
233
|
return False, f"{info} - task list error: {output[1]}"
|
|
188
234
|
|
|
189
235
|
async_available_cmd_list = ['task list >json']
|
|
190
|
-
output = execute(async_available_cmd_list)
|
|
236
|
+
output = CLIENT.execute(async_available_cmd_list)
|
|
191
237
|
if output[0]:
|
|
192
238
|
starts = '{'
|
|
193
239
|
ends = '}'
|
|
@@ -201,10 +247,11 @@ def micrOS_get_version():
|
|
|
201
247
|
info = "[ST] Run micrOS get version [version]"
|
|
202
248
|
print(info)
|
|
203
249
|
cmd_list = ['version']
|
|
204
|
-
output = execute(cmd_list)
|
|
250
|
+
output = CLIENT.execute(cmd_list)
|
|
205
251
|
if output[0]:
|
|
206
252
|
if '.' in output[1].strip() and '-' in output[1].strip():
|
|
207
253
|
return True, f"{info} v:{output[1].strip()}"
|
|
254
|
+
_add_metrics('version', output[1])
|
|
208
255
|
return False, f"{info} out: {output[1]}"
|
|
209
256
|
|
|
210
257
|
|
|
@@ -212,7 +259,7 @@ def json_format_check():
|
|
|
212
259
|
info = "[ST] Run micrOS raw output check aka >json [system rssi >json]"
|
|
213
260
|
print(info)
|
|
214
261
|
cmd_list = ['system rssi >json']
|
|
215
|
-
output = execute(cmd_list)
|
|
262
|
+
output = CLIENT.execute(cmd_list)
|
|
216
263
|
if output[0] and output[1].startswith("{") and output[1].endswith("}"):
|
|
217
264
|
return True, info + f" out: {output[1]}"
|
|
218
265
|
return False, info + f" out: {output[1]}"
|
|
@@ -223,25 +270,25 @@ def negative_interface_check():
|
|
|
223
270
|
print(info)
|
|
224
271
|
|
|
225
272
|
cmd_list = ['Apple']
|
|
226
|
-
output = execute(cmd_list)
|
|
273
|
+
output = CLIENT.execute(cmd_list)
|
|
227
274
|
if output[0]:
|
|
228
275
|
if 'Shell: for hints type help.' not in output[1].strip():
|
|
229
276
|
return False, f'[Wrong single command] {info} + not expected return: {output[1]}'
|
|
230
277
|
|
|
231
278
|
cmd_list = ['Apple test']
|
|
232
|
-
output = execute(cmd_list)
|
|
279
|
+
output = CLIENT.execute(cmd_list)
|
|
233
280
|
if output[0]:
|
|
234
281
|
if 'no module named' not in output[1].strip().lower():
|
|
235
282
|
return False, f'[Missing module] {info} + not expected return: {output[1]}'
|
|
236
283
|
|
|
237
284
|
cmd_list = ['conf', 'gmttimaaaa']
|
|
238
|
-
output = execute(cmd_list)
|
|
285
|
+
output = CLIENT.execute(cmd_list)
|
|
239
286
|
if output[0]:
|
|
240
287
|
if output[1].strip() != 'None':
|
|
241
288
|
return False, f'[Config invalid key] {info} + not expected return: {output[1]}'
|
|
242
289
|
|
|
243
290
|
cmd_list = ['conf', 'utc "type"']
|
|
244
|
-
output = execute(cmd_list)
|
|
291
|
+
output = CLIENT.execute(cmd_list)
|
|
245
292
|
if output[0]:
|
|
246
293
|
if output[1].strip() != 'Failed to save':
|
|
247
294
|
return False, f'[Config invalid key type] {info} + not expected return: {output[1]}'
|
|
@@ -265,11 +312,12 @@ def measure_package_response_time():
|
|
|
265
312
|
# Start time
|
|
266
313
|
start = time.time()
|
|
267
314
|
# Command exec
|
|
268
|
-
output = execute(cmd_list)
|
|
315
|
+
output = CLIENT.execute(cmd_list)
|
|
269
316
|
# Stop time
|
|
270
317
|
end = time.time() - start
|
|
271
318
|
# Get average response time
|
|
272
319
|
delta_cmd_rep_time = round(end/10, 4)
|
|
320
|
+
_add_metrics('shell_heartbeatX10_response_ms', int(delta_cmd_rep_time*1000))
|
|
273
321
|
# Create verdict
|
|
274
322
|
print(output)
|
|
275
323
|
if output[0] and "<3 heartbeat <3" in output[1]:
|
|
@@ -281,7 +329,7 @@ def micros_alarm_check():
|
|
|
281
329
|
info = "[ST] Test alarm state - system alarms should be null"
|
|
282
330
|
print(info)
|
|
283
331
|
cmd_list = ['system alarms']
|
|
284
|
-
output = execute(cmd_list)
|
|
332
|
+
output = CLIENT.execute(cmd_list)
|
|
285
333
|
alarm_cnt = 0
|
|
286
334
|
if output[0]:
|
|
287
335
|
try:
|
|
@@ -292,7 +340,7 @@ def micros_alarm_check():
|
|
|
292
340
|
print(e)
|
|
293
341
|
# Clean alarms
|
|
294
342
|
cmd_list = ['system alarms True']
|
|
295
|
-
execute(cmd_list)
|
|
343
|
+
CLIENT.execute(cmd_list)
|
|
296
344
|
# Evaluation
|
|
297
345
|
if alarm_cnt > 0:
|
|
298
346
|
return True, info + f" -1 !!!WARN!!! [{alarm_cnt}] out: {output[1]}"
|
|
@@ -301,10 +349,10 @@ def micros_alarm_check():
|
|
|
301
349
|
|
|
302
350
|
def oled_msg_end_result(result):
|
|
303
351
|
cmd_list = ['pacman moduls >json']
|
|
304
|
-
output = execute(cmd_list)
|
|
352
|
+
output = CLIENT.execute(cmd_list)
|
|
305
353
|
if output[0] and 'LM_oled_ui' in output[1]:
|
|
306
354
|
cmd_list = [f'oled_ui msgbox "{result} %"']
|
|
307
|
-
print(execute(cmd_list))
|
|
355
|
+
print(CLIENT.execute(cmd_list))
|
|
308
356
|
|
|
309
357
|
|
|
310
358
|
def check_device_by_hostname(dev):
|
|
@@ -325,7 +373,7 @@ def check_robustness_exception():
|
|
|
325
373
|
info_msg = '[ST] Check robustness - exception [robustness raise_error]'
|
|
326
374
|
print(info_msg)
|
|
327
375
|
cmd_list = ['robustness raise_error']
|
|
328
|
-
output = execute(cmd_list)
|
|
376
|
+
output = CLIENT.execute(cmd_list)
|
|
329
377
|
if output[0] and "Core error: LM_robustness->raise_error: Test exception" in output[1]:
|
|
330
378
|
return True, f'{info_msg}: Valid error msg: exec_lm_core *->raise_error: *'
|
|
331
379
|
else:
|
|
@@ -336,7 +384,7 @@ def check_robustness_memory():
|
|
|
336
384
|
info_msg = '[ST] Check robustness - memory_leak [robustness memory_leak 12]'
|
|
337
385
|
print(info_msg)
|
|
338
386
|
cmd_list = ['robustness memory_leak 12']
|
|
339
|
-
output = execute(cmd_list)
|
|
387
|
+
output = CLIENT.execute(cmd_list)
|
|
340
388
|
if output[0] and "[12] RAM Alloc" in output[1]:
|
|
341
389
|
end_result = output[1].split("\n")[-1]
|
|
342
390
|
return True, f'{info_msg}: Mem alloc: {end_result}'
|
|
@@ -348,7 +396,7 @@ def check_robustness_recursion():
|
|
|
348
396
|
info_msg = '[ST] Check robustness - recursion [robustness recursion_limit 8]'
|
|
349
397
|
print(info_msg)
|
|
350
398
|
cmd_list = ['robustness recursion_limit 8']
|
|
351
|
-
output = execute(cmd_list, tout=10)
|
|
399
|
+
output = CLIENT.execute(cmd_list, tout=10)
|
|
352
400
|
if output[0]:
|
|
353
401
|
last_line = output[1].split("\n")[-1]
|
|
354
402
|
if "Recursion limit:" in last_line:
|
|
@@ -372,7 +420,7 @@ def check_intercon(host=None):
|
|
|
372
420
|
_output = None
|
|
373
421
|
for _ in range(0, 2):
|
|
374
422
|
time.sleep(1)
|
|
375
|
-
_output = execute(_cmd_list, tout=8)
|
|
423
|
+
_output = CLIENT.execute(_cmd_list, tout=8)
|
|
376
424
|
if _output[0] and 'No task found:' not in _output[1]:
|
|
377
425
|
_state = True
|
|
378
426
|
break
|
|
@@ -382,7 +430,7 @@ def check_intercon(host=None):
|
|
|
382
430
|
print(info_msg)
|
|
383
431
|
host = 'test.local' if host is None else host
|
|
384
432
|
cmd_list = ['intercon sendcmd "{}" "hello" >json'.format(host)]
|
|
385
|
-
output = execute(cmd_list, tout=8)
|
|
433
|
+
output = CLIENT.execute(cmd_list, tout=8)
|
|
386
434
|
output = _convert_return_to_dict(output)
|
|
387
435
|
device_was_found = False
|
|
388
436
|
if output[0] is False or output[1] is None:
|
|
@@ -404,7 +452,7 @@ def check_intercon(host=None):
|
|
|
404
452
|
if device_was_found:
|
|
405
453
|
# DO Negative testing as well
|
|
406
454
|
cmd_list = ['intercon sendcmd "notavailable.local" "hello" >json']
|
|
407
|
-
output_neg = execute(cmd_list, tout=15)
|
|
455
|
+
output_neg = CLIENT.execute(cmd_list, tout=15)
|
|
408
456
|
output_neg = _convert_return_to_dict(output_neg)
|
|
409
457
|
state_neg = False, output_neg
|
|
410
458
|
if len(output_neg[1]) > 1 and "hello" in output_neg[1]['verdict']:
|
|
@@ -417,9 +465,11 @@ def check_intercon(host=None):
|
|
|
417
465
|
|
|
418
466
|
def measure_conn_metrics():
|
|
419
467
|
try:
|
|
420
|
-
verdict =
|
|
468
|
+
verdict, delta_t_single, delta_t_multi = CLIENT.connection_metrics()
|
|
469
|
+
_add_metrics("shell_single_session_dt_ms", int(delta_t_single*1000))
|
|
470
|
+
_add_metrics("shell_multi_session_dt_ms", int(delta_t_multi*1000))
|
|
421
471
|
for k in verdict:
|
|
422
|
-
print("\t\t{}"
|
|
472
|
+
print(f"\t\t{k}")
|
|
423
473
|
state = True if len(verdict) > 0 else False
|
|
424
474
|
except Exception as e:
|
|
425
475
|
state = False
|
|
@@ -429,7 +479,7 @@ def measure_conn_metrics():
|
|
|
429
479
|
|
|
430
480
|
def memory_usage():
|
|
431
481
|
cmd = ['system memory_usage >json']
|
|
432
|
-
out = execute(cmd, tout=TIMEOUT_SEC)
|
|
482
|
+
out = CLIENT.execute(cmd, tout=TIMEOUT_SEC)
|
|
433
483
|
state, raw_output = out[0], out[1]
|
|
434
484
|
try:
|
|
435
485
|
json_out = json.loads(raw_output)
|
|
@@ -437,6 +487,8 @@ def memory_usage():
|
|
|
437
487
|
return False, '[ST] {}ERR{}: {}: {}'.format(Colors.ERR, Colors.NC, raw_output, e)
|
|
438
488
|
|
|
439
489
|
# {"percent": 93.11, "mem_used": 103504}
|
|
490
|
+
_add_metrics('mem_percent', json_out.get('percent'))
|
|
491
|
+
_add_metrics('mem_used_byte', json_out.get('mem_used'))
|
|
440
492
|
if json_out.get('percent') > 70: # MEM USAGE WARNING INDICATOR: 80%
|
|
441
493
|
return state, '[ST] {}WARNING{}: memory usage {}% ({} bytes)'.format(Colors.WARN, Colors.NC,
|
|
442
494
|
json_out.get('percent'),
|
|
@@ -450,7 +502,7 @@ def disk_usage():
|
|
|
450
502
|
Check disk usage - manually defined 16% (336_000 byte) - check degradations...
|
|
451
503
|
"""
|
|
452
504
|
cmd = ['system disk_usage >json']
|
|
453
|
-
out = execute(cmd, tout=TIMEOUT_SEC)
|
|
505
|
+
out = CLIENT.execute(cmd, tout=TIMEOUT_SEC)
|
|
454
506
|
state, raw_output = out[0], out[1]
|
|
455
507
|
try:
|
|
456
508
|
json_out = json.loads(raw_output)
|
|
@@ -458,6 +510,8 @@ def disk_usage():
|
|
|
458
510
|
return False, '[ST] {}ERR{}: {}: {}'.format(Colors.ERR, Colors.NC, raw_output, e)
|
|
459
511
|
|
|
460
512
|
# {"percent": 15.4, "fs_used": 323_584}
|
|
513
|
+
_add_metrics('fs_percent', json_out.get('percent'))
|
|
514
|
+
_add_metrics('fs_used_byte', json_out.get('fs_used'))
|
|
461
515
|
if json_out.get('fs_used') > 700_000: # MEM USAGE WARNING INDICATOR: 700_000 bytes (700kb)
|
|
462
516
|
return state, '[ST] {}WARNING{}: disk usage {}% ({} bytes)'.format(Colors.WARN, Colors.NC,
|
|
463
517
|
json_out.get('percent'),
|
|
@@ -468,7 +522,7 @@ def disk_usage():
|
|
|
468
522
|
|
|
469
523
|
def task_list():
|
|
470
524
|
cmd = ['task list']
|
|
471
|
-
out = execute(cmd, tout=TIMEOUT_SEC)
|
|
525
|
+
out = CLIENT.execute(cmd, tout=TIMEOUT_SEC)
|
|
472
526
|
state, output = out[0], out[1]
|
|
473
527
|
if state:
|
|
474
528
|
return state, output.replace('\n', f'\n{" "*51}') # TODO format output
|
|
@@ -478,12 +532,12 @@ def task_list():
|
|
|
478
532
|
def webcli_test():
|
|
479
533
|
endpoints = []
|
|
480
534
|
cmd = ['conf', 'webui']
|
|
481
|
-
out = execute(cmd, tout=TIMEOUT_SEC)
|
|
535
|
+
out = CLIENT.execute(cmd, tout=TIMEOUT_SEC)
|
|
482
536
|
state, output = out[0], out[1]
|
|
483
537
|
if state:
|
|
484
538
|
verdict = f"[ST] WEBUI IS ENABLED ({output})" if output.strip() == 'True' else f"[ST] WEBUI IS DISABLED ({output})"
|
|
485
539
|
if output.strip() == 'True':
|
|
486
|
-
out = execute(['conf', 'devip'], tout=TIMEOUT_SEC)
|
|
540
|
+
out = CLIENT.execute(['conf', 'devip'], tout=TIMEOUT_SEC)
|
|
487
541
|
if out[0] and out[1] is not None:
|
|
488
542
|
devip = out[1]
|
|
489
543
|
endpoints.append(f'http://{devip}')
|
|
@@ -491,27 +545,35 @@ def webcli_test():
|
|
|
491
545
|
|
|
492
546
|
for endpoint in endpoints:
|
|
493
547
|
_start_t = time.time()
|
|
548
|
+
delta_t = -1
|
|
494
549
|
try:
|
|
495
550
|
response = requests.get(endpoint, timeout=5)
|
|
551
|
+
delta_t = round(time.time() - _start_t, 2)
|
|
496
552
|
# Check if the request was successful
|
|
497
553
|
if not (response.status_code == 200 and ('<!DOCTYPE html>' in str(response.content) or '"micrOS"' in str(response.content))):
|
|
498
|
-
verdict += f" Endpoint: {endpoint} [{Colors.ERR}NOK{Colors.NC}]({
|
|
554
|
+
verdict += f" Endpoint: {endpoint} [{Colors.ERR}NOK{Colors.NC}]({delta_t}s)"
|
|
499
555
|
print(response.content)
|
|
500
556
|
state = False
|
|
501
557
|
else:
|
|
502
|
-
verdict += f" Endpoint: {endpoint} [{Colors.OK}OK{Colors.NC}]({
|
|
558
|
+
verdict += f" Endpoint: {endpoint} [{Colors.OK}OK{Colors.NC}]({delta_t}s)"
|
|
559
|
+
|
|
560
|
+
metrics_name = 'landingpage' if "." in endpoint.split('/')[-1] else endpoint.split('/')[-1]
|
|
561
|
+
_add_metrics(f"web_{metrics_name}_response_ms", int(delta_t*1000))
|
|
503
562
|
except Exception as e:
|
|
504
|
-
verdict += f" Endpoint: {endpoint} [{Colors.ERR}NOK{Colors.NC}]({
|
|
563
|
+
verdict += f" Endpoint: {endpoint} [{Colors.ERR}NOK{Colors.NC}]({delta_t}s)"
|
|
505
564
|
print(f"webcli_test error: {e}")
|
|
506
565
|
state = False
|
|
507
566
|
return state, verdict
|
|
508
567
|
return state, output
|
|
509
568
|
|
|
569
|
+
#####################################
|
|
570
|
+
# HELPERS #
|
|
571
|
+
#####################################
|
|
510
572
|
|
|
511
573
|
def after_st_reboot():
|
|
512
574
|
verdict = False, 'reboot -h failed'
|
|
513
575
|
cmd = ['reboot -h']
|
|
514
|
-
out = execute(cmd, tout=TIMEOUT_SEC)
|
|
576
|
+
out = CLIENT.execute(cmd, tout=TIMEOUT_SEC)
|
|
515
577
|
state, output = out[0], out[1]
|
|
516
578
|
if state:
|
|
517
579
|
verdict = state, f'[reboot-h] commad out: {output}'
|
|
@@ -519,7 +581,7 @@ def after_st_reboot():
|
|
|
519
581
|
print(f"[reboot-h] Wait for node up again ({retry}/{retry*2}sec)")
|
|
520
582
|
time.sleep(2)
|
|
521
583
|
try:
|
|
522
|
-
up, o = execute(['hello'], tout=TIMEOUT_SEC)
|
|
584
|
+
up, o = CLIENT.execute(['hello'], tout=TIMEOUT_SEC)
|
|
523
585
|
if up:
|
|
524
586
|
verdict = True, f"[reboot-h][OK] successfully rebooted: {o} (boot time: ~{retry * 2}sec)"
|
|
525
587
|
print(verdict[1])
|
|
@@ -532,19 +594,37 @@ def after_st_reboot():
|
|
|
532
594
|
|
|
533
595
|
def get_dev_version():
|
|
534
596
|
cmd = ['version']
|
|
535
|
-
out = execute(cmd, tout=TIMEOUT_SEC)
|
|
597
|
+
out = CLIENT.execute(cmd, tout=TIMEOUT_SEC)
|
|
536
598
|
state, output = out[0], out[1]
|
|
599
|
+
_add_metrics("version", output)
|
|
537
600
|
if state:
|
|
538
601
|
return output
|
|
539
602
|
return '0.0.0-0'
|
|
540
603
|
|
|
604
|
+
def get_dev_board_type():
|
|
605
|
+
cmd = ['system info >json']
|
|
606
|
+
out = CLIENT.execute(cmd, tout=TIMEOUT_SEC)
|
|
607
|
+
state, output = out[0], out[1]
|
|
608
|
+
output = ast.literal_eval(output)
|
|
609
|
+
board = output.get("board")
|
|
610
|
+
upython = output.get("upython")
|
|
611
|
+
_add_metrics("board_type", board)
|
|
612
|
+
_add_metrics("micropython_version", str(upython))
|
|
613
|
+
if state:
|
|
614
|
+
return board, upython
|
|
615
|
+
return None, None
|
|
616
|
+
|
|
617
|
+
#####################################
|
|
618
|
+
# MAIN APP #
|
|
619
|
+
#####################################
|
|
620
|
+
|
|
541
621
|
def app(devfid=None, pwd=None):
|
|
542
|
-
global
|
|
543
|
-
|
|
544
|
-
DEVICE = devfid
|
|
545
|
-
if pwd is not None:
|
|
546
|
-
PASSWD = pwd
|
|
622
|
+
global CLIENT
|
|
623
|
+
CLIENT = AppBase(device=devfid, password=pwd)
|
|
547
624
|
|
|
625
|
+
# Get device info
|
|
626
|
+
version = get_dev_version()
|
|
627
|
+
get_dev_board_type() # update metrics
|
|
548
628
|
# Get test verdict
|
|
549
629
|
verdict = {'single_cmds': single_cmd_exec_check(),
|
|
550
630
|
'shell_cmds': shell_cmds_check(),
|
|
@@ -558,7 +638,7 @@ def app(devfid=None, pwd=None):
|
|
|
558
638
|
'json_check': json_format_check(),
|
|
559
639
|
'response_time': measure_package_response_time(),
|
|
560
640
|
'negative_api': negative_interface_check(),
|
|
561
|
-
'dhcp_hostname': check_device_by_hostname(
|
|
641
|
+
'dhcp_hostname': check_device_by_hostname(CLIENT.get_device()),
|
|
562
642
|
'lm_exception': check_robustness_exception(),
|
|
563
643
|
'mem_usage': memory_usage(),
|
|
564
644
|
'disk_usage': disk_usage(),
|
|
@@ -575,8 +655,8 @@ def app(devfid=None, pwd=None):
|
|
|
575
655
|
# Test Evaluation
|
|
576
656
|
final_state = True
|
|
577
657
|
ok_cnt = 0
|
|
578
|
-
|
|
579
|
-
print(f"\n----------------------------------- micrOS System Test results on {
|
|
658
|
+
create_report(CLIENT.get_device(), METRICS)
|
|
659
|
+
print(f"\n----------------------------------- micrOS System Test results on {CLIENT.get_device()}:{version} device -----------------------------------")
|
|
580
660
|
print("\tTEST NAME\t\tSTATE\t\tDescription\n")
|
|
581
661
|
for test, state_data in verdict.items():
|
|
582
662
|
state = Colors.ERR + 'NOK' + Colors.NC
|
|
@@ -596,11 +676,5 @@ def app(devfid=None, pwd=None):
|
|
|
596
676
|
oled_msg_end_result(f"System[{state}] {pass_rate}")
|
|
597
677
|
|
|
598
678
|
|
|
599
|
-
def execute(cmd_list, tout=5):
|
|
600
|
-
cmd_args = base_cmd() + cmd_list
|
|
601
|
-
print("[ST] test cmd: {}".format(cmd_args))
|
|
602
|
-
return socketClient.run(cmd_args, timeout=tout)
|
|
603
|
-
|
|
604
|
-
|
|
605
679
|
if __name__ == "__main__":
|
|
606
680
|
app()
|
|
@@ -2,28 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
import sys
|
|
5
|
-
import time
|
|
6
5
|
MYPATH = os.path.dirname(os.path.abspath(__file__))
|
|
7
|
-
sys.path.append(os.path.dirname(MYPATH))
|
|
8
|
-
import socketClient
|
|
9
6
|
sys.path.append(os.path.join(MYPATH, '../lib/'))
|
|
10
7
|
from TerminalColors import Colors
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def base_cmd():
|
|
17
|
-
if PASSWD is None:
|
|
18
|
-
return ['--dev', DEVICE]
|
|
19
|
-
return ['--dev', DEVICE, '--password', PASSWD]
|
|
20
|
-
|
|
21
|
-
def run_command(cmd):
|
|
22
|
-
# EDIT YOUR COMMAND
|
|
23
|
-
args = base_cmd() + cmd
|
|
24
|
-
status, answer = socketClient.run(args)
|
|
25
|
-
return status, answer
|
|
9
|
+
try:
|
|
10
|
+
from ._app_base import AppBase
|
|
11
|
+
except:
|
|
12
|
+
from _app_base import AppBase
|
|
26
13
|
|
|
14
|
+
CLIENT = None
|
|
27
15
|
|
|
28
16
|
def app(devfid=None, pwd=None):
|
|
29
17
|
"""
|
|
@@ -31,13 +19,13 @@ def app(devfid=None, pwd=None):
|
|
|
31
19
|
send command(s) over socket connection [socketClient.run(args)]
|
|
32
20
|
list load module commands and send in single connection
|
|
33
21
|
"""
|
|
34
|
-
global
|
|
35
|
-
|
|
36
|
-
DEVICE = devfid
|
|
37
|
-
if pwd is not None:
|
|
38
|
-
PASSWD = pwd
|
|
22
|
+
global CLIENT
|
|
23
|
+
CLIENT = AppBase(device=devfid, password=pwd)
|
|
39
24
|
|
|
40
|
-
|
|
25
|
+
output = CLIENT.execute(['help', 'version'])
|
|
26
|
+
status = output[0]
|
|
27
|
+
result = output[1]
|
|
28
|
+
print(f"{Colors.WARN}[{status}]{Colors.NC} {result}")
|
|
41
29
|
|
|
42
30
|
|
|
43
31
|
if __name__ == "__main__":
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#####################################
|
|
2
|
+
# APP CONFIG #
|
|
3
|
+
#####################################
|
|
4
|
+
import os, sys
|
|
5
|
+
MYPATH = os.path.dirname(os.path.abspath(__file__))
|
|
6
|
+
sys.path.append(os.path.dirname(MYPATH))
|
|
7
|
+
import socketClient
|
|
8
|
+
|
|
9
|
+
class AppBase:
|
|
10
|
+
|
|
11
|
+
def __init__(self, device:str, password:str):
|
|
12
|
+
self.device = device
|
|
13
|
+
self.password = password
|
|
14
|
+
|
|
15
|
+
def base_cmd(self) -> list:
|
|
16
|
+
if self.password is None:
|
|
17
|
+
return ['--dev', self.device]
|
|
18
|
+
return ['--dev', self.device, '--password', self.password]
|
|
19
|
+
|
|
20
|
+
def get_device(self):
|
|
21
|
+
return self.device
|
|
22
|
+
|
|
23
|
+
def execute(self, cmd_list, tout=5):
|
|
24
|
+
cmd_args = self.base_cmd() + cmd_list
|
|
25
|
+
print(f"Execute: {cmd_args}")
|
|
26
|
+
return socketClient.run(cmd_args, timeout=tout)
|
|
27
|
+
|
|
28
|
+
def run(self, cmd_list):
|
|
29
|
+
"""Legacy"""
|
|
30
|
+
out = self.execute(cmd_list)
|
|
31
|
+
return out[0], out[1]
|
|
32
|
+
|
|
33
|
+
def connection_metrics(self):
|
|
34
|
+
return socketClient.connection_metrics(f"{self.device}.local")
|