Skip to content

Commit 97a8e76

Browse files
authored
Support mocha test case on IoT Linux devices. (#143)
1 parent 392ce9f commit 97a8e76

File tree

2 files changed

+221
-0
lines changed

2 files changed

+221
-0
lines changed

testkitlite/engines/mocha.py

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#!/usr/bin/python
2+
#
3+
# Copyright (C) 2012 Intel Corporation
4+
#
5+
# This program is free software; you can redistribute it and/or
6+
# modify it under the terms of the GNU General Public License
7+
# as published by the Free Software Foundation; either version 2
8+
# of the License, or (at your option) any later version.
9+
#
10+
# This program is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU General Public License for more details.
14+
#
15+
# Authors:
16+
# Bruce Dai <feng.dai@intel.com>
17+
""" The implementation of mocha test engine"""
18+
19+
import commands
20+
import os
21+
import time
22+
import sys
23+
import threading
24+
import uuid
25+
from testkitlite.util.log import LOGGER
26+
from testkitlite.util.result import TestSetResut
27+
from testkitlite.util import tr_utils
28+
import subprocess
29+
30+
STR_PASS = 'PASS'
31+
STR_FAIL = 'FAIL'
32+
STR_BLOCK = 'BLOCK'
33+
DEFAULT_TIMEOUT = 90
34+
35+
def _mocha_test_exec(test_session, cases, result_obj, session_dir):
36+
"""function for running mocha tests"""
37+
result_obj.set_status(0)
38+
result_list = []
39+
for i_case in cases['cases']:
40+
i_case_timeout = i_case.get('timeout', DEFAULT_TIMEOUT)
41+
42+
try:
43+
case_entry = i_case['entry']
44+
status, output = commands.getstatusoutput("ssh %s 'ls %s'" % (os.environ["DEVICE_ID"], case_entry))
45+
if status != 0:
46+
i_case['result'] = STR_BLOCK
47+
i_case['stdout'] = "[Message]No such file or dirctory: %s" % case_entry
48+
result_list.append(i_case)
49+
continue
50+
51+
case_id = i_case['case_id']
52+
tmp_result_dir = "%s/json_results" % session_dir
53+
os.makedirs(tmp_result_dir)
54+
popen_args = "ssh %s 'mocha %s --reporter json' > %s/%s.json" % (os.environ["DEVICE_ID"], case_entry, tmp_result_dir, case_id)
55+
i_case_proc = subprocess.Popen(args=popen_args, shell=True)
56+
i_case_pre_time = time.time()
57+
while True:
58+
i_case_exit_code = i_case_proc.poll()
59+
i_case_elapsed_time = time.time() - i_case_pre_time
60+
if i_case_exit_code == None:
61+
if i_case_elapsed_time >= i_case_timeout:
62+
tr_utils.KillAllProcesses(ppid=i_case_proc.pid)
63+
i_case['result'] = STR_BLOCK
64+
i_case['stdout'] = "[Message]Timeout"
65+
LOGGER.debug("Run %s timeout" % case_id)
66+
break
67+
else:
68+
i_case['result'] = STR_FAIL
69+
i_case['stdout'] = tmp_result_dir
70+
break
71+
time.sleep(1)
72+
except Exception, e:
73+
i_case['result'] = STR_BLOCK
74+
i_case['stdout'] = "[Message]%s" % e
75+
LOGGER.error(
76+
"Run %s: failed: %s, exit from executer" % (case_id, e))
77+
result_list.append(i_case)
78+
result_obj.extend_result(result_list)
79+
result_obj.set_status(1)
80+
81+
82+
class TestWorker(object):
83+
84+
"""Test executor for testkit-lite"""
85+
86+
def __init__(self, conn):
87+
super(TestWorker, self).__init__()
88+
self.conn = conn
89+
self.server_url = None
90+
self.result_obj = None
91+
self.session_dir = None
92+
self.opts = dict({'block_size': 300,
93+
'test_type': None,
94+
'auto_iu': False,
95+
'fuzzy_match': False,
96+
'self_exec': False,
97+
'self_repeat': False,
98+
'debug_mode': False
99+
})
100+
101+
def init_test(self, params):
102+
"""init the test envrionment"""
103+
self.session_dir =params.get('session_dir', '')
104+
self.opts['testset_name'] = params.get('testset-name', '')
105+
self.opts['testsuite_name'] = params.get('testsuite-name', '')
106+
self.opts['debug_log_base'] = params.get("debug-log-base", '')
107+
return str(uuid.uuid1())
108+
109+
def run_test(self, sessionid, test_set):
110+
"""
111+
process the execution for a test set
112+
"""
113+
if sessionid is None:
114+
return False
115+
disabledlog = os.environ.get("disabledlog","")
116+
# start debug trace thread
117+
if len(disabledlog) > 0 :
118+
pass
119+
else:
120+
self.conn.start_debug(self.opts['debug_log_base'])
121+
time.sleep(1)
122+
self.result_obj = TestSetResut(
123+
self.opts['testsuite_name'], self.opts['testset_name'])
124+
self.opts['async_th'] = threading.Thread(
125+
target=_mocha_test_exec,
126+
args=(sessionid, test_set, self.result_obj, self.session_dir)
127+
)
128+
129+
self.opts['async_th'].start()
130+
return True
131+
132+
def get_test_status(self, sessionid):
133+
"""poll the test task status"""
134+
if sessionid is None:
135+
return None
136+
result = {}
137+
result["msg"] = []
138+
result["finished"] = str(self.result_obj.get_status())
139+
return result
140+
141+
def get_test_result(self, sessionid):
142+
"""get the test result for a test set """
143+
result = {}
144+
if sessionid is None:
145+
return result
146+
147+
result = self.result_obj.get_result()
148+
return result
149+
150+
def finalize_test(self, sessionid):
151+
"""clear the test stub and related resources"""
152+
if sessionid is None:
153+
return False
154+
155+
if self.result_obj is not None:
156+
self.result_obj.set_status(1)
157+
158+
# stop debug thread
159+
self.conn.stop_debug()
160+
161+
return True

testkitlite/util/session.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
from testkitlite.util.result import TestSetResut
4343
import subprocess
4444
import glob
45+
import json
4546

4647
if platform.system().startswith("Linux"):
4748
import fcntl
@@ -110,6 +111,7 @@ def __init__(self, connector, worker):
110111
self.bdd_test_files = []
111112
self.xcunit_test_files = []
112113
self.iosuiauto_test_files = []
114+
self.mocha_test_files = []
113115
self.testresult_dict = {"pass": 0, "fail": 0,
114116
"block": 0, "not_run": 0}
115117
self.current_test_xml = "none"
@@ -397,6 +399,15 @@ def run_case(self, latest_dir):
397399
else:
398400
self.testworker = TestWorker(self.connector)
399401
self.__run_with_worker(self.iosuiauto_test_files)
402+
if len(self.mocha_test_files) > 0:
403+
try:
404+
exec "from testkitlite.engines.mocha import TestWorker"
405+
LOGGER.info("TestWorker is mocha")
406+
except Exception as error:
407+
raise TestEngineException("mocha")
408+
else:
409+
self.testworker = TestWorker(self.connector)
410+
self.__run_with_worker(self.mocha_test_files)
400411

401412
def __run_with_worker(self, test_xml_set_list):
402413
try:
@@ -465,6 +476,7 @@ def __split_xml_to_set(self, webapi_file):
465476
bdd_test_set_list = []
466477
xcunit_set_list = []
467478
iosuiauto_set_list = []
479+
mocha_set_list = []
468480
auto_webdriver_flag = self.is_webdriver and webapi_file.split('.')[-3] == 'auto'
469481
if len(test_xml_set_list) > 1:
470482
test_xml_set_list.reverse()
@@ -508,6 +520,8 @@ def __split_xml_to_set(self, webapi_file):
508520
xcunit_set_list.append(test_xml_set)
509521
elif set_type == "iosuiauto":
510522
iosuiauto_set_list.append(test_xml_set)
523+
elif set_type == "mocha":
524+
mocha_set_list.append(test_xml_set)
511525

512526
set_keep_number += 1
513527
set_number -= 1
@@ -537,6 +551,8 @@ def __split_xml_to_set(self, webapi_file):
537551
self.xcunit_test_files.extend(xcunit_set_list)
538552
iosuiauto_set_list.reverse()
539553
self.iosuiauto_test_files.extend(iosuiauto_set_list)
554+
mocha_set_list.reverse()
555+
self.mocha_test_files.extend(mocha_set_list)
540556

541557
def lock(self, fl):
542558
try:
@@ -1013,6 +1029,8 @@ def __prepare_external_test_json(self, resultfile):
10131029
value = 'xcunit'
10141030
elif parameters['type'] == 'iosuiauto' :
10151031
value = 'iosuiauto'
1032+
elif parameters['type'] == 'mocha' :
1033+
value = 'mocha'
10161034
elif parameters['type'] == 'qunit':
10171035
value = 'default'
10181036
if value != None:
@@ -1437,6 +1455,46 @@ def write_file_result(set_result_xml, set_result, debug_log_file):
14371455
LOGGER.error(
14381456
"[ Error: fail to write cases result, error: %s ]\n" % error)
14391457

1458+
def __expand_subcases_mocha(tset, tcase, sub_num, result_msg):
1459+
sub_case_index = 1
1460+
1461+
if os.path.isdir(result_msg):
1462+
case_id = tcase.get("id")
1463+
case_purpose = tcase.get("purpose")
1464+
result_json_file = "%s/%s.json" % (result_msg, case_id)
1465+
with open(result_json_file) as js_handle:
1466+
result_content = json.load(js_handle)
1467+
for sub_test_details in result_content['tests']:
1468+
sub_case = copy.deepcopy(tcase)
1469+
sub_case.set("id", "/".join([case_id, str(sub_case_index)]))
1470+
sub_case.set("purpose", "/".join([case_purpose, sub_test_details['fullTitle']]))
1471+
sub_case.remove(sub_case.find("./result_info"))
1472+
result_info = etree.SubElement(sub_case, "result_info")
1473+
actual_result = etree.SubElement(result_info, "actual_result")
1474+
stdout = etree.SubElement(result_info, "stdout")
1475+
if len(sub_test_details['err']) == 0:
1476+
actual_result.text = 'PASS'
1477+
else:
1478+
actual_result.text = 'FAIL'
1479+
stderr = etree.SubElement(result_info, "stderr")
1480+
stderr.text = "%s" % sub_test_details['err']['stack']
1481+
sub_case.set("result", actual_result.text)
1482+
sub_case_index += 1
1483+
tset.append(sub_case)
1484+
for block_case_index in range(sub_case_index, sub_num + 1):
1485+
sub_case = copy.deepcopy(tcase)
1486+
sub_case.set("id", "/".join([case_id, str(block_case_index)]))
1487+
sub_case.set("purpose", "/".join([case_purpose, str(block_case_index)]))
1488+
sub_case.remove(sub_case.find("./result_info"))
1489+
result_info = etree.SubElement(sub_case, "result_info")
1490+
actual_result = etree.SubElement(result_info, "actual_result")
1491+
actual_result.text = 'BLOCK'
1492+
sub_case.set("result", actual_result.text)
1493+
stdout = etree.SubElement(result_info, "stdout")
1494+
stdout.text = "None result of this sub test case, please check the test case or \"subcase\" number."
1495+
block_case_index += 1
1496+
tset.append(sub_case)
1497+
tset.remove(tcase)
14401498

14411499
def __expand_subcases_bdd(tset, tcase, sub_num, result_msg):
14421500
sub_case_index = 1
@@ -1732,6 +1790,8 @@ def __write_by_caseid(tset, case_results):
17321790
else:
17331791
if tset.get('type') == 'nodeunit':
17341792
__expand_subcases_nodeunit(tset, tcase, sub_num, result_msg)
1793+
elif tset.get('type') == 'mocha':
1794+
__expand_subcases_mocha(tset, tcase, sub_num, result_msg)
17351795
else:
17361796
__expand_subcases(tset, tcase, sub_num, result_msg)
17371797

0 commit comments

Comments
 (0)