diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/.gitignore b/Ability/Sensormock/demo/SensorSimulateDemo/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..91d237bb144c7fb1777e50271857ef0f593286fc
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/.gitignore
@@ -0,0 +1,5 @@
+/node_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/README.md b/Ability/Sensormock/demo/SensorSimulateDemo/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..ecae5f8fa9267120b1fc64a09ad748b0ed25709d
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/README.md
@@ -0,0 +1 @@
+####传感器模拟的使用说明
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/build-profile.json5 b/Ability/Sensormock/demo/SensorSimulateDemo/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..3854f71fc436e7d67fb03828698562f4dc8a3abb
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/build-profile.json5
@@ -0,0 +1,27 @@
+{
+ "app": {
+ "signingConfigs": [],
+ "compileSdkVersion": 8,
+ "compatibleSdkVersion": 8,
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ }
+ ]
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/.gitignore b/Ability/Sensormock/demo/SensorSimulateDemo/entry/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..5a6ba80fa3d9498a23ae8ae7d9518f8743fa8a96
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/.gitignore
@@ -0,0 +1,4 @@
+/node_modules
+/.preview
+/build
+/.cxx
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/build-profile.json5 b/Ability/Sensormock/demo/SensorSimulateDemo/entry/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..cfdc90f805d1f7ef3a6557bc101de47b91895eb7
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/build-profile.json5
@@ -0,0 +1,14 @@
+{
+ "apiType": 'faMode',
+ "buildOption": {
+ },
+ "targets": [
+ {
+ "name": "default",
+ "runtimeOS": "HarmonyOS"
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/hvigorfile.js b/Ability/Sensormock/demo/SensorSimulateDemo/entry/hvigorfile.js
new file mode 100644
index 0000000000000000000000000000000000000000..bcec4c99653062cbf17702c40a2dd2a7b809b81a
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/hvigorfile.js
@@ -0,0 +1,2 @@
+// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
+module.exports = require('@ohos/hvigor-ohos-plugin').legacyHapTasks
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/package.json b/Ability/Sensormock/demo/SensorSimulateDemo/entry/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..c4e988f30f2ec9e3430a4d0c8f05e89fabbc2659
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "entry",
+ "version": "1.0.0",
+ "ohos": {
+ "org": "huawei",
+ "buildTool": "hvigor",
+ "directoryLevel": "module"
+ },
+ "description": "example description",
+ "repository": {},
+ "license": "ISC",
+ "dependencies": {}
+}
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/config.json b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/config.json
new file mode 100644
index 0000000000000000000000000000000000000000..4f5234964a8b01fd51bcbe3749ce8c57e639f3c0
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/config.json
@@ -0,0 +1,66 @@
+{
+ "app": {
+ "bundleName": "com.example.sensorsimulatedemo",
+ "vendor": "example",
+ "version": {
+ "code": 1000000,
+ "name": "1.0.0"
+ }
+ },
+ "deviceConfig": {},
+ "module": {
+ "package": "com.example.entry",
+ "name": ".entry",
+ "mainAbility": ".MainAbility",
+ "deviceType": [
+ "phone"
+ ],
+ "distro": {
+ "deliveryWithInstall": true,
+ "moduleName": "entry",
+ "moduleType": "entry",
+ "installationFree": false
+ },
+ "abilities": [
+ {
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ],
+ "orientation": "unspecified",
+ "formsEnabled": false,
+ "name": ".MainAbility",
+ "srcLanguage": "ets",
+ "srcPath": "MainAbility",
+ "icon": "$media:icon",
+ "description": "$string:MainAbility_desc",
+ "label": "$string:MainAbility_label",
+ "type": "page",
+ "visible": true,
+ "launchType": "standard"
+ }
+ ],
+ "js": [
+ {
+ "mode": {
+ "syntax": "ets",
+ "type": "pageAbility"
+ },
+ "pages": [
+ "pages/index"
+ ],
+ "name": ".MainAbility",
+ "window": {
+ "designWidth": 720,
+ "autoDesignWidth": false
+ }
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/ets/MainAbility/app.ets b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/ets/MainAbility/app.ets
new file mode 100644
index 0000000000000000000000000000000000000000..b7a0995c8e441cac86e21e06e7c9071664482b1c
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/ets/MainAbility/app.ets
@@ -0,0 +1,8 @@
+export default {
+ onCreate() {
+ console.info('Application onCreate')
+ },
+ onDestroy() {
+ console.info('Application onDestroy')
+ },
+}
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/ets/MainAbility/pages/index.ets b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/ets/MainAbility/pages/index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..d6ca48cf43988cd6f270a026f0c1a88b7bc57123
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/ets/MainAbility/pages/index.ets
@@ -0,0 +1,17 @@
+@Entry
+@Component
+struct Index {
+ @State message: string = 'Hello World'
+
+ build() {
+ Row() {
+ Column() {
+ Text(this.message)
+ .fontSize(50)
+ .fontWeight(FontWeight.Bold)
+ }
+ .width('100%')
+ }
+ .height('100%')
+ }
+}
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/element/color.json b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..1bbc9aa9617e97c45440e1d3d66afc1154837012
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "white",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/element/string.json b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..490210a3908f47722dc942d49dacc98b97669a5f
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "entry_desc",
+ "value": "description"
+ },
+ {
+ "name": "MainAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "MainAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/media/icon.png b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/media/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/media/icon.png differ
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/config.json b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/config.json
new file mode 100644
index 0000000000000000000000000000000000000000..a7d3be2ae277959d40c6df636d4099616f268466
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/config.json
@@ -0,0 +1,67 @@
+{
+ "app": {
+ "bundleName": "com.example.sensorsimulatedemo",
+ "vendor": "example",
+ "version": {
+ "code": 1000000,
+ "name": "1.0.0"
+ }
+ },
+ "deviceConfig": {},
+ "module": {
+ "package": "com.example.entry_test",
+ "name": ".entry_test",
+ "mainAbility": ".TestAbility",
+ "srcPath": "",
+ "deviceType": [
+ "phone"
+ ],
+ "distro": {
+ "deliveryWithInstall": true,
+ "moduleName": "entry_test",
+ "moduleType": "feature",
+ "installationFree": false
+ },
+ "abilities": [
+ {
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ],
+ "orientation": "unspecified",
+ "visible": true,
+ "srcPath": "TestAbility",
+ "name": ".TestAbility",
+ "srcLanguage": "ets",
+ "icon": "$media:icon",
+ "description": "$string:description_TestAbility",
+ "formsEnabled": false,
+ "label": "$string:entry_TestAbility",
+ "type": "page",
+ "launchType": "standard"
+ }
+ ],
+ "js": [
+ {
+ "mode": {
+ "syntax": "ets",
+ "type": "pageAbility"
+ },
+ "pages": [
+ "pages/index"
+ ],
+ "name": ".TestAbility",
+ "window": {
+ "designWidth": 720,
+ "autoDesignWidth": false
+ }
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/TestAbility/app.ets b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/TestAbility/app.ets
new file mode 100644
index 0000000000000000000000000000000000000000..5fd83b631f1806d46dcdf90ddbe96475ba3339c5
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/TestAbility/app.ets
@@ -0,0 +1,18 @@
+import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry'
+import { Hypium } from '@ohos/hypium'
+import testsuite from '../test/List.test'
+
+export default {
+ onCreate() {
+ console.info('Application onCreate')
+ var abilityDelegator: any
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
+ var abilityDelegatorArguments: any
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
+ console.info('start run testcase!!!')
+ Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite)
+ },
+ onDestroy() {
+ console.info('Application onDestroy')
+ },
+}
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/TestAbility/pages/index.ets b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/TestAbility/pages/index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..539eb9ae7b7cb0870b26b1a69d20fb977b55291d
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/TestAbility/pages/index.ets
@@ -0,0 +1,35 @@
+import router from '@system.router';
+
+@Entry
+@Component
+struct Index {
+ aboutToAppear() {
+ console.info('TestAbility index aboutToAppear')
+ }
+
+ @State message: string = 'Hello World'
+ build() {
+ Row() {
+ Column() {
+ Text(this.message)
+ .fontSize(50)
+ .fontWeight(FontWeight.Bold)
+ Button() {
+ Text('next page')
+ .fontSize(20)
+ .fontWeight(FontWeight.Bold)
+ }.type(ButtonType.Capsule)
+ .margin({
+ top: 20
+ })
+ .backgroundColor('#0D9FFB')
+ .width('35%')
+ .height('5%')
+ .onClick(()=>{
+ })
+ }
+ .width('100%')
+ }
+ .height('100%')
+ }
+ }
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1f5bcf0a2cfbb0478b7993dda7c157a1ab5f862d
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts
@@ -0,0 +1,68 @@
+import TestRunner from '@ohos.application.testRunner'
+import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry'
+
+var abilityDelegator = undefined
+var abilityDelegatorArguments = undefined
+
+function translateParamsToString(parameters) {
+ const keySet = new Set([
+ '-s class', '-s notClass', '-s suite', '-s itName',
+ '-s level', '-s testType', '-s size', '-s timeout',
+ '-s package', '-s dryRun'
+ ])
+ let targetParams = '';
+ for (const key in parameters) {
+ if (keySet.has(key)) {
+ targetParams += ' ' + key + ' ' + parameters[key]
+ }
+ }
+ return targetParams.trim()
+}
+
+async function onAbilityCreateCallback() {
+ console.log('onAbilityCreateCallback');
+}
+
+async function addAbilityMonitorCallback(err: any) {
+ console.info('addAbilityMonitorCallback : ' + JSON.stringify(err))
+}
+
+export default class OpenHarmonyTestRunner implements TestRunner {
+ constructor() {
+ }
+
+ onPrepare() {
+ console.info('OpenHarmonyTestRunner OnPrepare')
+ }
+
+ onRun() {
+ console.log('OpenHarmonyTestRunner onRun run')
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
+
+ let lMonitor = {
+ abilityName: testAbilityName,
+ onAbilityCreate: onAbilityCreateCallback,
+ };
+ var testAbilityName = abilityDelegatorArguments.parameters['-p'] + '.TestAbility'
+ abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
+ var cmd = 'aa start -d 0 -a ' + testAbilityName + ' -b ' + abilityDelegatorArguments.bundleName
+ cmd += ' '+translateParamsToString(abilityDelegatorArguments.parameters)
+ var debug = abilityDelegatorArguments.parameters["-D"]
+ if (debug == 'true')
+ {
+ cmd += ' -D'
+ }
+ console.info('cmd : '+cmd)
+ abilityDelegator.executeShellCommand(cmd,
+ (err: any, d: any) => {
+ console.info('executeShellCommand : err : ' + JSON.stringify(err));
+ console.info('executeShellCommand : data : ' + d.stdResult);
+ console.info('executeShellCommand : data : ' + d.exitCode);
+ })
+ console.info('OpenHarmonyTestRunner onRun call abilityDelegator.getAppContext')
+ var context = abilityDelegator.getAppContext()
+ console.info('getAppContext : ' + JSON.stringify(context))
+ console.info('OpenHarmonyTestRunner onRun end')
+ }
+};
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/test/List.test.ets b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/test/List.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..0f1243c9a112d3be3e5173d94e2bd73535681ff2
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/test/List.test.ets
@@ -0,0 +1,5 @@
+import SensorMockTest from './Sensormock.test'
+
+export default function testsuite() {
+ SensorMockTest()
+}
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/test/Sensormock.test.ets b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/test/Sensormock.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..fc510cafe18ac2ac48f1d148e00db6f16937235c
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/test/Sensormock.test.ets
@@ -0,0 +1,188 @@
+// @ts-nocheck
+import { describe, it, expect, MockKit, when } from '@ohos/hypium'
+import sensor from '@ohos.sensor';
+
+export default function SensorMockTest() {
+ describe('sensorTest', function () {
+ it('sensorTest_on', 0, function () {
+ let mocker = new MockKit();
+ let newObj = mocker.mockObject(sensor);
+ let mockedOnFunc = mocker.mockFunc(newObj, newObj.on);
+
+ function NeedData(x, y, z) {
+ this.x = x
+ this.y = y
+ this.z = z
+ }
+
+ when(mockedOnFunc)(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER).afterReturn(new NeedData(1, 2, 3));
+ //从回调中拿到预置的数据
+ newObj.on(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, function (data) {
+ console.log("mockSensor - on: " + JSON.stringify(data));
+ });
+ });
+
+ it('sensorTest_on_2', 0, function () {
+ let mocker = new MockKit();
+ let newObj = mocker.mockObject(sensor);
+ let mockedOnFunc = mocker.mockFunc(newObj, newObj.on);
+
+ function NeedData(x, y, z) {
+ this.x = x
+ this.y = y
+ this.z = z
+ }
+
+ when(mockedOnFunc)(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER).afterReturn(new NeedData(1, 2, 3));
+ //从回调中拿到预置的数据,并传入轮询周期时间
+ newObj.on(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, function (data) {
+ console.log("mockSensor - on: " + JSON.stringify(data));
+ }, {
+ interval: 3000000000
+ });
+ });
+
+ it('sensorTest_on_3', 0, function () {
+ let mocker = new MockKit();
+ let newObj = mocker.mockObject(sensor);
+ let mockedOnFunc = mocker.mockFunc(newObj, newObj.on);
+
+ function NeedData(x, y, z) {
+ this.x = x
+ this.y = y
+ this.z = z
+ }
+
+ when(mockedOnFunc)(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER).afterReturn(new NeedData(1, 2, 3)); //模拟的数据
+ let result = newObj.on(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER);
+ //从返回值中拿到预置的数据
+ console.log("mockSensor - on: " + JSON.stringify(result));
+ });
+
+ it('sensorTest_once', 0, function () {
+
+ let mocker = new MockKit();
+ let newObj = mocker.mockObject(sensor);
+ let mockedOnFunc = mocker.mockFunc(newObj, newObj.once);
+
+ function NeedData(x, y, z) {
+ this.x = x
+ this.y = y
+ this.z = z
+ }
+
+ when(mockedOnFunc)(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER).afterReturn(new NeedData(1, 2, 3)); //模拟的数据
+ newObj.once(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, function (data) {
+ //从回调中拿到预置的数据
+ console.log("mockSensor - once: " + JSON.stringify(data));
+ });
+ });
+
+
+ it('sensorTest_off', 0, function () {
+
+ let mocker = new MockKit();
+ let newObj = mocker.mockObject(sensor);
+ let mockedOnFunc = mocker.mockFunc(newObj, newObj.off);
+
+ function NeedData(x, y, z) {
+ this.x = x
+ this.y = y
+ this.z = z
+ }
+
+ when(mockedOnFunc)(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER).afterReturn(new NeedData(1, 2, 3)); //模拟的数据
+ newObj.off(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, function (data) {
+ console.log("mockSensor - off: " + JSON.stringify(data)); //从回调中拿到预置的数据
+ });
+ });
+
+
+ it('sensorTest_transformCoordinateSystem', 0, function () {
+
+ let mocker = new MockKit();
+ let newObj = mocker.mockObject(sensor);
+ let mockedOnFunc = mocker.mockFunc(newObj, newObj.transformCoordinateSystem);
+
+ function SuccessData(x, y, z) {
+ this.x = x
+ this.y = y
+ this.z = z
+ }
+
+ when(mockedOnFunc)('transformCoordinateSystem').afterReturn(new SuccessData(1, 2, 3)); //模拟的数据
+ newObj.transformCoordinateSystem('transformCoordinateSystem', function (data) {
+ //从回调中拿到预置的数据
+ console.log("mockSensor - transformCoordinateSystem: " + JSON.stringify(data));
+ });
+ });
+
+
+ it('sensorTest_transformCoordinateSystem_async', 0, async function () {
+
+ let mocker = new MockKit();
+ let newObj = mocker.mockObject(sensor);
+ let mockedOnFunc = mocker.mockFunc(newObj, newObj.transformCoordinateSystem);
+
+ //模拟的数据
+ when(mockedOnFunc)('transformCoordinateSystem').afterReturn(new Promise((data, err) => {
+ if (true) {
+ data('data you need');
+ } else {
+ err('some error');
+ }
+ }));
+
+ //从返回值中拿到预置的数据promise
+ newObj.transformCoordinateSystem('transformCoordinateSystem').then((data)=>{
+ console.info("mockSensor - Operation successed :" + data);
+ }).catch((err) => {
+ console.info("mockSensor - Operation failed :" + err);
+ });
+ });
+
+
+ it('sensorTest_getDirection', 0, function () {
+
+ let mocker = new MockKit();
+ let newObj = mocker.mockObject(sensor);
+ let mockedOnFunc = mocker.mockFunc(newObj, newObj.transformCoordinateSystem);
+
+ function SuccessData(x, y, z) {
+ this.x = x
+ this.y = y
+ this.z = z
+ }
+
+ when(mockedOnFunc)('getDirection').afterReturn(new SuccessData(1, 2, 3)); //模拟的数据
+ newObj.transformCoordinateSystem('getDirection', function (data) {
+ //从回调中拿到预置的数据
+ console.log("mockSensor - getDirection: " + JSON.stringify(data));
+ });
+ });
+
+
+ it('sensorTest_getDirection_async', 0, async function () {
+
+ let mocker = new MockKit();
+ let newObj = mocker.mockObject(sensor);
+ let mockedOnFunc = mocker.mockFunc(newObj, newObj.getDirection);
+
+ //模拟的数据
+ when(mockedOnFunc)('getDirection').afterReturn(new Promise((data, err) => {
+ if (true) {
+ data('data you need');
+ } else {
+ err('some error');
+ }
+ }));
+
+ //从返回值中拿到预置的数据promise
+ newObj.getDirection('getDirection').then((data)=>{
+ console.info("mockSensor - Operation successed :" + data);
+ }).catch((err) => {
+ console.info("mockSensor - Operation failed :" + err);
+ });
+ });
+ });
+}
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/resources/base/element/string.json b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..a0901cfced5abc1cb836b55896884b769adc7175
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/resources/base/element/string.json
@@ -0,0 +1,12 @@
+{
+ "string": [
+ {
+ "name": "description_TestAbility",
+ "value": "eTS_Empty Ability"
+ },
+ {
+ "name": "entry_TestAbility",
+ "value": "entry_TestAbility"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/resources/base/media/icon.png b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/resources/base/media/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/resources/base/media/icon.png differ
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/hvigorfile.js b/Ability/Sensormock/demo/SensorSimulateDemo/hvigorfile.js
new file mode 100644
index 0000000000000000000000000000000000000000..cff9f0dfcf8cb00cca34e7f50d61380cf5496868
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/hvigorfile.js
@@ -0,0 +1,2 @@
+// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
+module.exports = require('@ohos/hvigor-ohos-plugin').legacyAppTasks
\ No newline at end of file
diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/package.json b/Ability/Sensormock/demo/SensorSimulateDemo/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..dc9cc4081f16f3246ff030d90a026f2ad1bd5a38
--- /dev/null
+++ b/Ability/Sensormock/demo/SensorSimulateDemo/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "sensorsimulatedemo",
+ "version": "1.0.0",
+ "ohos": {
+ "org": "huawei",
+ "buildTool": "hvigor",
+ "directoryLevel": "project"
+ },
+ "description": "example description",
+ "repository": {},
+ "license": "ISC",
+ "dependencies": {
+ "@ohos/hypium": "1.0.1",
+ "@ohos/hvigor": "1.1.6",
+ "@ohos/hvigor-ohos-plugin": "1.1.6"
+ }
+}
diff --git a/Ability/Sensormock/hypium/LICENSE b/Ability/Sensormock/hypium/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..4947287f7b5ccb5d1e8b7b2d3aa5d89f322c160d
--- /dev/null
+++ b/Ability/Sensormock/hypium/LICENSE
@@ -0,0 +1,177 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/Ability/Sensormock/hypium/README.OpenSource b/Ability/Sensormock/hypium/README.OpenSource
new file mode 100644
index 0000000000000000000000000000000000000000..20515e91546dd51650db24d215f1584a3708e613
--- /dev/null
+++ b/Ability/Sensormock/hypium/README.OpenSource
@@ -0,0 +1,11 @@
+[
+ {
+ "Name": "@ohos/hypium",
+ "License": "Apache-2.0 License",
+ "License File": " LICENSE ",
+ "Version Number": "1.0.0",
+ "Owner" : "",
+ "Upstream URL": "https://gitee.com/openharmony/arkXtest",
+ "Description": "A unit test framework for OpenHarmony application."
+ }
+]
\ No newline at end of file
diff --git a/Ability/Sensormock/hypium/README.md b/Ability/Sensormock/hypium/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..8b18b6990a77d5029f7ed70c78246d211e4d28f0
--- /dev/null
+++ b/Ability/Sensormock/hypium/README.md
@@ -0,0 +1,152 @@
+
Hypium
+A unit test framework for OpenHarmonyOS application
+
+## Hypium是什么?
+***
+- Hypium是OpenHarmony上的测试框架,提供测试用例编写、执行、结果显示能力,用于OpenHarmony系统应用接口以及应用界面测试。
+- Hypium结构化模型:hypium工程主要由List.test.js与TestCase.test.js组成。
+```
+rootProject // Hypium工程根目录
+├── moduleA
+│ ├── src
+│ ├── main // 被测试应用目录
+│ ├── ohosTest // 测试用例目录
+│ ├── js/ets
+│ └── test
+│ └── List.test.js // 测试用例加载脚本,ets目录下为.ets后缀
+│ └── TestCase.test.js // 测试用例脚本,ets目录下为.ets后缀
+└── moduleB
+ ...
+│ └── List.test.js // 测试用例加载脚本,ets目录下为.ets后缀
+│ └── TestCase.test.js // 测试用例脚本,ets目录下为.ets后缀
+```
+
+## 安装使用
+***
+- 在DevEco Studio内使用Hypium
+- 工程级package.json内配置:
+```json
+"dependencies": {
+ "@ohos/hypium": "1.0.0"
+}
+```
+注:
+hypium服务于OpenHarmonyOS应用对外接口测试、系统对外接口测试(SDK中接口),完成HAP自动化测试。详细指导:
+DevEco Studio
+
+- 通用语法
+
+ 测试用例采用业内通用语法,describe代表一个测试套, it代表一条用例。
+
+| No. | API | 功能说明 |
+| ---- | ---------- | ------------------------------------------------------------ |
+| 1 | describe | 定义一个测试套,支持两个参数:测试套名称和测试套函数 |
+| 2 | beforeAll | 在测试套内定义一个预置条件,在所有测试用例开始前执行且仅执行一次,支持一个参数:预置动作函数 |
+| 3 | beforeEach | 在测试套内定义一个单元预置条件,在每条测试用例开始前执行,执行次数与it定义的测试用例数一致,支持一个参数:预置动作函数 |
+| 4 | afterEach | 在测试套内定义一个单元清理条件,在每条测试用例结束后执行,执行次数与it定义的测试用例数一致,支持一个参数:清理动作函数 |
+| 5 | afterAll | 在测试套内定义一个清理条件,在所有测试用例结束后执行且仅执行一次,支持一个参数:清理动作函数 |
+| 6 | it | 定义一条测试用例,支持三个参数:用例名称,过滤参数和用例函数 |
+| 7 | expect | 支持bool类型判断等多种断言方法 |
+
+- 断言库
+
+ 示例代码:
+
+```javascript
+ expect(${actualvalue}).assertX(${expectvalue})
+```
+
+ 断言功能列表:
+
+| No. | API | 功能说明 |
+| :--- | :--------------- | ------------------------------------------------------------ |
+| 1 | assertClose | 检验actualvalue和expectvalue(0)的接近程度是否是expectValue(1) |
+| 2 | assertContain | 检验actualvalue中是否包含expectvalue |
+| 3 | assertEqual | 检验actualvalue是否等于expectvalue[0] |
+| 4 | assertFail | 抛出一个错误 |
+| 5 | assertFalse | 检验actualvalue是否是false |
+| 6 | assertTrue | 检验actualvalue是否是true |
+| 7 | assertInstanceOf | 检验actualvalue是否是expectvalue类型 |
+| 8 | assertLarger | 检验actualvalue是否大于expectvalue |
+| 9 | assertLess | 检验actualvalue是否小于expectvalue |
+| 10 | assertNull | 检验actualvalue是否是null |
+| 11 | assertThrowError | 检验actualvalue抛出Error内容是否是expectValue |
+| 12 | assertUndefined | 检验actualvalue是否是undefined |
+
+ 示例代码:
+
+```javascript
+ import { describe, it, expect } from '@ohos/hypium'
+ export default async function assertCloseTest() {
+ describe('assertClose', function () {
+ it('assertClose_success', 0, function () {
+ let a = 100
+ let b = 0.1
+ expect(a).assertClose(99, b)
+ })
+ })
+ }
+```
+- 公共系统能力
+
+| No. | API | 功能描述 |
+| ---- | ------------------------------------------------------- | ------------------------------------------------------------ |
+| 1 | existKeyword(keyword: string, timeout: number): boolean | hilog日志中查找指定字段是否存在,keyword是待查找关键字,timeout为设置的查找时间 |
+
+ 示例代码:
+
+```javascript
+import { describe, it, expect, SysTestKit} from '@ohos/hypium'
+
+export default function existKeywordTest() {
+ describe('existKeywordTest', function () {
+ it('existKeyword',DEFAULT, async function () {
+ console.info("HelloTest")
+ let isExist = await SysTestKit.existKeyword('HelloTest')
+ console.info('isExist ------>' + isExist)
+ })
+ })
+}
+```
+- 专项能力
+用例筛选能力:hypium支持根据用例属性筛选执行指定测试用例,使用方式是在测试应用的启动shell命令后新增" -s ${Key} ${Value}"。
+
+| Key | 含义说明 | Value取值范围 |
+| ---- | ------------------------------------------------------- | ------------------------------------------------------------ |
+| level | 用例级别 | "0","1","2","3","4" |
+| size | 用例粒度 | "small","medium","large" |
+| testType | 用例测试类型 | "function","performance","power","reliability","security","global","compatibility","user","standard","safety","resilience" |
+
+ 示例代码
+
+```javascript
+import { describe, it, expect, TestType, Size, Level } from '@ohos/hypium'
+
+export default function attributeTest() {
+ describe('attributeTest', function () {
+ it("testAttributeIt", TestType.FUNCTION | Size.SMALLTEST | Level.LEVEL0, function () {
+ console.info('Hello Test')
+ })
+ })
+}
+```
+
+
+## 约束
+***
+ 本模块首批接口从OpenHarmony SDK API version 8开始支持。
+
+## Hypium开放能力隐私声明
+
+- 我们如何收集和使用您的个人信息
+ 您在使用集成了Hypium开放能力的测试应用时,Hypium不会处理您的个人信息。
+- SDK处理的个人信息
+ 不涉及。
+- SDK集成第三方服务声明
+ 不涉及。
+- SDK数据安全保护
+ 不涉及。
+- SDK版本更新声明
+ 为了向您提供最新的服务,我们会不时更新Hypium版本。我们强烈建议开发者集成使用最新版本的Hypium。
+
+
diff --git a/Ability/Sensormock/hypium/index.d.ts b/Ability/Sensormock/hypium/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0be3926c7146cc28770d93a5c7718a0f21e2faf2
--- /dev/null
+++ b/Ability/Sensormock/hypium/index.d.ts
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+export const DEFAULT = 0B0000
+
+export const when: when;
+
+export enum TestType {
+ FUNCTION = 0B1,
+ PERFORMANCE = 0B1 << 1,
+ POWER = 0B1 << 2,
+ RELIABILITY = 0B1 << 3,
+ SECURITY = 0B1 << 4,
+ GLOBAL = 0B1 << 5,
+ COMPATIBILITY = 0B1 << 6,
+ USER = 0B1 << 7,
+ STANDARD = 0B1 << 8,
+ SAFETY = 0B1 << 9,
+ RESILIENCE = 0B1 << 10
+}
+
+export enum Size {
+ SMALLTEST = 0B1 << 16,
+ MEDIUMTEST = 0B1 << 17,
+ LARGETEST = 0B1 << 18
+}
+
+export enum Level {
+ LEVEL0 = 0B1 << 24,
+ LEVEL1 = 0B1 << 25,
+ LEVEL2 = 0B1 << 26,
+ LEVEL3 = 0B1 << 27,
+ LEVEL4 = 0B1 << 28
+}
+
+export function describe(testSuiteName: string, callback: Function): void
+
+export function beforeEach(callback: Function): void
+
+export function afterEach(callback: Function): void
+
+export function beforeAll(callback: Function): void
+
+export function afterAll(callback: Function): void
+
+export function it(testCaseName: string, attribute: (TestType | Size | Level), callback: Function)
+
+export interface Assert {
+ assertClose(expectValue: number, precision: number): void
+ assertContain(expectValue: any): void
+ assertEqual(expectValue: any): void
+ assertFail(): void
+ assertFalse(): void
+ assertTrue(): void
+ assertInstanceOf(expectValue: string): void
+ assertLarger(expectValue: number): void
+ assertLess(expectValue: number): void
+ assertNull(): void
+ assertThrowError(expectValue: string): void
+ assertUndefined(): void
+}
+
+export function expect(actualValue?: any): Assert
+
+export class ArgumentMatchers {
+ static any;
+ static anyString;
+ static anyBoolean;
+ static anyNumber;
+ static anyObj;
+ static anyFunction;
+ static matchRegexs(Regex: RegExp): void
+}
+
+declare interface when {
+ afterReturn(value: any): any
+ afterReturnNothing(): undefined
+ afterAction(action: any): any
+ afterThrow(e_msg: string): string
+ (argMatchers: any): when;
+}
+
+export interface VerificationMode {
+ times(count: Number): void
+ never(): void
+ once(): void
+ atLeast(count: Number): void
+ atMost(count: Number): void
+}
+
+export class MockKit {
+ constructor()
+ mockFunc(obj: Object, func: Function): Function
+ mockObject(obj: Object): Object
+ verify(methodName: String, argsArray: Array): VerificationMode
+ ignoreMock(obj: Object, func: Function): void
+ clear(obj: Object): void
+ clearAll(): void
+}
+
+export class SysTestKit {
+ static actionStart(tag: string): void
+ static actionEnd(tag: string): void
+ static existKeyword(keyword: string, timeout?: number): boolean
+}
+
+export class Hypium {
+ static setData(data: {[key: string]: any}): void
+ static hypiumTest(abilityDelegator: any, abilityDelegatorArguments: any, testsuite: Function): void
+}
\ No newline at end of file
diff --git a/Ability/Sensormock/hypium/index.ets b/Ability/Sensormock/hypium/index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..b778d290cc41195afce90a5629c2cfc950b64558
--- /dev/null
+++ b/Ability/Sensormock/hypium/index.ets
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2021-2022 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 Core from './src/core'
+import {DEFAULT, TestType, Size, Level} from './src/Constant'
+import DataDriver from './src/module/config/DataDriver'
+import ExpectExtend from './src/module/assert/ExpectExtend'
+import OhReport from './src/module/report/OhReport'
+import SysTestKit from './src/module/kit/SysTestKit'
+import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from './src/interface'
+import {MockKit, when} from './src/module/mock/MockKit';
+import ArgumentMatchers from './src/module/mock/ArgumentMatchers';
+
+function dryRun(core, testParameters, abilityDelegator) {
+ if (testParameters['dryRun'] === 'true') {
+ let testSuitesObj = {}
+ let suitesArray = []
+ const suiteService = core.getDefaultService('suite')
+ for (const suiteItem of suiteService.rootSuite.childSuites) {
+ let itArray = []
+ let suiteName = suiteItem['description']
+ for (const itItem of suiteItem['specs']) {
+ itArray.push({'itName': itItem['description']})
+ }
+ let obj = {}
+ obj[suiteName] = itArray
+ suitesArray.push(obj)
+ }
+ testSuitesObj['suites'] = suitesArray
+
+ let strJson = JSON.stringify(testSuitesObj)
+ let strLen = strJson.length
+ let maxLen = 500
+ let maxCount = Math.floor(strLen / maxLen)
+
+ for (let count = 0; count <= maxCount; count++) {
+ abilityDelegator.print(strJson.substring(count * maxLen, (count + 1) * maxLen))
+ }
+ console.info('dryRun print success')
+ abilityDelegator.finishTest('dry run finished!!!', 0, () => { })
+ return true
+ }
+ return false
+}
+
+class Hypium {
+ static setData(data) {
+ const core = Core.getInstance()
+ const dataDriver = new DataDriver({data})
+ core.addService('dataDriver', dataDriver)
+ }
+
+ static hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) {
+ const core = Core.getInstance()
+ const expectExtend = new ExpectExtend({
+ 'id': 'extend'
+ })
+ core.addService('expect', expectExtend)
+ const ohReport = new OhReport({
+ 'delegator': abilityDelegator
+ })
+ SysTestKit.delegator = abilityDelegator
+ core.addService('report', ohReport)
+ core.init()
+ core.subscribeEvent('spec', ohReport)
+ core.subscribeEvent('suite', ohReport)
+ core.subscribeEvent('task', ohReport)
+ const configService = core.getDefaultService('config')
+ let testParameters = configService.translateParams(abilityDelegatorArguments.parameters)
+ console.info('parameters:' + JSON.stringify(testParameters))
+ configService.setConfig(testParameters)
+ testsuite()
+ if (dryRun(core, testParameters, abilityDelegator)) {
+ return
+ }
+ if (Object.prototype.hasOwnProperty.call(globalThis, 'setupUiTestEnvironment')) {
+ globalThis.setupUiTestEnvironment().then(() => {
+ console.info('UiTestKit::after run uitest setup, start run testcases')
+ core.execute()
+ }).catch((error) => {
+ console.error('UiTestKit:: call setupUiTestEnvironment failure:' + error)
+ core.execute()
+ })
+ } else {
+ console.info('UiTestKit:: no need to setup uitest, start run testcases')
+ core.execute()
+ }
+ }
+}
+
+export {
+ Hypium,
+ Core,
+ DEFAULT,
+ TestType,
+ Size,
+ Level,
+ DataDriver,
+ ExpectExtend,
+ OhReport,
+ SysTestKit,
+ describe, beforeAll, beforeEach, afterEach, afterAll, it, expect,
+ MockKit, when,
+ ArgumentMatchers
+}
\ No newline at end of file
diff --git a/Ability/Sensormock/hypium/index.js b/Ability/Sensormock/hypium/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..9ca084f253f0756acae4c64bd6edcf08032746eb
--- /dev/null
+++ b/Ability/Sensormock/hypium/index.js
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2021-2022 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 Core from './src/core';
+import {DEFAULT, TestType, Size, Level} from './src/Constant';
+import DataDriver from './src/module/config/DataDriver';
+import ExpectExtend from './src/module/assert/ExpectExtend';
+import OhReport from './src/module/report/OhReport';
+import SysTestKit from './src/module/kit/SysTestKit';
+import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from './src/interface';
+import {MockKit, when} from './src/module/mock/MockKit';
+import ArgumentMatchers from './src/module/mock/ArgumentMatchers';
+
+function dryRun(core, testParameters, abilityDelegator) {
+ if (testParameters['dryRun'] === 'true') {
+ let testSuitesObj = {};
+ let suitesArray = [];
+ const suiteService = core.getDefaultService('suite');
+ for (const suiteItem of suiteService.rootSuite.childSuites) {
+ let itArray = [];
+ let suiteName = suiteItem['description'];
+ for (const itItem of suiteItem['specs']) {
+ itArray.push({'itName': itItem['description']});
+ }
+ let obj = {};
+ obj[suiteName] = itArray;
+ suitesArray.push(obj);
+ }
+ testSuitesObj['suites'] = suitesArray;
+
+ let strJson = JSON.stringify(testSuitesObj);
+ let strLen = strJson.length;
+ let maxLen = 500;
+ let maxCount = Math.floor(strLen / maxLen);
+
+ for (let count = 0; count <= maxCount; count++) {
+ abilityDelegator.print(strJson.substring(count * maxLen, (count + 1) * maxLen));
+ }
+ console.info('dryRun print success');
+ abilityDelegator.finishTest('dry run finished!!!', 0, () => { });
+ return true;
+ }
+ return false;
+}
+
+class Hypium {
+ static setData(data) {
+ const core = Core.getInstance();
+ const dataDriver = new DataDriver({data});
+ core.addService('dataDriver', dataDriver);
+ }
+
+ static hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) {
+ const core = Core.getInstance();
+ const expectExtend = new ExpectExtend({
+ 'id': 'extend'
+ });
+ core.addService('expect', expectExtend);
+ const ohReport = new OhReport({
+ 'delegator': abilityDelegator
+ });
+ SysTestKit.delegator = abilityDelegator;
+ core.addService('report', ohReport);
+ core.init();
+ core.subscribeEvent('spec', ohReport);
+ core.subscribeEvent('suite', ohReport);
+ core.subscribeEvent('task', ohReport);
+ const configService = core.getDefaultService('config');
+ let testParameters = configService.translateParams(abilityDelegatorArguments.parameters);
+ console.info('parameters:' + JSON.stringify(testParameters));
+ configService.setConfig(testParameters);
+ testsuite();
+ if (dryRun(core, testParameters, abilityDelegator)) {
+ return;
+ }
+ if (Object.prototype.hasOwnProperty.call(globalThis, 'setupUiTestEnvironment')) {
+ globalThis.setupUiTestEnvironment().then(() => {
+ console.info('UiTestKit::after run uitest setup, start run testcases');
+ core.execute();
+ }).catch((error) => {
+ console.error('UiTestKit:: call setupUiTestEnvironment failure:' + error);
+ core.execute();
+ });
+ } else {
+ console.info('UiTestKit:: no need to setup uitest, start run testcases');
+ core.execute();
+ }
+ }
+}
+
+export {
+ Hypium,
+ Core,
+ DEFAULT,
+ TestType,
+ Size,
+ Level,
+ DataDriver,
+ ExpectExtend,
+ OhReport,
+ SysTestKit,
+ describe, beforeAll, beforeEach, afterEach, afterAll, it, expect,
+ MockKit, when,
+ ArgumentMatchers
+};
\ No newline at end of file
diff --git a/Ability/Sensormock/hypium/package.json b/Ability/Sensormock/hypium/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..dbac727312699a5b8b8a2ad8fb2b8a253b3b1077
--- /dev/null
+++ b/Ability/Sensormock/hypium/package.json
@@ -0,0 +1,50 @@
+{
+ "_from": "@ohos/hypium@1.0.1",
+ "_id": "@ohos/hypium@1.0.1",
+ "_inBundle": false,
+ "_integrity": "sha512-HaztFbgwYZCdVlayXirBlmJaNTXUO65qRgYnUmrhWGEzG7wFU2fyFbeXgQeYMVWFXgeezFOoHAPoS96TEE7TIQ==",
+ "_location": "/@ohos/hypium",
+ "_phantomChildren": {},
+ "_requested": {
+ "type": "version",
+ "registry": true,
+ "raw": "@ohos/hypium@1.0.1",
+ "name": "@ohos/hypium",
+ "escapedName": "@ohos%2fhypium",
+ "scope": "@ohos",
+ "rawSpec": "1.0.1",
+ "saveSpec": null,
+ "fetchSpec": "1.0.1"
+ },
+ "_requiredBy": [
+ "/"
+ ],
+ "_resolved": "https://repo.harmonyos.com/npm/@ohos/hypium/-/@ohos/hypium-1.0.1.tgz",
+ "_shasum": "788c286f5b18e41774c606d12fd93f625a4318ed",
+ "_spec": "@ohos/hypium@1.0.1",
+ "_where": "C:\\Users\\Administrator\\DevEcoStudioProjects\\SensorSimulateDemo",
+ "author": "",
+ "bundleDependencies": false,
+ "dependencies": {},
+ "deprecated": false,
+ "description": "A unit test framework for OpenHarmony application.",
+ "keywords": [
+ "OpenHarmony",
+ "hypium"
+ ],
+ "license": "Apache-2.0",
+ "main": "index.js",
+ "name": "@ohos/hypium",
+ "ohos": {
+ "org": "ohos"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://gitee.com/openharmony/arkXtest"
+ },
+ "tags": [
+ "OpenHarmony",
+ "hypium"
+ ],
+ "version": "1.0.1"
+}
diff --git a/Ability/Sensormock/hypium/src/Constant.js b/Ability/Sensormock/hypium/src/Constant.js
new file mode 100644
index 0000000000000000000000000000000000000000..f1829107720a64df7b571a4bfd11a25e6d9022b6
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/Constant.js
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+/**
+ * define the testcase type : TestType, Size , Level
+ */
+export const DEFAULT = 0B0000;
+
+export class TestType {
+ static FUNCTION = 0B1;
+ static PERFORMANCE = 0B1 << 1;
+ static POWER = 0B1 << 2;
+ static RELIABILITY = 0B1 << 3;
+ static SECURITY = 0B1 << 4;
+ static GLOBAL = 0B1 << 5;
+ static COMPATIBILITY = 0B1 << 6;
+ static USER = 0B1 << 7;
+ static STANDARD = 0B1 << 8;
+ static SAFETY = 0B1 << 9;
+ static RESILIENCE = 0B1 << 10;
+}
+
+export class Size {
+ static SMALLTEST = 0B1 << 16;
+ static MEDIUMTEST = 0B1 << 17;
+ static LARGETEST = 0B1 << 18;
+}
+
+export class Level {
+ static LEVEL0 = 0B1 << 24;
+ static LEVEL1 = 0B1 << 25;
+ static LEVEL2 = 0B1 << 26;
+ static LEVEL3 = 0B1 << 27;
+ static LEVEL4 = 0B1 << 28;
+}
diff --git a/Ability/Sensormock/hypium/src/core.js b/Ability/Sensormock/hypium/src/core.js
new file mode 100644
index 0000000000000000000000000000000000000000..0daf042635bf5b98815e4e06d96bfcba74e6e756
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/core.js
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2021-2022 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 {SuiteService, SpecService, ExpectService, ReportService} from './service';
+import {ConfigService} from './module/config/configService';
+import {SpecEvent, TaskEvent, SuiteEvent} from './event';
+
+/**
+ * core service for execute testcase.
+ */
+class Core {
+ static getInstance() {
+ if (!this.instance) {
+ this.instance = new Core();
+ }
+ return this.instance;
+ }
+
+ constructor() {
+ this.instance = null;
+ this.services = {
+ suite: {},
+ spec: {},
+ config: {},
+ expect: {},
+ log: {},
+ report: {}
+
+ };
+ this.events = {
+ suite: {},
+ spec: {},
+ task: {}
+ };
+ }
+
+ addService(name, service) {
+ let serviceObj = {};
+ if (!this.services[name]) {
+ this.services[name] = serviceObj;
+ } else {
+ serviceObj = this.services[name];
+ }
+ serviceObj[service.id] = service;
+ }
+
+ getDefaultService(name) {
+ return this.services[name].default;
+ }
+
+ getServices(name) {
+ return this.services[name];
+ }
+
+ registerEvent(serviceName, event) {
+ let eventObj = {};
+ if (!this.events[serviceName]) {
+ this.events[serviceName] = eventObj;
+ } else {
+ eventObj = this.events[serviceName];
+ }
+ eventObj[event.id] = event;
+ }
+
+ unRegisterEvent(serviceName, eventID) {
+ const eventObj = this.events[serviceName];
+ if (eventObj) {
+ delete eventObj[eventID];
+ }
+ }
+
+ subscribeEvent(serviceName, serviceObj) {
+ const eventObj = this.events[serviceName];
+ if (eventObj) {
+ for (const attr in eventObj) {
+ eventObj[attr]['subscribeEvent'](serviceObj);
+ }
+ }
+ }
+
+ fireEvents(serviceName, eventName) {
+ const eventObj = this.events[serviceName];
+ if (!eventObj) {
+ return;
+ }
+ for (const attr in eventObj) {
+ eventObj[attr][eventName]();
+ }
+ }
+
+ addToGlobal(apis) {
+ if (typeof globalThis !== 'undefined') {
+ for (let api in apis) {
+ globalThis[api] = apis[api];
+ }
+ }
+ for (const api in apis) {
+ this[api] = apis[api];
+ }
+ }
+
+ init() {
+ this.addService('suite', new SuiteService({id: 'default'}));
+ this.addService('spec', new SpecService({id: 'default'}));
+ this.addService('expect', new ExpectService({id: 'default'}));
+ this.addService('report', new ReportService({id: 'default'}));
+ this.addService('config', new ConfigService({id: 'default'}));
+ this.registerEvent('task', new TaskEvent({id: 'default', coreContext: this}));
+ this.registerEvent('suite', new SuiteEvent({id: 'default', coreContext: this}));
+ this.registerEvent('spec', new SpecEvent({id: 'default', coreContext: this}));
+ this.subscribeEvent('spec', this.getDefaultService('report'));
+ this.subscribeEvent('suite', this.getDefaultService('report'));
+ this.subscribeEvent('task', this.getDefaultService('report'));
+ const context = this;
+ for (const key in this.services) {
+ const serviceObj = this.services[key];
+ for (const serviceID in serviceObj) {
+ const service = serviceObj[serviceID];
+ service.init(context);
+
+ if (typeof service.apis !== 'function') {
+ continue;
+ }
+ const apis = service.apis();
+ if (apis) {
+ this.addToGlobal(apis);
+ }
+ }
+ }
+ }
+
+ execute() {
+ const suiteService = this.getDefaultService('suite');
+ suiteService.execute();
+ }
+}
+
+export default Core;
diff --git a/Ability/Sensormock/hypium/src/event.js b/Ability/Sensormock/hypium/src/event.js
new file mode 100644
index 0000000000000000000000000000000000000000..28299c36697a833d0a3e7887d2f3439271b69888
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/event.js
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+class SpecEvent {
+ constructor(attr) {
+ this.id = attr.id;
+ this.coreContext = attr.context;
+ this.eventMonitors = [];
+ }
+
+ subscribeEvent(service) {
+ this.eventMonitors.push(service);
+ }
+
+ specStart() {
+ for (let monitor in this.eventMonitors) {
+ this.eventMonitors[monitor]['specStart']();
+ }
+ }
+
+ specDone() {
+ for (const monitor in this.eventMonitors) {
+ this.eventMonitors[monitor]['specDone']();
+ }
+ }
+}
+
+class SuiteEvent {
+ constructor(attr) {
+ this.id = attr.id;
+ this.suiteContext = attr.coreContext;
+ this.eventMonitors = [];
+ }
+
+ subscribeEvent(service) {
+ this.eventMonitors.push(service);
+ }
+
+ suiteStart() {
+ for (let monitor in this.eventMonitors) {
+ this.eventMonitors[monitor]['suiteStart']();
+ }
+ }
+
+ suiteDone() {
+ for (let monitor in this.eventMonitors) {
+ this.eventMonitors[monitor]['suiteDone']();
+ }
+ }
+}
+
+class TaskEvent {
+ constructor(attr) {
+ this.id = attr.id;
+ this.coreContext = attr.coreContext;
+ this.eventMonitors = [];
+ }
+
+ subscribeEvent(service) {
+ this.eventMonitors.push(service);
+ }
+
+ taskStart() {
+ for (let monitor in this.eventMonitors) {
+ this.eventMonitors[monitor]['taskStart']();
+ }
+ }
+
+ taskDone() {
+ for (let monitor in this.eventMonitors) {
+ this.eventMonitors[monitor]['taskDone']();
+ }
+ }
+
+ incorrectFormat() {
+ for (let monitor in this.eventMonitors) {
+ this.eventMonitors[monitor]['incorrectFormat']();
+ }
+ }
+}
+
+export {SpecEvent, TaskEvent, SuiteEvent};
diff --git a/Ability/Sensormock/hypium/src/interface.js b/Ability/Sensormock/hypium/src/interface.js
new file mode 100644
index 0000000000000000000000000000000000000000..b4f145dccfa405f90d150a20abd8fd8d10539431
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/interface.js
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2021-2022 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 Core from './core';
+
+const core = Core.getInstance();
+
+const describe = function (desc, func) {
+ if (typeof globalThis !== 'undefined') {
+ return globalThis.describe(desc, func);
+ }
+ return core.describe(desc, func);
+};
+const it = function (desc, filter, func) {
+ if (typeof globalThis !== 'undefined') {
+ return globalThis.it(desc, filter, func);
+ }
+ return core.it(desc, filter, func);
+};
+const beforeEach = function (func) {
+ if (typeof globalThis !== 'undefined') {
+ return globalThis.beforeEach(func);
+ }
+ return core.beforeEach(func);
+};
+const afterEach = function (func) {
+ if (typeof globalThis !== 'undefined') {
+ return globalThis.afterEach(func);
+ }
+ return core.afterEach(func);
+};
+const beforeAll = function (func) {
+ if (typeof globalThis !== 'undefined') {
+ return globalThis.beforeAll(func);
+ }
+ return core.beforeAll(func);
+};
+const afterAll = function (func) {
+ if (typeof globalThis !== 'undefined') {
+ return globalThis.afterAll(func);
+ }
+ return core.afterAll(func);
+};
+const expect = function (actualValue) {
+ if (typeof globalThis !== 'undefined') {
+ return globalThis.expect(actualValue);
+ }
+ return core.expect(actualValue);
+};
+
+export {
+ describe, it, beforeAll, beforeEach, afterEach, afterAll, expect
+};
diff --git a/Ability/Sensormock/hypium/src/module/assert/ExpectExtend.js b/Ability/Sensormock/hypium/src/module/assert/ExpectExtend.js
new file mode 100644
index 0000000000000000000000000000000000000000..9ea94a9415bc5f7c5d7cfcddb94cab26a1f01e25
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/assert/ExpectExtend.js
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2021-2022 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 assertNull from './assertNull';
+import assertClose from './assertClose';
+import assertContain from './assertContain';
+import assertLess from './assertLess';
+import assertLarger from './assertLarger';
+import assertFail from './assertFail';
+import assertUndefined from './assertUndefined';
+import assertFalse from './assertFalse';
+import assertInstanceOf from './assertInstanceOf';
+import assertThrowError from './assertThrowError';
+
+class ExpectExtend {
+ constructor(attr) {
+ this.id = attr.id;
+ this.matchers = {};
+ }
+
+ extendsMatchers() {
+ this.matchers.assertNull = assertNull;
+ this.matchers.assertClose = assertClose;
+ this.matchers.assertContain = assertContain;
+ this.matchers.assertLess = assertLess;
+ this.matchers.assertLarger = assertLarger;
+ this.matchers.assertFail = assertFail;
+ this.matchers.assertUndefined = assertUndefined;
+ this.matchers.assertFalse = assertFalse;
+ this.matchers.assertInstanceOf = assertInstanceOf;
+ this.matchers.assertThrowError = assertThrowError;
+ }
+
+ init(coreContext) {
+ this.coreContext = coreContext;
+ this.extendsMatchers();
+ const expectService = this.coreContext.getDefaultService('expect');
+ expectService.addMatchers(this.matchers);
+ }
+
+ apis() {
+ return {
+ 'expect': function (actualValue) {
+ return this.coreContext.getDefaultService('expect').expect(actualValue);
+ }
+ };
+ }
+}
+
+export default ExpectExtend;
diff --git a/Ability/Sensormock/hypium/src/module/assert/assertClose.js b/Ability/Sensormock/hypium/src/module/assert/assertClose.js
new file mode 100644
index 0000000000000000000000000000000000000000..63635bea5bf1298776de565260e0e0babae56857
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/assert/assertClose.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+function assertClose(actualValue, expected) {
+ console.log('expected:' + expected[0] + ',precision:' + expected[1]);
+ if (actualValue === null && expected[0] === null) {
+ throw new Error('actualValue and expected can not be both null!!!');
+ }
+ let result;
+ let diff = Math.abs(expected[0] - actualValue);
+ let actualAbs = Math.abs(actualValue);
+ if ((actualAbs - 0) === 0) {
+ if ((diff - 0) === 0) {
+ result = true;
+ } else {
+ result = false;
+ }
+ } else if (diff / actualAbs < expected[1]) {
+ result = true;
+ } else {
+ result = false;
+ }
+ return {
+ pass: result,
+ message: '|' + actualValue + ' - ' + expected[0] + '|/' + actualValue + ' is not less than ' + expected[1]
+ };
+}
+
+export default assertClose;
diff --git a/Ability/Sensormock/hypium/src/module/assert/assertContain.js b/Ability/Sensormock/hypium/src/module/assert/assertContain.js
new file mode 100644
index 0000000000000000000000000000000000000000..6b33e08ba38479895bfa428957fd02224c08caa8
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/assert/assertContain.js
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+function assertContain(actualValue, expect) {
+ let result = false;
+ if (Object.prototype.toString.call(actualValue).indexOf('Array')) {
+ for (let i in actualValue) {
+ if (actualValue[i] == expect[0]) {
+ result = true;
+ }
+ }
+ }
+ let type = Object.prototype.toString.call(actualValue);
+ if (type === '[object String]') {
+ result = actualValue.indexOf(expect[0]) >= 0;
+ }
+ return {
+ pass: result,
+ message: 'except false, ' + actualValue + ' do not have ' + expect[0]
+ };
+}
+
+export default assertContain;
diff --git a/Ability/Sensormock/hypium/src/module/assert/assertFail.js b/Ability/Sensormock/hypium/src/module/assert/assertFail.js
new file mode 100644
index 0000000000000000000000000000000000000000..8ab4ac5caef712c75c4eac49dfbbb91d33669d9a
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/assert/assertFail.js
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+function assertFail() {
+ return {
+ pass: false,
+ message: 'fail '
+ };
+}
+
+export default assertFail;
diff --git a/Ability/Sensormock/hypium/src/module/assert/assertFalse.js b/Ability/Sensormock/hypium/src/module/assert/assertFalse.js
new file mode 100644
index 0000000000000000000000000000000000000000..5800fc7ffd0fdce8189d8af329beba830cfd8350
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/assert/assertFalse.js
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+function assertFalse(actualValue) {
+ return {
+ pass: (actualValue) === false,
+ message: 'except false, actualValue is ' + actualValue
+ };
+}
+
+export default assertFalse;
diff --git a/Ability/Sensormock/hypium/src/module/assert/assertInstanceOf.js b/Ability/Sensormock/hypium/src/module/assert/assertInstanceOf.js
new file mode 100644
index 0000000000000000000000000000000000000000..1e11b93f7251c67f5455c5007cd7be268aa53b32
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/assert/assertInstanceOf.js
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+function assertInstanceOf(actualValue, expected) {
+ if (Object.prototype.toString.call(actualValue) == '[object ' + expected[0] + ']') {
+ return {
+ pass: true
+ };
+ } else {
+ return {
+ pass: false,
+ message: actualValue + ' is ' + Object.prototype.toString.call(actualValue) + 'not ' + expected[0]
+ };
+ }
+}
+
+export default assertInstanceOf;
diff --git a/Ability/Sensormock/hypium/src/module/assert/assertLarger.js b/Ability/Sensormock/hypium/src/module/assert/assertLarger.js
new file mode 100644
index 0000000000000000000000000000000000000000..a74f4a8cedaf3add9c2dc2d3799081a83198732f
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/assert/assertLarger.js
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+function assertLarger(actualValue, expected) {
+ return {
+ pass: (actualValue) > expected[0],
+ message: (actualValue) + ' is not larger than ' + expected[0]
+ };
+}
+
+export default assertLarger;
diff --git a/Ability/Sensormock/hypium/src/module/assert/assertLess.js b/Ability/Sensormock/hypium/src/module/assert/assertLess.js
new file mode 100644
index 0000000000000000000000000000000000000000..17e84b0abaeb20804048a5a15c19e0603634846d
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/assert/assertLess.js
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+function assertLess(actualValue, expected) {
+ return {
+ pass: (actualValue) < expected[0],
+ message: (actualValue) + ' is not less than ' + expected[0]
+ };
+}
+
+export default assertLess;
diff --git a/Ability/Sensormock/hypium/src/module/assert/assertNull.js b/Ability/Sensormock/hypium/src/module/assert/assertNull.js
new file mode 100644
index 0000000000000000000000000000000000000000..53a7bad827323a98d3302a4e7eea679551b459c5
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/assert/assertNull.js
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+function assertNull(actualValue) {
+ return {
+ pass: (actualValue) === null,
+ message: 'expect null, actualValue is ' + (actualValue)
+ };
+}
+
+export default assertNull;
diff --git a/Ability/Sensormock/hypium/src/module/assert/assertThrowError.js b/Ability/Sensormock/hypium/src/module/assert/assertThrowError.js
new file mode 100644
index 0000000000000000000000000000000000000000..749cab0daee3f156909f60c9375146c23d7aa322
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/assert/assertThrowError.js
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+function assertThrowError(actualValue, expected) {
+ let result = false;
+ let err;
+ if (typeof actualValue !== 'function') {
+ throw new Error('actualValue is not a function');
+ }
+ try {
+ actualValue();
+ return {
+ pass: result,
+ message: ' An error is not thrown while it is expected!'
+ };
+ } catch (e) {
+ err = e;
+ }
+
+ if (err instanceof Error) {
+ console.log(err.message);
+ if (err.message == expected[0]) {
+ result = true;
+ }
+ }
+ return {
+ pass: result,
+ message: 'expected throw failed , ' + err.message + ' is not ' + expected[0]
+ };
+}
+
+export default assertThrowError;
diff --git a/Ability/Sensormock/hypium/src/module/assert/assertUndefined.js b/Ability/Sensormock/hypium/src/module/assert/assertUndefined.js
new file mode 100644
index 0000000000000000000000000000000000000000..61f092d715dd1630297518b59ff13ef0940991e1
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/assert/assertUndefined.js
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+function assertUndefined(actualValue) {
+ return {
+ pass: undefined === (actualValue),
+ message: 'expect Undefined, actualValue is ' + (actualValue)
+ };
+}
+
+export default assertUndefined;
diff --git a/Ability/Sensormock/hypium/src/module/assert/isPromiseLike.js b/Ability/Sensormock/hypium/src/module/assert/isPromiseLike.js
new file mode 100644
index 0000000000000000000000000000000000000000..015ab19a2a0c4872d7cb490b61f8e1dd6a8ac90b
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/assert/isPromiseLike.js
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+function isPromiseLike(obj) {
+ return !!obj && isFunction_(obj.then);
+}
+
+function isFunction_(value) {
+ return isA_('Function', value);
+}
+
+function isA_(typeName, value) {
+ return getType_(value) === '[object ' + typeName + ']';
+}
+
+function getType_(value) {
+ return Object.prototype.toString.apply(value);
+}
+
+export default isPromiseLike;
diff --git a/Ability/Sensormock/hypium/src/module/config/DataDriver.js b/Ability/Sensormock/hypium/src/module/config/DataDriver.js
new file mode 100644
index 0000000000000000000000000000000000000000..e521e455b26290fefae4c3bb5785b8d32271baad
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/config/DataDriver.js
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+const SUITES_KEY = 'suites';
+const SPECS_KEY = 'items';
+const DESCRIBE_KEY = 'describe';
+const IT_KEY = 'it';
+const PARAMS_KEY = 'params';
+const STRESS_KEY = 'stress';
+
+class ObjectUtils {
+ static get(object, name, defaultValue) {
+ let result = defaultValue;
+ for (const key in object) {
+ if (key === name) {
+ return object[key];
+ }
+ }
+ return result;
+ }
+
+ static has(object, key) {
+ return Object.prototype.hasOwnProperty.call(object, key);
+ }
+}
+
+class DataDriver {
+ constructor(attr) {
+ this.id = 'dataDriver';
+ this.data = attr.data || {};
+ }
+
+ init(coreContext) {
+ this.coreContext = coreContext;
+ this.suiteService = this.coreContext.getDefaultService('suite');
+ this.specService = this.coreContext.getDefaultService('spec');
+ }
+
+ getSpecParams() {
+ let specParams = [];
+ let suiteDesc = this.suiteService.getCurrentRunningSuite().description;
+ let specDesc = this.specService.getCurrentRunningSpec().description;
+ let suites = ObjectUtils.get(this.data, SUITES_KEY, []);
+ for (const suiteItem of suites) {
+ let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, '');
+ if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && describeValue === suiteDesc && (typeof describeValue === 'string') && describeValue.constructor === String) {
+ let specs = ObjectUtils.get(suiteItem, SPECS_KEY, []);
+ for (const specItem of specs) {
+ if (ObjectUtils.has(specItem, IT_KEY) && ObjectUtils.get(specItem, IT_KEY) === specDesc) {
+ return ObjectUtils.get(specItem, PARAMS_KEY, specParams);
+ }
+ }
+ }
+ }
+ return specParams;
+ }
+
+ getSuiteParams() {
+ let suiteParams = {};
+ let suiteDesc = this.suiteService.getCurrentRunningSuite().description;
+ let suites = ObjectUtils.get(this.data, SUITES_KEY, []);
+ for (const suiteItem of suites) {
+ let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, []);
+ if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) {
+ suiteParams = Object.assign({}, suiteParams, ObjectUtils.get(suiteItem, PARAMS_KEY, suiteParams));
+ }
+ }
+ return suiteParams;
+ }
+
+ getSpecStress(specDesc) {
+ let stress = 1;
+ let suiteDesc = this.suiteService.getCurrentRunningSuite().description;
+ let suites = ObjectUtils.get(this.data, SUITES_KEY, []);
+ for (const suiteItem of suites) {
+ let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, '');
+ if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && describeValue === suiteDesc && (typeof describeValue === 'string') && describeValue.constructor === String) {
+ let specs = ObjectUtils.get(suiteItem, SPECS_KEY, []);
+ for (const specItem of specs) {
+ if (ObjectUtils.has(specItem, IT_KEY) && ObjectUtils.get(specItem, IT_KEY) === specDesc) {
+ let tempStress = ObjectUtils.get(specItem, STRESS_KEY, stress);
+ return (Number.isInteger(tempStress) && tempStress >= 1) ? tempStress : stress;
+ }
+ }
+ }
+ }
+ return stress;
+ }
+
+ getSuiteStress(suiteDesc) {
+ let stress = 1;
+ let suites = ObjectUtils.get(this.data, SUITES_KEY, []);
+ for (const suiteItem of suites) {
+ let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, []);
+ if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && describeValue === suiteDesc && (typeof describeValue === 'string') && describeValue.constructor === String) {
+ let tempStress = ObjectUtils.get(suiteItem, STRESS_KEY, stress);
+ return (Number.isInteger(tempStress) && tempStress >= 1) ? tempStress : stress;
+ }
+ }
+ return stress;
+ }
+}
+
+export default DataDriver;
diff --git a/Ability/Sensormock/hypium/src/module/config/Filter.js b/Ability/Sensormock/hypium/src/module/config/Filter.js
new file mode 100644
index 0000000000000000000000000000000000000000..356e5bc4c00cc04375105461e3ae0acd43494d3e
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/config/Filter.js
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+class ClassFilter {
+ constructor(suiteName, itName, params) {
+ this.suiteName = suiteName;
+ this.itName = itName;
+ this.params = params;
+ }
+
+ filterSuite() {
+ return !this.params.split(',').map(item => item.split('#')[0]).map(item => item == this.suiteName).reduce((pre, cur) => pre || cur, false);
+ }
+
+ filterIt() {
+ let classArray = this.params.split(',') || [];
+ let suiteFilterResult = classArray.filter(item => !item.includes('#')).map(item => item == this.suiteName).reduce((pre, cur) => pre || cur, false);
+ let itFilterResult = classArray.filter(item => item.includes('#')).map(item => item == (this.suiteName + '#' + this.itName)).reduce((pre, cur) => pre || cur, false);
+ return !(suiteFilterResult || itFilterResult);
+ }
+}
+
+class NotClassFilter {
+ constructor(suiteName, itName, params) {
+ this.suiteName = suiteName;
+ this.itName = itName;
+ this.params = params;
+ }
+
+ filterSuite() {
+ return this.params.split(',').map(item => item == this.suiteName).reduce((pre, cur) => pre || cur, false);
+ }
+
+ filterIt() {
+ return this.params.includes(this.suiteName + '#' + this.itName);
+ }
+}
+
+class SuiteAndItNameFilter {
+ constructor(suiteName, itName, params) {
+ this.suiteName = suiteName;
+ this.itName = itName;
+ this.params = params;
+ }
+
+ filterSuite() {
+ return !this.params.split(',').map(item => item == this.suiteName).reduce((pre, cur) => pre || cur, false);
+ }
+
+ filterIt() {
+ return !this.params.split(',').map(item => item == this.itName).reduce((pre, cur) => pre || cur, false);
+ }
+}
+
+
+class TestTypesFilter {
+ constructor(suiteName, itName, fi, params) {
+ this.suiteName = suiteName;
+ this.itName = itName;
+ this.params = params;
+ this.fi = fi;
+ }
+
+ filterIt() {
+ return !((this.params === (this.fi & this.params)) || this.fi === 0);
+ }
+}
+
+export {ClassFilter, NotClassFilter, SuiteAndItNameFilter, TestTypesFilter};
diff --git a/Ability/Sensormock/hypium/src/module/config/configService.js b/Ability/Sensormock/hypium/src/module/config/configService.js
new file mode 100644
index 0000000000000000000000000000000000000000..682fd1431322dcfa60c05d781966454d80b29400
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/config/configService.js
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2021-2022 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 {ClassFilter, NotClassFilter, SuiteAndItNameFilter, TestTypesFilter} from './Filter';
+
+class ConfigService {
+ constructor(attr) {
+ this.id = attr.id;
+ this.supportAsync = false;
+ this.random = false;
+ this.filterValid = [];
+ }
+
+ init(coreContext) {
+ this.coreContext = coreContext;
+ }
+
+ isNormalInteger(str) {
+ const n = Math.floor(Number(str));
+ return n !== Infinity && String(n) === String(str) && n >= 0;
+ }
+
+ basicParamValidCheck(params) {
+ let size = params.size;
+ if (size !== undefined && size !== '' && size !== null) {
+ let sizeArray = ['small', 'medium', 'large'];
+ if (sizeArray.indexOf(size) === -1) {
+ this.filterValid.push('size:' + size);
+ }
+ }
+ let level = params.level;
+ if (level !== undefined && level !== '' && level !== null) {
+ let levelArray = ['0', '1', '2', '3', '4'];
+ if (levelArray.indexOf(level) === -1) {
+ this.filterValid.push('level:' + level);
+ }
+ }
+ let testType = params.testType;
+ if (testType !== undefined && testType !== '' && testType !== null) {
+ let testTypeArray = ['function', 'performance', 'power', 'reliability', 'security',
+ 'global', 'compatibility', 'user', 'standard', 'safety', 'resilience'];
+ if (testTypeArray.indexOf(testType) === -1) {
+ this.filterValid.push('testType:' + testType);
+ }
+ }
+ }
+
+ filterParamValidCheck(params) {
+ let timeout = params.timeout;
+ if (timeout !== undefined && timeout !== '' && timeout !== null) {
+ if (!this.isNormalInteger(timeout)) {
+ this.filterValid.push('timeout:' + timeout);
+ }
+ }
+
+ if (params.dryRun !== undefined && params.dryRun !== 'true' && params.dryRun !== 'false') {
+ this.filterValid.push('dryRun:' + params.dryRun);
+ }
+
+ let classes = params.class;
+ let nameRule = /^[A-Za-z]{1}[\w#,.]*$/;
+ if (classes !== undefined && classes !== '' && classes !== null) {
+ let classArray = classes.split(',');
+ for (let className of classArray) {
+ if (!className.match(nameRule)) {
+ this.filterValid.push('class:' + classes);
+ break;
+ }
+ }
+ }
+ let notClasses = params.notClass;
+ if (notClasses !== undefined && notClasses !== '' && notClasses !== null) {
+ let notClassArray = notClasses.split(',');
+ for (let notClassName of notClassArray) {
+ if (!notClassName.match(nameRule)) {
+ this.filterValid.push('notClass:' + notClasses);
+ break;
+ }
+ }
+ }
+ }
+
+ setConfig(params) {
+ this.basicParamValidCheck(params);
+ this.filterParamValidCheck(params);
+ try {
+ this.class = params.class;
+ this.notClass = params.notClass;
+ this.flag = params.flag || {flag: false};
+ this.suite = params.suite;
+ this.itName = params.itName;
+ this.filter = params.filter;
+ this.testType = params.testType;
+ this.level = params.level;
+ this.size = params.size;
+ this.timeout = params.timeout;
+ this.filterParam = {
+ testType: {
+ 'function': 1,
+ 'performance': 1 << 1,
+ 'power': 1 << 2,
+ 'reliability': 1 << 3,
+ 'security': 1 << 4,
+ 'global': 1 << 5,
+ 'compatibility': 1 << 6,
+ 'user': 1 << 7,
+ 'standard': 1 << 8,
+ 'safety': 1 << 9,
+ 'resilience': 1 << 10,
+ },
+ level: {
+ '0': 1 << 24,
+ '1': 1 << 25,
+ '2': 1 << 26,
+ '3': 1 << 27,
+ '4': 1 << 28,
+ },
+ size: {
+ 'small': 1 << 16,
+ 'medium': 1 << 17,
+ 'large': 1 << 18,
+ }
+ };
+ this.parseParams();
+ } catch (err) {
+ this.filter = 0;
+ this.flag = false;
+ this.suite = null;
+ this.itName = null;
+ this.testType = null;
+ this.level = null;
+ this.size = null;
+ this.class = null;
+ this.notClass = null;
+ this.timeout = null;
+ }
+ }
+
+ parseParams() {
+ if (this.filter != null) {
+ return;
+ }
+ let testTypeFilter = 0;
+ let sizeFilter = 0;
+ let levelFilter = 0;
+ if (this.testType != null) {
+ testTypeFilter = this.testType.split(',')
+ .map(item => this.filterParam.testType[item] || 0)
+ .reduce((pre, cur) => pre | cur, 0);
+ }
+ if (this.level != null) {
+ levelFilter = this.level.split(',')
+ .map(item => this.filterParam.level[item] || 0)
+ .reduce((pre, cur) => pre | cur, 0);
+ }
+ if (this.size != null) {
+ sizeFilter = this.size.split(',')
+ .map(item => this.filterParam.size[item] || 0)
+ .reduce((pre, cur) => pre | cur, 0);
+ }
+ this.filter = testTypeFilter | sizeFilter | levelFilter;
+ console.info('filter params:' + this.filter);
+ }
+
+ isCurrentSuite(description) {
+ if (this.suite !== undefined && this.suite !== '' && this.suite !== null) {
+ let suiteArray = this.suite.split(',');
+ return suiteArray.indexOf(description) !== -1;
+ }
+ return false;
+ }
+
+ filterSuite(currentSuiteName) {
+ let filterArray = [];
+ if (this.suite !== undefined && this.suite !== '' && this.suite !== null) {
+ filterArray.push(new SuiteAndItNameFilter(currentSuiteName, '', this.suite));
+ }
+ if (this.class !== undefined && this.class !== '' && this.class !== null) {
+ filterArray.push(new ClassFilter(currentSuiteName, '', this.class));
+ }
+ if (this.notClass !== undefined && this.notClass !== '' && this.notClass !== null) {
+ filterArray.push(new NotClassFilter(currentSuiteName, '', this.notClass));
+ }
+
+ let result = filterArray.map(item => item.filterSuite()).reduce((pre, cur) => pre || cur, false);
+ return result;
+ }
+
+ filterDesc(currentSuiteName, desc, fi, coreContext) {
+ let filterArray = [];
+ if (this.itName !== undefined && this.itName !== '' && this.itName !== null) {
+ filterArray.push(new SuiteAndItNameFilter(currentSuiteName, desc, this.itName));
+ }
+ if (this.class !== undefined && this.class !== '' && this.class !== null) {
+ filterArray.push(new ClassFilter(currentSuiteName, desc, this.class));
+ }
+ if (this.notClass !== undefined && this.notClass !== '' && this.notClass !== null) {
+ filterArray.push(new NotClassFilter(currentSuiteName, desc, this.notClass));
+ }
+ if (typeof (this.filter) !== 'undefined' && this.filter !== 0 && fi !== 0) {
+ filterArray.push(new TestTypesFilter('', '', fi, this.filter));
+ }
+ let result = filterArray.map(item => item.filterIt()).reduce((pre, cur) => pre || cur, false);
+ return result;
+ }
+
+ isRandom() {
+ return this.random || false;
+ }
+
+ setSupportAsync(value) {
+ this.supportAsync = value;
+ }
+
+ isSupportAsync() {
+ return this.supportAsync;
+ }
+
+ translateParams(parameters) {
+ const keySet = new Set([
+ '-s class', '-s notClass', '-s suite', '-s itName',
+ '-s level', '-s testType', '-s size', '-s timeout',
+ '-s dryRun', 'class', 'notClass', 'suite', 'itName',
+ 'level', 'testType', 'size', 'timeout', 'dryRun'
+ ]);
+ let targetParams = {};
+ for (const key in parameters) {
+ if (keySet.has(key)) {
+ var newKey = key.replace("-s ", "");
+ targetParams[newKey] = parameters[key];
+ }
+ }
+ return targetParams;
+ }
+ translateParamsToString(parameters) {
+ const keySet = new Set([
+ '-s class', '-s notClass', '-s suite', '-s itName',
+ '-s level', '-s testType', '-s size', '-s timeout',
+ '-s dryRun', 'class', 'notClass', 'suite', 'itName',
+ 'level', 'testType', 'size', 'timeout', 'dryRun'
+ ]);
+ let targetParams = '';
+ for (const key in parameters) {
+ if (keySet.has(key)) {
+ targetParams += ' ' + key + ' ' + parameters[key];
+ }
+ }
+ return targetParams.trim();
+ }
+
+ execute() {
+ }
+}
+
+export {
+ ConfigService
+};
diff --git a/Ability/Sensormock/hypium/src/module/kit/SysTestKit.js b/Ability/Sensormock/hypium/src/module/kit/SysTestKit.js
new file mode 100644
index 0000000000000000000000000000000000000000..ded7e4bde5939f718da025c519ae5d23d92e6abb
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/kit/SysTestKit.js
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2022 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.
+ */
+
+class SysTestKit {
+
+ static delegator = null;
+
+ constructor() {
+ this.id = 'sysTestKit';
+ this.index = 0;
+ }
+
+ static actionStart(tag) {
+ console.info(JSON.stringify(tag));
+ var message = '\n' + 'OHOS_REPORT_ACTIONSTART: ' + JSON.stringify(tag) + '\n';
+ SysTestKit.delegator.print(message).then(() => {
+ console.info(tag + ' actionStart print success');
+ });
+ }
+
+ static actionEnd(tag) {
+ console.info(JSON.stringify(tag));
+ var message = '\n' + 'OHOS_REPORT_ACTIONEND: ' + JSON.stringify(tag) + '\n';
+ SysTestKit.delegator.print(message).then(() => {
+ console.info(tag + ' actionEnd print success');
+ });
+ }
+
+ static async existKeyword(keyword, timeout) {
+ keyword = keyword || 'jsapp';
+ timeout = timeout || 4;
+
+ let searchResult = false;
+ let cmd = 'hilog -x | grep -i \'' + keyword + '\' | wc -l';
+ await executePromise(cmd, timeout).then((data) => {
+ searchResult = data;
+ });
+ return searchResult;
+ }
+}
+
+function executePromise(cmd, timeout) {
+ return new Promise((resolve, reject) => {
+ SysTestKit.delegator.executeShellCommand(cmd, timeout,
+ (error, data) => {
+ console.info('existKeyword CallBack: err : ' + JSON.stringify(error));
+ console.info('existKeyword CallBack: data : ' + JSON.stringify(data));
+ resolve(parseInt(data.stdResult) > 3 ? true : false);
+ });
+ });
+}
+
+export default SysTestKit;
\ No newline at end of file
diff --git a/Ability/Sensormock/hypium/src/module/mock/ArgumentMatchers.js b/Ability/Sensormock/hypium/src/module/mock/ArgumentMatchers.js
new file mode 100644
index 0000000000000000000000000000000000000000..6a9d7aac464e95383ea31385284b6603c34e084c
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/mock/ArgumentMatchers.js
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2022 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.
+ */
+
+class ArgumentMatchers {
+ ANY = "";
+ ANY_STRING = "";
+ ANY_BOOLEAN = "";
+ ANY_NUMBER = "";
+ ANY_OBJECT = "";
+ ANY_FUNCTION = "";
+ MATCH_REGEXS = "";
+
+ static any() {
+ }
+
+ static anyString() {
+ }
+
+ static anyBoolean() {
+ }
+
+ static anyNumber() {
+ }
+
+ static anyObj() {
+ }
+
+ static anyFunction() {
+ }
+
+ static matchRegexs() {
+ let regex = arguments[0];
+ if (ArgumentMatchers.isRegExp(regex)) {
+ return regex;
+ }
+ throw Error("not a regex");
+ }
+
+ static isRegExp(value) {
+ return Object.prototype.toString.call(value) === "[object RegExp]";
+ }
+
+ matcheReturnKey() {
+ let arg = arguments[0];
+ let regex = arguments[1];
+ let stubSetKey = arguments[2];
+
+ if (stubSetKey && stubSetKey == this.ANY) {
+ return this.ANY;
+ }
+
+ if (typeof arg === "string" && !regex) {
+ return this.ANY_STRING;
+ }
+
+ if (typeof arg === "boolean" && !regex) {
+ return this.ANY_BOOLEAN;
+ }
+
+ if (typeof arg === "number" && !regex) {
+ return this.ANY_NUMBER;
+ }
+
+ if (typeof arg === "object" && !regex) {
+ return this.ANY_OBJECT;
+ }
+
+ if (typeof arg === "function" && !regex) {
+ return this.ANY_FUNCTION;
+ }
+
+ if (typeof arg === "string" && regex) {
+ return regex.test(arg);
+ }
+
+ return null;
+ }
+
+ matcheStubKey() {
+ let key = arguments[0];
+
+ if (key === ArgumentMatchers.any) {
+ return this.ANY;
+ }
+
+ if (key === ArgumentMatchers.anyString) {
+ return this.ANY_STRING;
+ }
+ if (key === ArgumentMatchers.anyBoolean) {
+ return this.ANY_BOOLEAN;
+ }
+ if (key === ArgumentMatchers.anyNumber) {
+ return this.ANY_NUMBER;
+ }
+ if (key === ArgumentMatchers.anyObj) {
+ return this.ANY_OBJECT;
+ }
+ if (key === ArgumentMatchers.anyFunction) {
+ return this.ANY_FUNCTION;
+ }
+
+ if (ArgumentMatchers.isRegExp(key)) {
+ return key;
+ }
+
+ return null;
+ }
+}
+
+export default ArgumentMatchers;
\ No newline at end of file
diff --git a/Ability/Sensormock/hypium/src/module/mock/ExtendInterface.js b/Ability/Sensormock/hypium/src/module/mock/ExtendInterface.js
new file mode 100644
index 0000000000000000000000000000000000000000..c6a866a6df662ad10a7f6869dcbc2381fa47bcdc
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/mock/ExtendInterface.js
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2022 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.
+ */
+
+class ExtendInterface {
+ constructor(mocker) {
+ this.mocker = mocker;
+ }
+
+ stub() {
+ this.params = arguments;
+ return this;
+ }
+
+ stubMockedCall(returnInfo) {
+ this.mocker.stubApply(this, this.params, returnInfo);
+ }
+
+ afterReturn(value) {
+ this.stubMockedCall(function () {
+ return value;
+ });
+ }
+
+ afterReturnNothing() {
+ this.stubMockedCall(function () {
+ return undefined;
+ });
+ }
+
+ afterAction(action) {
+ this.stubMockedCall(action);
+ }
+
+ afterThrow(msg) {
+ this.stubMockedCall(function () {
+ throw msg;
+ });
+ }
+
+ clear() {
+ this.mocker.clear();
+ }
+}
+
+export default ExtendInterface;
\ No newline at end of file
diff --git a/Ability/Sensormock/hypium/src/module/mock/MockKit.js b/Ability/Sensormock/hypium/src/module/mock/MockKit.js
new file mode 100644
index 0000000000000000000000000000000000000000..bcd7768c5d7aa1678f841e6f91d9e61253e91ac3
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/mock/MockKit.js
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2022 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 ExtendInterface from "./ExtendInterface";
+import VerificationMode from "./VerificationMode";
+import ArgumentMatchers from "./ArgumentMatchers";
+
+class MockKit {
+ constructor() {
+ this.mFunctions = [];
+ this.stubs = new Map();
+ this.recordCalls = new Map();
+ this.currentSetKey = null;
+ this.mockObj = null;
+ this.recordMockedMethod = new Map();
+ }
+
+ init() {
+ this.reset();
+ }
+
+ reset() {
+ this.mFunctions = [];
+ this.stubs = {};
+ this.recordCalls = {};
+ this.currentSetKey = null;
+ this.mockObj = null;
+ this.recordMockedMethod = new Map();
+ }
+
+ clearAll() {
+ this.reset();
+ var props = Object.keys(this);
+ for (var i = 0; i < props.length; i++) {
+ delete this[props[i]];
+ }
+
+ var props = Object.getOwnPropertyNames(this);
+ for (var i = 0; i < props.length; i++) {
+ delete this[props[i]];
+ }
+ for (var key in this) {
+ delete this[key];
+ }
+ }
+
+ clear(obj) {
+ if (!obj) throw Error("Please enter an object to be cleaned");
+ if (typeof (obj) != 'object') throw new Error('Not a object');
+ this.recordMockedMethod.forEach(function (value, key, map) {
+ if (key) {
+ obj[key] = value;
+ }
+ });
+ }
+
+ ignoreMock(obj, method) {
+ if (typeof (obj) != 'object') throw new Error('Not a object');
+ if (typeof (method) != 'function') throw new Error('Not a function');
+ let og = this.recordMockedMethod.get(method.propName);
+ if (og) {
+ obj[method.propName] = og;
+ this.recordMockedMethod.set(method.propName, undefined);
+ }
+ }
+
+ extend(dest, source) {
+ dest["stub"] = source["stub"];
+ dest["afterReturn"] = source["afterReturn"];
+ dest["afterReturnNothing"] = source["afterReturnNothing"];
+ dest["afterAction"] = source["afterAction"];
+ dest["afterThrow"] = source["afterThrow"];
+ dest["stubMockedCall"] = source["stubMockedCall"];
+ dest["clear"] = source["clear"];
+ return dest;
+ }
+
+ stubApply(f, params, returnInfo) {
+ let values = this.stubs.get(f);
+ if (!values) {
+ values = new Map();
+ }
+ let key = params[0];
+ let matcher = new ArgumentMatchers();
+ if (matcher.matcheStubKey(key)) {
+ key = matcher.matcheStubKey(key);
+ if (key) {
+ this.currentSetKey = key;
+ }
+ }
+ values.set(key, returnInfo);
+ console.info(
+ "set stub:" + f + ";" + "key:" + key + ",returnInfo:" + returnInfo
+ );
+ this.stubs.set(f, values);
+ }
+
+ getReturnInfo(f, params) {
+ let values = this.stubs.get(f);
+ console.info(
+ "getReruntInfo:" + f + ",values:" + values + ",params:" + params[0]
+ );
+
+ if (!values) {
+ return undefined;
+ }
+ let retrunKet = params[0];
+ let stubSetKey = this.currentSetKey;
+
+ if (this.currentSetKey && retrunKet) {
+ retrunKet = stubSetKey;
+
+ }
+ let matcher = new ArgumentMatchers();
+ if (matcher.matcheReturnKey(params[0], undefined, stubSetKey) && matcher.matcheReturnKey(params[0], undefined, stubSetKey) != stubSetKey) {
+ retrunKet = params[0];
+ }
+
+ values.forEach(function (value, key, map) {
+ if (ArgumentMatchers.isRegExp(key) && matcher.matcheReturnKey(params[0], key)) {
+ retrunKet = key;
+ }
+ });
+
+ console.info("detail:" + values.get(retrunKet));
+ return values.get(retrunKet);
+ }
+
+ findName(obj, value) {
+ let properties = this.findProperties(obj);
+ let name = null;
+ properties.forEach(
+ function (va1, idx, array) {
+ if (obj[va1] === value) {
+ name = va1;
+ }
+ }
+ );
+ return name;
+ }
+
+ isFunctionFromPrototype(f, container, propName) {
+ if (container.constructor != Object && container.constructor.prototype !== container) {
+ return container.constructor.prototype[propName] === f;
+ }
+ return false;
+ }
+
+ findProperties(obj, ...arg) {
+
+ function getProperty(new_obj) {
+ if (new_obj.__proto__ === null) {
+ return [];
+ }
+ let properties = Object.getOwnPropertyNames(new_obj);
+ return [...properties, ...getProperty(new_obj.__proto__)];
+ }
+
+ return getProperty(obj);
+ }
+
+ recordMethodCall(originalMethod, args) {
+ Function.prototype.getName = function () {
+ return this.name || this.toString().match(/function\s*([^(]*)\(/)[1];
+ };
+ let name = originalMethod.getName();
+ let arglistString = name + '(' + Array.from(args).toString() + ')';
+ let records = this.recordCalls.get(arglistString);
+ console.log(records);
+ if (!records) {
+ records = 0;
+ }
+ records++;
+ this.recordCalls.set(arglistString, records);
+ }
+
+ mockFunc(originalObject, originalMethod) {
+ let tmp = this;
+ this.originalMethod = originalMethod;
+ let f = function () {
+ let args = arguments;
+ let action = tmp.getReturnInfo(f, args);
+ if (originalMethod) {
+ tmp.recordMethodCall(originalMethod, args);
+ }
+ //1.0.3版本 新改动
+ if (action) {
+ let result = action.apply(this, args);
+ if (args[1] && typeof args[1] == 'function') {
+ if (args[2]) {
+ let time = 0;
+ for (let o in args[2]) {
+ if (o == 'interval') {
+ time = args[2][o];
+ }
+ }
+ setInterval(args[1](result), time / 1000000 > 0 ? time / 1000000 : 2000);
+ } else {
+ args[1](result);
+ }
+ }
+ return result;
+ }
+ ;
+ };
+
+ f.container = null || originalObject;
+ f.original = originalMethod || null;
+
+ if (originalObject && originalMethod) {
+ if (typeof (originalMethod) != 'function') throw new Error('Not a function');
+ var name = this.findName(originalObject, originalMethod);
+ originalObject[name] = f;
+ this.recordMockedMethod.set(name, originalMethod);
+ f.propName = name;
+ f.originalFromPrototype = this.isFunctionFromPrototype(f.original, originalObject, f.propName);
+ }
+ f.mocker = this;
+ this.mFunctions.push(f);
+ this.extend(f, new ExtendInterface(this));
+ return f;
+ }
+
+ verify(methodName, argsArray) {
+ if (!methodName) {
+ throw Error("not a function name");
+ }
+ let a = this.recordCalls.get(methodName + '(' + argsArray.toString() + ')');
+ return new VerificationMode(a ? a : 0);
+ }
+
+ /**
+ * 1.0.3版本 传感器,地理位置模拟新增接口
+ * @param object
+ */
+ mockObject(object) {
+ if (!object || typeof object === "string") {
+ throw Error(`this ${object} cannot be mocked`);
+ }
+ const _this = this;
+ let mockedObject = {};
+ let keys = Reflect.ownKeys(object);
+ keys.filter(key => (typeof Reflect.get(object, key)) === 'function')
+ .forEach(key => {
+ mockedObject[key] = object[key];
+ mockedObject[key] = _this.mockFunc(mockedObject, mockedObject[key]);
+ });
+ return mockedObject;
+ }
+}
+
+function ifMockedFunction(f) {
+ if (Object.prototype.toString.call(f) != "[object Function]" &&
+ Object.prototype.toString.call(f) != "[object AsyncFunction]") {
+ throw Error("not a function");
+ }
+ if (!f.stub) {
+ throw Error("not a mock function");
+ }
+ return true;
+}
+
+function when(f) {
+ if (ifMockedFunction(f)) {
+ return f.stub.bind(f);
+ }
+}
+
+export { MockKit, when };
\ No newline at end of file
diff --git a/Ability/Sensormock/hypium/src/module/mock/VerificationMode.js b/Ability/Sensormock/hypium/src/module/mock/VerificationMode.js
new file mode 100644
index 0000000000000000000000000000000000000000..8103a86399e53e725e45e40985b280b1d0a0b153
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/mock/VerificationMode.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2022 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 {expect} from "@ohos/hypium";
+
+class VerificationMode {
+ constructor(times) {
+ this.doTimes = times;
+ }
+
+ times(count) {
+ expect(count).assertEqual(this.doTimes);
+ }
+
+ never() {
+ console.log(this.doTimes);
+ expect(0).assertEqual(this.doTimes);
+ }
+
+ once() {
+ expect(1).assertEqual(this.doTimes);
+ }
+
+ atLeast(count) {
+ if (count > this.doTimes) {
+ throw Error('failed ' + count + ' greater than the actual execution times of method');
+ }
+ }
+
+ atMost(count) {
+ if (count < this.doTimes) {
+ throw Error('failed ' + count + ' less than the actual execution times of method');
+ }
+ }
+}
+
+export default VerificationMode;
\ No newline at end of file
diff --git a/Ability/Sensormock/hypium/src/module/report/OhReport.js b/Ability/Sensormock/hypium/src/module/report/OhReport.js
new file mode 100644
index 0000000000000000000000000000000000000000..0ee22a8782345b6d707c1f383e79bf0970523cff
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/report/OhReport.js
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+class OhReport {
+ constructor(attr) {
+ this.delegator = attr.delegator;
+ this.id = 'report';
+ this.index = 0;
+ this.duration = 0;
+ }
+
+ init(coreContext) {
+ this.coreContext = coreContext;
+ this.suiteService = this.coreContext.getDefaultService('suite');
+ this.specService = this.coreContext.getDefaultService('spec');
+ }
+
+ taskStart() {
+ this.taskStartTime = new Date().getTime();
+ }
+
+ taskDone() {
+ this.taskDoneTime = new Date().getTime();
+ this.duration = this.taskDoneTime - this.taskStartTime;
+ let summary = this.suiteService.getSummary();
+ var message = '\n' + 'OHOS_REPORT_RESULT: stream=Tests run: ' + summary.total + ', Failure: ' + summary.failure;
+ message += ', Error: ' + summary.error;
+ message += ', Pass: ' + summary.pass;
+ message += '\n' + 'OHOS_REPORT_CODE: ' + (summary.failure > 0 ? -1 : 0) + '\n';
+ message += 'OHOS_REPORT_STATUS: consuming=' + this.duration + '\n';
+ this.delegator.print(message).then(() => {
+ console.info('report print success');
+ this.delegator.finishTest('your test finished!!!', 0, () => { });
+ });
+ }
+
+ incorrectFormat() {
+ if (this.coreContext.getDefaultService('config').filterValid.length !== 0) {
+ var value = this.coreContext.getDefaultService('config').filterValid;
+ var message = 'this param ' + value.join(',') + ' is invalid' + '\n';
+ this.delegator.finishTest(message, 0, () => { });
+ }
+ }
+
+ suiteStart() {
+ let suiteService = this.coreContext.getDefaultService('suite');
+ var message = '\n' + 'OHOS_REPORT_SUM: ' + suiteService.getSummary().total;
+ message += '\n' + 'OHOS_REPORT_STATUS: class=' + suiteService.getCurrentRunningSuite().description + '\n';
+ this.delegator.print(message).then(() => {
+ console.info(suiteService.getCurrentRunningSuite().description + ' print success');
+ });
+ }
+
+ suiteDone() {
+ var message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description;
+ message += '\n' + 'OHOS_REPORT_STATUS: consuming=' + this.suiteService.currentRunningSuite.duration + '\n';
+ this.delegator.print(message).then(() => {
+ console.info(suiteService.getCurrentRunningSuite().description + ' print success');
+ });
+ }
+
+ specStart() {
+ let suiteService = this.coreContext.getDefaultService('suite');
+ var message = '\n' + 'OHOS_REPORT_STATUS: class=' + suiteService.getCurrentRunningSuite().description;
+ message += '\n' + 'OHOS_REPORT_STATUS: current=' + (++this.index);
+ message += '\n' + 'OHOS_REPORT_STATUS: id=JS';
+ message += '\n' + 'OHOS_REPORT_STATUS: numtests=' + suiteService.getSummary().total;
+ message += '\n' + 'OHOS_REPORT_STATUS: stream=';
+ message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description;
+ message += '\n' + 'OHOS_REPORT_STATUS_CODE: 1' + '\n';
+ this.delegator.print(message).then(() => {
+ console.info(this.specService.currentRunningSpec.description + ' start print success');
+ });
+ }
+
+ specDone() {
+ var message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description;
+ message += '\n' + 'OHOS_REPORT_STATUS: current=' + (this.index);
+ message += '\n' + 'OHOS_REPORT_STATUS: id=JS';
+ message += '\n' + 'OHOS_REPORT_STATUS: numtests=' + this.suiteService.getSummary().total;
+ let emsg = '';
+ if (this.specService.currentRunningSpec.error) {
+ message += '\n' + 'OHOS_REPORT_STATUS: stack=' + this.specService.currentRunningSpec.error;
+ message += '\n' + 'OHOS_REPORT_STATUS: stream=';
+ message += '\n' + 'Error in ' + this.specService.currentRunningSpec.description;
+ message += '\n' + this.specService.currentRunningSpec.error;
+ message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description;
+ message += '\n' + 'OHOS_REPORT_STATUS_CODE: -1' + '\n';
+ } else if (this.specService.currentRunningSpec.result) {
+ if (this.specService.currentRunningSpec.result.failExpects.length > 0) {
+ this.specService.currentRunningSpec.result.failExpects.forEach(failExpect => {
+ emsg = failExpect.message || ('expect ' + failExpect.actualValue + ' ' + failExpect.checkFunc + ' ' + (failExpect.expectValue || ''));
+ });
+ message += '\n' + 'OHOS_REPORT_STATUS: stack=' + emsg;
+ message += '\n' + 'OHOS_REPORT_STATUS: stream=';
+ message += '\n' + 'Error in ' + this.specService.currentRunningSpec.description;
+ message += '\n' + emsg + '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description;
+ message += '\n' + 'OHOS_REPORT_STATUS_CODE: -2' + '\n';
+ } else {
+ message += '\n' + 'OHOS_REPORT_STATUS: stream=';
+ message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description;
+ message += '\n' + 'OHOS_REPORT_STATUS_CODE: 0' + '\n';
+ }
+ } else {
+ message += '\n';
+ }
+ message += 'OHOS_REPORT_STATUS: consuming=' + this.specService.currentRunningSpec.duration + '\n';
+ this.delegator.print(message).then(() => {
+ console.info(this.specService.currentRunningSpec.description + ' end print success');
+ });
+ }
+}
+
+export default OhReport;
diff --git a/Ability/Sensormock/hypium/src/module/report/ReportExtend.js b/Ability/Sensormock/hypium/src/module/report/ReportExtend.js
new file mode 100644
index 0000000000000000000000000000000000000000..852fbcd5cbf97e776ebe5177a029df0f516594a5
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/module/report/ReportExtend.js
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+class ReportExtend {
+ constructor(fileModule) {
+ this.id = 'extend';
+ this.fileModule = fileModule;
+ }
+
+ init(coreContext) {
+ this.coreContext = coreContext;
+ this.suiteService = this.coreContext.getDefaultService('suite');
+ }
+
+ taskStart() {
+
+ }
+
+ taskDone() {
+ const report = {
+ tag: 'testsuites',
+ name: 'summary_report',
+ timestamp: new Date().toDateString(),
+ time: '1',
+ errors: 0,
+ failures: 0,
+ tests: 0,
+ children: []
+ };
+ const rootSuite = this.suiteService.rootSuite;
+ if (rootSuite && rootSuite.childSuites) {
+ for (let testsuite of rootSuite.childSuites) {
+ let suiteReport = {
+ tag: 'testsuite',
+ name: testsuite['description'],
+ errors: 0,
+ tests: 0,
+ failures: 0,
+ time: '0.1',
+ children: []
+ };
+ let specs = testsuite['specs'];
+ for (let testcase of specs) {
+ report.tests++;
+ suiteReport.tests++;
+ let caseReport = {
+ tag: 'testcase',
+ name: testcase['description'],
+ status: 'run',
+ time: '0.0',
+ classname: testsuite['description']
+ };
+ if (testcase.error) {
+ caseReport['result'] = false;
+ caseReport['children'] = [{
+ tag: 'error',
+ type: '',
+ message: testcase.error.message
+ }];
+ report.errors++;
+ suiteReport.errors++;
+ } else if (testcase.result.failExpects.length > 0) {
+ caseReport['result'] = false;
+ let message = '';
+ testcase.result.failExpects.forEach(failExpect => {
+ message += failExpect.message || ('expect ' + failExpect.actualValue + ' ' + failExpect.checkFunc + ' ' + (failExpect.expectValue || '')) + ';';
+ });
+ caseReport['children'] = [{
+ tag: 'failure',
+ type: '',
+ message: message
+ }];
+ report.failures++;
+ suiteReport.failures++;
+ } else {
+ caseReport['result'] = true;
+ }
+ suiteReport.children.push(caseReport);
+ }
+ report.children.push(suiteReport);
+ }
+ }
+
+ let reportXml = '\n' + json2xml(report);
+ this.fileModule.writeText({
+ uri: 'internal://app/report.xml',
+ text: reportXml,
+ success: function () {
+ console.info('call success callback success');
+ },
+ fail: function (data, code) {
+ console.info('call fail callback success:');
+ },
+ complete: function () {
+ console.info('call complete callback success');
+ }
+ });
+ }
+}
+
+function json2xml(json) {
+ let tagName;
+ let hasChildren = false;
+ let childrenStr = '';
+ let attrStr = '';
+ for (let key in json) {
+ if (key === 'tag') {
+ tagName = json[key];
+ } else if (key === 'children') {
+ if (json[key].length > 0) {
+ hasChildren = true;
+ for (let child of json[key]) {
+ childrenStr += json2xml(child);
+ }
+ }
+ } else {
+ attrStr += ` ${key}="${json[key]}"`;
+ }
+ }
+ let xml = `<${tagName}${attrStr}`;
+ xml += hasChildren ? `>${childrenStr}${tagName}>` : '/>';
+ return xml;
+}
+
+export default ReportExtend;
diff --git a/Ability/Sensormock/hypium/src/service.js b/Ability/Sensormock/hypium/src/service.js
new file mode 100644
index 0000000000000000000000000000000000000000..dc74de3c4d5c6b5cb9e878c3d858f6729adfdf29
--- /dev/null
+++ b/Ability/Sensormock/hypium/src/service.js
@@ -0,0 +1,702 @@
+/*
+ * Copyright (c) 2021-2022 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.
+ */
+
+function processFunc(coreContext, func) {
+ let argNames = ((func || '').toString()
+ .replace(/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg, '')
+ .match(/^(function)?\s*[^\(]*\(\s*([^\)]*)\)/m) || ['', '', ''])[2]
+ .split(',') // split parameters
+ .map(item => item.replace(/^\s*(_?)(.+?)\1\s*$/, name => name.split('=')[0].trim()))
+ .filter(String);
+ let funcLen = func.length;
+ let processedFunc;
+ coreContext.getDefaultService('config').setSupportAsync(true);
+ switch (funcLen) {
+ case 0: {
+ processedFunc = func;
+ break;
+ }
+ case 1: {
+ if (argNames[0] === 'data') {
+ processedFunc = function (paramItem) {
+ func(paramItem);
+ };
+ } else {
+ processedFunc = function () {
+ return new Promise((resolve, reject) => {
+ function done() {
+ resolve();
+ }
+
+ let funcType = func(done);
+ if (funcType instanceof Promise) {
+ funcType.catch(err => {reject(err);});
+ }
+ });
+ };
+ }
+ break;
+ }
+ default: {
+ processedFunc = function (paramItem) {
+ return new Promise((resolve, reject) => {
+ function done() {
+ resolve();
+ }
+
+ let funcType = func(done, paramItem);
+ if (funcType instanceof Promise) {
+ funcType.catch(err => {reject(err);});
+ }
+ });
+ };
+ break;
+ }
+ }
+ return processedFunc;
+}
+
+function secureRandomNumber() {
+ return crypto.randomBytes(8).readUInt32LE() / 0xffffffff;
+}
+
+class SuiteService {
+ constructor(attr) {
+ this.id = attr.id;
+ this.rootSuite = new SuiteService.Suite({});
+ this.currentRunningSuite = this.rootSuite;
+ }
+
+ describe(desc, func) {
+ if (this.coreContext.getDefaultService('config').filterSuite(desc)) {
+ console.info('filter suite :' + desc);
+ return;
+ }
+ const suite = new SuiteService.Suite({description: desc});
+ if (typeof this.coreContext.getServices('dataDriver') !== 'undefined') {
+ let suiteStress = this.coreContext.getServices('dataDriver').dataDriver.getSuiteStress(desc);
+ for (let i = 1; i < suiteStress; i++) {
+ this.currentRunningSuite.childSuites.push(suite);
+ }
+ }
+ const currentSuiteCache = this.currentRunningSuite;
+ this.currentRunningSuite.childSuites.push(suite);
+ this.currentRunningSuite = suite;
+ func.call();
+ this.currentRunningSuite = currentSuiteCache;
+ }
+
+ beforeAll(func) {
+ this.currentRunningSuite.beforeAll.push(processFunc(this.coreContext, func));
+ }
+
+ beforeEach(func) {
+ this.currentRunningSuite.beforeEach.push(processFunc(this.coreContext, func));
+ }
+
+ afterAll(func) {
+ this.currentRunningSuite.afterAll.push(processFunc(this.coreContext, func));
+ }
+
+ afterEach(func) {
+ this.currentRunningSuite.afterEach.push(processFunc(this.coreContext, func));
+ }
+
+ getCurrentRunningSuite() {
+ return this.currentRunningSuite;
+ }
+
+ setCurrentRunningSuite(suite) {
+ this.currentRunningSuite = suite;
+ }
+
+ getSummary() {
+ let total = 0;
+ let error = 0;
+ let failure = 0;
+ let pass = 0;
+ let rootSuite = this.coreContext.getDefaultService('suite').rootSuite;
+ if (rootSuite && rootSuite.childSuites) {
+ for (let i = 0; i < rootSuite.childSuites.length; i++) {
+ let testsuite = rootSuite.childSuites[i];
+ let specs = testsuite['specs'];
+ for (let j = 0; j < specs.length; j++) {
+ total++;
+ let testcase = specs[j];
+ if (testcase.error) {
+ error++;
+ } else if (testcase.result.failExpects.length > 0) {
+ failure++;
+ } else if (testcase.result.pass === true) {
+ pass++;
+ }
+ }
+ }
+ }
+ return {total: total, failure: failure, error: error, pass: pass};
+ }
+
+ init(coreContext) {
+ this.coreContext = coreContext;
+ }
+
+ execute() {
+ if (this.coreContext.getDefaultService('config').filterValid.length !== 0) {
+ this.coreContext.fireEvents('task', 'incorrectFormat');
+ return;
+ }
+ this.coreContext.fireEvents('task', 'taskStart');
+ if (this.coreContext.getDefaultService('config').isSupportAsync()) {
+ let asyncExecute = async () => {
+ await this.rootSuite.asyncRun(this.coreContext);
+ };
+ asyncExecute().then(() => {
+ this.coreContext.fireEvents('task', 'taskDone');
+ });
+ } else {
+ this.rootSuite.run(this.coreContext);
+ this.coreContext.fireEvents('task', 'taskDone');
+ }
+ }
+
+ apis() {
+ const _this = this;
+ return {
+ describe: function (desc, func) {
+ return _this.describe(desc, func);
+ },
+ beforeAll: function (func) {
+ return _this.beforeAll(func);
+ },
+ beforeEach: function (func) {
+ return _this.beforeEach(func);
+ },
+ afterAll: function (func) {
+ return _this.afterAll(func);
+ },
+ afterEach: function (func) {
+ return _this.afterEach(func);
+ }
+ };
+ }
+}
+
+SuiteService.Suite = class {
+ constructor(attrs) {
+ this.description = attrs.description || '';
+ this.childSuites = [];
+ this.specs = [];
+ this.beforeAll = [];
+ this.afterAll = [];
+ this.beforeEach = [];
+ this.afterEach = [];
+ this.duration = 0;
+ }
+
+ pushSpec(spec) {
+ this.specs.push(spec);
+ }
+
+ removeSpec(desc) {
+ this.specs = this.specs.filter((item, index) => {
+ return item.description !== desc;
+ });
+ }
+
+ getSpecsNum() {
+ return this.specs.length;
+ }
+
+ run(coreContext) {
+ const suiteService = coreContext.getDefaultService('suite');
+ suiteService.setCurrentRunningSuite(this);
+ if (this.description !== '') {
+ coreContext.fireEvents('suite', 'suiteStart', this);
+ }
+ let startTime = new Date().getTime();
+ this.runHookFunc('beforeAll');
+ if (this.specs.length > 0) {
+ const configService = coreContext.getDefaultService('config');
+ if (configService.isRandom()) {
+ this.specs.sort(function () {
+ return secureRandomNumber() > 0.5 ? -1 : 1;
+ });
+ }
+ this.specs.forEach(spec => {
+ this.runHookFunc('beforeEach');
+ spec.run(coreContext);
+ this.runHookFunc('afterEach');
+ });
+ }
+ if (this.childSuites.length > 0) {
+ this.childSuites.forEach(childSuite => {
+ childSuite.run(coreContext);
+ suiteService.setCurrentRunningSuite(childSuite);
+ });
+ }
+ this.runHookFunc('afterAll');
+ let endTime = new Date().getTime();
+ this.duration = endTime - startTime;
+ if (this.description !== '') {
+ coreContext.fireEvents('suite', 'suiteDone');
+ }
+ }
+
+ asyncRun(coreContext) {
+ const suiteService = coreContext.getDefaultService('suite');
+ suiteService.setCurrentRunningSuite(this);
+ return new Promise(async resolve => {
+ if (this.description !== '') {
+ coreContext.fireEvents('suite', 'suiteStart', this);
+ }
+ let startTime = new Date().getTime();
+ await this.runAsyncHookFunc('beforeAll');
+ if (this.specs.length > 0) {
+ const configService = coreContext.getDefaultService('config');
+ if (configService.isRandom()) {
+ this.specs.sort(function () {
+ return secureRandomNumber() > 0.5 ? -1 : 1;
+ });
+ }
+ for (let i = 0; i < this.specs.length; i++) {
+ await this.runAsyncHookFunc('beforeEach');
+ await this.specs[i].asyncRun(coreContext);
+ await this.runAsyncHookFunc('afterEach');
+ }
+ }
+
+ if (this.childSuites.length > 0) {
+ for (let i = 0; i < this.childSuites.length; i++) {
+ suiteService.setCurrentRunningSuite(this.childSuites[i]);
+ await this.childSuites[i].asyncRun(coreContext);
+ }
+ }
+
+ await this.runAsyncHookFunc('afterAll');
+ let endTime = new Date().getTime();
+ this.duration = endTime - startTime;
+ if (this.description !== '') {
+ coreContext.fireEvents('suite', 'suiteDone');
+ }
+ resolve();
+ });
+ }
+
+ runHookFunc(hookName) {
+ if (this[hookName] && this[hookName].length > 0) {
+ this[hookName].forEach(func => {
+ try {
+ func();
+ } catch (e) {
+ console.error(e);
+ }
+ });
+ }
+ }
+
+ runAsyncHookFunc(hookName) {
+ if (this[hookName] && this[hookName].length > 0) {
+ return new Promise(async resolve => {
+ for (let i = 0; i < this[hookName].length; i++) {
+ try {
+ await this[hookName][i]();
+ } catch (e) {
+ console.error(e);
+ }
+ }
+ resolve();
+ });
+ }
+ }
+};
+
+class SpecService {
+ constructor(attr) {
+ this.id = attr.id;
+ }
+
+ init(coreContext) {
+ this.coreContext = coreContext;
+ }
+
+ setCurrentRunningSpec(spec) {
+ this.currentRunningSpec = spec;
+ }
+
+ getCurrentRunningSpec() {
+ return this.currentRunningSpec;
+ }
+
+ it(desc, filter, func) {
+ const configService = this.coreContext.getDefaultService('config');
+ const currentSuiteName = this.coreContext.getDefaultService('suite').getCurrentRunningSuite().description;
+ if (configService.filterDesc(currentSuiteName, desc, filter, this.coreContext)) {
+ console.info('filter it :' + desc);
+ } else {
+ let processedFunc = processFunc(this.coreContext, func);
+ const spec = new SpecService.Spec({description: desc, fi: filter, fn: processedFunc});
+ const suiteService = this.coreContext.getDefaultService('suite');
+ if (typeof this.coreContext.getServices('dataDriver') !== 'undefined') {
+ let specStress = this.coreContext.getServices('dataDriver').dataDriver.getSpecStress(desc);
+ for (let i = 1; i < specStress; i++) {
+ suiteService.getCurrentRunningSuite().pushSpec(spec);
+ }
+ }
+ suiteService.getCurrentRunningSuite().pushSpec(spec);
+ }
+ }
+
+ apis() {
+ const _this = this;
+ return {
+ it: function (desc, filter, func) {
+ return _this.it(desc, filter, func);
+ }
+ };
+ }
+}
+
+SpecService.Spec = class {
+ constructor(attrs) {
+ this.description = attrs.description || '';
+ this.fi = attrs.fi;
+ this.fn = attrs.fn || function () {
+ };
+ this.result = {
+ failExpects: [],
+ passExpects: []
+ };
+ this.error = undefined;
+ this.duration = 0;
+ }
+
+ setResult() {
+ if (this.result.failExpects.length > 0) {
+ this.result.pass = false;
+ } else {
+ this.result.pass = true;
+ }
+ console.info('testcase ' + this.description + ' result:' + this.result.pass);
+ }
+
+ run(coreContext) {
+ const specService = coreContext.getDefaultService('spec');
+ specService.setCurrentRunningSpec(this);
+ coreContext.fireEvents('spec', 'specStart', this);
+ let startTime = new Date().getTime();
+ try {
+ let dataDriver = coreContext.getServices('dataDriver');
+ if (typeof dataDriver === 'undefined') {
+ this.fn();
+ } else {
+ let suiteParams = dataDriver.dataDriver.getSuiteParams();
+ let specParams = dataDriver.dataDriver.getSpecParams();
+ console.info('[suite params] ' + JSON.stringify(suiteParams));
+ console.info('[spec params] ' + JSON.stringify(specParams));
+ if (this.fn.length === 0) {
+ this.fn();
+ } else if (specParams.length === 0) {
+ this.fn(suiteParams);
+ } else {
+ specParams.forEach(paramItem => this.fn(Object.assign({}, paramItem, suiteParams)));
+ }
+ }
+ this.setResult();
+ } catch (e) {
+ this.error = e;
+ }
+ let endTime = new Date().getTime();
+ this.duration = endTime - startTime;
+ coreContext.fireEvents('spec', 'specDone', this);
+ }
+
+ asyncRun(coreContext) {
+ const specService = coreContext.getDefaultService('spec');
+ specService.setCurrentRunningSpec(this);
+ const config = coreContext.getDefaultService('config');
+ const timeout = + (config.timeout === undefined ? 5000 : config.timeout);
+ return new Promise(async resolve => {
+ coreContext.fireEvents('spec', 'specStart', this);
+ let startTime = new Date().getTime();
+
+ function timeoutPromise() {
+ return new Promise(function (resolve, reject) {
+ setTimeout(() => reject(new Error('execute timeout ' + timeout + 'ms')), timeout);
+ });
+ }
+
+ try {
+ let dataDriver = coreContext.getServices('dataDriver');
+ if (typeof dataDriver === 'undefined') {
+ const p = Promise.race([this.fn(), timeoutPromise()]);
+ await p.then(() => {
+ this.setResult();
+ });
+ } else {
+ let suiteParams = dataDriver.dataDriver.getSuiteParams();
+ let specParams = dataDriver.dataDriver.getSpecParams();
+ console.info('[suite params] ' + JSON.stringify(suiteParams));
+ console.info('[spec params] ' + JSON.stringify(specParams));
+ if (this.fn.length === 0) {
+ const p = Promise.race([this.fn(), timeoutPromise()]);
+ await p.then(() => {
+ this.setResult();
+ });
+ } else if (specParams.length === 0) {
+ const p = Promise.race([this.fn(suiteParams), timeoutPromise()]);
+ await p.then(() => {
+ this.setResult();
+ });
+ } else {
+ for (const paramItem of specParams) {
+ const p = Promise.race([this.fn(Object.assign({}, paramItem, suiteParams)), timeoutPromise()]);
+ await p.then(() => {
+ this.setResult();
+ });
+ }
+ }
+ }
+ } catch (e) {
+ this.error = e;
+ }
+ let endTime = new Date().getTime();
+ this.duration = endTime - startTime;
+ coreContext.fireEvents('spec', 'specDone', this);
+ resolve();
+ });
+ }
+
+ filterCheck(coreContext) {
+ const specService = coreContext.getDefaultService('spec');
+ specService.setCurrentRunningSpec(this);
+ return true;
+ }
+
+ addExpectationResult(expectResult) {
+ if (expectResult.pass) {
+ this.result.passExpects.push(expectResult);
+ } else {
+ this.result.failExpects.push(expectResult);
+ }
+ }
+};
+
+class ExpectService {
+ constructor(attr) {
+ this.id = attr.id;
+ this.matchers = {};
+ }
+
+ expect(actualValue) {
+ return this.wrapMatchers(actualValue);
+ }
+
+ init(coreContext) {
+ this.coreContext = coreContext;
+ this.addMatchers(this.basicMatchers());
+ }
+
+ addMatchers(matchers) {
+ for (const matcherName in matchers) {
+ if (Object.prototype.hasOwnProperty.call(matchers, matcherName)) {
+ this.matchers[matcherName] = matchers[matcherName];
+ }
+ }
+ }
+
+ basicMatchers() {
+ return {
+ assertTrue: function (actualValue) {
+ return {
+ pass: (actualValue) === true
+ };
+ },
+ assertEqual: function (actualValue, args) {
+ return {
+ pass: (actualValue) === args[0],
+ expectValue: args[0]
+ };
+ },
+ assertThrow: function (actual, args) {
+ const result = {
+ pass: false
+ };
+ if (typeof actual !== 'function') {
+ result.message = 'toThrow\'s Actual should be a Function';
+ } else {
+ let hasThrow = false;
+ let throwError;
+ try {
+ actual();
+ } catch (e) {
+ hasThrow = true;
+ throwError = e;
+ }
+ if (!hasThrow) {
+ result.message = 'function did not throw an exception';
+ } else if (throwError && throwError.message === args[0]) {
+ result.pass = true;
+ } else {
+ result.message = `expect to throw ${args[0]} , actual throw ${throwError.message}`;
+ }
+ }
+ return result;
+ }
+ };
+ }
+
+ wrapMatchers(actualValue) {
+ const _this = this;
+ const wrappedMatchers = {};
+ const specService = _this.coreContext.getDefaultService('spec');
+ const currentRunningSpec = specService.getCurrentRunningSpec();
+ for (const matcherName in this.matchers) {
+ if (Object.prototype.hasOwnProperty.call(this.matchers, matcherName)) {
+ wrappedMatchers[matcherName] = function () {
+ const result = _this.matchers[matcherName](actualValue, arguments);
+ result.actualValue = actualValue;
+ result.checkFunc = matcherName;
+ currentRunningSpec.addExpectationResult(result);
+ };
+ }
+ }
+ return wrappedMatchers;
+ }
+
+ apis() {
+ const _this = this;
+ return {
+ expect: function (actualValue) {
+ return _this.expect(actualValue);
+ }
+ };
+ }
+}
+
+class ReportService {
+ constructor(attr) {
+ this.id = attr.id;
+ }
+
+ init(coreContext) {
+ this.coreContext = coreContext;
+ this.specService = this.coreContext.getDefaultService('spec');
+ this.suiteService = this.coreContext.getDefaultService('suite');
+ this.duration = 0;
+ }
+
+ taskStart() {
+ this.sleep(50);
+ this.taskStartTime = new Date().getTime();
+ console.info('[start] start run suites');
+ }
+
+ suiteStart() {
+ this.sleep(50);
+ console.info('[suite start]' + this.suiteService.getCurrentRunningSuite().description);
+ }
+
+ specStart() {
+ this.sleep(50);
+ console.info('start running case \'' + this.specService.currentRunningSpec.description + '\'');
+ this.index = this.index + 1;
+ }
+
+ specDone() {
+ this.sleep(50);
+ let msg = '';
+ let spec = this.specService.currentRunningSpec;
+ if (spec.error) {
+ this.formatPrint('error', spec.description + ' ; consuming ' + spec.duration + 'ms');
+ this.formatPrint('errorDetail', spec.error);
+ } else if (spec.result) {
+ if (spec.result.failExpects.length > 0) {
+ this.formatPrint('fail', spec.description + ' ; consuming ' + spec.duration + 'ms');
+ spec.result.failExpects.forEach(failExpect => {
+ msg = failExpect.message || ('expect ' + failExpect.actualValue + ' '
+ + failExpect.checkFunc + ' ' + (failExpect.expectValue || ''));
+ this.formatPrint('failDetail', msg);
+ });
+ } else {
+ this.formatPrint('pass', spec.description + ' ; consuming ' + spec.duration + 'ms');
+ }
+ }
+ this.formatPrint(this.specService.currentRunningSpec.error, msg);
+ }
+
+ suiteDone() {
+ this.sleep(50);
+ let suite = this.suiteService.currentRunningSuite;
+ console.info('[suite end]' + ' consuming ' + suite.duration + 'ms');
+ }
+
+ taskDone() {
+ this.sleep(50);
+ let msg = '';
+ this.taskDoneTime = new Date().getTime();
+ this.duration = this.taskDoneTime - this.taskStartTime;
+ let summary = this.suiteService.getSummary();
+ msg = 'total cases:' + summary.total + ';failure ' + summary.failure + ',' + 'error ' + summary.error;
+ msg += ',pass ' + summary.pass + '; consuming ' + this.duration + 'ms';
+ console.info(msg);
+ console.info('[end] run suites end');
+ }
+
+ incorrectFormat() {
+ if (this.coreContext.getDefaultService('config').filterValid.length !== 0) {
+ this.coreContext.getDefaultService('config').filterValid.forEach(function (item) {
+ console.info('this param ' + item + ' is invalid');
+ });
+ }
+ }
+
+ formatPrint(type, msg) {
+ switch (type) {
+ case 'pass':
+ console.info('[pass]' + msg);
+ break;
+ case 'fail':
+ console.info('[fail]' + msg);
+ break;
+ case 'failDetail':
+ console.info('[failDetail]' + msg);
+ break;
+ case 'error':
+ console.info('[error]' + msg);
+ break;
+ case 'errorDetail':
+ console.info('[errorDetail]' + msg);
+ break;
+ }
+ }
+
+ sleep(numberMillis) {
+ var now = new Date();
+ var exitTime = now.getTime() + numberMillis;
+ while (true) {
+ now = new Date();
+ if (now.getTime() > exitTime) {
+ return;
+ }
+ }
+ }
+}
+
+export {
+ SuiteService,
+ SpecService,
+ ExpectService,
+ ReportService
+};