• 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 { TransformerManager } from '../../../src/transformers/TransformerManager';
18import { assert, expect } from 'chai';
19import { FileUtils } from '../../../src/utils/FileUtils';
20import path from 'path';
21import { IOptions } from '../../../src/configs/IOptions';
22import fs from 'fs';
23import ts, {
24  TransformationResult,
25  factory,
26  transform,
27  SourceFile,
28  Node,
29  IndexedAccessTypeNode,
30  LiteralTypeNode,
31  setParentRecursive,
32  UnionTypeNode
33} from 'typescript';
34import secharmony from '../../../src/transformers/rename/RenamePropertiesTransformer';
35import { ArkObfuscator } from '../../../src/ArkObfuscator';
36import { compareStringsIgnoreNewlines } from './RenameIdentifierTransformer.spec';
37import { ArkObfuscatorForTest } from '../../../src/ArkObfuscatorForTest'
38import { PropCollections } from '../../../src/utils/CommonCollections';
39
40
41describe('Tester Cases for <RenamePropertiesTransformer>.', function () {
42  describe('Tester Cases for <renameIndexedAccessProperty>.', function () {
43    let options: IOptions;
44    beforeEach(() => {
45      options = {
46        mNameObfuscation: {
47          mEnable: true,
48          mNameGeneratorType: 1,
49          mRenameProperties: true,
50          mKeepStringProperty: false,
51          mReservedProperties: []
52        },
53      }
54    });
55
56    it('should rename string property in indexedAccessType when using prop+strProp', function () {
57      ArkObfuscator.isKeptCurrentFile = false;
58      const renamePropertiesFactory = secharmony.transformerPlugin.createTransformerFactory(options as IOptions);
59      let sourcefile = factory.createIndexedAccessTypeNode(
60        factory.createTypeReferenceNode(
61          factory.createIdentifier("T"),
62          undefined
63        ),
64        factory.createLiteralTypeNode(factory.createStringLiteral("X"))
65      )
66      let parentNodes = setParentRecursive(sourcefile, true);
67      let transfomedResult: TransformationResult<Node> = transform(parentNodes, [renamePropertiesFactory], {});
68      let node = transfomedResult.transformed[0] as IndexedAccessTypeNode;
69      expect((node.indexType as LiteralTypeNode).literal).not.to.be.equal((parentNodes.indexType as LiteralTypeNode).literal);
70    });
71
72    it('should not rename string property in indexedAccessType when using prop', function () {
73      ArkObfuscator.isKeptCurrentFile = false;
74      options = {
75        mNameObfuscation: {
76          mEnable: true,
77          mNameGeneratorType: 1,
78          mRenameProperties: true,
79          mKeepStringProperty: true,
80          mReservedProperties: []
81        },
82      };
83      const renamePropertiesFactory = secharmony.transformerPlugin.createTransformerFactory(options as IOptions);
84      let sourcefile = factory.createIndexedAccessTypeNode(
85        factory.createTypeReferenceNode(
86          factory.createIdentifier("T"),
87          undefined
88        ),
89        factory.createLiteralTypeNode(factory.createStringLiteral("X"))
90      )
91      let parentNodes = setParentRecursive(sourcefile, true);
92      let transfomedResult: TransformationResult<Node> = transform(parentNodes, [renamePropertiesFactory], {});
93      let node = transfomedResult.transformed[0] as IndexedAccessTypeNode;
94      expect((node.indexType as LiteralTypeNode).literal).to.be.equal((parentNodes.indexType as LiteralTypeNode).literal);
95    });
96
97    it('should not rename numeric property in indexedAccessType when using prop+strProp', function () {
98      ArkObfuscator.isKeptCurrentFile = false;
99      options = {
100        mNameObfuscation: {
101          mEnable: true,
102          mNameGeneratorType: 1,
103          mRenameProperties: true,
104          mKeepStringProperty: false,
105          mReservedProperties: []
106        },
107      };
108      const renamePropertiesFactory = secharmony.transformerPlugin.createTransformerFactory(options as IOptions);
109      let sourcefile = factory.createIndexedAccessTypeNode(
110        factory.createTypeReferenceNode(
111          factory.createIdentifier("T"),
112          undefined
113        ),
114        factory.createLiteralTypeNode(factory.createNumericLiteral(1))
115      )
116      let parentNodes = setParentRecursive(sourcefile, true);
117      let transfomedResult: TransformationResult<Node> = transform(parentNodes, [renamePropertiesFactory], {});
118      let node = transfomedResult.transformed[0] as IndexedAccessTypeNode;
119      expect((node.indexType as LiteralTypeNode).literal).to.be.equal((parentNodes.indexType as LiteralTypeNode).literal);
120    });
121
122    it('should rename string property in unionType of indexedAccessType when using prop+strProp', function () {
123      ArkObfuscator.isKeptCurrentFile = false;
124      options = {
125        mNameObfuscation: {
126          mEnable: true,
127          mNameGeneratorType: 1,
128          mRenameProperties: true,
129          mKeepStringProperty: false,
130          mReservedProperties: []
131        },
132      };
133      const renamePropertiesFactory = secharmony.transformerPlugin.createTransformerFactory(options as IOptions);
134      let sourcefile = factory.createIndexedAccessTypeNode(
135        factory.createTypeReferenceNode(
136          factory.createIdentifier("T"),
137          undefined
138        ),
139        factory.createUnionTypeNode([
140          factory.createLiteralTypeNode(factory.createStringLiteral("U")),
141          factory.createLiteralTypeNode(factory.createStringLiteral("V"))
142        ])
143      )
144      let parentNodes = setParentRecursive(sourcefile, true);
145      let transfomedResult: TransformationResult<Node> = transform(parentNodes, [renamePropertiesFactory], {});
146      let node = transfomedResult.transformed[0] as IndexedAccessTypeNode;
147      expect(((node.indexType as UnionTypeNode).types[0] as LiteralTypeNode).literal).not.to.be.equal(((parentNodes.indexType as UnionTypeNode).types[0] as LiteralTypeNode).literal);
148      expect(((node.indexType as UnionTypeNode).types[1] as LiteralTypeNode).literal).not.to.be.equal(((parentNodes.indexType as UnionTypeNode).types[1] as LiteralTypeNode).literal);
149    });
150
151    it('should not rename string property in unionType of indexedAccessType when using prop', function () {
152      ArkObfuscator.isKeptCurrentFile = false;
153      options = {
154        mNameObfuscation: {
155          mEnable: true,
156          mNameGeneratorType: 1,
157          mRenameProperties: true,
158          mKeepStringProperty: true,
159          mReservedProperties: []
160        },
161      };
162      const renamePropertiesFactory = secharmony.transformerPlugin.createTransformerFactory(options as IOptions);
163      let sourcefile = factory.createIndexedAccessTypeNode(
164        factory.createTypeReferenceNode(
165          factory.createIdentifier("T"),
166          undefined
167        ),
168        factory.createUnionTypeNode([
169          factory.createLiteralTypeNode(factory.createStringLiteral("U")),
170          factory.createLiteralTypeNode(factory.createStringLiteral("V"))
171        ])
172      )
173      let parentNodes = setParentRecursive(sourcefile, true);
174      let transfomedResult: TransformationResult<Node> = transform(parentNodes, [renamePropertiesFactory], {});
175      let node = transfomedResult.transformed[0] as IndexedAccessTypeNode;
176      expect(((node.indexType as UnionTypeNode).types[0] as LiteralTypeNode).literal).to.be.equal(((parentNodes.indexType as UnionTypeNode).types[0] as LiteralTypeNode).literal);
177      expect(((node.indexType as UnionTypeNode).types[1] as LiteralTypeNode).literal).to.be.equal(((parentNodes.indexType as UnionTypeNode).types[1] as LiteralTypeNode).literal);
178    });
179
180    it('should not rename numeric property in unionType of indexedAccessType when using prop+strProp', function () {
181      ArkObfuscator.isKeptCurrentFile = false;
182      options = {
183        mNameObfuscation: {
184          mEnable: true,
185          mNameGeneratorType: 1,
186          mRenameProperties: true,
187          mKeepStringProperty: false,
188          mReservedProperties: []
189        },
190      };
191      const renamePropertiesFactory = secharmony.transformerPlugin.createTransformerFactory(options as IOptions);
192      let sourcefile = factory.createIndexedAccessTypeNode(
193        factory.createTypeReferenceNode(
194          factory.createIdentifier("T"),
195          undefined
196        ),
197        factory.createUnionTypeNode([
198          factory.createLiteralTypeNode(factory.createNumericLiteral(1)),
199          factory.createLiteralTypeNode(factory.createNumericLiteral(2))
200        ])
201      )
202      let parentNodes = setParentRecursive(sourcefile, true);
203      let transfomedResult: TransformationResult<Node> = transform(parentNodes, [renamePropertiesFactory], {});
204      let node = transfomedResult.transformed[0] as IndexedAccessTypeNode;
205      expect(((node.indexType as UnionTypeNode).types[0] as LiteralTypeNode).literal).to.be.equal(((parentNodes.indexType as UnionTypeNode).types[0] as LiteralTypeNode).literal);
206      expect(((node.indexType as UnionTypeNode).types[1] as LiteralTypeNode).literal).to.be.equal(((parentNodes.indexType as UnionTypeNode).types[1] as LiteralTypeNode).literal);
207    });
208
209    it('should not rename property in annotation decl and callsite when using prop', function () {
210      ArkObfuscator.isKeptCurrentFile = false;
211      options = {
212        mNameObfuscation: {
213          mEnable: true,
214          mNameGeneratorType: 1,
215          mRenameProperties: true,
216          mKeepStringProperty: false,
217          mReservedProperties: []
218        },
219      };
220      const renameIdentifierFactory = secharmony.transformerPlugin.createTransformerFactory(options as IOptions);
221      const fileContent = `
222        @interface __$$ETS_ANNOTATION$$__Anno1 {
223          prop1: number = 1;
224        }
225        @__$$ETS_ANNOTATION$$__Anno1({prop: 1})
226        class myClass1 {
227          prop1: number = 1;
228        }
229        let var1: myClass1 = new myClass1();
230        let var2 = var1.prop1;
231      `;
232      const textWriter = ts.createTextWriter('\n');
233      let arkobfuscator = new ArkObfuscatorForTest();
234      arkobfuscator.init(options);
235      const sourceFile: ts.SourceFile = ts.createSourceFile('demo.ts', fileContent, ts.ScriptTarget.ES2015, true, undefined, {
236        'etsAnnotationsEnable': true
237      }, true);
238      let transformedResult: ts.TransformationResult<ts.Node> = ts.transform(sourceFile, [renameIdentifierFactory], {});
239      let ast: ts.SourceFile = transformedResult.transformed[0] as ts.SourceFile;
240      arkobfuscator.createObfsPrinter(ast.isDeclarationFile).writeFile(ast, textWriter, undefined);
241      const actualContent = textWriter.getText();
242      const expectContent = `
243        @interface __$$ETS_ANNOTATION$$__Anno1 {
244            prop1: number = 1;
245        }
246        @__$$ETS_ANNOTATION$$__Anno1({ prop: 1 })
247        class myClass1 {
248            g: number = 1;
249        }
250        let var1: myClass1 = new myClass1();
251        let var2 = var1.g;
252      `;
253      assert.strictEqual(compareStringsIgnoreNewlines(actualContent, expectContent), true);
254      PropCollections.clearPropsCollections();
255    });
256
257    it('should rename annotation called as prop when using prop obfuscation', function () {
258      ArkObfuscator.isKeptCurrentFile = false;
259      options = {
260        mNameObfuscation: {
261          mEnable: true,
262          mNameGeneratorType: 1,
263          mRenameProperties: true,
264          mKeepStringProperty: false,
265          mReservedProperties: []
266        },
267      };
268      const renameIdentifierFactory = secharmony.transformerPlugin.createTransformerFactory(options as IOptions);
269      const fileContent = `
270        @ns.__$$ETS_ANNOTATION$$__Anno1({prop: 1})
271        class myClass1 {}
272      `;
273      const textWriter = ts.createTextWriter('\n');
274      let arkobfuscator = new ArkObfuscatorForTest();
275      arkobfuscator.init(options);
276      const sourceFile: ts.SourceFile = ts.createSourceFile('demo.ts', fileContent, ts.ScriptTarget.ES2015, true, undefined, {
277        'etsAnnotationsEnable': true
278      }, true);
279      let transformedResult: ts.TransformationResult<ts.Node> = ts.transform(sourceFile, [renameIdentifierFactory], {});
280      let ast: ts.SourceFile = transformedResult.transformed[0] as ts.SourceFile;
281      arkobfuscator.createObfsPrinter(ast.isDeclarationFile).writeFile(ast, textWriter, undefined);
282      const actualContent = textWriter.getText();
283      const expectContent = `
284        @ns.__$$ETS_ANNOTATION$$__g({ prop: 1 })
285        class myClass1 {}
286      `;
287      assert.strictEqual(compareStringsIgnoreNewlines(actualContent, expectContent), true);
288      PropCollections.clearPropsCollections();
289    });
290  });
291});
292