diff --git a/examples/app_info/BUILD.gn b/examples/app_info/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..f19459b2349b6ca16af96de19ac4740db2f0a959 --- /dev/null +++ b/examples/app_info/BUILD.gn @@ -0,0 +1,27 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +############################################################################### +config("app_info_config") { + visibility = [ ":*" ] + include_dirs = [ "include" ] +} + +ohos_shared_library("app_info") { + sources = [] + public_configs = [ ":app_info_config" ] + subsystem_name = "subsystem_examples" +} +############################################################################### diff --git a/examples/app_info/test/BUILD.gn b/examples/app_info/test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3f38132198b65c7429d0d2b5038a71d1c59149d0 --- /dev/null +++ b/examples/app_info/test/BUILD.gn @@ -0,0 +1,23 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") + +#################################group######################################### +group("unittest") { + testonly = true + deps = [] + + deps += [ "unittest/common/get_app_info:unittest" ] +} +############################################################################### diff --git a/examples/app_info/test/unittest/common/get_app_info/BUILD.gn b/examples/app_info/test/unittest/common/get_app_info/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..2b4c186b21cc52c216cdb00da17e8d4d088f08af --- /dev/null +++ b/examples/app_info/test/unittest/common/get_app_info/BUILD.gn @@ -0,0 +1,28 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") + +module_output_path = "subsystem_examples/app_info" + +ohos_js_unittest("GetAppInfoJsTest") { + module_out_path = module_output_path + + hap_profile = "./config.json" + certificate_profile = "//test/developertest/signature/openharmony_sx.p7b" +} + +group("unittest") { + testonly = true + deps = [ ":GetAppInfoJsTest" ] +} diff --git a/examples/app_info/test/unittest/common/get_app_info/ExampleJsunit.test.js b/examples/app_info/test/unittest/common/get_app_info/ExampleJsunit.test.js new file mode 100644 index 0000000000000000000000000000000000000000..26e84e5f71805e789a93f89d96179a334c071432 --- /dev/null +++ b/examples/app_info/test/unittest/common/get_app_info/ExampleJsunit.test.js @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import app from '@system.app' + +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from 'deccjsunit/index' + +describe("AppInfoTest", function () { + beforeAll(function() { + /* + * @tc.setup: setup invoked before all testcases + */ + console.info('beforeAll caled') + }) + + afterAll(function() { + /* + * @tc.teardown: teardown invoked after all testcases + */ + console.info('afterAll caled') + }) + + beforeEach(function() { + /* + * @tc.setup: setup invoked before each testcases + */ + console.info('beforeEach caled') + }) + + afterEach(function() { + /* + * @tc.teardown: teardown invoked after each testcases + */ + console.info('afterEach caled') + }) + + /* + * @tc.name:appInfoTest001 + * @tc.desc:verify app info is not null + * @tc.author:renxiang + */ + it("appInfoTest001", 0, function () { + var info = app.getInfo() + expect(info != null).assertEqual(true) + }) + + /* + * @tc.name:appInfoTest002 + * @tc.desc:verify app info name and code + * @tc.author:renxiang + */ + it("appInfoTest002", 0, function () { + var info = app.getInfo() + expect(info.versionName).assertEqual('') + expect(info.versionCode).assertEqual('0') + }) + +}) diff --git a/examples/app_info/test/unittest/common/get_app_info/config.json b/examples/app_info/test/unittest/common/get_app_info/config.json new file mode 100644 index 0000000000000000000000000000000000000000..9889c145cf45093c6b938d34bb050c555653f09e --- /dev/null +++ b/examples/app_info/test/unittest/common/get_app_info/config.json @@ -0,0 +1,59 @@ +{ + "app": { + "bundleName": "com.example.myapplication", + "vendor": "example", + "version": { + "code": 1, + "name": "1.0" + }, + "apiVersion": { + "compatible": 4, + "target": 5 + } + }, + "deviceConfig": {}, + "module": { + "package": "com.example.myapplication", + "name": ".MyApplication", + "deviceType": [ + "phone" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry", + "moduleType": "entry" + }, + "abilities": [ + { + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "name": "com.example.myapplication.MainAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "MyApplication", + "type": "page", + "launchType": "standard" + } + ], + "js": [ + { + "pages": [ + "pages/index/index" + ], + "name": "default", + "window": { + "designWidth": 720, + "autoDesignWidth": false + } + } + ] + } +} diff --git a/examples/ohos.build b/examples/ohos.build index ba3c3da48f4615e2475007e2da2f073c7286d5e9..8bea01699242c13464bc91aca3d9b2561e44603b 100755 --- a/examples/ohos.build +++ b/examples/ohos.build @@ -3,11 +3,13 @@ "parts": { "subsystem_examples": { "module_list": [ + "//test/developertest/examples/app_info:app_info", "//test/developertest/examples/detector:detector", "//test/developertest/examples/calculator:calculator", "//test/developertest/examples/calculator:calculator_static" ], "test_list": [ + "//test/developertest/examples/app_info/test:unittest", "//test/developertest/examples/calculator/test:unittest", "//test/developertest/examples/calculator/test:fuzztest", "//test/developertest/examples/detector/test:unittest", diff --git a/libs/js_template/src/main/js/default/app.js b/libs/js_template/src/main/js/default/app.js new file mode 100644 index 0000000000000000000000000000000000000000..83cc355c87c42fd4f00b239657d2c081cf0e9aa0 --- /dev/null +++ b/libs/js_template/src/main/js/default/app.js @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import device from '@system.device'; + +export default { + onCreate() { + console.info('AceApplication onCreate'); + }, + onDestroy() { + console.info('AceApplication onDestroy'); + } +}; diff --git a/libs/js_template/src/main/js/default/i18n/en-US.json b/libs/js_template/src/main/js/default/i18n/en-US.json new file mode 100644 index 0000000000000000000000000000000000000000..e63c70d978a3a53be988388c87182f81785e170c --- /dev/null +++ b/libs/js_template/src/main/js/default/i18n/en-US.json @@ -0,0 +1,6 @@ +{ + "strings": { + "hello": "Hello", + "world": "World" + } +} \ No newline at end of file diff --git a/libs/js_template/src/main/js/default/i18n/zh-CN.json b/libs/js_template/src/main/js/default/i18n/zh-CN.json new file mode 100644 index 0000000000000000000000000000000000000000..de6ee5748322f44942c1b003319d8e66c837675f --- /dev/null +++ b/libs/js_template/src/main/js/default/i18n/zh-CN.json @@ -0,0 +1,6 @@ +{ + "strings": { + "hello": "您好", + "world": "世界" + } +} \ No newline at end of file diff --git a/libs/js_template/src/main/js/default/pages/index/index.css b/libs/js_template/src/main/js/default/pages/index/index.css new file mode 100644 index 0000000000000000000000000000000000000000..a6053c61f9615fcd50fefb51f878568f3e39e59b --- /dev/null +++ b/libs/js_template/src/main/js/default/pages/index/index.css @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + left: 0px; + top: 0px; + width: 100%; + height: 100%; +} + +.title { + font-size: 60px; + text-align: center; + width: 100%; + height: 40%; + margin: 10px; +} +.btn { + width: 50%; + height: 100px; + font-size: 40px; +} diff --git a/libs/js_template/src/main/js/default/pages/index/index.hml b/libs/js_template/src/main/js/default/pages/index/index.hml new file mode 100644 index 0000000000000000000000000000000000000000..6069a046a35c4409ab85e4595a079a1670a9c7fe --- /dev/null +++ b/libs/js_template/src/main/js/default/pages/index/index.hml @@ -0,0 +1,21 @@ + + +
+ + {{ $t('strings.hello') }} {{title}} + + +
diff --git a/libs/js_template/src/main/js/default/pages/index/index.js b/libs/js_template/src/main/js/default/pages/index/index.js new file mode 100644 index 0000000000000000000000000000000000000000..37d3d82171002a3214286dc10315e4baef40f4e6 --- /dev/null +++ b/libs/js_template/src/main/js/default/pages/index/index.js @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import app from '@system.app' + +import {Core, ExpectExtend} from 'deccjsunit/index' + +export default { + data: { + title: "" + }, + onInit() { + this.title = this.$t('strings.world'); + }, + onShow() { + console.info('onShow finish') + const core = Core.getInstance() + const expectExtend = new ExpectExtend({ + 'id': 'extend' + }) + + core.addService('expect', expectExtend) + core.init() + + const configService = core.getDefaultService('config') + configService.setConfig(this) + + require('../../test/List.test') + core.execute() + }, + onReady() { + }, +} diff --git a/libs/js_template/src/main/js/default/test/List.test.js b/libs/js_template/src/main/js/default/test/List.test.js new file mode 100644 index 0000000000000000000000000000000000000000..b12d92d99666f2c83ecc116a470dc2f4fa1d10c2 --- /dev/null +++ b/libs/js_template/src/main/js/default/test/List.test.js @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/libs/js_template/src/main/resources/base/element/string.json b/libs/js_template/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..76e501f214f84c96a44d08973dbbdeab8515e1de --- /dev/null +++ b/libs/js_template/src/main/resources/base/element/string.json @@ -0,0 +1,12 @@ +{ + "string": [ + { + "name": "app_name", + "value": "JsHelloWorld" + }, + { + "name": "mainability_description", + "value": "hap sample empty page" + } + ] +} \ No newline at end of file diff --git a/libs/js_template/src/main/resources/base/media/icon.png b/libs/js_template/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/libs/js_template/src/main/resources/base/media/icon.png differ diff --git a/signature/openharmony_sx.p7b b/signature/openharmony_sx.p7b new file mode 100644 index 0000000000000000000000000000000000000000..9be1e98fa4c0c28ca997ed660112fa16b194f0f5 Binary files /dev/null and b/signature/openharmony_sx.p7b differ diff --git a/src/core/build/build_manager.py b/src/core/build/build_manager.py index 04192552db515ea9ddcebde43edbc03a55da48e4..839da9aa799b7aad39175a2124dddf88db16cc92 100755 --- a/src/core/build/build_manager.py +++ b/src/core/build/build_manager.py @@ -21,6 +21,7 @@ from xdevice import platform_logger from core.utils import scan_support_product from core.config.config_manager import UserConfigManager from core.build.select_targets import SelectTargets +from core.build.pretreat_targets import PretreatTargets from core.build.build_testcases import BuildTestcases from core.command.gen import Gen @@ -95,6 +96,7 @@ class BuildManager(object): LOG.warning("No build target found.") return False + PretreatTargets(target_list).pretreat_targets_from_list() build_cfg_filepath = os.path.join(project_root_path, "test", "developertest", @@ -111,6 +113,7 @@ class BuildManager(object): para.productform, "make_temp_test") self._make_gn_file(build_cfg_filepath, []) + PretreatTargets(target_list).disassemble_targets_from_list() return build_result diff --git a/src/core/build/pretreat_targets.py b/src/core/build/pretreat_targets.py new file mode 100644 index 0000000000000000000000000000000000000000..bc6e9dc7cfb1da9b245ff94c2b5af943cbd600ce --- /dev/null +++ b/src/core/build/pretreat_targets.py @@ -0,0 +1,282 @@ +#!/usr/bin/env python3 +# coding=utf-8 + +# +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import os +import sys +import json +import shutil + +from core.constants import JsTestConst +from xdevice import platform_logger + +LOG = platform_logger("PretreatTargets") + + +############################################################################## +############################################################################## + +class PretreatTargets(object): + def __init__(self, target_list): + self.target_list = target_list + + def pretreat_targets_from_list(self): + path_list, name_list = self.parse_target_info() + self.pretreat_by_target_name(path_list, name_list) + + def disassemble_targets_from_list(self): + path_list, name_list = self.parse_target_info() + self.disassemble_by_target_name(path_list, name_list) + + def parse_target_info(self): + path_list = [] + name_list = [] + + for line in self.target_list: + path = line.split(':')[0][2:] + name = line.split(':')[1].split('(')[0] + path_list.append(path) + name_list.append(name) + + LOG.info("path_list: %s" % path_list) + LOG.info("name_list: %s" % name_list) + return path_list, name_list + + def pretreat_by_target_name(self, path_list, name_list): + for name, path in zip(name_list, path_list): + LOG.info("name: %s path: %s" % (name, path)) + if name.endswith("JsTest"): + self.pretreat_js_target(path, name) + LOG.info("js test pretreat success") + + def pretreat_js_target(self, path, name): + template_path = os.path.join(sys.framework_root_dir, "libs", + "js_template", "src") + target_path = os.path.join(sys.source_code_root_path, path) + config_path = os.path.join(target_path, "config.json") + gn_path = os.path.join(target_path, "BUILD.gn") + gn_bak_path = os.path.join(target_path, "BuildBak") + test_path = os.path.join(target_path, "src", "main", "js", + "default", "test") + if not os.path.exists(config_path): + LOG.error("js test needs config.json file") + return + if not os.path.exists(gn_path): + LOG.error("js test needs BUILD.gn file") + return + LOG.info("template_path: %s" % template_path) + LOG.info("target_path: %s" % target_path) + + #modify BUILD.gn file to compile hap + output_path = self.parse_output_path_in_gn(gn_path) + if output_path == "": + LOG.error(" BUILD.gn needs 'module_output_path'") + return + os.rename(gn_path, gn_bak_path) + template_args = {'output_path': output_path, 'suite_name': name} + with open(gn_path, 'w') as filehandle: + filehandle.write(JsTestConst.BUILD_GN_FILE_TEMPLATE % + template_args) + + #copy js hap template to target path + shutil.copytree(template_path, os.path.join(target_path, "src")) + shutil.copy(config_path, os.path.join(target_path, "src", "main")) + file_name = os.listdir(target_path) + for file in file_name: + LOG.info("file: %s" % file) + if file.endswith(".js"): + shutil.copy(os.path.join(target_path, file), test_path) + with open(os.path.join(test_path, "List.test.js"), 'a') \ + as list_data: + list_data.write("require('./%s')" % file) + + def parse_output_path_in_gn(self, gn_path): + output_path = "" + with open(gn_path, 'r') as gn_file: + for line in gn_file.readlines(): + if line.startswith("module_output_path"): + LOG.info("output path: %s" % line.split()[2].strip('"')) + output_path = line.split()[2].strip('"') + break + return output_path + + def disassemble_by_target_name(self, path_list, name_list): + for name, path in zip(name_list, path_list): + LOG.info("name: %s path: %s" % (name, path)) + if name.endswith("JsTest"): + self.disassemble_js_target(path, name) + LOG.info("js test disassemble success") + + def disassemble_js_target(self, path, name): + target_path = os.path.join(sys.source_code_root_path, path) + src_path = os.path.join(target_path, "src") + gn_path = os.path.join(target_path, "BUILD.gn") + gn_bak_path = os.path.join(target_path, "BuildBak") + + if os.path.exists(src_path): + shutil.rmtree(src_path) + if os.path.exists(gn_path) and os.path.exists(gn_bak_path): + os.remove(gn_path) + os.rename(gn_bak_path, gn_path) + + + @classmethod + def _get_mlf_data_from_file(cls, filepath): + data_list = [] + if os.path.exists(filepath): + with open(filepath, 'r') as mlf_file: + data_list = json.load(mlf_file) + if not data_list: + LOG.warning("The %s file load error." % filepath) + data_list = [] + return data_list + + @classmethod + def _get_part_path_data(cls, productform): + part_path_dic = {} + parser = ParsePartsConfig(productform) + + part_infos = parser.get_part_infos() + if part_infos is None: + LOG.error("part_infos is None.") + return part_path_dic + + for part_name in part_infos: + part_info = part_infos.get(part_name, None) + if part_info is None: + continue + + origin_part_name = part_info.get("origin_part_name") + build_out_dir = part_info.get("build_out_dir") + + part_path_list = [] + default_part_path = os.path.join( + get_build_output_path(productform), + "module_list_files", + origin_part_name) + if os.path.exists(default_part_path): + part_path_list.append(default_part_path) + + if build_out_dir != ".": + product_part_path = os.path.join( + get_build_output_path(productform), + build_out_dir, + "module_list_files", + origin_part_name) + if os.path.exists(product_part_path): + part_path_list.append(product_part_path) + part_path_dic[part_name] = part_path_list + return part_path_dic + + def _get_target_list_from_path(self, typelist, check_path): + target_list = [] + if os.path.exists(check_path): + mlf_file_list = get_file_list_by_postfix( + check_path, ".mlf") + for filepath in mlf_file_list: + mlf_info_list = self._get_mlf_data_from_file(filepath) + for data in mlf_info_list: + test_type = data.get("test_type") + target_path = data.get("label") + if "ALL" in typelist: + target_list.append(target_path) + continue + if test_type in typelist: + target_list.append(target_path) + return target_list + + def _get_target_list_by_type(self, productform, typelist): + target_list = [] + part_path_dic = self._get_part_path_data(productform) + for item in part_path_dic: + part_path_list = part_path_dic.get(item) + for part_path in part_path_list: + print("part_path = %s" % part_path) + temp_list = self._get_target_list_from_path(typelist, + part_path) + target_list.extend(temp_list) + return target_list + + def _get_target_list_by_part(self, productform, typelist, partlist): + target_list = [] + part_path_dic = self._get_part_path_data(productform) + for partname in partlist: + part_path_list = part_path_dic.get(partname, []) + for part_path in part_path_list: + temp_list = self._get_target_list_from_path(typelist, + part_path) + target_list.extend(temp_list) + return target_list + + def _get_target_list_by_module(self, productform, typelist, partlist, + testmodule): + target_list = [] + part_path_dic = self._get_part_path_data(productform) + for partname in partlist: + part_path_list = part_path_dic.get(partname, []) + for part_path in part_path_list: + module_path = os.path.join(part_path, testmodule) + LOG.info("module_path = %s." % module_path) + if os.path.exists(module_path): + temp_list = self._get_target_list_from_path(typelist, + module_path) + target_list.extend(temp_list) + return target_list + + def get_build_targets(self, productform, typelist, partlist, testmodule): + target_list = [] + + if productform == "" or len(typelist) == 0: + LOG.warning("Error: productform or typelist is empty.") + return [] + + if len(partlist) == 0 and testmodule != "": + LOG.warning( + "The part cannot be empty When the module is not empty.") + return [] + + if len(partlist) == 0 and testmodule == "": + target_list = self._get_target_list_by_type(productform, typelist) + return target_list + + if len(partlist) != 0 and testmodule == "": + target_list = self._get_target_list_by_part(productform, typelist, + partlist) + return target_list + + if len(partlist) != 0 and testmodule != "": + target_list = self._get_target_list_by_module(productform, + typelist, + partlist, + testmodule) + + return target_list + + def filter_build_targets(self, para): + productform = para.productform + typelist = para.testtype + partlist = para.partname_list + testmodule = para.testmodule + + print("partlist = %s" % str(partlist)) + target_list = self.get_build_targets(productform, typelist, + partlist, testmodule) + return target_list + + +############################################################################## +############################################################################## diff --git a/src/core/constants.py b/src/core/constants.py index 29dc0c4d61af1d805f0eda4fa7091f53b5bc0c80..a1a3187a8c7a5d4924569780f8b3702f50e8fe1e 100755 --- a/src/core/constants.py +++ b/src/core/constants.py @@ -75,3 +75,51 @@ class ConfigFileConst(object): def user_config_file(self): return ConfigFileConst.USERCONFIG_FILEPATH + +class JsTestConst(object): + BUILD_GN_FILE_TEMPLATE = """\ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") + +module_output_path = "%(output_path)s" + +ohos_js_unittest("%(suite_name)s") { + module_out_path = module_output_path + hap_profile = "./src/main/config.json" + deps = [ + ":%(suite_name)s_js_assets", + ":%(suite_name)s_resources", + ] + + certificate_profile = "//test/developertest/signature/openharmony_sx.p7b" + hap_name = "%(suite_name)s" +} +ohos_js_assets("%(suite_name)s_js_assets") { + source_dir = "./src/main/js/default" +} +ohos_resources("%(suite_name)s_resources") { + sources = [ "./src/main/resources" ] + hap_profile = "./src/main/config.json" +} + +group("unittest") { + testonly = true + deps = [ ":%(suite_name)s" ] +} +""" + + @property + def build_gn_template(self): + return JsTestConst.BUILD_GN_FILE_TEMPLATE diff --git a/src/core/driver/drivers.py b/src/core/driver/drivers.py index 51e1cf6e573fc351a9fea572d1b7f8c9ed953872..4ea53429d85c9c303e6d69ca50f577ca196626ef 100755 --- a/src/core/driver/drivers.py +++ b/src/core/driver/drivers.py @@ -16,20 +16,26 @@ # limitations under the License. # +import json import os import re +import shutil import time import platform +import zipfile from dataclasses import dataclass from xdevice import DeviceTestType from xdevice import DeviceLabelType from xdevice import ExecuteTerminate from xdevice import DeviceError +from xdevice import ShellHandler from xdevice import IDriver from xdevice import platform_logger from xdevice import Plugin +from xdevice import get_plugin +from xdevice_extension._core.constants import CommonParserType from core.utils import get_decode from core.utils import get_fuzzer_path from core.config.resource_manager import ResourceManager @@ -38,6 +44,7 @@ from core.config.config_manager import FuzzerConfigManager __all__ = [ "CppTestDriver", + "JSUnitTestDriver", "disable_keyguard", "GTestConst"] @@ -564,3 +571,239 @@ class CppTestDriver(IDriver): ############################################################################## ############################################################################## + +@Plugin(type=Plugin.DRIVER, id=DeviceTestType.jsunit_test) +class JSUnitTestDriver(IDriver): + """ + JSUnitTestDriver is a Test that runs a native test package on given device. + """ + + def __init__(self): + self.config = None + self.result = "" + self.start_time = None + self.ability_name = "" + self.package_name = "" + + def __check_environment__(self, device_options): + pass + + def __check_config__(self, config): + pass + + def __result__(self): + return self.result if os.path.exists(self.result) else "" + + def __execute__(self, request): + try: + LOG.info("developertest driver") + self.result = os.path.join(request.config.report_path, + "result", + '.'.join((request.get_module_name(), + "xml"))) + self.config = request.config + self.config.target_test_path = DEFAULT_TEST_PATH + self.config.device = request.config.environment.devices[0] + + suite_file = request.root.source.source_file + if not suite_file: + LOG.error("test source '%s' not exists" % + request.root.source.source_string) + return + + if not self.config.device: + result = ResultManager(suite_file, self.config) + result.set_is_coverage(False) + result.make_empty_result_file( + "No test device is found") + return + + package_name, ability_name = self._get_package_and_ability_name( + suite_file) + self.package_name = package_name + self.ability_name = ability_name + self.config.test_hap_out_path = \ + "/data/data/%s/files/" % self.package_name + + self._init_jsunit_test() + self._run_jsunit(suite_file) + self.generate_console_output(request) + + finally: + self.config.device.stop_catch_device_log() + + def _init_jsunit_test(self): + self.config.device.hdc_command("target mount") + self.config.device.execute_shell_command( + "rm -rf %s" % self.config.target_test_path) + self.config.device.execute_shell_command( + "mkdir -p %s" % self.config.target_test_path) + self.config.device.execute_shell_command( + "mount -o rw,remount,rw /%s" % "system") + self.config.device.hdc_command("shell hilog -r") + + + def _run_jsunit(self, suite_file): + filename = os.path.basename(suite_file) + + resource_manager = ResourceManager() + resource_data_dic, resource_dir = \ + resource_manager.get_resource_data_dic(suite_file) + resource_manager.process_preparer_data(resource_data_dic, resource_dir, + self.config.device) + + main_result = self._install_hap(suite_file) + result = ResultManager(suite_file, self.config) + + if main_result: + self._execute_hapfile_jsunittest() + self._uninstall_hap(self.package_name) + else: + self.result = result.get_test_results("Error: install hap failed") + LOG.error("Error: install hap failed") + + resource_manager.process_cleaner_data(resource_data_dic, resource_dir, + self.config.device) + + def generate_console_output(self, request): + report_name = request.get_module_name() + parsers = get_plugin( + Plugin.PARSER, CommonParserType.jsunit) + if parsers: + parsers = parsers[:1] + for listener in request.listeners: + listener.device_sn = self.config.device.device_sn + parser_instances = [] + + for parser in parsers: + parser_instance = parser.__class__() + parser_instance.suites_name = "{}_suites".format(report_name) + parser_instance.suites_name = request.listeners + parser_instance.listeners = request.listeners + parser_instances.append(parser_instance) + handler = ShellHandler(parser_instances) + + from xdevice_extension._core import utils + command = "hdc_std -t %s shell hilog -x " % self.config.device. \ + device_sn + + output = utils.start_standing_subprocess(command, return_result=True) + LOG.debug("start to parsing hilog") + handler.__read__(output) + handler.__done__() + + + def _execute_hapfile_jsunittest(self): + _unlock_screen(self.config.device) + _unlock_device(self.config.device) + + try: + return_message = self.start_hap_activity() + except (ExecuteTerminate, DeviceError) as exception: + return_message = str(exception.args) + + _lock_screen(self.config.device) + return return_message + + def _install_hap(self, suite_file): + message = self.config.device.hdc_command("install %s" % suite_file) + message = str(message).rstrip() + if message == "" or "success" in message: + return_code = True + if message != "": + LOG.info(message) + else: + return_code = False + if message != "": + LOG.warning(message) + + _sleep_according_to_result(return_code) + return return_code + + def start_hap_activity(self): + try: + command = "aa start -d 123 -a %s.MainAbility -b %s" \ + % (self.package_name, self.package_name) + self.start_time = time.time() + result_value = self.config.device.execute_shell_command( + command, timeout=TIME_OUT) + LOG.info("result_value [[[[[%s]]]]]" % result_value) + + if "success" in str(result_value).lower(): + LOG.info("execute %s's testcase success. result value=%s" + % (self.package_name, result_value)) + time.sleep(60) + else: + LOG.info("execute %s's testcase failed. result value=%s" + % (self.package_name, result_value)) + + _sleep_according_to_result(result_value) + return_message = result_value + except (ExecuteTerminate, DeviceError) as exception: + return_message = exception.args + + return return_message + + def _uninstall_hap(self, package_name): + return_message = self.config.device.execute_shell_command( + "bm uninstall -n %s" % package_name) + _sleep_according_to_result(return_message) + return return_message + + @staticmethod + def _get_package_and_ability_name(hap_filepath): + package_name = "" + ability_name = "" + + if os.path.exists(hap_filepath): + filename = os.path.basename(hap_filepath) + + #unzip the hap file + hap_bak_path = os.path.abspath(os.path.join( + os.path.dirname(hap_filepath), + "%s.bak" % filename)) + zf_desc = zipfile.ZipFile(hap_filepath) + try: + zf_desc.extractall(path=hap_bak_path) + except RuntimeError as error: + print(error) + zf_desc.close() + + #verify config.json file + app_profile_path = os.path.join(hap_bak_path, "config.json") + if not os.path.exists(app_profile_path): + print("file %s not exist" % app_profile_path) + return package_name, ability_name + + if os.path.isdir(app_profile_path): + print("%s is a folder, and not a file" % app_profile_path) + return package_name, ability_name + + #get package_name and ability_name value + load_dict = {} + with open(app_profile_path, 'r') as load_f: + load_dict = json.load(load_f) + profile_list = load_dict.values() + for profile in profile_list: + package_name = profile.get("package") + if not package_name: + continue + + abilities = profile.get("abilities") + for abilitie in abilities: + abilities_name = abilitie.get("name") + if abilities_name.startswith("."): + ability_name = package_name + abilities_name[ + abilities_name.find("."):] + else: + ability_name = abilities_name + break + break + + #delete hap_bak_path + if os.path.exists(hap_bak_path): + shutil.rmtree(hap_bak_path) + else: + print("file %s not exist" % hap_filepath) + + return package_name, ability_name diff --git a/src/core/testcase/testcase_manager.py b/src/core/testcase/testcase_manager.py index fcfa13ef3b7bc6b3cedf624c79bb50a8ac7162f7..d0ac52af924604fa789f25c1dff2895ea3282e7c 100755 --- a/src/core/testcase/testcase_manager.py +++ b/src/core/testcase/testcase_manager.py @@ -30,6 +30,7 @@ TESTFILE_TYPE_DATA_DIC = { "PYT": [], "CXX": [], "BIN": [], + "JST": [], } FILTER_SUFFIX_NAME_LIST = [".TOC", ".info", ".pyc"] @@ -109,7 +110,7 @@ class TestCaseManager(object): if suffix_name == ".dex": suite_file_dictionary["DEX"].append(suite_file) elif suffix_name == ".hap": - suite_file_dictionary["HAP"].append(suite_file) + suite_file_dictionary["JST"].append(suite_file) elif suffix_name == ".py": if not self.check_python_test_file(suite_file): continue