• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2024 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 { describe, it } from 'mocha';
17import { assert, expect } from 'chai';
18import { ArkObfuscator, FileUtils, UnobfuscationCollections, wildcardTransformer } from '../../../src/ArkObfuscator';
19import { ArkObfuscatorForTest } from '../../../src/ArkObfuscatorForTest'
20import path from 'path';
21import { TransformerFactory, Node, SourceFile, createSourceFile, ScriptTarget, Printer, createTextWriter, RawSourceMap } from 'typescript';
22import { IOptions } from '../../../src/configs/IOptions';
23import { getSourceMapGenerator } from '../../../src/utils/SourceMapUtil';
24import fs from 'fs';
25import esInfo from '../../../src/configs/preset/es_reserved_properties.json';
26import optimizeEsInfo from '../../../src/configs/preset/es_reserved_properties_optimized.json'
27
28describe('Tester Cases for <ArkObfuscatorForTest>.', function () {
29  describe('Tester Cases for <ArkObfuscatorForTest>.', function () {
30    let etsSourceFile: SourceFile;
31    let dEtsSourceFile: SourceFile;
32    let tsSourceFile: SourceFile;
33    let etsSourceFilePath: string = 'demo.ets';
34    let dEtsSourceFilePath: string = 'demo.d.ets';
35    let tsSourceFilePath: string = 'demo.ts';
36
37    before('init sourceFile', function () {
38      const etsfileContent = `//This is a comment
39//This is a comment
40//This is a comment
41//This is a comment
42class 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      const dEtsFileContent = `
51      /**
52       * This is a comment
53       */
54
55      class Demo{
56          constructor(public  title: string, public  content: string, public  mark: number) {
57              this.title = title
58              this.content = content
59              this.mark = mark
60          }
61      }
62      `;
63
64      const tsFileContent = `
65      //This is a comment
66      class Demo{
67          constructor(public  title: string, public  content: string, public  mark: number) {
68              this.title = title
69              this.content = content
70              this.mark = mark
71          }
72      }
73      `;
74
75      etsSourceFile = createSourceFile('demo.ts', etsfileContent, ScriptTarget.ES2015, true);
76      dEtsSourceFile = createSourceFile(dEtsSourceFilePath, dEtsFileContent, ScriptTarget.ES2015, true);
77      tsSourceFile = createSourceFile(tsSourceFilePath, tsFileContent, ScriptTarget.ES2015, true);
78    });
79
80    it('Tester: test case for handleTsHarComments for ets file', function () {
81      let mCustomProfiles: IOptions | undefined = FileUtils.readFileAsJson(path.join(__dirname, "default_config.json"));
82      let arkobfuscator = new ArkObfuscatorForTest();
83      arkobfuscator.init(mCustomProfiles);
84      let originalFilePath = 'demo.ets';
85      ArkObfuscatorForTest.projectInfo = { packageDir: '', projectRootPath: '', localPackageSet: new Set<string>(), useNormalized: false, useTsHar: true };
86      arkobfuscator.handleTsHarComments(etsSourceFile, originalFilePath);
87      let sourceMapGenerator = getSourceMapGenerator(originalFilePath);
88      const textWriter = createTextWriter('\n');
89      arkobfuscator.createObfsPrinter(etsSourceFile.isDeclarationFile).writeFile(etsSourceFile, textWriter, sourceMapGenerator);
90      const actualContent = textWriter.getText();
91      const expectContent = `
92      // @keepTs
93      // @ts-nocheck
94      class Demo {
95          constructor(public title: string, public content: string, public mark: number) {
96              this.title = title;
97              this.content = content;
98              this.mark = mark;
99          }
100      }`;
101
102      let actualSourceMap: RawSourceMap = sourceMapGenerator.toJSON();
103      actualSourceMap.sourceRoot = "";
104      let expectSourceMap = {
105          "version": 3,
106          "file": "demo.ets",
107          "sourceRoot": "",
108          "sources": [
109            "demo.ts"
110          ],
111          "names": [],
112          "mappings": ";;AAIA,MAAM,IAAI;IACR,YAAY,MAAM,CAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAE,IAAI,EAAE,MAAM;QAC5E,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QAClB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IACpB,CAAC;CACF"
113        }
114      assert.strictEqual(compareStringsIgnoreNewlines(actualContent, expectContent), true);
115      assert.strictEqual(compareStringsIgnoreNewlines(JSON.stringify(actualSourceMap, null, 2), JSON.stringify(expectSourceMap, null, 2)), true);
116    });
117
118    it('Tester: test case for handleTsHarComments for d.ets file', function () {
119      let mCustomProfiles: IOptions | undefined = FileUtils.readFileAsJson(path.join(__dirname, "default_config.json"));
120      let arkobfuscator = new ArkObfuscatorForTest();
121      arkobfuscator.init(mCustomProfiles);
122      ArkObfuscatorForTest.projectInfo = { packageDir: '', projectRootPath: '', localPackageSet: new Set<string>(), useNormalized: false, useTsHar: true };
123      arkobfuscator.handleTsHarComments(dEtsSourceFile, dEtsSourceFilePath);
124      let sourceMapGenerator = getSourceMapGenerator(dEtsSourceFilePath);
125      const textWriter = createTextWriter('\n');
126      arkobfuscator.createObfsPrinter(dEtsSourceFile.isDeclarationFile).writeFile(dEtsSourceFile, textWriter, sourceMapGenerator);
127      const actualContent = textWriter.getText();
128      const expectContent = `
129      /**
130       * This is a comment
131       */
132      class Demo {
133          constructor(public title: string, public content: string, public mark: number) {
134              this.title = title;
135              this.content = content;
136              this.mark = mark;
137          }
138      }`;
139      assert.strictEqual(compareStringsIgnoreNewlines(actualContent, expectContent), true);
140    });
141
142    it('Tester: test case for handleTsHarComments for ts file', function () {
143      let mCustomProfiles: IOptions | undefined = FileUtils.readFileAsJson(path.join(__dirname, "default_config.json"));
144      let arkobfuscator = new ArkObfuscatorForTest();
145      arkobfuscator.init(mCustomProfiles);
146      ArkObfuscatorForTest.projectInfo = { packageDir: '', projectRootPath: '', localPackageSet: new Set<string>(), useNormalized: false, useTsHar: true };
147      arkobfuscator.handleTsHarComments(tsSourceFile, tsSourceFilePath);
148      let sourceMapGenerator = getSourceMapGenerator(tsSourceFilePath);
149      const textWriter = createTextWriter('\n');
150      arkobfuscator.createObfsPrinter(tsSourceFile.isDeclarationFile).writeFile(tsSourceFile, textWriter, sourceMapGenerator);
151      const actualContent = textWriter.getText();
152      const expectContent = `
153        class Demo {
154          constructor(public title: string, public content: string, public mark: number) {
155            this.title = title;
156            this.content = content;
157            this.mark = mark;
158          }
159        }`;
160      assert.strictEqual(compareStringsIgnoreNewlines(actualContent, expectContent), true);
161    });
162  });
163
164  describe('Tester Cases for <ArkObfuscatorForTest>.', function () {
165    it('Tester: test case for ArkObfuscatorForTest.ini', function (){
166      let configPath = "test/ut/arkobfuscator/iniTestObfConfig.json"
167      let obfuscator: ArkObfuscatorForTest = new ArkObfuscatorForTest();
168      const originalConfig: IOptions | undefined = FileUtils.readFileAsJson(configPath);
169      obfuscator.init(originalConfig);
170      let config = obfuscator.customProfiles;
171      let reservedTopelevelNames = config.mNameObfuscation?.mReservedToplevelNames;
172      let reservedProperty = config.mNameObfuscation?.mReservedProperties;
173      let universalReservedToplevelNames = config.mNameObfuscation?.mUniversalReservedToplevelNames as RegExp[];
174      let universalReservedProperties = config.mNameObfuscation?.mUniversalReservedProperties as RegExp[];
175      assert.isTrue(reservedTopelevelNames?.includes("func2"));
176      assert.isTrue(reservedProperty?.includes("prop"));
177      assert.equal(universalReservedToplevelNames[0].toString(), new RegExp(`^${wildcardTransformer("a*")}$`).toString());
178      assert.equal(universalReservedToplevelNames[1].toString(), new RegExp(`^${wildcardTransformer("*shoul?keep*")}$`).toString());
179      assert.equal(universalReservedProperties[0].toString(), new RegExp(`^${wildcardTransformer("prop?")}$`).toString());
180      assert.equal(universalReservedProperties[2].toString(), new RegExp(`^${wildcardTransformer("*pro?")}$`).toString());
181      assert.equal(universalReservedProperties[1].toString(), new RegExp(`^${wildcardTransformer("function*")}$`).toString());
182    });
183
184    it('Tester: test case for ArkObfuscator.ini', function (){
185      let configPath = "test/ut/arkobfuscator/iniTestObfConfig.json"
186      let obfuscator: ArkObfuscator = new ArkObfuscator();
187      let config = FileUtils.readFileAsJson(configPath) as IOptions;
188      obfuscator.init(config);
189      let reservedTopelevelNames = config.mNameObfuscation?.mReservedToplevelNames;
190      let reservedProperty = config.mNameObfuscation?.mReservedProperties;
191      let universalReservedToplevelNames = config.mNameObfuscation?.mUniversalReservedToplevelNames;
192      let universalReservedProperties = config.mNameObfuscation?.mUniversalReservedProperties;
193      assert.isTrue(reservedTopelevelNames?.includes("func2"));
194      assert.isTrue(reservedTopelevelNames?.includes("a*"));
195      assert.isTrue(reservedTopelevelNames?.includes("*shoul?keep*"));
196      assert.isTrue(reservedProperty?.includes("prop"));
197      assert.isTrue(reservedProperty?.includes("prop?"));
198      assert.isTrue(reservedProperty?.includes("*pro?"));
199      assert.isTrue(reservedProperty?.includes("function*"));
200      assert.equal(universalReservedToplevelNames, undefined);
201      assert.equal(universalReservedProperties, undefined);
202    });
203
204    it('Tester: test case for use default preset language whitelist', function (){
205      let obfuscator: ArkObfuscator = new ArkObfuscator();
206      let config: IOptions = {
207        "mNameObfuscation": {
208            "mEnable": true,
209            "mNameGeneratorType": 1,
210            "mDictionaryList": [],
211            "mRenameProperties": true,
212            "mReservedProperties": [],
213            "mKeepStringProperty": false,
214            "mTopLevel": true,
215            "mReservedToplevelNames": []
216        },
217        "mEnableSourceMap": false,
218        "mEnableNameCache": false,
219        "mStripLanguageDefaultWhitelist": false
220      };
221
222      obfuscator.init(config);
223      let languageSet: Set<string> = new Set();
224      let presetLanguageWhitelist = esInfo;
225      for (const key of Object.keys(presetLanguageWhitelist)) {
226        const valueArray = presetLanguageWhitelist[key];
227        valueArray.forEach((element: string) => {
228          languageSet.add(element);
229        });
230      }
231      expect(languageSet).to.deep.equal(UnobfuscationCollections.reservedLangForProperty);
232    });
233
234    it('Tester: test case for use optimized preset language whitelist', function (){
235      let obfuscator: ArkObfuscator = new ArkObfuscator();
236      let config: IOptions = {
237        "mNameObfuscation": {
238            "mEnable": true,
239            "mNameGeneratorType": 1,
240            "mDictionaryList": [],
241            "mRenameProperties": true,
242            "mReservedProperties": [],
243            "mKeepStringProperty": false,
244            "mTopLevel": true,
245            "mReservedToplevelNames": []
246        },
247        "mEnableSourceMap": false,
248        "mEnableNameCache": false,
249        "mStripLanguageDefaultWhitelist": true
250      };
251
252      obfuscator.init(config);
253      let languageSet: Set<string> = new Set();
254      let presetLanguageWhitelist = optimizeEsInfo;
255      for (const key of Object.keys(presetLanguageWhitelist)) {
256        const valueArray = presetLanguageWhitelist[key];
257        valueArray.forEach((element: string) => {
258          languageSet.add(element);
259        });
260      }
261      expect(languageSet).to.deep.equal(UnobfuscationCollections.reservedLangForProperty);
262    });
263
264    it('Tester: test case for enable annotation', function (){
265      let configPath = "test/ut/arkobfuscator/iniTestObfConfig.json"
266      let obfuscator: ArkObfuscator = new ArkObfuscator();
267      let config = FileUtils.readFileAsJson(configPath) as IOptions;
268      obfuscator.init(config);
269
270      expect(config.mAllowEtsAnnotations).to.be.true;
271    });
272  });
273});
274
275function compareStringsIgnoreNewlines(str1: string, str2: string): boolean {
276  const normalize = (str: string) => str.replace(/[\n\r\s]+/g, '');
277  return normalize(str1) === normalize(str2);
278}