• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023 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 { before } from 'mocha';
17import { assert } from 'chai';
18import ts from 'typescript';
19import {
20  collectExistNames,
21  isInLocalWhitelist,
22  isInPropertyWhitelist,
23  isInTopLevelWhitelist,
24  isMatchWildcard,
25  recordHistoryUnobfuscatedNames,
26  separateUniversalReservedItem,
27  wildcardTransformer
28} from '../../../src/utils/TransformUtil';
29import type { ReservedNameInfo } from '../../../src/utils/TransformUtil';
30import {
31  LocalVariableCollections,
32  PropCollections,
33  UnobfuscationCollections
34} from '../../../src/utils/CommonCollections';
35import secharmony from '../../../src/transformers/rename/RenameIdentifierTransformer';
36
37describe('test for TransformUtil', function () {
38  let sourceFile: ts.SourceFile;
39
40  before('init ast for source file', function () {
41    const fileContent = `
42    class Demo{
43      constructor(public  title: string, public  content: string, public  mark: number) {
44          this.title = title
45          this.content = content
46          this.mark = mark
47      }
48    }
49    `;
50
51    sourceFile = ts.createSourceFile('demo.js', fileContent, ts.ScriptTarget.ES2015, true);
52  });
53
54  describe('test for function collectExistNames', function () {
55    it('test collectExistNames', function () {
56      const nameSets = collectExistNames(sourceFile);
57      const targetNames = ['Demo', 'title', 'content', 'mark'];
58
59      assert.strictEqual(nameSets.size, targetNames.length);
60      targetNames.forEach((value) => {
61        assert.isTrue(nameSets.has(value));
62      });
63    });
64  });
65
66  describe('test for function wildcardTransformer', function () {
67    it('test wildcardTransformer', function () {
68      // special characters: '\', '^', '$', '.', '+', '|', '[', ']', '{', '}', '(', ')'
69      const reserved1 = 'a\\+b*';
70      const reserved2 = '{*}[*](*)';
71      const reserved3 = '*^';
72      const reserved4 = '?$\\..';
73      const reserved5 = '?|123';
74
75      const result1 = wildcardTransformer(reserved1);
76      const result2 = wildcardTransformer(reserved2);
77      const result3 = wildcardTransformer(reserved3);
78      const result4 = wildcardTransformer(reserved4);
79      const result5 = wildcardTransformer(reserved5);
80
81      assert.strictEqual(result1, String.raw`a\\\+b.*`);
82      assert.strictEqual(result2, String.raw`\{.*\}\[.*\]\(.*\)`);
83      assert.strictEqual(result3, String.raw`.*\^`);
84      assert.strictEqual(result4, String.raw`.\$\\\.\.`);
85      assert.strictEqual(result5, String.raw`.\|123`);
86    });
87  });
88
89  describe('test for function separateUniversalReservedItem', function () {
90    it('should throw errors because originalArray is undefined', function () {
91      assert.throws(() => {
92        separateUniversalReservedItem(undefined, false);
93      }, Error, 'Unable to handle the empty array.');
94    });
95
96    it('should return reservedInfo because originalArray is defined', function () {
97      let originalArray: string[] = ['*', '?', 'originalArray'];
98      let reservedInfo: ReservedNameInfo = separateUniversalReservedItem(originalArray, true);
99
100      assert.deepStrictEqual(reservedInfo.universalReservedArray, [/^.*$/, /^.$/]);
101      assert.deepStrictEqual(reservedInfo.specificReservedArray, ['originalArray']);
102
103      UnobfuscationCollections.clear();
104    });
105  });
106
107  describe('test for function isMatchWildcard', function () {
108    it('The item can match wildcard characters', function () {
109      let result: boolean = isMatchWildcard([/foo/, /bar/, /baz/], 'foobar');
110      assert.isTrue(result);
111    });
112
113    it('The item can not match wildcard characters', function () {
114      let result: boolean = isMatchWildcard([/foo/, /bar/, /baz/], 'abc');
115      assert.isFalse(result);
116    });
117  });
118
119  describe('test for function isInTopLevelWhitelist', function () {
120    const recordMap: Map<string, Set<string>> = new Map();
121    const nameWithScope:string = 'nameWithScope';
122
123    describe('printKeptName is true', function () {
124      it('isInTopLevelWhitelist returns false', function() {
125        const originalName: string = 'isInTopLevelWhitelist';
126
127        const needToRecordProperty: boolean = isInTopLevelWhitelist(originalName, recordMap, nameWithScope, true, true);
128        assert.isFalse(needToRecordProperty);
129
130        PropCollections.clearPropsCollections();
131        UnobfuscationCollections.clear();
132      });
133
134      it('isInTopLevelWhitelist returns true', function() {
135        const originalName1: string = '__global';
136        const originalName2: string = 'abc';
137        UnobfuscationCollections.reservedSdkApiForGlobal.add('abc');
138        UnobfuscationCollections.reservedExportName.add('abc');
139        PropCollections.reservedProperties.add('abc');
140
141        const reservedFlag1: boolean = isInTopLevelWhitelist(originalName1, recordMap, nameWithScope, false, true);
142        const reservedFlag2: boolean = isInTopLevelWhitelist(originalName2, recordMap, nameWithScope, false, true);
143        assert.isTrue(reservedFlag1);
144        assert.isTrue(reservedFlag2);
145
146        PropCollections.clearPropsCollections();
147        UnobfuscationCollections.clear();
148      });
149    });
150
151    describe('printKeptName is false', function () {
152      it('isInTopLevelWhitelist returns false', function () {
153        const originalName: string = 'isInTopLevelWhitelist';
154        const isReservedTopLevel: boolean = isInTopLevelWhitelist(originalName, recordMap, nameWithScope, true, false);
155        assert.isFalse(isReservedTopLevel);
156
157        PropCollections.clearPropsCollections();
158        UnobfuscationCollections.clear();
159      });
160
161      it('isInTopLevelWhitelist returns true', function () {
162        const originalName: string = '__global';
163        const isReservedTopLevel: boolean = isInTopLevelWhitelist(originalName, recordMap, nameWithScope, false, false);
164        assert.isTrue(isReservedTopLevel);
165
166        PropCollections.clearPropsCollections();
167        UnobfuscationCollections.clear();
168      });
169    });
170  });
171
172  describe('test for function isInPropertyWhitelist', function () {
173    const originalName: string = 'isInPropertyWhitelist';
174    const recordMap: Map<string, Set<string>> = new Map();
175
176    it('printKeptName is true', function () {
177      UnobfuscationCollections.reservedSdkApiForProp.add('isInPropertyWhitelist');
178      UnobfuscationCollections.reservedLangForProperty.add('isInPropertyWhitelist');
179      UnobfuscationCollections.reservedStruct.add('isInPropertyWhitelist');
180      UnobfuscationCollections.reservedExportNameAndProp.add('isInPropertyWhitelist');
181      UnobfuscationCollections.reservedStrProp.add('isInPropertyWhitelist');
182      UnobfuscationCollections.reservedEnum.add('isInPropertyWhitelist');
183      PropCollections.reservedProperties.add('isInPropertyWhitelist');
184
185      const needToRecordProperty: boolean = isInPropertyWhitelist(originalName, recordMap, true);
186      assert.isTrue(needToRecordProperty);
187
188      PropCollections.clearPropsCollections();
189      UnobfuscationCollections.clear();
190    });
191
192    it('printKeptName is false', function () {
193      const isReservedProperty: boolean = isInPropertyWhitelist(originalName, recordMap, false);
194      assert.isFalse(isReservedProperty);
195      UnobfuscationCollections.clear();
196    });
197  });
198
199  describe('test for function isInLocalWhitelist', function () {
200    it('printKeptName is true', function () {
201      const originalName: string = 'isInLocalWhitelist';
202      const recordMap: Map<string, Set<string>> = new Map();
203      const nameWithScope: string = '246810';
204      LocalVariableCollections.reservedLangForLocal.add('isInLocalWhitelist');
205      UnobfuscationCollections.reservedSdkApiForLocal.add('isInLocalWhitelist');
206      UnobfuscationCollections.reservedExportName.add('isInLocalWhitelist');
207      LocalVariableCollections.reservedConfig.add('isInLocalWhitelist');
208
209      const reservedFlag: boolean = isInLocalWhitelist(originalName, recordMap, nameWithScope, true);
210      assert.isTrue(reservedFlag);
211
212      LocalVariableCollections.clear();
213      UnobfuscationCollections.clear();
214    });
215
216    it('printKeptName is false', function () {
217      const originalName: string = 'originalName';
218      const recordMap: Map<string, Set<string>> = new Map();
219      const nameWithScope: string = '12345';
220
221      const isReservedLocalVariable: boolean = isInLocalWhitelist(originalName, recordMap, nameWithScope,false);
222      assert.isFalse(isReservedLocalVariable);
223      UnobfuscationCollections.clear();
224    });
225
226    it('The local variables whitelist should be the same when printKeptName is enabled and disabled', function () {
227      const recordMap: Map<string, Set<string>> = new Map();
228      const nameWithScope: string = '246810';
229      LocalVariableCollections.reservedLangForLocal.add('isInLocalWhitelist1');
230      UnobfuscationCollections.reservedSdkApiForLocal.add('isInLocalWhitelist2');
231      UnobfuscationCollections.reservedExportName.add('isInLocalWhitelist3');
232      LocalVariableCollections.reservedConfig.add('isInLocalWhitelist4');
233      UnobfuscationCollections.reservedSdkApiForProp.add('notInLocalWhitelist');
234
235      const reservedFlag1: boolean = isInLocalWhitelist('isInLocalWhitelist1', recordMap, nameWithScope, true);
236      const reservedFlag2: boolean = isInLocalWhitelist('isInLocalWhitelist2', recordMap, nameWithScope, true);
237      const reservedFlag3: boolean = isInLocalWhitelist('isInLocalWhitelist3', recordMap, nameWithScope, true);
238      const reservedFlag4: boolean = isInLocalWhitelist('isInLocalWhitelist4', recordMap, nameWithScope, true);
239      const reservedFlag5: boolean = isInLocalWhitelist('notInLocalWhitelist', recordMap, nameWithScope, true);
240      assert.isTrue(reservedFlag1);
241      assert.isTrue(reservedFlag2);
242      assert.isTrue(reservedFlag3);
243      assert.isTrue(reservedFlag4);
244      assert.isFalse(reservedFlag5);
245
246      const isReservedLocalVariable1: boolean = isInLocalWhitelist('isInLocalWhitelist1', recordMap, nameWithScope, false);
247      const isReservedLocalVariable2: boolean = isInLocalWhitelist('isInLocalWhitelist2', recordMap, nameWithScope, false);
248      const isReservedLocalVariable3: boolean = isInLocalWhitelist('isInLocalWhitelist3', recordMap, nameWithScope, false);
249      const isReservedLocalVariable4: boolean = isInLocalWhitelist('isInLocalWhitelist4', recordMap, nameWithScope, false);
250      const isReservedLocalVariable5: boolean = isInLocalWhitelist('notInLocalWhitelist', recordMap, nameWithScope, false);
251      assert.isTrue(isReservedLocalVariable1);
252      assert.isTrue(isReservedLocalVariable2);
253      assert.isTrue(isReservedLocalVariable3);
254      assert.isTrue(isReservedLocalVariable4);
255      assert.isFalse(isReservedLocalVariable5);
256      LocalVariableCollections.clear();
257      UnobfuscationCollections.clear();
258    });
259  });
260
261  describe('test for function recordHistoryUnobfuscatedNames', function () {
262    const nameWithScope: string = 'abc';
263
264    it('historyUnobfuscatedNamesMap?.has(nameWithScope) is false', function () {
265      recordHistoryUnobfuscatedNames(nameWithScope);
266      assert.isFalse(UnobfuscationCollections.unobfuscatedNamesMap.has('abc'));
267    });
268
269    it('historyUnobfuscatedNamesMap?.has(nameWithScope) is true', function () {
270      secharmony.historyUnobfuscatedNamesMap = new Map<string, string[]>();
271      secharmony.historyUnobfuscatedNamesMap.set('abc', ['bcd', 'efg']);
272      recordHistoryUnobfuscatedNames(nameWithScope);
273      assert.isTrue(UnobfuscationCollections.unobfuscatedNamesMap.has('abc'));
274      UnobfuscationCollections.clear();
275      secharmony.clearCaches();
276    });
277  });
278});