• 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 * as fs from 'fs';
17import * as path from 'path';
18import {
19  PerfMode,
20  TimeAndMemTimeTracker,
21  clearTimeAndMemPrinterData,
22  configurePerformancePrinter,
23  disablePrinterTimeAndMemConfig,
24  enableTimeAndMemoryPrint,
25  endSingleFileForMoreTimeEvent,
26  getObfuscationCacheDir,
27  getMemoryPerformanceData,
28  getTimePerformanceData,
29  initPerformanceTimeAndMemPrinter,
30  initPrinterTimeAndMemConfig,
31  startSingleFileForMoreTimeEvent,
32  writeTimeAndMemoryPerformanceData,
33} from '../../../src/utils/PrinterTimeAndMemUtils';
34import { expect } from 'chai';
35import { performanceTimeAndMemPrinter } from '../../../src/ArkObfuscator';
36import { printerTimeAndMemDataConfig } from '../../../src/initialization/Initializer';
37
38describe('test Cases for <PrinterTimAndMemUtils>.', function () {
39  beforeEach(() => {
40    performanceTimeAndMemPrinter.filesPrinter = new TimeAndMemTimeTracker();
41    performanceTimeAndMemPrinter.singleFilePrinter = new TimeAndMemTimeTracker();
42  });
43
44  describe('Tester Cases for <TimeTimeAndMemTracker>.', function () {
45    let printer: TimeAndMemTimeTracker;
46
47    beforeEach(() => {
48      printer = new TimeAndMemTimeTracker();
49    });
50
51    describe('Tester Cases for <startEvent>', () => {
52      /** test for startEvent */
53      it('Tester: <start test event> case for TimeTimeAndMemTracker#startEvent', () => {
54        const eventName = 'test event';
55        printer.startEvent(eventName);
56        const eventStack = printer.getEventStack();
57        const event = eventStack.find((e) => e.eventName === eventName);
58        expect(event?.data.endMemory).to.equal(0);
59      });
60    });
61
62    describe('Tester Cases for <endEvent>', () => {
63      /** test for endEvent */
64      it('should throw an error if the event has not started', function () {
65        printer.startEvent('testEvent');
66        printer.endEvent('testEvent');
67        expect(() => printer.endEvent('unstartedEvent')).to.throw(`Event stack is empty`);
68      });
69    });
70  });
71
72  describe('Tester Cases for <initPerformanceTimeAndMemPrinter>', () => {
73    it('should block performance printer when mTimeAndMemPrinter is false', () => {
74      printerTimeAndMemDataConfig.mTimeAndMemPrinter = false;
75      performanceTimeAndMemPrinter.singleFilePrinter = new TimeAndMemTimeTracker();
76      performanceTimeAndMemPrinter.filesPrinter = new TimeAndMemTimeTracker();
77
78      initPerformanceTimeAndMemPrinter();
79
80      expect(performanceTimeAndMemPrinter.singleFilePrinter).to.be.undefined;
81      expect(performanceTimeAndMemPrinter.filesPrinter).to.be.undefined;
82    });
83
84    it('should not block performance printer when mTimeAndMemPrinter is true', () => {
85      printerTimeAndMemDataConfig.mTimeAndMemPrinter = true;
86      performanceTimeAndMemPrinter.singleFilePrinter = new TimeAndMemTimeTracker();
87      performanceTimeAndMemPrinter.filesPrinter = new TimeAndMemTimeTracker();
88
89      initPerformanceTimeAndMemPrinter();
90
91      expect(performanceTimeAndMemPrinter.singleFilePrinter).to.not.be.undefined;
92      expect(performanceTimeAndMemPrinter.filesPrinter).to.not.be.undefined;
93    });
94  });
95
96  describe('Tester Cases for <configurePerformancePrinter>', () => {
97    it('should configure performance printer for advanced mode', () => {
98      printerTimeAndMemDataConfig.mTimeAndMemPrinter = false;
99      performanceTimeAndMemPrinter.singleFilePrinter = undefined;
100      performanceTimeAndMemPrinter.filesPrinter = undefined;
101
102      configurePerformancePrinter(PerfMode.ADVANCED);
103
104      expect(performanceTimeAndMemPrinter.singleFilePrinter).to.not.be.undefined;
105      expect(performanceTimeAndMemPrinter.filesPrinter).to.not.be.undefined;
106      expect(printerTimeAndMemDataConfig.mTimeAndMemPrinter).to.be.true;
107    });
108
109    it('should block performance printer for normal mode', () => {
110      performanceTimeAndMemPrinter.singleFilePrinter = new TimeAndMemTimeTracker();
111      performanceTimeAndMemPrinter.filesPrinter = new TimeAndMemTimeTracker();
112
113      configurePerformancePrinter(PerfMode.NORMAL);
114
115      expect(performanceTimeAndMemPrinter.singleFilePrinter).to.be.undefined;
116      expect(performanceTimeAndMemPrinter.filesPrinter).to.be.undefined;
117    });
118  });
119
120  describe('Tester Cases for <clearTimeAndMemPrinterData>', () => {
121    it('start a clearTimeAndMemPrinterData event', () => {
122      if (performanceTimeAndMemPrinter.filesPrinter) {
123        performanceTimeAndMemPrinter.filesPrinter.timeDataArr.push({
124          name: 'test',
125          ph: 'X',
126          pid: 1,
127          tid: 1,
128          ts: 5,
129          dur: 5,
130        });
131        performanceTimeAndMemPrinter.filesPrinter.memoryDataArr.push({
132          name: 'test',
133          startMemory: '5MB',
134          endMemory: '5MB',
135        });
136      }
137      if (performanceTimeAndMemPrinter.singleFilePrinter) {
138        performanceTimeAndMemPrinter.singleFilePrinter.timeDataArr.push({
139          name: 'test',
140          ph: 'X',
141          pid: 1,
142          tid: 1,
143          ts: 5,
144          dur: 5,
145        });
146        performanceTimeAndMemPrinter.singleFilePrinter.memoryDataArr.push({
147          name: 'test',
148          startMemory: '5MB',
149          endMemory: '5MB',
150        });
151      }
152
153      clearTimeAndMemPrinterData();
154
155      expect(performanceTimeAndMemPrinter.filesPrinter?.timeDataArr.length).to.equal(0);
156      expect(performanceTimeAndMemPrinter.filesPrinter?.memoryDataArr.length).to.equal(0);
157      expect(performanceTimeAndMemPrinter.singleFilePrinter?.timeDataArr.length).to.equal(0);
158      expect(performanceTimeAndMemPrinter.singleFilePrinter?.memoryDataArr.length).to.equal(0);
159    });
160
161    it('start a clearTimeAndMemPrinterData event is not set', () => {
162      performanceTimeAndMemPrinter.filesPrinter = undefined;
163      performanceTimeAndMemPrinter.singleFilePrinter = undefined;
164      clearTimeAndMemPrinterData();
165      expect(performanceTimeAndMemPrinter.filesPrinter === undefined).to.be.true;
166      expect(performanceTimeAndMemPrinter.singleFilePrinter === undefined).to.be.true;
167    });
168  });
169
170  describe('Tester Cases for <initPrinterTimeAndMemConfig>', () => {
171    it('start a initPrinterTimeAndMemConfig', () => {
172      printerTimeAndMemDataConfig.mTimeAndMemPrinter = false;
173      initPrinterTimeAndMemConfig();
174      expect(printerTimeAndMemDataConfig.mTimeAndMemPrinter).to.be.true;
175    });
176  });
177
178  describe('Tester Cases for <disablePrinterTimeAndMemConfig>', () => {
179    it('start a disablePrinterTimeAndMemConfig', () => {
180      printerTimeAndMemDataConfig.mTimeAndMemPrinter = true;
181      disablePrinterTimeAndMemConfig();
182      expect(printerTimeAndMemDataConfig.mTimeAndMemPrinter).to.be.false;
183    });
184  });
185
186  describe('Tester Cases for <startSingleFileForMoreTimeEvent>', () => {
187    it('start a singleFile event for more timeEvent when mMoreTimePrint is true', () => {
188      if (!performanceTimeAndMemPrinter.singleFilePrinter) {
189        performanceTimeAndMemPrinter.singleFilePrinter = new TimeAndMemTimeTracker();
190      }
191      const eventName = 'test event';
192      printerTimeAndMemDataConfig.mMoreTimePrint = true;
193      startSingleFileForMoreTimeEvent(eventName);
194      const eventStack = performanceTimeAndMemPrinter.singleFilePrinter?.getEventStack();
195      const event = eventStack!.find((e) => e.eventName === eventName);
196      expect(event?.eventName).to.be.equal('test event');
197    });
198
199    it('start a singleFile event for more timeEvent when mMoreTimePrint is false', () => {
200      const eventName = 'test event';
201      printerTimeAndMemDataConfig.mMoreTimePrint = false;
202      startSingleFileForMoreTimeEvent(eventName);
203      const eventStack = performanceTimeAndMemPrinter.singleFilePrinter?.getEventStack();
204      const event = eventStack?.find((e) => e.eventName === eventName);
205      expect(event).to.be.undefined;
206    });
207
208    it('start a singleFile event for more timeEvent when performanceTimeAndMemPrinter.singleFilePrinter is undefined', () => {
209      const eventName = 'test event';
210      printerTimeAndMemDataConfig.mMoreTimePrint = true;
211      performanceTimeAndMemPrinter.singleFilePrinter = undefined;
212      expect(() => startSingleFileForMoreTimeEvent(eventName)).to.not.throw;
213    });
214  });
215
216  describe('Tester Cases for <endSingleFileForMoreTimeEvent>', () => {
217    it('end a singleFile event for more timeEvent', async () => {
218      if (!performanceTimeAndMemPrinter.singleFilePrinter) {
219        performanceTimeAndMemPrinter.singleFilePrinter = new TimeAndMemTimeTracker();
220      }
221      const eventName = 'test event';
222      printerTimeAndMemDataConfig.mMoreTimePrint = true;
223      startSingleFileForMoreTimeEvent(eventName);
224
225      const eventStackBeforeEnd = performanceTimeAndMemPrinter.singleFilePrinter!.getEventStack();
226      const eventBeforeEnd = eventStackBeforeEnd.find((e) => e.eventName === eventName);
227
228      expect(eventBeforeEnd?.data.start).to.be.greaterThan(0);
229
230      endSingleFileForMoreTimeEvent(eventName);
231
232      const eventStackAfterEnd = performanceTimeAndMemPrinter.singleFilePrinter!.getEventStack();
233      expect(eventStackAfterEnd.length).to.equal(0);
234    });
235
236    it('start a singleFile event for more timeEvent when performanceTimeAndMemPrinter.singleFilePrinter is undefined', () => {
237      const eventName = 'test event';
238      printerTimeAndMemDataConfig.mMoreTimePrint = true;
239      performanceTimeAndMemPrinter.singleFilePrinter = undefined;
240      expect(() => endSingleFileForMoreTimeEvent(eventName)).to.not.throw;
241    });
242  });
243
244  describe('Tester Cases for <enableTimeAndMemoryPrint>', () => {
245    const testCacheDir = path.join(__dirname, 'test-cache');
246    const timePerformanceFilePath = path.join(testCacheDir, 'timePerformanceData.json');
247    const memoryPerformanceFilePath = path.join(testCacheDir, 'memoryPerformanceData.json');
248
249    beforeEach(() => {
250      if (!fs.existsSync(testCacheDir)) {
251        fs.mkdirSync(testCacheDir, { recursive: true });
252      }
253      if (fs.existsSync(timePerformanceFilePath)) {
254        fs.unlinkSync(timePerformanceFilePath);
255      }
256      if (fs.existsSync(memoryPerformanceFilePath)) {
257        fs.unlinkSync(memoryPerformanceFilePath);
258      }
259
260      TimeAndMemTimeTracker.obfuscationCacheDir = testCacheDir;
261
262      if (performanceTimeAndMemPrinter.singleFilePrinter) {
263        performanceTimeAndMemPrinter.singleFilePrinter.timeDataArr = [];
264        performanceTimeAndMemPrinter.singleFilePrinter.memoryDataArr = [];
265      }
266
267      if (performanceTimeAndMemPrinter.filesPrinter) {
268        performanceTimeAndMemPrinter.filesPrinter.timeDataArr = [];
269        performanceTimeAndMemPrinter.filesPrinter.memoryDataArr = [];
270      }
271    });
272
273    afterEach(() => {
274      if (fs.existsSync(timePerformanceFilePath)) {
275        fs.unlinkSync(timePerformanceFilePath);
276      }
277      if (fs.existsSync(memoryPerformanceFilePath)) {
278        fs.unlinkSync(memoryPerformanceFilePath);
279      }
280    });
281
282    it('should not print time and memory data when mTimeAndMemPrinter is false', () => {
283      printerTimeAndMemDataConfig.mTimeAndMemPrinter = false;
284
285      enableTimeAndMemoryPrint();
286
287      expect(fs.existsSync(timePerformanceFilePath)).to.be.false;
288      expect(fs.existsSync(memoryPerformanceFilePath)).to.be.false;
289    });
290
291    it('should print time and memory data when mTimeAndMemPrinter is true', async () => {
292      printerTimeAndMemDataConfig.mTimeAndMemPrinter = true;
293
294      performanceTimeAndMemPrinter.singleFilePrinter = new TimeAndMemTimeTracker();
295      performanceTimeAndMemPrinter.singleFilePrinter.timeDataArr.push({
296        name: 'Test Event',
297        ph: 'X',
298        pid: 1,
299        tid: 1,
300        ts: 1000,
301        dur: 500,
302      });
303      performanceTimeAndMemPrinter.singleFilePrinter.memoryDataArr.push({
304        name: 'Test Event',
305        startMemory: '10MB',
306        endMemory: '15MB',
307      });
308
309      await enableTimeAndMemoryPrint();
310      await new Promise(resolve => setTimeout(resolve, 100));
311
312      expect(fs.existsSync(timePerformanceFilePath)).to.be.true;
313      expect(fs.existsSync(memoryPerformanceFilePath)).to.be.true;
314    });
315  });
316
317  describe('Tester Cases for <writeTimeAndMemoryPerformanceData>', () => {
318    it('Write file error', () => {
319      const projectConfig = {
320        obfuscationOptions: {
321          obfuscationCacheDir: 'test/',
322        },
323      };
324      const data = [
325        {
326          'name': 'BreakpointConstants.ts',
327          'startMemory': '318.945MB',
328          'endMemory': '320.114MB',
329        },
330      ];
331      const fileName = '';
332      getObfuscationCacheDir(projectConfig);
333      expect(writeTimeAndMemoryPerformanceData(data, fileName)).to.be.throw;
334    });
335  });
336
337  describe('Tester Cases for <getObfuscationCacheDir>', () => {
338    it('get obfuscation and cache dir when cacheDir is exited', () => {
339      const projectConfig = {
340        obfuscationOptions: {
341          obfuscationCacheDir: 'test/',
342        },
343      };
344      getObfuscationCacheDir(projectConfig);
345      expect(TimeAndMemTimeTracker.obfuscationCacheDir).to.equal('test/');
346    });
347
348    it('get obfuscation and cache dir when obfuscationOptions is undefined', () => {
349      const projectConfig = {
350        obfuscationOptions: undefined,
351      };
352      getObfuscationCacheDir(projectConfig);
353      expect(TimeAndMemTimeTracker.obfuscationCacheDir).to.be.undefined;
354    });
355  });
356
357  describe('Tester Cases for <getTimePerformanceData>', () => {
358    it('get time performance data', () => {
359      performanceTimeAndMemPrinter.filesPrinter = undefined;
360      performanceTimeAndMemPrinter.singleFilePrinter = undefined;
361      const array = getTimePerformanceData();
362      expect(array.length === 0).to.be.true;
363    });
364  });
365
366  describe('Tester Cases for <getMemoryPerformanceData>', () => {
367    it('get memory performance data', () => {
368      performanceTimeAndMemPrinter.filesPrinter = undefined;
369      performanceTimeAndMemPrinter.singleFilePrinter = undefined;
370      const array = getMemoryPerformanceData();
371      expect(array.length === 0).to.be.true;
372    });
373  });
374});
375