1886da342Sopenharmony_ci/*
2886da342Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3886da342Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4886da342Sopenharmony_ci * you may not use this file except in compliance with the License.
5886da342Sopenharmony_ci * You may obtain a copy of the License at
6886da342Sopenharmony_ci *
7886da342Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8886da342Sopenharmony_ci *
9886da342Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10886da342Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11886da342Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12886da342Sopenharmony_ci * See the License for the specific language governing permissions and
13886da342Sopenharmony_ci * limitations under the License.
14886da342Sopenharmony_ci */
15886da342Sopenharmony_ci
16886da342Sopenharmony_ciimport SysTestKit from './module/kit/SysTestKit';
17886da342Sopenharmony_ciimport { TAG } from './Constant';
18886da342Sopenharmony_ciimport LogExpectError from './module/report/LogExpectError';
19886da342Sopenharmony_ciimport { NestFilter } from './module/config/Filter';
20886da342Sopenharmony_ci
21886da342Sopenharmony_cifunction assertTrueFun(actualValue) {
22886da342Sopenharmony_ci    let result = {
23886da342Sopenharmony_ci        pass: (actualValue) === true,
24886da342Sopenharmony_ci        message: 'expect true, actualValue is ' + actualValue
25886da342Sopenharmony_ci    };
26886da342Sopenharmony_ci    return result;
27886da342Sopenharmony_ci}
28886da342Sopenharmony_ci
29886da342Sopenharmony_cifunction assertEqualFun(actualValue, args) {
30886da342Sopenharmony_ci    let msg = 'expect ' + actualValue + ' equals ' + args[0];
31886da342Sopenharmony_ci    if (actualValue === args[0]) { // 数值相同,提示数据类型
32886da342Sopenharmony_ci        const aClassName = Object.prototype.toString.call(actualValue);
33886da342Sopenharmony_ci        const bClassName = Object.prototype.toString.call(args[0]);
34886da342Sopenharmony_ci        msg = 'expect ' + actualValue + aClassName + ' equals ' + args[0] + bClassName + 'strict mode inspect type';
35886da342Sopenharmony_ci    }
36886da342Sopenharmony_ci    let result = {
37886da342Sopenharmony_ci        pass: (actualValue) === args[0],
38886da342Sopenharmony_ci        expectValue: args[0],
39886da342Sopenharmony_ci        message: msg
40886da342Sopenharmony_ci    };
41886da342Sopenharmony_ci    return result;
42886da342Sopenharmony_ci}
43886da342Sopenharmony_ci
44886da342Sopenharmony_cifunction assertThrowFun(actual, args) {
45886da342Sopenharmony_ci    const result = {
46886da342Sopenharmony_ci        pass: false
47886da342Sopenharmony_ci    };
48886da342Sopenharmony_ci    if (typeof actual !== 'function') {
49886da342Sopenharmony_ci        result.message = 'toThrow\'s Actual should be a Function';
50886da342Sopenharmony_ci    } else {
51886da342Sopenharmony_ci        let hasThrow = false;
52886da342Sopenharmony_ci        let throwError;
53886da342Sopenharmony_ci        try {
54886da342Sopenharmony_ci            actual();
55886da342Sopenharmony_ci        } catch (e) {
56886da342Sopenharmony_ci            hasThrow = true;
57886da342Sopenharmony_ci            throwError = e;
58886da342Sopenharmony_ci        }
59886da342Sopenharmony_ci        if (!hasThrow) {
60886da342Sopenharmony_ci            result.message = 'function did not throw an exception';
61886da342Sopenharmony_ci        } else if (throwError && throwError.message === args[0]) {
62886da342Sopenharmony_ci            result.pass = true;
63886da342Sopenharmony_ci        } else {
64886da342Sopenharmony_ci            result.message = `expect to throw ${args[0]} , actual throw ${throwError.message}`;
65886da342Sopenharmony_ci        }
66886da342Sopenharmony_ci    }
67886da342Sopenharmony_ci    return result;
68886da342Sopenharmony_ci}
69886da342Sopenharmony_ci
70886da342Sopenharmony_ciclass AssertException extends Error {
71886da342Sopenharmony_ci    constructor(message) {
72886da342Sopenharmony_ci        super();
73886da342Sopenharmony_ci        this.name = 'AssertException';
74886da342Sopenharmony_ci        this.message = message;
75886da342Sopenharmony_ci    }
76886da342Sopenharmony_ci}
77886da342Sopenharmony_ci
78886da342Sopenharmony_cifunction getFuncWithArgsZero(func, timeout, isStressTest) {
79886da342Sopenharmony_ci    return new Promise(async (resolve, reject) => {
80886da342Sopenharmony_ci        let timer = null;
81886da342Sopenharmony_ci        if (!isStressTest) {
82886da342Sopenharmony_ci            timer = setTimeout(() => {
83886da342Sopenharmony_ci                reject(new Error('execute timeout ' + timeout + 'ms'));
84886da342Sopenharmony_ci            }, timeout);
85886da342Sopenharmony_ci        }
86886da342Sopenharmony_ci        try {
87886da342Sopenharmony_ci            await func();
88886da342Sopenharmony_ci        } catch (err) {
89886da342Sopenharmony_ci            reject(err);
90886da342Sopenharmony_ci        }
91886da342Sopenharmony_ci        timer !== null ? clearTimeout(timer) : null;
92886da342Sopenharmony_ci        resolve();
93886da342Sopenharmony_ci    });
94886da342Sopenharmony_ci}
95886da342Sopenharmony_ci
96886da342Sopenharmony_cifunction getFuncWithArgsOne(func, timeout, isStressTest) {
97886da342Sopenharmony_ci    return new Promise(async (resolve, reject) => {
98886da342Sopenharmony_ci        let timer = null;
99886da342Sopenharmony_ci        if (!isStressTest) {
100886da342Sopenharmony_ci            timer = setTimeout(() => {
101886da342Sopenharmony_ci                reject(new Error('execute timeout ' + timeout + 'ms'));
102886da342Sopenharmony_ci            }, timeout);
103886da342Sopenharmony_ci        }
104886da342Sopenharmony_ci
105886da342Sopenharmony_ci        function done() {
106886da342Sopenharmony_ci            timer !== null ? clearTimeout(timer) : null;
107886da342Sopenharmony_ci            resolve();
108886da342Sopenharmony_ci        }
109886da342Sopenharmony_ci
110886da342Sopenharmony_ci        try {
111886da342Sopenharmony_ci            await func(done);
112886da342Sopenharmony_ci        } catch (err) {
113886da342Sopenharmony_ci            timer !== null ? clearTimeout(timer) : null;
114886da342Sopenharmony_ci            reject(err);
115886da342Sopenharmony_ci        }
116886da342Sopenharmony_ci    });
117886da342Sopenharmony_ci}
118886da342Sopenharmony_ci
119886da342Sopenharmony_cifunction getFuncWithArgsTwo(func, timeout, paramItem, isStressTest) {
120886da342Sopenharmony_ci    return new Promise(async (resolve, reject) => {
121886da342Sopenharmony_ci        let timer = null;
122886da342Sopenharmony_ci        if (!isStressTest) {
123886da342Sopenharmony_ci            timer = setTimeout(() => {
124886da342Sopenharmony_ci                reject(new Error('execute timeout ' + timeout + 'ms'));
125886da342Sopenharmony_ci            }, timeout);
126886da342Sopenharmony_ci        }
127886da342Sopenharmony_ci
128886da342Sopenharmony_ci        function done() {
129886da342Sopenharmony_ci            timer !== null ? clearTimeout(timer) : null;
130886da342Sopenharmony_ci            resolve();
131886da342Sopenharmony_ci        }
132886da342Sopenharmony_ci
133886da342Sopenharmony_ci        try {
134886da342Sopenharmony_ci            await func(done, paramItem);
135886da342Sopenharmony_ci        } catch (err) {
136886da342Sopenharmony_ci            timer !== null ? clearTimeout(timer) : null;
137886da342Sopenharmony_ci            reject(err);
138886da342Sopenharmony_ci        }
139886da342Sopenharmony_ci    });
140886da342Sopenharmony_ci}
141886da342Sopenharmony_ci
142886da342Sopenharmony_cifunction processFunc(coreContext, func) {
143886da342Sopenharmony_ci    let argNames = ((func || '').toString()
144886da342Sopenharmony_ci        .replace(/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg, '')
145886da342Sopenharmony_ci        .match(/^(function)?\s*[^\(]*\(\s*([^\)]*)\)/m) || ['', '', ''])[2]
146886da342Sopenharmony_ci        .split(',') // split parameters
147886da342Sopenharmony_ci        .map(item => item.replace(/^\s*(_?)(.+?)\1\s*$/, name => name.split('=')[0].trim()))
148886da342Sopenharmony_ci        .filter(String);
149886da342Sopenharmony_ci    let funcLen = func.length;
150886da342Sopenharmony_ci    let processedFunc;
151886da342Sopenharmony_ci    const config = coreContext.getDefaultService('config');
152886da342Sopenharmony_ci    config.setSupportAsync(true);
153886da342Sopenharmony_ci    const timeout = + (config.timeout === undefined ? 5000 : config.timeout);
154886da342Sopenharmony_ci    const isStressTest = (coreContext.getServices('dataDriver') !== undefined || config.getStress() > 1);
155886da342Sopenharmony_ci    switch (funcLen) {
156886da342Sopenharmony_ci        case 0: {
157886da342Sopenharmony_ci            processedFunc = function () {
158886da342Sopenharmony_ci                return getFuncWithArgsZero(func, timeout, isStressTest);
159886da342Sopenharmony_ci            };
160886da342Sopenharmony_ci            break;
161886da342Sopenharmony_ci        }
162886da342Sopenharmony_ci        case 1: {
163886da342Sopenharmony_ci            processedFunc = function () {
164886da342Sopenharmony_ci                return getFuncWithArgsOne(func, timeout, isStressTest);
165886da342Sopenharmony_ci            };
166886da342Sopenharmony_ci            break;
167886da342Sopenharmony_ci        }
168886da342Sopenharmony_ci        default: {
169886da342Sopenharmony_ci            processedFunc = function (paramItem) {
170886da342Sopenharmony_ci                return getFuncWithArgsTwo(func, timeout, paramItem, isStressTest);
171886da342Sopenharmony_ci            };
172886da342Sopenharmony_ci            break;
173886da342Sopenharmony_ci        }
174886da342Sopenharmony_ci    }
175886da342Sopenharmony_ci    return processedFunc;
176886da342Sopenharmony_ci}
177886da342Sopenharmony_ci
178886da342Sopenharmony_cifunction secureRandomNumber() {
179886da342Sopenharmony_ci    return crypto.randomBytes(8).readUInt32LE() / 0xffffffff;
180886da342Sopenharmony_ci}
181886da342Sopenharmony_ci
182886da342Sopenharmony_ci
183886da342Sopenharmony_ci
184886da342Sopenharmony_ciclass SuiteService {
185886da342Sopenharmony_ci    constructor(attr) {
186886da342Sopenharmony_ci        this.id = attr.id;
187886da342Sopenharmony_ci        this.rootSuite = new SuiteService.Suite({});
188886da342Sopenharmony_ci        this.currentRunningSuite = this.rootSuite;
189886da342Sopenharmony_ci        this.suitesStack = [this.rootSuite];
190886da342Sopenharmony_ci        this.targetSuiteArray = [];
191886da342Sopenharmony_ci        this.targetSpecArray = [];
192886da342Sopenharmony_ci        this.currentRunningSuiteDesc = null;
193886da342Sopenharmony_ci        this.fullRun = false;
194886da342Sopenharmony_ci        this.isSkipSuite = false;
195886da342Sopenharmony_ci        this.suiteSkipReason = null;
196886da342Sopenharmony_ci    }
197886da342Sopenharmony_ci
198886da342Sopenharmony_ci    describe(desc, func) {
199886da342Sopenharmony_ci        const configService = this.coreContext.getDefaultService('config');
200886da342Sopenharmony_ci        if (this.suitesStack.some(suite => { return suite.description === desc })) {
201886da342Sopenharmony_ci            console.error(`${TAG} Loop nesting occurs : ${desc}`);
202886da342Sopenharmony_ci            this.suiteSkipReason = '';
203886da342Sopenharmony_ci            this.isSkipSuite = false;
204886da342Sopenharmony_ci            return;
205886da342Sopenharmony_ci        }
206886da342Sopenharmony_ci        let isFilter = this.analyzeConfigServiceClass(configService.class, desc);
207886da342Sopenharmony_ci        if (configService.filterSuite(desc) && isFilter) {
208886da342Sopenharmony_ci            if (this.currentRunningSuite.description === '' || this.currentRunningSuite.description == null) {
209886da342Sopenharmony_ci                console.info(`${TAG}filter suite : ${desc}`);
210886da342Sopenharmony_ci                this.suiteSkipReason = '';
211886da342Sopenharmony_ci                this.isSkipSuite = false;
212886da342Sopenharmony_ci                return;
213886da342Sopenharmony_ci            }
214886da342Sopenharmony_ci        }
215886da342Sopenharmony_ci        const suite = new SuiteService.Suite({ description: desc });
216886da342Sopenharmony_ci        if (this.isSkipSuite) {
217886da342Sopenharmony_ci            suite.isSkip = true;
218886da342Sopenharmony_ci            suite.skipReason = this.suiteSkipReason;
219886da342Sopenharmony_ci        }
220886da342Sopenharmony_ci        this.suiteSkipReason = '';
221886da342Sopenharmony_ci        this.isSkipSuite = false;
222886da342Sopenharmony_ci        if (typeof this.coreContext.getServices('dataDriver') !== 'undefined' && configService['dryRun'] !== 'true') {
223886da342Sopenharmony_ci            let suiteStress = this.coreContext.getServices('dataDriver').dataDriver.getSuiteStress(desc);
224886da342Sopenharmony_ci            for (let i = 1; i < suiteStress; i++) {
225886da342Sopenharmony_ci                this.currentRunningSuite.childSuites.push(suite);
226886da342Sopenharmony_ci            }
227886da342Sopenharmony_ci        }
228886da342Sopenharmony_ci        this.currentRunningSuite.childSuites.push(suite);
229886da342Sopenharmony_ci        this.currentRunningSuite = suite;
230886da342Sopenharmony_ci        this.suitesStack.push(suite);
231886da342Sopenharmony_ci        func.call();
232886da342Sopenharmony_ci        this.suitesStack.pop();
233886da342Sopenharmony_ci        this.currentRunningSuite = this.suitesStack.pop();
234886da342Sopenharmony_ci        this.suitesStack.push(this.currentRunningSuite);
235886da342Sopenharmony_ci    }
236886da342Sopenharmony_ci    xdescribe(desc, func, reason) {
237886da342Sopenharmony_ci        const configService = this.coreContext.getDefaultService('config');
238886da342Sopenharmony_ci        if (!configService.skipMessage && configService.runSkipped !== 'all') {
239886da342Sopenharmony_ci            if (configService.runSkipped != null && configService.runSkipped !== '') {
240886da342Sopenharmony_ci                let finalDesc = '';
241886da342Sopenharmony_ci                this.suitesStack.map(suite => {
242886da342Sopenharmony_ci                    finalDesc = finalDesc + '.' + suite.description;
243886da342Sopenharmony_ci                });
244886da342Sopenharmony_ci                finalDesc = (finalDesc + '.' + desc).substring(2);
245886da342Sopenharmony_ci                console.info(`${TAG} finalDesc ${finalDesc}`);
246886da342Sopenharmony_ci                if (configService.checkIfSuiteInSkipRun(finalDesc)) {
247886da342Sopenharmony_ci                    console.info(`${TAG} runSkipped suite: ${desc}`);
248886da342Sopenharmony_ci                } else {
249886da342Sopenharmony_ci                    console.info(reason == null ? `${TAG} skip suite: ${desc}` : `${TAG} skip suite: ${desc}, and the reason is ${reason}`);
250886da342Sopenharmony_ci                    return;
251886da342Sopenharmony_ci                }
252886da342Sopenharmony_ci            } else {
253886da342Sopenharmony_ci                console.info(reason == null ? `${TAG} skip suite: ${desc}` : `${TAG} skip suite: ${desc}, and the reason is ${reason}`);
254886da342Sopenharmony_ci                return;
255886da342Sopenharmony_ci            }
256886da342Sopenharmony_ci        }
257886da342Sopenharmony_ci        this.isSkipSuite = true;
258886da342Sopenharmony_ci        this.suiteSkipReason = reason;
259886da342Sopenharmony_ci        this.describe(desc, func);
260886da342Sopenharmony_ci    }
261886da342Sopenharmony_ci
262886da342Sopenharmony_ci    beforeAll(func) {
263886da342Sopenharmony_ci        this.currentRunningSuite.beforeAll.push(processFunc(this.coreContext, func));
264886da342Sopenharmony_ci    }
265886da342Sopenharmony_ci
266886da342Sopenharmony_ci    beforeEach(func) {
267886da342Sopenharmony_ci        this.currentRunningSuite.beforeEach.push(processFunc(this.coreContext, func));
268886da342Sopenharmony_ci    }
269886da342Sopenharmony_ci
270886da342Sopenharmony_ci    beforeItSpecified(itDescs, func) {
271886da342Sopenharmony_ci        this.currentRunningSuite.beforeItSpecified.set(itDescs, processFunc(this.coreContext, func));
272886da342Sopenharmony_ci    }
273886da342Sopenharmony_ci
274886da342Sopenharmony_ci    afterItSpecified(itDescs, func) {
275886da342Sopenharmony_ci        this.currentRunningSuite.afterItSpecified.set(itDescs, processFunc(this.coreContext, func));
276886da342Sopenharmony_ci    }
277886da342Sopenharmony_ci
278886da342Sopenharmony_ci    afterAll(func) {
279886da342Sopenharmony_ci        this.currentRunningSuite.afterAll.push(processFunc(this.coreContext, func));
280886da342Sopenharmony_ci    }
281886da342Sopenharmony_ci
282886da342Sopenharmony_ci    afterEach(func) {
283886da342Sopenharmony_ci        this.currentRunningSuite.afterEach.push(processFunc(this.coreContext, func));
284886da342Sopenharmony_ci    }
285886da342Sopenharmony_ci
286886da342Sopenharmony_ci    getCurrentRunningSuite() {
287886da342Sopenharmony_ci        return this.currentRunningSuite;
288886da342Sopenharmony_ci    }
289886da342Sopenharmony_ci
290886da342Sopenharmony_ci    setCurrentRunningSuite(suite) {
291886da342Sopenharmony_ci        this.currentRunningSuite = suite;
292886da342Sopenharmony_ci    }
293886da342Sopenharmony_ci
294886da342Sopenharmony_ci    getRootSuite() {
295886da342Sopenharmony_ci        return this.rootSuite;
296886da342Sopenharmony_ci    }
297886da342Sopenharmony_ci
298886da342Sopenharmony_ci    getCurrentRunningSuiteDesc() {
299886da342Sopenharmony_ci        return this.currentRunningSuiteDesc;
300886da342Sopenharmony_ci    }
301886da342Sopenharmony_ci
302886da342Sopenharmony_ci
303886da342Sopenharmony_ci    setCurrentRunningSuiteDesc(suite, currentSuite, prefix) {
304886da342Sopenharmony_ci        if (suite != null && suite === currentSuite) {
305886da342Sopenharmony_ci            this.currentRunningSuiteDesc = prefix;
306886da342Sopenharmony_ci        } else if (suite != null && suite !== currentSuite) {
307886da342Sopenharmony_ci            suite.childSuites.forEach(it => {
308886da342Sopenharmony_ci                let temp = prefix;
309886da342Sopenharmony_ci                if (it.description != null || it.description !== '') {
310886da342Sopenharmony_ci                    temp = prefix === '' ? it.description : prefix + '.' + it.description;
311886da342Sopenharmony_ci                }
312886da342Sopenharmony_ci                this.setCurrentRunningSuiteDesc(it, currentSuite, temp);
313886da342Sopenharmony_ci            }
314886da342Sopenharmony_ci            );
315886da342Sopenharmony_ci        }
316886da342Sopenharmony_ci    }
317886da342Sopenharmony_ci    analyzeConfigServiceClass(configServiceClass, desc) {
318886da342Sopenharmony_ci        if (configServiceClass == null || configServiceClass === '') {
319886da342Sopenharmony_ci            this.fullRun = true;
320886da342Sopenharmony_ci            return false;
321886da342Sopenharmony_ci        }
322886da342Sopenharmony_ci        if (this.targetSuiteArray.length === 0) {
323886da342Sopenharmony_ci            const targetArray = configServiceClass.split(',');
324886da342Sopenharmony_ci            for (let index in targetArray) {
325886da342Sopenharmony_ci                if (targetArray[index].includes('#')) {
326886da342Sopenharmony_ci                    this.targetSpecArray.push(targetArray[index]);
327886da342Sopenharmony_ci                } else {
328886da342Sopenharmony_ci                    this.targetSuiteArray.push(targetArray[index]);
329886da342Sopenharmony_ci                }
330886da342Sopenharmony_ci            }
331886da342Sopenharmony_ci
332886da342Sopenharmony_ci        }
333886da342Sopenharmony_ci        return !configServiceClass.includes(desc);
334886da342Sopenharmony_ci
335886da342Sopenharmony_ci    }
336886da342Sopenharmony_ci    traversalResults(suite, obj, breakOnError) {
337886da342Sopenharmony_ci        if (suite.childSuites.length === 0 && suite.specs.length === 0) {
338886da342Sopenharmony_ci            return;
339886da342Sopenharmony_ci        }
340886da342Sopenharmony_ci        if (suite.specs.length > 0) {
341886da342Sopenharmony_ci            for (const itItem of suite.specs) {
342886da342Sopenharmony_ci                obj.total++;
343886da342Sopenharmony_ci                let itInfo = {
344886da342Sopenharmony_ci                    currentThreadName: 'mainThread',
345886da342Sopenharmony_ci                    description: suite.description + '#' + itItem.description,
346886da342Sopenharmony_ci                    result: -3
347886da342Sopenharmony_ci                };
348886da342Sopenharmony_ci                if (SysTestKit.workerPort !== null) {
349886da342Sopenharmony_ci                    itInfo.currentThreadName = SysTestKit.workerPort.name;
350886da342Sopenharmony_ci                }
351886da342Sopenharmony_ci                obj.itItemList.push(itInfo);
352886da342Sopenharmony_ci                if (breakOnError && (obj.error > 0 || obj.failure > 0)) { // breakOnError模式
353886da342Sopenharmony_ci                    continue;
354886da342Sopenharmony_ci                }
355886da342Sopenharmony_ci                if (itItem.error) {
356886da342Sopenharmony_ci                    obj.error++;
357886da342Sopenharmony_ci                    itInfo.result = -1;
358886da342Sopenharmony_ci                } else if (itItem.fail) {
359886da342Sopenharmony_ci                    obj.failure++;
360886da342Sopenharmony_ci                    itInfo.result = -2;
361886da342Sopenharmony_ci                } else if (itItem.pass === true) {
362886da342Sopenharmony_ci                    obj.pass++;
363886da342Sopenharmony_ci                    itInfo.result = 0;
364886da342Sopenharmony_ci                }
365886da342Sopenharmony_ci            }
366886da342Sopenharmony_ci        }
367886da342Sopenharmony_ci
368886da342Sopenharmony_ci        obj.duration += suite.duration;
369886da342Sopenharmony_ci
370886da342Sopenharmony_ci        if (suite.childSuites.length > 0) {
371886da342Sopenharmony_ci            for (const suiteItem of suite.childSuites) {
372886da342Sopenharmony_ci                this.traversalResults(suiteItem, obj, breakOnError);
373886da342Sopenharmony_ci            }
374886da342Sopenharmony_ci        }
375886da342Sopenharmony_ci
376886da342Sopenharmony_ci    }
377886da342Sopenharmony_ci
378886da342Sopenharmony_ci    async setSuiteResults(suite, error, coreContext) {
379886da342Sopenharmony_ci        if (suite.childSuites.length === 0 && suite.specs.length === 0) {
380886da342Sopenharmony_ci            return;
381886da342Sopenharmony_ci        }
382886da342Sopenharmony_ci        if (suite.specs.length > 0) {
383886da342Sopenharmony_ci            const specService = coreContext.getDefaultService('spec');
384886da342Sopenharmony_ci            for (const specItem of suite.specs) {
385886da342Sopenharmony_ci                specService.setCurrentRunningSpec(specItem);
386886da342Sopenharmony_ci                if (error instanceof AssertException) {
387886da342Sopenharmony_ci                    specItem.fail = error;
388886da342Sopenharmony_ci                } else {
389886da342Sopenharmony_ci                    specItem.error = error;
390886da342Sopenharmony_ci                }
391886da342Sopenharmony_ci                await coreContext.fireEvents('spec', 'specStart', specItem);
392886da342Sopenharmony_ci                await coreContext.fireEvents('spec', 'specDone', specItem);
393886da342Sopenharmony_ci            }
394886da342Sopenharmony_ci        }
395886da342Sopenharmony_ci        if (suite.childSuites.length > 0) {
396886da342Sopenharmony_ci            for (const suiteItem of suite.childSuites) {
397886da342Sopenharmony_ci                await this.setSuiteResults(suiteItem, error, coreContext);
398886da342Sopenharmony_ci            }
399886da342Sopenharmony_ci        }
400886da342Sopenharmony_ci    }
401886da342Sopenharmony_ci
402886da342Sopenharmony_ci    getSummary() {
403886da342Sopenharmony_ci        let suiteService = this.coreContext.getDefaultService('suite');
404886da342Sopenharmony_ci        let rootSuite = suiteService.rootSuite;
405886da342Sopenharmony_ci        const specService = this.coreContext.getDefaultService('spec');
406886da342Sopenharmony_ci        const configService = this.coreContext.getDefaultService('config');
407886da342Sopenharmony_ci        let breakOnError = configService.isBreakOnError();
408886da342Sopenharmony_ci        let isError = specService.getStatus();
409886da342Sopenharmony_ci        let isBreaKOnError = breakOnError && isError;
410886da342Sopenharmony_ci        // itItemList 保存当前用例执行情况, 发送到主线程用例计算最终结果
411886da342Sopenharmony_ci        let obj = { total: 0, failure: 0, error: 0, pass: 0, ignore: 0, duration: 0, itItemList: []};
412886da342Sopenharmony_ci        for (const suiteItem of rootSuite.childSuites) {
413886da342Sopenharmony_ci            this.traversalResults(suiteItem, obj, isBreaKOnError);
414886da342Sopenharmony_ci        }
415886da342Sopenharmony_ci        obj.ignore = obj.total - obj.pass - obj.failure - obj.error;
416886da342Sopenharmony_ci        return obj;
417886da342Sopenharmony_ci    }
418886da342Sopenharmony_ci
419886da342Sopenharmony_ci    init(coreContext) {
420886da342Sopenharmony_ci        this.coreContext = coreContext;
421886da342Sopenharmony_ci    }
422886da342Sopenharmony_ci
423886da342Sopenharmony_ci    traversalSuites(suite, obj, configService) {
424886da342Sopenharmony_ci        if (suite.childSuites.length === 0 && suite.specs.length === 0) {
425886da342Sopenharmony_ci            return [];
426886da342Sopenharmony_ci        }
427886da342Sopenharmony_ci        if (suite.specs.length > 0) {
428886da342Sopenharmony_ci            let itArray = [];
429886da342Sopenharmony_ci            for (const itItem of suite['specs']) {
430886da342Sopenharmony_ci                if (!configService.filterDesc(suite.description, itItem.description, itItem.fi, null)) {
431886da342Sopenharmony_ci                    itArray.push({ 'itName': itItem.description });
432886da342Sopenharmony_ci                }
433886da342Sopenharmony_ci            }
434886da342Sopenharmony_ci            obj[suite.description] = itArray;
435886da342Sopenharmony_ci        }
436886da342Sopenharmony_ci        if (suite.childSuites.length > 0) {
437886da342Sopenharmony_ci            let suiteArray = [];
438886da342Sopenharmony_ci            for (const suiteItem of suite.childSuites) {
439886da342Sopenharmony_ci                let suiteObj = {};
440886da342Sopenharmony_ci                this.traversalSuites(suiteItem, suiteObj, configService);
441886da342Sopenharmony_ci                if (!configService.filterSuite(suiteItem.description)) {
442886da342Sopenharmony_ci                    suiteArray.push(suiteObj);
443886da342Sopenharmony_ci                }
444886da342Sopenharmony_ci            }
445886da342Sopenharmony_ci            obj.suites = suiteArray;
446886da342Sopenharmony_ci        }
447886da342Sopenharmony_ci    }
448886da342Sopenharmony_ci
449886da342Sopenharmony_ci    async dryRun(abilityDelegator) {
450886da342Sopenharmony_ci        console.info(`${TAG} rootSuite : ` + JSON.stringify(this.rootSuite));
451886da342Sopenharmony_ci        let obj = this.rootSuite;
452886da342Sopenharmony_ci        let prefixStack = [];
453886da342Sopenharmony_ci        let suiteArray = [];
454886da342Sopenharmony_ci        let skipSuiteArray = [];
455886da342Sopenharmony_ci        this.analyzeSuitesArray(prefixStack, suiteArray, skipSuiteArray, obj);
456886da342Sopenharmony_ci        const configService = this.coreContext.getDefaultService('config');
457886da342Sopenharmony_ci        let result;
458886da342Sopenharmony_ci        if (configService.skipMessage) {
459886da342Sopenharmony_ci            result = { 'suites': suiteArray, 'skipSuites': skipSuiteArray };
460886da342Sopenharmony_ci        } else {
461886da342Sopenharmony_ci            result = { 'suites': suiteArray };
462886da342Sopenharmony_ci        }
463886da342Sopenharmony_ci        let strJson = JSON.stringify(result);
464886da342Sopenharmony_ci        let strLen = strJson.length;
465886da342Sopenharmony_ci        let maxLen = 500;
466886da342Sopenharmony_ci        let maxCount = Math.floor(strLen / maxLen);
467886da342Sopenharmony_ci        for (let count = 0; count <= maxCount; count++) {
468886da342Sopenharmony_ci            await SysTestKit.print(strJson.substring(count * maxLen, (count + 1) * maxLen));
469886da342Sopenharmony_ci        }
470886da342Sopenharmony_ci        console.info(`${TAG}dryRun print success`);
471886da342Sopenharmony_ci        abilityDelegator.finishTest('dry run finished!!!', 0, () => { });
472886da342Sopenharmony_ci    }
473886da342Sopenharmony_ci
474886da342Sopenharmony_ci    //将suitesArray的嵌套结构展开成三层结构
475886da342Sopenharmony_ci    analyzeSuitesArray(prefixStack, suiteArray, skipSuiteArray, obj) {
476886da342Sopenharmony_ci        obj.childSuites.map(suite => {
477886da342Sopenharmony_ci            if (suite.description != null && suite.description !== '') {
478886da342Sopenharmony_ci                let prefix = '';
479886da342Sopenharmony_ci                if (prefixStack.length > 0) {
480886da342Sopenharmony_ci                    prefix = prefixStack.join('.') + '.' + suite.description;
481886da342Sopenharmony_ci                } else {
482886da342Sopenharmony_ci                    prefix = suite.description;
483886da342Sopenharmony_ci                }
484886da342Sopenharmony_ci                prefixStack.push(suite.description);
485886da342Sopenharmony_ci                let temp = {};
486886da342Sopenharmony_ci                temp[prefix] = [];
487886da342Sopenharmony_ci                let skipTemp = {};
488886da342Sopenharmony_ci                skipTemp[prefix] = [];
489886da342Sopenharmony_ci                suite.specs.map(spec => {
490886da342Sopenharmony_ci                    let it = { 'itName': spec.description };
491886da342Sopenharmony_ci                    spec.isSkip ? skipTemp[prefix].push(it) : temp[prefix].push(it);
492886da342Sopenharmony_ci                });
493886da342Sopenharmony_ci                suiteArray.push(temp);
494886da342Sopenharmony_ci                skipSuiteArray.push(skipTemp);
495886da342Sopenharmony_ci            }
496886da342Sopenharmony_ci            this.analyzeSuitesArray(prefixStack, suiteArray, skipSuiteArray, suite);
497886da342Sopenharmony_ci            prefixStack.pop();
498886da342Sopenharmony_ci        });
499886da342Sopenharmony_ci    }
500886da342Sopenharmony_ci    //获取当前测试套下的所有测试用例数量
501886da342Sopenharmony_ci    getAllChildSuiteNum(suite, specArray) {
502886da342Sopenharmony_ci        if (suite.specs != null) {
503886da342Sopenharmony_ci            suite.specs.forEach(spec => specArray.push(spec));
504886da342Sopenharmony_ci        }
505886da342Sopenharmony_ci        if (suite.childSuites != null) {
506886da342Sopenharmony_ci            suite.childSuites.forEach(it => this.getAllChildSuiteNum(it, specArray));
507886da342Sopenharmony_ci        }
508886da342Sopenharmony_ci    }
509886da342Sopenharmony_ci
510886da342Sopenharmony_ci    execute() {
511886da342Sopenharmony_ci        const configService = this.coreContext.getDefaultService('config');
512886da342Sopenharmony_ci        if (configService.filterValid.length !== 0) {
513886da342Sopenharmony_ci            this.coreContext.fireEvents('task', 'incorrectFormat');
514886da342Sopenharmony_ci            return;
515886da342Sopenharmony_ci        }
516886da342Sopenharmony_ci        if (configService.filterXdescribe.length !== 0) {
517886da342Sopenharmony_ci            this.coreContext.fireEvents('task', 'incorrectTestSuiteFormat');
518886da342Sopenharmony_ci            return;
519886da342Sopenharmony_ci        }
520886da342Sopenharmony_ci        if (configService.isRandom() && this.rootSuite.childSuites.length > 0) {
521886da342Sopenharmony_ci            this.rootSuite.childSuites.sort(function () {
522886da342Sopenharmony_ci                return +('0.' + (+ new Date() + '').split('').reverse().join('')) > 0.5 ? -1 : 1;
523886da342Sopenharmony_ci            });
524886da342Sopenharmony_ci            this.currentRunningSuite = this.rootSuite.childSuites[0];
525886da342Sopenharmony_ci        }
526886da342Sopenharmony_ci        if (configService.isSupportAsync()) {
527886da342Sopenharmony_ci            console.info(`${TAG} rootSuite:` + JSON.stringify(this.rootSuite));
528886da342Sopenharmony_ci            let asyncExecute = async () => {
529886da342Sopenharmony_ci                await this.coreContext.fireEvents('task', 'taskStart');
530886da342Sopenharmony_ci                await this.rootSuite.asyncRun(this.coreContext);
531886da342Sopenharmony_ci            };
532886da342Sopenharmony_ci            asyncExecute().then(async () => {
533886da342Sopenharmony_ci                await this.coreContext.fireEvents('task', 'taskDone');
534886da342Sopenharmony_ci            });
535886da342Sopenharmony_ci        } else {
536886da342Sopenharmony_ci            console.info('${TAG} rootSuite:' + JSON.stringify(this.rootSuite));
537886da342Sopenharmony_ci            this.coreContext.fireEvents('task', 'taskStart');
538886da342Sopenharmony_ci            this.rootSuite.run(this.coreContext);
539886da342Sopenharmony_ci            this.coreContext.fireEvents('task', 'taskDone');
540886da342Sopenharmony_ci        }
541886da342Sopenharmony_ci    }
542886da342Sopenharmony_ci
543886da342Sopenharmony_ci    apis() {
544886da342Sopenharmony_ci        const _this = this;
545886da342Sopenharmony_ci        return {
546886da342Sopenharmony_ci            describe: function (desc, func) {
547886da342Sopenharmony_ci                return _this.describe(desc, func);
548886da342Sopenharmony_ci            },
549886da342Sopenharmony_ci            xdescribe: function (desc, func, reason) {
550886da342Sopenharmony_ci                return _this.xdescribe(desc, func, reason);
551886da342Sopenharmony_ci            },
552886da342Sopenharmony_ci            beforeItSpecified: function (itDescs, func) {
553886da342Sopenharmony_ci                return _this.beforeItSpecified(itDescs, func);
554886da342Sopenharmony_ci            },
555886da342Sopenharmony_ci            afterItSpecified: function (itDescs, func) {
556886da342Sopenharmony_ci                return _this.afterItSpecified(itDescs, func);
557886da342Sopenharmony_ci            },
558886da342Sopenharmony_ci            beforeAll: function (func) {
559886da342Sopenharmony_ci                return _this.beforeAll(func);
560886da342Sopenharmony_ci            },
561886da342Sopenharmony_ci            beforeEach: function (func) {
562886da342Sopenharmony_ci                return _this.beforeEach(func);
563886da342Sopenharmony_ci            },
564886da342Sopenharmony_ci            afterAll: function (func) {
565886da342Sopenharmony_ci                return _this.afterAll(func);
566886da342Sopenharmony_ci            },
567886da342Sopenharmony_ci            afterEach: function (func) {
568886da342Sopenharmony_ci                return _this.afterEach(func);
569886da342Sopenharmony_ci            }
570886da342Sopenharmony_ci        };
571886da342Sopenharmony_ci    }
572886da342Sopenharmony_ci}
573886da342Sopenharmony_ci
574886da342Sopenharmony_ciSuiteService.Suite = class {
575886da342Sopenharmony_ci    constructor(attrs) {
576886da342Sopenharmony_ci        this.description = attrs.description || '';
577886da342Sopenharmony_ci        this.childSuites = [];
578886da342Sopenharmony_ci        this.specs = [];
579886da342Sopenharmony_ci        this.beforeAll = [];
580886da342Sopenharmony_ci        this.afterAll = [];
581886da342Sopenharmony_ci        this.beforeItSpecified = new Map();
582886da342Sopenharmony_ci        this.afterItSpecified = new Map();
583886da342Sopenharmony_ci        this.beforeEach = [];
584886da342Sopenharmony_ci        this.afterEach = [];
585886da342Sopenharmony_ci        this.duration = 0;
586886da342Sopenharmony_ci        this.hookError = null;
587886da342Sopenharmony_ci        this.isSkip = false;
588886da342Sopenharmony_ci        this.skipReason = '';
589886da342Sopenharmony_ci    }
590886da342Sopenharmony_ci
591886da342Sopenharmony_ci    pushSpec(spec) {
592886da342Sopenharmony_ci        this.specs.push(spec);
593886da342Sopenharmony_ci    }
594886da342Sopenharmony_ci
595886da342Sopenharmony_ci    removeSpec(desc) {
596886da342Sopenharmony_ci        this.specs = this.specs.filter((item, index) => {
597886da342Sopenharmony_ci            return item.description !== desc;
598886da342Sopenharmony_ci        });
599886da342Sopenharmony_ci    }
600886da342Sopenharmony_ci
601886da342Sopenharmony_ci    getSpecsNum() {
602886da342Sopenharmony_ci        return this.specs.length;
603886da342Sopenharmony_ci    }
604886da342Sopenharmony_ci
605886da342Sopenharmony_ci    isRun(coreContext) {
606886da342Sopenharmony_ci        const configService = coreContext.getDefaultService('config');
607886da342Sopenharmony_ci        const suiteService = coreContext.getDefaultService('suite');
608886da342Sopenharmony_ci        const specService = coreContext.getDefaultService('spec');
609886da342Sopenharmony_ci        let breakOnError = configService.isBreakOnError();
610886da342Sopenharmony_ci        let isError = specService.getStatus();
611886da342Sopenharmony_ci        return breakOnError && isError;
612886da342Sopenharmony_ci    }
613886da342Sopenharmony_ci
614886da342Sopenharmony_ci    run(coreContext) {
615886da342Sopenharmony_ci        const suiteService = coreContext.getDefaultService('suite');
616886da342Sopenharmony_ci        suiteService.setCurrentRunningSuite(this);
617886da342Sopenharmony_ci        if (this.description !== '') {
618886da342Sopenharmony_ci            coreContext.fireEvents('suite', 'suiteStart', this);
619886da342Sopenharmony_ci        }
620886da342Sopenharmony_ci        this.runHookFunc('beforeAll');
621886da342Sopenharmony_ci        if (this.specs.length > 0) {
622886da342Sopenharmony_ci            const configService = coreContext.getDefaultService('config');
623886da342Sopenharmony_ci            if (configService.isRandom()) {
624886da342Sopenharmony_ci                this.specs.sort(function () {
625886da342Sopenharmony_ci                    return +('0.' + (+ new Date() + '').split('').reverse().join('')) > 0.5 ? -1 : 1;
626886da342Sopenharmony_ci                });
627886da342Sopenharmony_ci            }
628886da342Sopenharmony_ci            for (let spec in this.specs) {
629886da342Sopenharmony_ci                let isBreakOnError = this.isRun(coreContext);
630886da342Sopenharmony_ci                if (isBreakOnError) {
631886da342Sopenharmony_ci                    break;
632886da342Sopenharmony_ci                }
633886da342Sopenharmony_ci                this.runHookFunc('beforeEach');
634886da342Sopenharmony_ci                spec.run(coreContext);
635886da342Sopenharmony_ci                this.runHookFunc('afterEach');
636886da342Sopenharmony_ci            }
637886da342Sopenharmony_ci        }
638886da342Sopenharmony_ci        if (this.childSuites.length > 0) {
639886da342Sopenharmony_ci            for (let suite in this.childSuites) {
640886da342Sopenharmony_ci                let isBreakOnError = this.isRun(coreContext);
641886da342Sopenharmony_ci                if (isBreakOnError) {
642886da342Sopenharmony_ci                    break;
643886da342Sopenharmony_ci                }
644886da342Sopenharmony_ci                suite.run(coreContext);
645886da342Sopenharmony_ci                suiteService.setCurrentRunningSuite(suite);
646886da342Sopenharmony_ci            }
647886da342Sopenharmony_ci        }
648886da342Sopenharmony_ci        this.runHookFunc('afterAll');
649886da342Sopenharmony_ci        if (this.description !== '') {
650886da342Sopenharmony_ci            coreContext.fireEvents('suite', 'suiteDone');
651886da342Sopenharmony_ci        }
652886da342Sopenharmony_ci    }
653886da342Sopenharmony_ci
654886da342Sopenharmony_ci    async runBeforeItSpecified(beforeItSpecified, specItem) {
655886da342Sopenharmony_ci        for (const [itNames, hookFunc] of beforeItSpecified) {
656886da342Sopenharmony_ci            if ((Object.prototype.toString.call(itNames) === '[object Array]' && itNames.includes(specItem.description)) ||
657886da342Sopenharmony_ci                (Object.prototype.toString.call(itNames) === '[object String]' && itNames === specItem.description)) {
658886da342Sopenharmony_ci                await Reflect.apply(hookFunc, null, []);
659886da342Sopenharmony_ci            }
660886da342Sopenharmony_ci            break;
661886da342Sopenharmony_ci        }
662886da342Sopenharmony_ci    }
663886da342Sopenharmony_ci
664886da342Sopenharmony_ci    async runAfterItSpecified(beforeItSpecified, specItem) {
665886da342Sopenharmony_ci        for (const [itNames, hookFunc] of beforeItSpecified) {
666886da342Sopenharmony_ci            if ((Object.prototype.toString.call(itNames) === '[object Array]' && itNames.includes(specItem.description)) ||
667886da342Sopenharmony_ci                (Object.prototype.toString.call(itNames) === '[object String]' && itNames === specItem.description)) {
668886da342Sopenharmony_ci                await Reflect.apply(hookFunc, null, []);
669886da342Sopenharmony_ci            }
670886da342Sopenharmony_ci            break;
671886da342Sopenharmony_ci        }
672886da342Sopenharmony_ci    }
673886da342Sopenharmony_ci
674886da342Sopenharmony_ci    async asyncRunSpecs(coreContext) {
675886da342Sopenharmony_ci        const configService = coreContext.getDefaultService('config');
676886da342Sopenharmony_ci        if (configService.isRandom()) {
677886da342Sopenharmony_ci            this.specs.sort(function () {
678886da342Sopenharmony_ci                return +('0.' + (+ new Date() + '').split('').reverse().join('')) > 0.5 ? -1 : 1;
679886da342Sopenharmony_ci            });
680886da342Sopenharmony_ci        }
681886da342Sopenharmony_ci        const specService = coreContext.getDefaultService('spec');
682886da342Sopenharmony_ci        for (let specItem of this.specs) {
683886da342Sopenharmony_ci            specService.setCurrentRunningSpec(specItem);
684886da342Sopenharmony_ci            // 遇错即停模式,发现用例有问题,直接返回,不在执行后面的it
685886da342Sopenharmony_ci            let isBreakOnError = this.isRun(coreContext);
686886da342Sopenharmony_ci            if (isBreakOnError) {
687886da342Sopenharmony_ci                console.info('break description :' + this.description);
688886da342Sopenharmony_ci                break;
689886da342Sopenharmony_ci            }
690886da342Sopenharmony_ci            await coreContext.fireEvents('spec', 'specStart', specItem);
691886da342Sopenharmony_ci            try {
692886da342Sopenharmony_ci                await this.runBeforeItSpecified(this.beforeItSpecified, specItem);
693886da342Sopenharmony_ci                await this.runAsyncHookFunc('beforeEach');
694886da342Sopenharmony_ci                await specItem.asyncRun(coreContext);
695886da342Sopenharmony_ci                await this.runAfterItSpecified(this.afterItSpecified, specItem);
696886da342Sopenharmony_ci                await this.runAsyncHookFunc('afterEach');
697886da342Sopenharmony_ci            } catch (e) {
698886da342Sopenharmony_ci                console.error(`${TAG}stack:${e?.stack}`);
699886da342Sopenharmony_ci                console.error(`${TAG}stack end`);
700886da342Sopenharmony_ci                if (e instanceof AssertException) {
701886da342Sopenharmony_ci                    specItem.fail = e;
702886da342Sopenharmony_ci                } else {
703886da342Sopenharmony_ci                    specItem.error = e;
704886da342Sopenharmony_ci                }
705886da342Sopenharmony_ci                specService.setStatus(true);
706886da342Sopenharmony_ci            }
707886da342Sopenharmony_ci            specItem.setResult();
708886da342Sopenharmony_ci            await coreContext.fireEvents('spec', 'specDone', specItem);
709886da342Sopenharmony_ci            specService.setCurrentRunningSpec(null);
710886da342Sopenharmony_ci        }
711886da342Sopenharmony_ci    }
712886da342Sopenharmony_ci
713886da342Sopenharmony_ci    async asyncRunChildSuites(coreContext) {
714886da342Sopenharmony_ci        for (let i = 0; i < this.childSuites.length; i++) {
715886da342Sopenharmony_ci            // 遇错即停模式, 发现用例有问题,直接返回,不在执行后面的description
716886da342Sopenharmony_ci            let isBreakOnError = this.isRun(coreContext);
717886da342Sopenharmony_ci            if (isBreakOnError) {
718886da342Sopenharmony_ci                console.info(`${TAG}break description : ${this.description}`);
719886da342Sopenharmony_ci                break;
720886da342Sopenharmony_ci            }
721886da342Sopenharmony_ci            await this.childSuites[i].asyncRun(coreContext);
722886da342Sopenharmony_ci        }
723886da342Sopenharmony_ci    }
724886da342Sopenharmony_ci
725886da342Sopenharmony_ci    async asyncRun(coreContext) {
726886da342Sopenharmony_ci        const suiteService = coreContext.getDefaultService('suite');
727886da342Sopenharmony_ci        const specService = coreContext.getDefaultService('spec');
728886da342Sopenharmony_ci
729886da342Sopenharmony_ci        suiteService.setCurrentRunningSuite(this);
730886da342Sopenharmony_ci        suiteService.suitesStack.push(this);
731886da342Sopenharmony_ci        if (this.description !== '') {
732886da342Sopenharmony_ci            await coreContext.fireEvents('suite', 'suiteStart', this);
733886da342Sopenharmony_ci        }
734886da342Sopenharmony_ci
735886da342Sopenharmony_ci        try {
736886da342Sopenharmony_ci            await this.runAsyncHookFunc('beforeAll');
737886da342Sopenharmony_ci        } catch (error) {
738886da342Sopenharmony_ci            console.error(`${TAG}${error?.stack}`);
739886da342Sopenharmony_ci            this.hookError = error;
740886da342Sopenharmony_ci        }
741886da342Sopenharmony_ci
742886da342Sopenharmony_ci        if (this.hookError !== null) {
743886da342Sopenharmony_ci            specService.setStatus(true);
744886da342Sopenharmony_ci            await suiteService.setSuiteResults(this, this.hookError, coreContext);
745886da342Sopenharmony_ci        }
746886da342Sopenharmony_ci
747886da342Sopenharmony_ci        if (this.specs.length > 0 && this.hookError === null) {
748886da342Sopenharmony_ci            await this.asyncRunSpecs(coreContext);
749886da342Sopenharmony_ci        }
750886da342Sopenharmony_ci
751886da342Sopenharmony_ci        if (this.childSuites.length > 0 && this.hookError === null) {
752886da342Sopenharmony_ci            await this.asyncRunChildSuites(coreContext);
753886da342Sopenharmony_ci        }
754886da342Sopenharmony_ci
755886da342Sopenharmony_ci        try {
756886da342Sopenharmony_ci            await this.runAsyncHookFunc('afterAll');
757886da342Sopenharmony_ci        } catch (error) {
758886da342Sopenharmony_ci            console.error(`${TAG}${error?.stack}`);
759886da342Sopenharmony_ci            this.hookError = error;
760886da342Sopenharmony_ci            specService.setStatus(true);
761886da342Sopenharmony_ci        }
762886da342Sopenharmony_ci
763886da342Sopenharmony_ci        if (this.description !== '') {
764886da342Sopenharmony_ci            await coreContext.fireEvents('suite', 'suiteDone');
765886da342Sopenharmony_ci            let childSuite = suiteService.suitesStack.pop();
766886da342Sopenharmony_ci            let currentRunningSuite = suiteService.suitesStack.pop();
767886da342Sopenharmony_ci            suiteService.setCurrentRunningSuite(currentRunningSuite);
768886da342Sopenharmony_ci            suiteService.suitesStack.push(currentRunningSuite);
769886da342Sopenharmony_ci        }
770886da342Sopenharmony_ci    }
771886da342Sopenharmony_ci
772886da342Sopenharmony_ci    runHookFunc(hookName) {
773886da342Sopenharmony_ci        if (this[hookName] && this[hookName].length > 0) {
774886da342Sopenharmony_ci            this[hookName].forEach(func => {
775886da342Sopenharmony_ci                try {
776886da342Sopenharmony_ci                    func();
777886da342Sopenharmony_ci                } catch (e) {
778886da342Sopenharmony_ci                    console.error(`${TAG}${e.stack}`);
779886da342Sopenharmony_ci                }
780886da342Sopenharmony_ci            });
781886da342Sopenharmony_ci        }
782886da342Sopenharmony_ci    }
783886da342Sopenharmony_ci
784886da342Sopenharmony_ci    async runAsyncHookFunc(hookName) {
785886da342Sopenharmony_ci        for (const hookItem of this[hookName]) {
786886da342Sopenharmony_ci            try {
787886da342Sopenharmony_ci                await hookItem();
788886da342Sopenharmony_ci            } catch (error) {
789886da342Sopenharmony_ci                error['message'] += `, error in ${hookName} function`;
790886da342Sopenharmony_ci                throw error;
791886da342Sopenharmony_ci            }
792886da342Sopenharmony_ci
793886da342Sopenharmony_ci        }
794886da342Sopenharmony_ci    }
795886da342Sopenharmony_ci};
796886da342Sopenharmony_ci
797886da342Sopenharmony_ciclass SpecService {
798886da342Sopenharmony_ci    constructor(attr) {
799886da342Sopenharmony_ci        this.id = attr.id;
800886da342Sopenharmony_ci        this.totalTest = 0;
801886da342Sopenharmony_ci        this.hasError = false;
802886da342Sopenharmony_ci        this.skipSpecNum = 0;
803886da342Sopenharmony_ci        this.isSkipSpec = false;
804886da342Sopenharmony_ci        this.specSkipReason = '';
805886da342Sopenharmony_ci    }
806886da342Sopenharmony_ci
807886da342Sopenharmony_ci    init(coreContext) {
808886da342Sopenharmony_ci        this.coreContext = coreContext;
809886da342Sopenharmony_ci    }
810886da342Sopenharmony_ci
811886da342Sopenharmony_ci    setCurrentRunningSpec(spec) {
812886da342Sopenharmony_ci        this.currentRunningSpec = spec;
813886da342Sopenharmony_ci    }
814886da342Sopenharmony_ci
815886da342Sopenharmony_ci    setStatus(obj) {
816886da342Sopenharmony_ci        this.hasError = obj;
817886da342Sopenharmony_ci    }
818886da342Sopenharmony_ci
819886da342Sopenharmony_ci    getStatus() {
820886da342Sopenharmony_ci        return this.hasError;
821886da342Sopenharmony_ci    }
822886da342Sopenharmony_ci
823886da342Sopenharmony_ci    getTestTotal() {
824886da342Sopenharmony_ci        return this.totalTest;
825886da342Sopenharmony_ci    }
826886da342Sopenharmony_ci
827886da342Sopenharmony_ci    getCurrentRunningSpec() {
828886da342Sopenharmony_ci        return this.currentRunningSpec;
829886da342Sopenharmony_ci    }
830886da342Sopenharmony_ci
831886da342Sopenharmony_ci
832886da342Sopenharmony_ci    getSkipSpecNum() {
833886da342Sopenharmony_ci        return this.skipSpecNum;
834886da342Sopenharmony_ci    }
835886da342Sopenharmony_ci
836886da342Sopenharmony_ci    initSpecService() {
837886da342Sopenharmony_ci        this.isSkipSpec = false;
838886da342Sopenharmony_ci        this.specSkipReason = '';
839886da342Sopenharmony_ci    }
840886da342Sopenharmony_ci
841886da342Sopenharmony_ci    it(desc, filter, func) {
842886da342Sopenharmony_ci        const suiteService = this.coreContext.getDefaultService('suite');
843886da342Sopenharmony_ci        const configService = this.coreContext.getDefaultService('config');
844886da342Sopenharmony_ci        let isFilter = new NestFilter().filterNestName(suiteService.targetSuiteArray, suiteService.targetSpecArray, suiteService.suitesStack, desc);
845886da342Sopenharmony_ci        if (configService.filterWithNest(desc, filter)) {
846886da342Sopenharmony_ci            console.info(`${TAG}filter it :${desc}`);
847886da342Sopenharmony_ci            this.initSpecService();
848886da342Sopenharmony_ci            return;
849886da342Sopenharmony_ci        }
850886da342Sopenharmony_ci        if (configService.filterDesc(suiteService.currentRunningSuite.description, desc, filter, this.coreContext) && isFilter && !suiteService.fullRun) {
851886da342Sopenharmony_ci            console.info(`${TAG}filter it :${desc}`);
852886da342Sopenharmony_ci            this.initSpecService();
853886da342Sopenharmony_ci        } else {
854886da342Sopenharmony_ci            let processedFunc = processFunc(this.coreContext, func);
855886da342Sopenharmony_ci            const spec = new SpecService.Spec({ description: desc, fi: filter, fn: processedFunc });
856886da342Sopenharmony_ci            if (this.isSkipSpec) {
857886da342Sopenharmony_ci                spec.isSkip = true;
858886da342Sopenharmony_ci                spec.skipReason = this.specSkipReason;
859886da342Sopenharmony_ci            }
860886da342Sopenharmony_ci            this.initSpecService();
861886da342Sopenharmony_ci            if (configService.runSkipped === 'skipped' && !spec.isSkip) {
862886da342Sopenharmony_ci                console.info(`${TAG} runSkipped is skipped , just run xit, don't run it: ${spec.description}`);
863886da342Sopenharmony_ci                return;
864886da342Sopenharmony_ci            }
865886da342Sopenharmony_ci            if (suiteService.getCurrentRunningSuite().isSkip && !spec.isSkip) {
866886da342Sopenharmony_ci                configService.filterXdescribe.push(suiteService.getCurrentRunningSuite().description);
867886da342Sopenharmony_ci            }
868886da342Sopenharmony_ci            if (typeof this.coreContext.getServices('dataDriver') !== 'undefined' && configService['dryRun'] !== 'true') {
869886da342Sopenharmony_ci                let specStress = this.coreContext.getServices('dataDriver').dataDriver.getSpecStress(desc);
870886da342Sopenharmony_ci                for (let i = 1; i < specStress; i++) {
871886da342Sopenharmony_ci                    this.totalTest++;
872886da342Sopenharmony_ci                    suiteService.getCurrentRunningSuite().pushSpec(spec);
873886da342Sopenharmony_ci                }
874886da342Sopenharmony_ci            }
875886da342Sopenharmony_ci            // dryRun 状态下不统计压力测试重复数据
876886da342Sopenharmony_ci            if (configService['dryRun'] !== 'true') {
877886da342Sopenharmony_ci                let stress = configService.getStress(); // 命令配置压力测试
878886da342Sopenharmony_ci                console.info(`${TAG}stress length : ${stress}`);
879886da342Sopenharmony_ci                for (let i = 1; i < stress; i++) {
880886da342Sopenharmony_ci                    this.totalTest++;
881886da342Sopenharmony_ci                    suiteService.getCurrentRunningSuite().pushSpec(spec);
882886da342Sopenharmony_ci                }
883886da342Sopenharmony_ci            }
884886da342Sopenharmony_ci            this.totalTest++;
885886da342Sopenharmony_ci            suiteService.getCurrentRunningSuite().pushSpec(spec);
886886da342Sopenharmony_ci        }
887886da342Sopenharmony_ci    }
888886da342Sopenharmony_ci
889886da342Sopenharmony_ci    xit(desc, filter, func, reason) {
890886da342Sopenharmony_ci        const configService = this.coreContext.getDefaultService('config');
891886da342Sopenharmony_ci        const suiteService = this.coreContext.getDefaultService('suite');
892886da342Sopenharmony_ci        if (!configService.skipMessage && configService.runSkipped !== 'all') {
893886da342Sopenharmony_ci            if (configService.runSkipped != null && configService.runSkipped !== '') {
894886da342Sopenharmony_ci                let finalDesc = '';
895886da342Sopenharmony_ci                suiteService.suitesStack.map(suite => {
896886da342Sopenharmony_ci                    finalDesc = finalDesc + '.' + suite.description;
897886da342Sopenharmony_ci                });
898886da342Sopenharmony_ci                finalDesc = (finalDesc + '#' + desc).substring(2);
899886da342Sopenharmony_ci                if (configService.checkIfSpecInSkipRun(finalDesc)) {
900886da342Sopenharmony_ci                    console.info(`${TAG} runSkipped spec: ${desc}`);
901886da342Sopenharmony_ci                } else {
902886da342Sopenharmony_ci                    console.info(reason == null ? `${TAG} skip spec: ${desc}` : `${TAG} skip spec: ${desc}, and the reason is ${reason}`);
903886da342Sopenharmony_ci                    return;
904886da342Sopenharmony_ci                }
905886da342Sopenharmony_ci            } else {
906886da342Sopenharmony_ci                console.info(reason == null ? `${TAG} skip spec: ${desc}` : `${TAG} skip spec: ${desc}, and the reason is ${reason}`);
907886da342Sopenharmony_ci                return;
908886da342Sopenharmony_ci            }
909886da342Sopenharmony_ci        }
910886da342Sopenharmony_ci        this.skipSpecNum++;
911886da342Sopenharmony_ci        this.isSkipSpec = true;
912886da342Sopenharmony_ci        this.specSkipReason = reason;
913886da342Sopenharmony_ci        this.it(desc, filter, func);
914886da342Sopenharmony_ci    }
915886da342Sopenharmony_ci
916886da342Sopenharmony_ci    apis() {
917886da342Sopenharmony_ci        const _this = this;
918886da342Sopenharmony_ci        return {
919886da342Sopenharmony_ci            it: function (desc, filter, func) {
920886da342Sopenharmony_ci                return _this.it(desc, filter, func);
921886da342Sopenharmony_ci            },
922886da342Sopenharmony_ci            xit: function (desc, filter, func, reason) {
923886da342Sopenharmony_ci                return _this.xit(desc, filter, func, reason);
924886da342Sopenharmony_ci            }
925886da342Sopenharmony_ci        };
926886da342Sopenharmony_ci    }
927886da342Sopenharmony_ci}
928886da342Sopenharmony_ci
929886da342Sopenharmony_ciSpecService.Spec = class {
930886da342Sopenharmony_ci    constructor(attrs) {
931886da342Sopenharmony_ci        this.description = attrs.description || '';
932886da342Sopenharmony_ci        this.fi = attrs.fi;
933886da342Sopenharmony_ci        this.fn = attrs.fn || function () {
934886da342Sopenharmony_ci        };
935886da342Sopenharmony_ci        this.fail = undefined;
936886da342Sopenharmony_ci        this.error = undefined;
937886da342Sopenharmony_ci        this.duration = 0;
938886da342Sopenharmony_ci        this.startTime = 0;
939886da342Sopenharmony_ci        this.isExecuted = false; // 当前用例是否执行
940886da342Sopenharmony_ci        this.isSkip = false;
941886da342Sopenharmony_ci        this.skipReason = '';
942886da342Sopenharmony_ci        this.expectMsg = '';
943886da342Sopenharmony_ci    }
944886da342Sopenharmony_ci
945886da342Sopenharmony_ci    setResult() {
946886da342Sopenharmony_ci        if (this.fail) {
947886da342Sopenharmony_ci            this.pass = false;
948886da342Sopenharmony_ci        } else {
949886da342Sopenharmony_ci            this.pass = true;
950886da342Sopenharmony_ci        }
951886da342Sopenharmony_ci    }
952886da342Sopenharmony_ci
953886da342Sopenharmony_ci    run(coreContext) {
954886da342Sopenharmony_ci        const specService = coreContext.getDefaultService('spec');
955886da342Sopenharmony_ci        specService.setCurrentRunningSpec(this);
956886da342Sopenharmony_ci        coreContext.fireEvents('spec', 'specStart', this);
957886da342Sopenharmony_ci        this.isExecuted = true;
958886da342Sopenharmony_ci        try {
959886da342Sopenharmony_ci            let dataDriver = coreContext.getServices('dataDriver');
960886da342Sopenharmony_ci            if (typeof dataDriver === 'undefined') {
961886da342Sopenharmony_ci                this.fn();
962886da342Sopenharmony_ci            } else {
963886da342Sopenharmony_ci                let suiteParams = dataDriver.dataDriver.getSuiteParams();
964886da342Sopenharmony_ci                let specParams = dataDriver.dataDriver.getSpecParams();
965886da342Sopenharmony_ci                console.info(`${TAG}[suite params] ${JSON.stringify(suiteParams)}`);
966886da342Sopenharmony_ci                console.info(`${TAG}[spec params] ${JSON.stringify(specParams)}`);
967886da342Sopenharmony_ci                if (this.fn.length === 0) {
968886da342Sopenharmony_ci                    this.fn();
969886da342Sopenharmony_ci                } else if (specParams.length === 0) {
970886da342Sopenharmony_ci                    this.fn(suiteParams);
971886da342Sopenharmony_ci                } else {
972886da342Sopenharmony_ci                    specParams.forEach(paramItem => this.fn(Object.assign({}, paramItem, suiteParams)));
973886da342Sopenharmony_ci                }
974886da342Sopenharmony_ci            }
975886da342Sopenharmony_ci            this.setResult();
976886da342Sopenharmony_ci        } catch (e) {
977886da342Sopenharmony_ci            this.error = e;
978886da342Sopenharmony_ci            specService.setStatus(true);
979886da342Sopenharmony_ci        }
980886da342Sopenharmony_ci        coreContext.fireEvents('spec', 'specDone', this);
981886da342Sopenharmony_ci    }
982886da342Sopenharmony_ci
983886da342Sopenharmony_ci    async asyncRun(coreContext) {
984886da342Sopenharmony_ci        const dataDriver = coreContext.getServices('dataDriver');
985886da342Sopenharmony_ci        if (typeof dataDriver === 'undefined') {
986886da342Sopenharmony_ci            await this.fn();
987886da342Sopenharmony_ci        } else {
988886da342Sopenharmony_ci            const suiteParams = dataDriver.dataDriver.getSuiteParams();
989886da342Sopenharmony_ci            const specParams = dataDriver.dataDriver.getSpecParams();
990886da342Sopenharmony_ci            console.info(`[suite params] ${JSON.stringify(suiteParams)}`);
991886da342Sopenharmony_ci            console.info(`[spec params] ${JSON.stringify(specParams)}`);
992886da342Sopenharmony_ci            if (this.fn.length === 0) {
993886da342Sopenharmony_ci                await this.fn();
994886da342Sopenharmony_ci            } else if (specParams.length === 0) {
995886da342Sopenharmony_ci                await this.fn(suiteParams);
996886da342Sopenharmony_ci            } else {
997886da342Sopenharmony_ci                for (const paramItem of specParams) {
998886da342Sopenharmony_ci                    await this.fn(Object.assign({}, paramItem, suiteParams));
999886da342Sopenharmony_ci                }
1000886da342Sopenharmony_ci            }
1001886da342Sopenharmony_ci        }
1002886da342Sopenharmony_ci
1003886da342Sopenharmony_ci        this.isExecuted = true;
1004886da342Sopenharmony_ci    }
1005886da342Sopenharmony_ci
1006886da342Sopenharmony_ci    filterCheck(coreContext) {
1007886da342Sopenharmony_ci        const specService = coreContext.getDefaultService('spec');
1008886da342Sopenharmony_ci        specService.setCurrentRunningSpec(this);
1009886da342Sopenharmony_ci        return true;
1010886da342Sopenharmony_ci    }
1011886da342Sopenharmony_ci};
1012886da342Sopenharmony_ci
1013886da342Sopenharmony_ciclass ExpectService {
1014886da342Sopenharmony_ci    constructor(attr) {
1015886da342Sopenharmony_ci        this.id = attr.id;
1016886da342Sopenharmony_ci        this.matchers = {};
1017886da342Sopenharmony_ci        this.customMatchers = [];
1018886da342Sopenharmony_ci    }
1019886da342Sopenharmony_ci
1020886da342Sopenharmony_ci    expect(actualValue) {
1021886da342Sopenharmony_ci        return this.wrapMatchers(actualValue);
1022886da342Sopenharmony_ci    }
1023886da342Sopenharmony_ci
1024886da342Sopenharmony_ci    init(coreContext) {
1025886da342Sopenharmony_ci        this.coreContext = coreContext;
1026886da342Sopenharmony_ci        this.addMatchers(this.basicMatchers());
1027886da342Sopenharmony_ci    }
1028886da342Sopenharmony_ci
1029886da342Sopenharmony_ci    addMatchers(matchers) {
1030886da342Sopenharmony_ci        for (const matcherName in matchers) {
1031886da342Sopenharmony_ci            if (Object.prototype.hasOwnProperty.call(matchers, matcherName)) {
1032886da342Sopenharmony_ci                this.matchers[matcherName] = matchers[matcherName];
1033886da342Sopenharmony_ci            }
1034886da342Sopenharmony_ci        }
1035886da342Sopenharmony_ci    }
1036886da342Sopenharmony_ci
1037886da342Sopenharmony_ci    removeMatchers(customAssertionName) {
1038886da342Sopenharmony_ci        if (customAssertionName === 'all') {
1039886da342Sopenharmony_ci            for (const matcherName in this.matchers) {
1040886da342Sopenharmony_ci                this.matchers[matcherName] = this.customMatchers.includes(matcherName)
1041886da342Sopenharmony_ci                    ? (() => {throw new Error(`${matcherName} is unregistered`)}) : undefined;
1042886da342Sopenharmony_ci            }
1043886da342Sopenharmony_ci        } else {
1044886da342Sopenharmony_ci            this.matchers[customAssertionName] = () => {
1045886da342Sopenharmony_ci                throw new Error(`${customAssertionName} is unregistered`);
1046886da342Sopenharmony_ci            };
1047886da342Sopenharmony_ci        }
1048886da342Sopenharmony_ci    }
1049886da342Sopenharmony_ci
1050886da342Sopenharmony_ci    basicMatchers() {
1051886da342Sopenharmony_ci        return {
1052886da342Sopenharmony_ci            assertTrue: assertTrueFun,
1053886da342Sopenharmony_ci            assertEqual: assertEqualFun,
1054886da342Sopenharmony_ci            assertThrow: assertThrowFun
1055886da342Sopenharmony_ci        };
1056886da342Sopenharmony_ci    }
1057886da342Sopenharmony_ci
1058886da342Sopenharmony_ci    initWrapMatchers(currentRunningSpec) {
1059886da342Sopenharmony_ci        return {
1060886da342Sopenharmony_ci            // 翻转标识
1061886da342Sopenharmony_ci            isNot: false,
1062886da342Sopenharmony_ci            // 翻转方法
1063886da342Sopenharmony_ci            not: function () {
1064886da342Sopenharmony_ci                this.isNot = true;
1065886da342Sopenharmony_ci                return this;
1066886da342Sopenharmony_ci            },
1067886da342Sopenharmony_ci            message: function (msg) {
1068886da342Sopenharmony_ci                currentRunningSpec.expectMsg = msg;
1069886da342Sopenharmony_ci                console.info(`${TAG} msg: ${msg}`);
1070886da342Sopenharmony_ci                return this;
1071886da342Sopenharmony_ci            }
1072886da342Sopenharmony_ci        };
1073886da342Sopenharmony_ci
1074886da342Sopenharmony_ci    }
1075886da342Sopenharmony_ci
1076886da342Sopenharmony_ci    handleWithAssertPromise(_this, wrappedMatchers, matcherName, actualValue, currentRunningSpec, currentRunningSuite) {
1077886da342Sopenharmony_ci        wrappedMatchers[matcherName] = async function (...args) {
1078886da342Sopenharmony_ci            await _this.matchers[matcherName](actualValue, args).then(function (result) {
1079886da342Sopenharmony_ci                if (wrappedMatchers.isNot) {
1080886da342Sopenharmony_ci                    result.pass = !result.pass;
1081886da342Sopenharmony_ci                }
1082886da342Sopenharmony_ci                result.actualValue = actualValue;
1083886da342Sopenharmony_ci                result.checkFunc = matcherName;
1084886da342Sopenharmony_ci                if (!result.pass) {
1085886da342Sopenharmony_ci                    const assertError = new AssertException(result.message);
1086886da342Sopenharmony_ci                    currentRunningSpec ? currentRunningSpec.fail = assertError : currentRunningSuite.hookError = assertError;
1087886da342Sopenharmony_ci                    throw assertError;
1088886da342Sopenharmony_ci                }
1089886da342Sopenharmony_ci            });
1090886da342Sopenharmony_ci        };
1091886da342Sopenharmony_ci    }
1092886da342Sopenharmony_ci
1093886da342Sopenharmony_ci    handleWithoutAssertPromise(_this, wrappedMatchers, matcherName, actualValue, currentRunningSpec, currentRunningSuite) {
1094886da342Sopenharmony_ci        wrappedMatchers[matcherName] = function (...args) {
1095886da342Sopenharmony_ci            const result = _this.customMatchers.includes(matcherName)
1096886da342Sopenharmony_ci                ? _this.matchers[matcherName](actualValue, args[0]) : _this.matchers[matcherName](actualValue, args);
1097886da342Sopenharmony_ci            if (wrappedMatchers.isNot) {
1098886da342Sopenharmony_ci                result.pass = !result.pass;
1099886da342Sopenharmony_ci                result.message = LogExpectError.getErrorMsg(matcherName, actualValue, args[0], result.message);
1100886da342Sopenharmony_ci            }
1101886da342Sopenharmony_ci            result.actualValue = actualValue;
1102886da342Sopenharmony_ci            result.checkFunc = matcherName;
1103886da342Sopenharmony_ci            if (!result.pass) {
1104886da342Sopenharmony_ci                const assertError = new AssertException(result.message);
1105886da342Sopenharmony_ci                currentRunningSpec ? currentRunningSpec.fail = assertError : currentRunningSuite.hookError = assertError;
1106886da342Sopenharmony_ci                throw assertError;
1107886da342Sopenharmony_ci            }
1108886da342Sopenharmony_ci        };
1109886da342Sopenharmony_ci    }
1110886da342Sopenharmony_ci
1111886da342Sopenharmony_ci    addAssert(wrappedMatchers, matcherName, actualValue) {
1112886da342Sopenharmony_ci        const _this = this;
1113886da342Sopenharmony_ci        const specService = _this.coreContext.getDefaultService('spec');
1114886da342Sopenharmony_ci        const currentRunningSpec = specService.getCurrentRunningSpec();
1115886da342Sopenharmony_ci        const currentRunningSuite = _this.coreContext.getDefaultService('suite').getCurrentRunningSuite();
1116886da342Sopenharmony_ci        if (matcherName.search('assertPromise') === 0) {
1117886da342Sopenharmony_ci            this.handleWithAssertPromise(_this, wrappedMatchers, matcherName, actualValue, currentRunningSpec, currentRunningSuite);
1118886da342Sopenharmony_ci        } else {
1119886da342Sopenharmony_ci            this.handleWithoutAssertPromise(_this, wrappedMatchers, matcherName, actualValue, currentRunningSpec, currentRunningSuite);
1120886da342Sopenharmony_ci        }
1121886da342Sopenharmony_ci    }
1122886da342Sopenharmony_ci
1123886da342Sopenharmony_ci    wrapMatchers(actualValue) {
1124886da342Sopenharmony_ci        const _this = this;
1125886da342Sopenharmony_ci        const specService = _this.coreContext.getDefaultService('spec');
1126886da342Sopenharmony_ci        const currentRunningSpec = specService.getCurrentRunningSpec();
1127886da342Sopenharmony_ci        const wrappedMatchers = this.initWrapMatchers(currentRunningSpec);
1128886da342Sopenharmony_ci        const currentRunningSuite = _this.coreContext.getDefaultService('suite').getCurrentRunningSuite();
1129886da342Sopenharmony_ci        for (const matcherName in this.matchers) {
1130886da342Sopenharmony_ci            let result = Object.prototype.hasOwnProperty.call(this.matchers, matcherName);
1131886da342Sopenharmony_ci            if (!result) {
1132886da342Sopenharmony_ci                continue;
1133886da342Sopenharmony_ci            }
1134886da342Sopenharmony_ci            this.addAssert(wrappedMatchers, matcherName, actualValue);
1135886da342Sopenharmony_ci        }
1136886da342Sopenharmony_ci        return wrappedMatchers;
1137886da342Sopenharmony_ci    }
1138886da342Sopenharmony_ci
1139886da342Sopenharmony_ci    apis() {
1140886da342Sopenharmony_ci        const _this = this;
1141886da342Sopenharmony_ci        return {
1142886da342Sopenharmony_ci            expect: function (actualValue) {
1143886da342Sopenharmony_ci                return _this.expect(actualValue);
1144886da342Sopenharmony_ci            }
1145886da342Sopenharmony_ci        };
1146886da342Sopenharmony_ci    }
1147886da342Sopenharmony_ci}
1148886da342Sopenharmony_ci
1149886da342Sopenharmony_ciclass ReportService {
1150886da342Sopenharmony_ci    constructor(attr) {
1151886da342Sopenharmony_ci        this.id = attr.id;
1152886da342Sopenharmony_ci    }
1153886da342Sopenharmony_ci
1154886da342Sopenharmony_ci    init(coreContext) {
1155886da342Sopenharmony_ci        this.coreContext = coreContext;
1156886da342Sopenharmony_ci        this.specService = this.coreContext.getDefaultService('spec');
1157886da342Sopenharmony_ci        this.suiteService = this.coreContext.getDefaultService('suite');
1158886da342Sopenharmony_ci        this.duration = 0;
1159886da342Sopenharmony_ci    }
1160886da342Sopenharmony_ci
1161886da342Sopenharmony_ci    taskStart() {
1162886da342Sopenharmony_ci        console.info(`${TAG}[start] start run suites`);
1163886da342Sopenharmony_ci    }
1164886da342Sopenharmony_ci
1165886da342Sopenharmony_ci    async suiteStart() {
1166886da342Sopenharmony_ci        console.info(`${TAG}[suite start]${this.suiteService.getCurrentRunningSuite().description}`);
1167886da342Sopenharmony_ci    }
1168886da342Sopenharmony_ci
1169886da342Sopenharmony_ci    async specStart() {
1170886da342Sopenharmony_ci        console.info(`${TAG}start running case '${this.specService.currentRunningSpec.description}'`);
1171886da342Sopenharmony_ci        this.index = this.index + 1;
1172886da342Sopenharmony_ci        let spec = this.specService.currentRunningSpec;
1173886da342Sopenharmony_ci        spec.startTime = await SysTestKit.getRealTime();
1174886da342Sopenharmony_ci    }
1175886da342Sopenharmony_ci
1176886da342Sopenharmony_ci    async specDone() {
1177886da342Sopenharmony_ci        let msg = '';
1178886da342Sopenharmony_ci        let spec = this.specService.currentRunningSpec;
1179886da342Sopenharmony_ci        let suite = this.suiteService.currentRunningSuite;
1180886da342Sopenharmony_ci        spec.duration = await SysTestKit.getRealTime() - spec.startTime;
1181886da342Sopenharmony_ci        suite.duration += spec.duration;
1182886da342Sopenharmony_ci        if (spec.error) {
1183886da342Sopenharmony_ci            this.formatPrint('error', spec.description + ' ; consuming ' + spec.duration + 'ms');
1184886da342Sopenharmony_ci            this.formatPrint('errorDetail', spec.error);
1185886da342Sopenharmony_ci        } else if (spec.fail) {
1186886da342Sopenharmony_ci            this.formatPrint('fail', spec.description + ' ; consuming ' + spec.duration + 'ms');
1187886da342Sopenharmony_ci            this.formatPrint('failDetail', spec.fail?.message);
1188886da342Sopenharmony_ci        } else {
1189886da342Sopenharmony_ci            this.formatPrint('pass', spec.description + ' ; consuming ' + spec.duration + 'ms');
1190886da342Sopenharmony_ci        }
1191886da342Sopenharmony_ci        this.formatPrint(this.specService.currentRunningSpec.error, msg);
1192886da342Sopenharmony_ci    }
1193886da342Sopenharmony_ci
1194886da342Sopenharmony_ci    suiteDone() {
1195886da342Sopenharmony_ci        let suite = this.suiteService.currentRunningSuite;
1196886da342Sopenharmony_ci        let message = suite.hookError ? `, ${suite.hookError?.message}` : '';
1197886da342Sopenharmony_ci        console.info(`[suite end] ${suite.description} consuming ${suite.duration} ms${message}`);
1198886da342Sopenharmony_ci    }
1199886da342Sopenharmony_ci
1200886da342Sopenharmony_ci    taskDone() {
1201886da342Sopenharmony_ci        let msg = '';
1202886da342Sopenharmony_ci        let summary = this.suiteService.getSummary();
1203886da342Sopenharmony_ci        msg = 'total cases:' + summary.total + ';failure ' + summary.failure + ',' + 'error ' + summary.error;
1204886da342Sopenharmony_ci        msg += ',pass ' + summary.pass + '; consuming ' + summary.duration + 'ms';
1205886da342Sopenharmony_ci        console.info(`${TAG}${msg}`);
1206886da342Sopenharmony_ci        console.info(`${TAG}[end] run suites end`);
1207886da342Sopenharmony_ci    }
1208886da342Sopenharmony_ci
1209886da342Sopenharmony_ci    incorrectFormat() {
1210886da342Sopenharmony_ci        if (this.coreContext.getDefaultService('config').filterValid.length !== 0) {
1211886da342Sopenharmony_ci            this.coreContext.getDefaultService('config').filterValid.forEach(function (item) {
1212886da342Sopenharmony_ci                console.info(`${TAG}this param ${item} is invalid`);
1213886da342Sopenharmony_ci            });
1214886da342Sopenharmony_ci        }
1215886da342Sopenharmony_ci    }
1216886da342Sopenharmony_ci
1217886da342Sopenharmony_ci    incorrectTestSuiteFormat() {
1218886da342Sopenharmony_ci        if (this.coreContext.getDefaultService('config').filterXdescribe.length !== 0) {
1219886da342Sopenharmony_ci            this.coreContext.getDefaultService('config').filterXdescribe.forEach(function (item) {
1220886da342Sopenharmony_ci                console.info(`${TAG}xdescribe: ${item} should not contain it`);
1221886da342Sopenharmony_ci            });
1222886da342Sopenharmony_ci        }
1223886da342Sopenharmony_ci    }
1224886da342Sopenharmony_ci
1225886da342Sopenharmony_ci    formatPrint(type, msg) {
1226886da342Sopenharmony_ci        switch (type) {
1227886da342Sopenharmony_ci            case 'pass':
1228886da342Sopenharmony_ci                console.info(`${TAG}[pass]${msg}`);
1229886da342Sopenharmony_ci                break;
1230886da342Sopenharmony_ci            case 'fail':
1231886da342Sopenharmony_ci                console.info(`${TAG}[fail]${msg}`);
1232886da342Sopenharmony_ci                break;
1233886da342Sopenharmony_ci            case 'failDetail':
1234886da342Sopenharmony_ci                console.info(`${TAG}[failDetail]${msg}`);
1235886da342Sopenharmony_ci                break;
1236886da342Sopenharmony_ci            case 'error':
1237886da342Sopenharmony_ci                console.info(`${TAG}[error]${msg}`);
1238886da342Sopenharmony_ci                break;
1239886da342Sopenharmony_ci            case 'errorDetail':
1240886da342Sopenharmony_ci                console.info(`${TAG}[errorDetail]${msg}`);
1241886da342Sopenharmony_ci                break;
1242886da342Sopenharmony_ci        }
1243886da342Sopenharmony_ci    }
1244886da342Sopenharmony_ci
1245886da342Sopenharmony_ci    sleep(numberMillis) {
1246886da342Sopenharmony_ci        var now = new Date();
1247886da342Sopenharmony_ci        var exitTime = now.getTime() + numberMillis;
1248886da342Sopenharmony_ci        while (true) {
1249886da342Sopenharmony_ci            now = new Date();
1250886da342Sopenharmony_ci            if (now.getTime() > exitTime) {
1251886da342Sopenharmony_ci                return;
1252886da342Sopenharmony_ci            }
1253886da342Sopenharmony_ci        }
1254886da342Sopenharmony_ci    }
1255886da342Sopenharmony_ci}
1256886da342Sopenharmony_ci
1257886da342Sopenharmony_ciexport {
1258886da342Sopenharmony_ci    SuiteService,
1259886da342Sopenharmony_ci    SpecService,
1260886da342Sopenharmony_ci    ExpectService,
1261886da342Sopenharmony_ci    ReportService
1262886da342Sopenharmony_ci};
1263