• 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 {
17  isViewPUBasedClass,
18  getElementAccessExpressionProperties,
19  getIndexedAccessTypeProperties,
20  stringPropsSet,
21  structPropsSet,
22  getTypeAliasProperties,
23  getInterfaceProperties,
24  getClassProperties,
25  getEnumProperties,
26  getObjectProperties,
27  getViewPUClassProperties
28} from '../../../src/utils/OhsUtil';
29import {
30  UnobfuscationCollections
31} from '../../../src/utils/CommonCollections';
32import { describe, it } from 'mocha';
33import { expect } from 'chai';
34import * as ts from 'typescript';
35import {
36  projectWhiteListManager,
37  initProjectWhiteListManager,
38  clearProjectWhiteListManager
39} from '../../../src/utils/ProjectCollections';
40
41describe('unit test for OhsUtil.ts', function () {
42  describe('test for isViewPUBasedClass function', function () {
43    it('should return false if classNode is an empty object', () => {
44      const classNode = {} as any;
45      expect(isViewPUBasedClass(classNode)).to.be.false;
46    });
47
48    it('should return false if heritageClauses is undefined', () => {
49      const classNode = ts.factory.createClassDeclaration(undefined, "Class", undefined, undefined, []);
50      expect(isViewPUBasedClass(classNode)).to.be.false;
51    });
52
53    it('should return false if classNode is undefined', () => {
54      expect(isViewPUBasedClass(undefined)).to.be.false;
55    });
56
57    it('should return false if heritageClause.types is undefined', () => {
58      const heritageClause = ts.factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, undefined);
59      const classNode = ts.factory.createClassDeclaration(undefined, "Class", undefined, [heritageClause], []);
60      expect(isViewPUBasedClass(classNode)).to.be.false;
61    });
62
63    it('should return false if classNode.heritageClause.types.member is undefined', () => {
64      const heritageClause = ts.factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [undefined]);
65      const classNode = ts.factory.createClassDeclaration(undefined, "Class", undefined, [heritageClause], []);
66      expect(isViewPUBasedClass(classNode)).to.be.false;
67    })
68
69    it('should return true if classNode is set', () => {
70      const typeArguments = [
71        ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),
72      ];
73      const type = ts.factory.createExpressionWithTypeArguments(ts.factory.createIdentifier('ViewPU'), typeArguments);
74      const heritageClause = ts.factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [type]);
75      const classNode = ts.factory.createClassDeclaration(undefined, "Class", undefined, [heritageClause], []);
76      expect(isViewPUBasedClass(classNode)).to.be.true;
77    });
78  })
79
80  describe('test for getTypeAliasProperties function', function () {
81    it('should not add items to propertySet if type is undefined', () => {
82      const name = ts.factory.createIdentifier('MyType');
83      const typeAliasNode = ts.factory.createTypeAliasDeclaration(undefined, name, undefined, undefined);
84      const propertySet = new Set<string>();
85      getTypeAliasProperties(typeAliasNode, propertySet);
86      expect(stringPropsSet.size == 0).to.be.true;
87    });
88
89    it('should add to propertySet if member.name is set', () => {
90      const name = ts.factory.createIdentifier('MyType');
91      const type = ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
92      const identifierName = ts.factory.createIdentifier('Identifier');
93      const stringName = ts.factory.createStringLiteral('String');
94      const computedPropertyName = ts.factory.createComputedPropertyName(ts.factory.createStringLiteral('3 + 2'));
95      const types = ts.factory.createTypeLiteralNode([
96        ts.factory.createPropertySignature(undefined, undefined, undefined, type),
97        ts.factory.createPropertySignature(undefined, identifierName, undefined, type),
98        ts.factory.createPropertySignature(undefined, stringName, undefined, type),
99        ts.factory.createPropertySignature(undefined, computedPropertyName, undefined, type),
100      ]);
101      const typeAliasNode = ts.factory.createTypeAliasDeclaration(undefined, name, undefined, types);
102      const propertySet = new Set<string>();
103      getTypeAliasProperties(typeAliasNode, propertySet);
104      expect(propertySet.has('Identifier') && propertySet.has('String') && propertySet.has('3 + 2')).to.be.true;
105      expect(stringPropsSet.has('String') && propertySet.has('3 + 2')).to.be.true;
106    });
107  })
108
109  describe('test for getElementAccessExpressionProperties function', function () {
110    it('should not add items to propertySet if elementAccessExpression is undefined', () => {
111      const propertySet = new Set<string>();
112      getElementAccessExpressionProperties(undefined);
113      expect(stringPropsSet.has('value')).to.be.false;
114    });
115
116    it('should add to propertySet if elementAccessExpressionNode.argumentExpression is set string value', () => {
117      const key = ts.factory.createStringLiteral('key');
118      const value = ts.factory.createStringLiteral('value');
119      const elementAccessExpression = ts.factory.createElementAccessExpression(key, value);
120      const propertySet = new Set<string>();
121      getElementAccessExpressionProperties(elementAccessExpression);
122      expect(stringPropsSet.has('value')).to.be.true;
123    });
124
125    it('should not add items to propertySet if elementAccessExpressionNode.argumentExpression is set int value', () => {
126      const key = ts.factory.createIdentifier('key');
127      const value = ts.factory.createBigIntLiteral("9999999");
128      const elementAccessExpression = ts.factory.createElementAccessExpression(key, value);
129      const propertySet = new Set<string>();
130      getElementAccessExpressionProperties(elementAccessExpression)
131      expect(stringPropsSet.has('9999999')).to.be.false;
132    });
133  })
134
135  describe('test for getIndexedAccessTypeProperties function', function () {
136    beforeEach(() => {
137      stringPropsSet.clear();
138      let cachePath = 'test/ut/utils/obfuscation';
139      initProjectWhiteListManager(cachePath, false, false);
140      projectWhiteListManager?.setCurrentCollector('demo.ts');
141    });
142
143    afterEach(()=>{
144      clearProjectWhiteListManager();
145    });
146
147    it('should not add items to propertySet if indexedAccessType is undefined', () => {
148      getIndexedAccessTypeProperties(undefined);
149      expect(stringPropsSet.has('value')).to.be.false;
150      expect(projectWhiteListManager?.fileWhiteListInfo.fileKeepInfo.stringProperties.has('value')).to.be.false;
151    });
152
153    it('should add to propertySet if indexedAccessType.indexType is literalType and set string value', () => {
154      const indexedAccessType = ts.factory.createIndexedAccessTypeNode(
155        ts.factory.createTypeReferenceNode(
156          ts.factory.createIdentifier("T"),
157          undefined
158        ),
159        ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral("U"))
160      )
161      getIndexedAccessTypeProperties(indexedAccessType);
162      expect(stringPropsSet.has("U")).to.be.true;
163      expect(projectWhiteListManager?.fileWhiteListInfo.fileKeepInfo.stringProperties.has("U")).to.be.true;
164    });
165
166    it('should add to propertySet if indexedAccessType.indexType is unionType and set string value', () => {
167      const indexedAccessType = ts.factory.createIndexedAccessTypeNode(
168        ts.factory.createTypeReferenceNode(
169          ts.factory.createIdentifier("T1"),
170          undefined
171        ),
172        ts.factory.createUnionTypeNode([
173          ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral("U")),
174          ts.factory.createLiteralTypeNode(ts.factory.createNumericLiteral(1))
175        ])
176      )
177      getIndexedAccessTypeProperties(indexedAccessType);
178      expect(stringPropsSet.has("U")).to.be.true;
179      expect(stringPropsSet.has('1')).to.be.false;
180      expect(projectWhiteListManager?.fileWhiteListInfo.fileKeepInfo.stringProperties.has("U")).to.be.true;
181      expect(projectWhiteListManager?.fileWhiteListInfo.fileKeepInfo.stringProperties.has('1')).to.be.false;
182    });
183
184    it('should not add items to propertySet if indexedAccessType.literalType is set numberic value', () => {
185      const indexedAccessType = ts.factory.createIndexedAccessTypeNode(
186        ts.factory.createTypeReferenceNode(
187          ts.factory.createIdentifier("T"),
188          undefined
189        ),
190        ts.factory.createLiteralTypeNode(ts.factory.createNumericLiteral(1))
191      )
192      getIndexedAccessTypeProperties(indexedAccessType)
193      expect(stringPropsSet.has('1')).to.be.false;
194      expect(projectWhiteListManager?.fileWhiteListInfo.fileKeepInfo.stringProperties.has('1')).to.be.false;
195    });
196  })
197
198  describe('test for getInterfaceProperties function', function () {
199    it('should not add items to propertySet if interfaceNode is undefined', () => {
200      const propertySet = new Set<string>();
201      getInterfaceProperties(undefined, propertySet);
202      expect(stringPropsSet.has('property')).to.be.false;
203    });
204
205    it('should add to propertySet if member.name is set string value', () => {
206      const members = [
207        ts.factory.createPropertySignature([], undefined, undefined, undefined),
208        ts.factory.createPropertySignature([], ts.factory.createStringLiteral('property'), undefined, undefined)
209      ];
210      const interfaceNode = ts.factory.createInterfaceDeclaration(undefined, 'Interface', undefined, undefined, members);
211      const propertySet = new Set<string>();
212      getInterfaceProperties(interfaceNode, propertySet);
213      expect(stringPropsSet.has('property')).to.be.true;
214      expect(propertySet.has('property')).to.be.true;
215    });
216  })
217
218  describe('test for getClassProperties function', function () {
219    it('should not add items to propertySet if classNode is undefined', () => {
220      const propertySet = new Set<string>();
221      getClassProperties(undefined, propertySet);
222      expect(propertySet.size == 0).to.be.true;
223    });
224
225    it('should add to propertySet if classNode is StructDeclaration', () => {
226      const classProperty = ts.factory.createClassExpression(
227        undefined,
228        undefined,
229        undefined,
230        undefined,
231        undefined,
232        []
233      );
234      const parameters = [
235        ts.factory.createParameterDeclaration(
236          [ts.factory.createModifier(ts.SyntaxKind.AbstractKeyword)],
237          undefined,
238          'parameter',
239          undefined,
240          ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),
241          undefined
242        ),
243        ts.factory.createParameterDeclaration(
244          [ts.factory.createModifier(ts.SyntaxKind.PublicKeyword)],
245          undefined,
246          'classParameter',
247          undefined,
248          ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),
249          classProperty
250        )
251      ];
252      const expression = ts.factory.createBinaryExpression(
253        ts.factory.createIdentifier('left'),
254        ts.SyntaxKind.EqualsToken,
255        ts.factory.createIdentifier('right')
256      );
257      const statements = [ts.factory.createExpressionStatement(expression)];
258      const members = [
259        undefined,
260        ts.factory.createPropertyDeclaration(undefined, 'name', undefined, undefined, undefined),
261        ts.factory.createConstructorDeclaration(
262          undefined,
263          undefined,
264          parameters,
265          ts.factory.createBlock(statements, true)
266        )
267      ];
268      const structDeclaration = ts.factory.createStructDeclaration(undefined, undefined, undefined, undefined, members);
269      const propertySet = new Set<string>();
270      getClassProperties(structDeclaration, propertySet);
271      expect(structPropsSet.has('name')).to.be.true;
272      expect(propertySet.has('parameter')).to.be.false;
273      expect(propertySet.has('classParameter')).to.be.true;
274    });
275
276    describe('test for getEnumProperties function', function () {
277      it('should not add items to propertySet if enumNode is undefined', () => {
278        const propertySet = new Set<string>();
279        getEnumProperties(undefined, propertySet);
280        expect(propertySet.size === 0).to.be.true;
281      });
282
283      it('should add to propertySet if member.name is set', () => {
284        const members = [
285          undefined,
286          ts.factory.createEnumMember('enumMember', ts.factory.createIdentifier('enumMember')),
287        ];
288        const enumNode = ts.factory.createEnumDeclaration(undefined, undefined, 'enum', members);
289        const propertySet = new Set<string>();
290        getEnumProperties(enumNode, propertySet);
291        expect(propertySet.has('enumMember')).to.be.true;
292      });
293    })
294
295    describe('test for getObjectProperties function', function () {
296      it('should not add items to propertySet if objNode is undefined', () => {
297        const propertySet = new Set<string>();
298        getObjectProperties(undefined, propertySet);
299        expect(propertySet.size === 0).to.be.true;
300      });
301
302      it('should add to propertySet if property.name is set', () => {
303        const objProperties = [
304          ts.factory.createPropertyAssignment('objKey', ts.factory.createStringLiteral('objValue'))
305        ];
306        const obj = ts.factory.createObjectLiteralExpression(objProperties);
307        const properties = [
308          undefined,
309          ts.factory.createPropertyAssignment('key', obj),
310          ts.factory.createShorthandPropertyAssignment('key2', obj)
311        ];
312        const objNode = ts.factory.createObjectLiteralExpression(properties, true);
313        const propertySet = new Set<string>();
314        getObjectProperties(objNode, propertySet);
315        expect(propertySet.has('key')).to.be.true;
316        expect(propertySet.has('objKey')).to.be.true;
317      });
318    })
319
320    describe('test for getViewPUClassProperties function', function () {
321      it('should collectReservedStruct', () => {
322        const fileContent = `
323              class A {
324              ["name1"] = "aa";
325              "name2" = 2;
326              name3 = 3;
327              }
328            `;
329        let cachePath = 'test/ut/utils/obfuscation';
330        const sourceFile: ts.SourceFile = ts.createSourceFile('demo.ts', fileContent, ts.ScriptTarget.ES2015, true);
331        UnobfuscationCollections.reservedStruct.clear();
332        initProjectWhiteListManager(cachePath, false, false);
333        projectWhiteListManager?.setCurrentCollector('demo.ts');
334        getViewPUClassProperties(sourceFile.statements[0] as ts.ClassDeclaration);
335        expect(UnobfuscationCollections.reservedStruct.has("name1")).to.be.true;
336        expect(UnobfuscationCollections.reservedStruct.has("name2")).to.be.true;
337        expect(UnobfuscationCollections.reservedStruct.has("name3")).to.be.true;
338        expect(projectWhiteListManager!.fileWhiteListInfo.fileKeepInfo.structProperties.has("name1")).to.be.true;
339        expect(projectWhiteListManager!.fileWhiteListInfo.fileKeepInfo.structProperties.has("name2")).to.be.true;
340        expect(projectWhiteListManager!.fileWhiteListInfo.fileKeepInfo.structProperties.has("name3")).to.be.true;
341      });
342    })
343  })
344});
345