• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { ServiceAttrIF, ApiIF } from '../../interface';
17import { NestFilter } from '../config/Filter';
18import { Core } from '../../core';
19import { StaticSpec } from './StaticSpec';
20import { StaticSuite } from './StaticSuite';
21import { TAG } from '../../Constant';
22import {
23  processFunc,
24  processAsyncFunc,
25  processFuncWithArgOne,
26  processAsyncFuncWithArgOne,
27  processFuncWithArgTwo,
28  processAsyncFuncWithArgTwo,
29  getFunctionArgumentsCount,
30  checkIsAsyncFunction
31} from '../../util';
32import { SuiteService } from './SuiteService';
33import { ConfigService } from '../config/configService';
34import DataDriver from '../config/DataDriver';
35import { ItfnType, AnyType } from '../types/common';
36class SpecService {
37  public id: string;
38  public totalTest: int;
39  public hasError: boolean;
40  public skipSpecNum: int;
41  public isSkipSpec: boolean;
42  public specSkipReason: string;
43  public coreContext: Core | null;
44  public currentRunningSpec: StaticSpec | null;
45  constructor(attr: ServiceAttrIF) {
46    this.id = attr.id;
47    this.totalTest = 0;
48    this.hasError = false;
49    this.skipSpecNum = 0;
50    this.isSkipSpec = false;
51    this.specSkipReason = '';
52    this.coreContext = null;
53    this.currentRunningSpec = new StaticSpec({ description: '', fi: 0, fn: (): void => {} });
54  }
55
56  init(coreContext: Core) {
57    this.coreContext = coreContext;
58  }
59
60  setCurrentRunningSpec(spec: StaticSpec | null) {
61    this.currentRunningSpec = spec;
62  }
63
64  setStatus(hasError: boolean) {
65    this.hasError = hasError;
66  }
67
68  getStatus(): boolean {
69    return this.hasError;
70  }
71
72  getTestTotal() {
73    return this.totalTest;
74  }
75
76  getCurrentRunningSpec() {
77    return this.currentRunningSpec;
78  }
79  getSkipSpecNum() {
80    return this.skipSpecNum;
81  }
82
83  initSpecService() {
84    this.isSkipSpec = false;
85    this.specSkipReason = '';
86  }
87
88  it(desc: string, filter: int, func: ItfnType): void {
89    const coreContext = this.coreContext;
90    if (coreContext !== null) {
91      const suiteService = coreContext.getDefaultService('suite');
92      const configService = coreContext.getDefaultService('config');
93
94      if (suiteService !== null && configService !== null) {
95        const sService = suiteService as SuiteService;
96        const cService = configService as ConfigService;
97        let isFilter = new NestFilter().filterNestName(
98          sService.targetSuiteArray,
99          sService.targetSpecArray,
100          sService.suitesStack,
101          desc
102        );
103
104        if (cService.filterWithNest(desc, filter)) {
105          this.initSpecService();
106          return;
107        }
108        const curSuite = sService.getCurrentRunningSuite() as StaticSuite;
109        if (cService.filterDesc(curSuite.description, desc, filter) && isFilter && !sService.fullRun) {
110          this.initSpecService();
111        } else {
112          const funcStr = Type.of(func as object).getLiteral();
113          const argsCount = getFunctionArgumentsCount(funcStr);
114
115          const isAsync = checkIsAsyncFunction(funcStr);
116          let processedFunc: (() => Promise<void>) | ((paramItem: AnyType) => Promise<void>) = (): Promise<void> => {
117            return Promise.resolve();
118          };
119          if (argsCount === 2) {
120            if (isAsync) {
121              const fn = func as (done: () => void, param: AnyType) => Promise<void>;
122              processedFunc = processAsyncFuncWithArgTwo(coreContext, fn);
123            } else {
124              const fn = func as (done: () => void, param: AnyType) => void;
125              processedFunc = processFuncWithArgTwo(coreContext, fn);
126            }
127          } else if (argsCount === 1) {
128            if (isAsync) {
129              const fn = func as (done: () => void) => Promise<void>;
130              processedFunc = processAsyncFuncWithArgOne(coreContext, fn);
131            } else {
132              const fn = func as (done: () => void) => void;
133              processedFunc = processFuncWithArgOne(coreContext, fn);
134            }
135          } else {
136            if (isAsync) {
137              const fn = func as () => Promise<void>;
138              processedFunc = processAsyncFunc(coreContext, fn);
139            } else {
140              const fn = func as () => void;
141              processedFunc = processFunc(coreContext, fn);
142            }
143          }
144          const spec = new StaticSpec({ description: desc, fi: filter, asyncFn: processedFunc });
145          if (this.isSkipSpec) {
146            spec.isSkip = true;
147            spec.skipReason = this.specSkipReason;
148          }
149          this.initSpecService();
150          if (cService.runSkipped === 'skipped' && !spec.isSkip) {
151            console.info(`${TAG} runSkipped is skipped , just run xit, don't run it: ${spec.description}`);
152            return;
153          }
154
155          if (curSuite.isSkip && !spec.isSkip) {
156            cService.filterXdescribe.push(curSuite.description);
157          }
158          if (cService.dryRun !== 'true') {
159            const dataDriverMap = coreContext.getServices('dataDriver');
160            if (dataDriverMap) {
161              const dataDriver = dataDriverMap.get('dataDriver') as DataDriver;
162              const specStress = dataDriver.getSpecStress(desc);
163              for (let i = 1; i < specStress; i++) {
164                  this.totalTest++;
165                  curSuite.pushSpec(spec);
166              }
167            }
168            let stress = cService.getStress(); // 命令配置压力测试
169            for (let i = 1; i < stress; i++) {
170              this.totalTest++;
171              curSuite.pushSpec(spec);
172            }
173          }
174
175          this.totalTest++;
176          curSuite.pushSpec(spec);
177        }
178      }
179    }
180  }
181
182  xit(desc: string, filter: int, func: ItfnType, reason: string) {
183    const coreContext = this.coreContext;
184    if (coreContext) {
185      const suiteService = coreContext.getDefaultService('suite');
186      const configService = coreContext.getDefaultService('config');
187      if (suiteService !== null && configService !== null) {
188        const sService = suiteService as SuiteService;
189        const cService = configService as ConfigService;
190        if (!cService.skipMessage && cService.runSkipped !== 'all') {
191          if (cService.runSkipped != null && cService.runSkipped !== '') {
192            let finalDesc = '';
193            sService.suitesStack.map((suite: StaticSuite) => {
194              finalDesc = finalDesc + '.' + suite.description;
195            });
196            finalDesc = (finalDesc + '#' + desc).substring(2);
197            if (cService.checkIfSpecInSkipRun(finalDesc)) {
198              console.info(`${TAG} runSkipped spec: ${desc}`);
199            } else {
200              console.info(
201                reason == null ? `${TAG} skip spec: ${desc}` : `${TAG} skip spec: ${desc}, and the reason is ${reason}`
202              );
203              return;
204            }
205          } else {
206            console.info(
207              reason == null ? `${TAG} skip spec: ${desc}` : `${TAG} skip spec: ${desc}, and the reason is ${reason}`
208            );
209            return;
210          }
211        }
212        this.skipSpecNum++;
213        this.isSkipSpec = true;
214        this.specSkipReason = reason;
215        this.it(desc, filter, func);
216      }
217    }
218  }
219
220  apis(): ApiIF {
221    const _this = this;
222    return {
223      name: 'SpecService',
224      it: (desc: string, filter: int, func: ItfnType) => {
225        return _this.it(desc, filter, func);
226      },
227      xit: (desc: string, filter: int, func: ItfnType, reason: string) => {
228        return _this.xit(desc, filter, func, reason);
229      },
230    };
231  }
232}
233
234export { SpecService };
235