1/* 2 * Copyright 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.tools.build.jetifier.processor.transform.proguard 18 19import com.android.tools.build.jetifier.core.config.Config 20import com.android.tools.build.jetifier.core.proguard.ProGuardType 21import com.android.tools.build.jetifier.core.proguard.ProGuardTypesMap 22import com.android.tools.build.jetifier.core.rule.RewriteRule 23import com.android.tools.build.jetifier.core.rule.RewriteRulesMap 24import com.android.tools.build.jetifier.core.type.JavaType 25import com.android.tools.build.jetifier.core.type.TypesMap 26import com.android.tools.build.jetifier.processor.archive.ArchiveFile 27import com.android.tools.build.jetifier.processor.transform.TransformationContext 28import com.google.common.truth.Truth 29import java.nio.charset.StandardCharsets 30import java.nio.file.Paths 31 32/** 33 * Helper to test ProGuard rewriting logic using lightweight syntax. 34 */ 35class ProGuardTester { 36 37 private var javaTypes = emptyList<Pair<String, String>>() 38 private var rewriteRules = emptyList<Pair<String, String>>() 39 private var proGuardTypes = emptyList<Pair<ProGuardType, Set<ProGuardType>>>() 40 private var prefixes = emptySet<String>() 41 42 fun forGivenPrefixes(vararg prefixes: String): ProGuardTester { 43 this.prefixes = prefixes.toSet() 44 return this 45 } 46 47 fun forGivenTypesMap(vararg types: Pair<String, String>): ProGuardTester { 48 this.javaTypes = types.toList() 49 return this 50 } 51 52 fun forGivenRules(vararg rules: Pair<String, String>): ProGuardTester { 53 this.rewriteRules = rules.toList() 54 return this 55 } 56 57 fun forGivenProGuardMap(vararg rules: Pair<String, String>): ProGuardTester { 58 return forGivenProGuardMapSet(*(rules.map { it.first to setOf(it.second) }.toTypedArray())) 59 } 60 61 fun forGivenProGuardMapSet(vararg rules: Pair<String, Set<String>>): ProGuardTester { 62 this.proGuardTypes = rules.map { 63 ProGuardType.fromDotNotation(it.first) to it.second.map { 64 ProGuardType.fromDotNotation(it) } 65 .toSet() }.toList() 66 return this 67 } 68 69 fun testThatGivenType(givenType: String): ProGuardTesterForType { 70 return ProGuardTesterForType(createConfig(), givenType) 71 } 72 73 fun testThatGivenArguments(givenArgs: String): ProGuardTesterForArgs { 74 return ProGuardTesterForArgs(createConfig(), givenArgs) 75 } 76 77 fun testThatGivenProGuard(given: String): ProGuardTesterForFile { 78 return ProGuardTesterForFile(createConfig(), given) 79 } 80 81 private fun createConfig(): Config { 82 return Config.fromOptional( 83 restrictToPackagePrefixes = prefixes, 84 rulesMap = RewriteRulesMap(rewriteRules 85 .map { RewriteRule(it.first, it.second) } 86 .toList()), 87 typesMap = TypesMap( 88 types = javaTypes.map { JavaType(it.first) to JavaType(it.second) }.toMap() 89 ), 90 proGuardMap = ProGuardTypesMap(proGuardTypes.toMap())) 91 } 92 93 class ProGuardTesterForFile(private val config: Config, private val given: String) { 94 95 fun rewritesTo(expected: String) { 96 val context = TransformationContext(config) 97 val transformer = ProGuardTransformer(context) 98 val file = ArchiveFile(Paths.get("proguard.txt"), given.toByteArray()) 99 transformer.runTransform(file) 100 101 val result = file.data.toString(StandardCharsets.UTF_8) 102 103 Truth.assertThat(result).isEqualTo(expected) 104 Truth.assertThat(context.errorsTotal()).isEqualTo(0) 105 } 106 } 107 108 class ProGuardTesterForType(private val config: Config, private val given: String) { 109 110 fun getsRewrittenTo(vararg expectedType: String) { 111 val context = TransformationContext(config, useFallbackIfTypeIsMissing = false) 112 val mapper = ProGuardTypesMapper(context) 113 val result = mapper.replaceType(given) 114 115 Truth.assertThat(result).containsExactlyElementsIn(expectedType.toSet()) 116 Truth.assertThat(context.errorsTotal()).isEqualTo(0) 117 } 118 } 119 120 class ProGuardTesterForArgs(private val config: Config, private val given: String) { 121 122 fun getRewrittenTo(expectedArguments: String) { 123 val context = TransformationContext(config) 124 val mapper = ProGuardTypesMapper(context) 125 val result = mapper.replaceMethodArgs(given) 126 127 Truth.assertThat(result.size).isEqualTo(1) 128 Truth.assertThat(result.first()).isEqualTo(expectedArguments) 129 Truth.assertThat(context.errorsTotal()).isEqualTo(0) 130 } 131 } 132}