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