• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 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 
17 package com.android.tools.build.jetifier.processor.transform.bytecode
18 
19 import com.android.tools.build.jetifier.core.config.Config
20 import com.android.tools.build.jetifier.core.rule.RewriteRule
21 import com.android.tools.build.jetifier.core.rule.RewriteRulesMap
22 import com.android.tools.build.jetifier.core.type.JavaType
23 import com.android.tools.build.jetifier.core.type.TypesMap
24 import com.android.tools.build.jetifier.processor.FileMapping
25 import com.android.tools.build.jetifier.processor.Processor
26 import com.android.tools.build.jetifier.processor.archive.Archive
27 import com.android.tools.build.jetifier.processor.archive.ArchiveFile
28 import com.android.tools.build.jetifier.processor.archive.ArchiveItemVisitor
29 import com.google.common.truth.Truth
30 import org.junit.Test
31 import java.io.File
32 
33 /**
34  * Tests that individual files were moved properly due to their owner types rewrites.
35  */
36 class ClassFilesMoveTest {
37 
38     companion object {
39         private val TEST_CONFIG = Config.fromOptional(
40             restrictToPackagePrefixes = setOf("android/support"),
41             reversedRestrictToPackagesPrefixes = setOf("androidx"),
42             rulesMap = RewriteRulesMap(
43                 RewriteRule("android/support/annotation/(.*)", "ignore"),
44                 RewriteRule("android/support/v7/preference/R(.*)", "ignore"),
45                 RewriteRule("android/support/v4/(.*)", "ignore")
46             ),
47             slRules = listOf(
48                 RewriteRule("android/support/annotation/(.*)", "ignore"),
49                 RewriteRule("android/support/v7/preference/R(.*)", "ignore"),
50                 RewriteRule("android/support/v4/(.*)", "ignore")
51             ),
52             typesMap = TypesMap(mapOf(
53                 "android/support/v7/preference/Preference"
54                         to "androidx/support/preference/Preference",
55                 "android/support/v7/preference/TwoStatePreference"
56                         to "androidx/support/preference/TwoStatePreference",
57                 "android/support/v7/preference/PreferenceGroup"
58                         to "androidx/support/preference/PreferenceGroup",
59                 "android/support/v7/preference/PreferenceViewHolder"
60                         to "androidx/support/preference/PreferenceViewHolder",
61                 "android/support/v7/preference/PreferenceManager"
62                         to "androidx/support/preference/PreferenceManager",
63                 "android/support/v14/preference/SwitchPreference"
64                         to "androidx/support/preference/SwitchPreference",
65                 "android/support/v7/preference/PreferenceDataStore"
66                         to "androidx/support/preference/PreferenceDataStore"
<lambda>null67             ).map { JavaType(it.key) to JavaType(it.value) }.toMap())
68         )
69     }
70 
71     /**
72      * Tests that after rewrite of a input archive the internal classes are properly moved to new
73      * locations (based on the rewrite rules) which is compared with the expected archive.
74      *
75      * Note: The expected archive does not contain rewritten classes - they were only manually
76      * moved. Which is fine because this test validates only files locations.
77      */
fileMove_forwardRewrite_shouldMoveFilesProperlynull78     @Test fun fileMove_forwardRewrite_shouldMoveFilesProperly() {
79         val inputZipPath = "/fileRenameTest/inputTestLib.zip"
80         val expectedZipPath = "/fileRenameTest/expectedTestLib.zip"
81 
82         val processor = Processor.createProcessor(TEST_CONFIG)
83         val inputFile = File(javaClass.getResource(inputZipPath).file)
84 
85         val tempDir = createTempDir()
86         val expectedFile = File(createTempDir(), "test.zip")
87 
88         val resultFiles = processor.transform(setOf(FileMapping(inputFile, expectedFile)))
89 
90         Truth.assertThat(resultFiles).hasSize(1)
91         testArchivesAreSame(resultFiles.first(), File(javaClass.getResource(expectedZipPath).file))
92 
93         tempDir.delete()
94     }
95 
96     /**
97      * Does exactly the same as [fileMove_forwardRewrite_nestedArchive_shouldMoveFilesProperly] but
98      * the files are in a nested archive e.g. archive.zip/classes.jar/some files.
99      */
fileMove_forwardRewrite_nestedArchive_shouldMoveFilesProperlynull100     @Test fun fileMove_forwardRewrite_nestedArchive_shouldMoveFilesProperly() {
101         val inputZipPath = "/fileRenameTest/inputTestLibNested.zip"
102         val expectedZipPath = "/fileRenameTest/expectedTestLibNested.zip"
103 
104         val processor = Processor.createProcessor(TEST_CONFIG)
105         val inputFile = File(javaClass.getResource(inputZipPath).file)
106 
107         val tempDir = createTempDir()
108         val expectedFile = File(createTempDir(), "test.zip")
109 
110         val resultFiles = processor.transform(setOf(FileMapping(inputFile, expectedFile)))
111 
112         Truth.assertThat(resultFiles).hasSize(1)
113         testArchivesAreSame(resultFiles.first(), File(javaClass.getResource(expectedZipPath).file))
114 
115         tempDir.delete()
116     }
117 
118     /**
119      * Rewrites the input archive and then applies reversed mode to rewrite it back. The final
120      * produced archive has to have the same directory structure as the input one.
121      */
fileMove_forwardRewrite_backwardsRewrite_shouldKeepFilesProperlynull122     @Test fun fileMove_forwardRewrite_backwardsRewrite_shouldKeepFilesProperly() {
123         val inputZipPath = "/fileRenameTest/inputTestLib.zip"
124 
125         // Transform forward
126         val processor = Processor.createProcessor(TEST_CONFIG)
127         val inputFile = File(javaClass.getResource(inputZipPath).file)
128 
129         val tempDir = createTempDir()
130         val expectedFile = File(createTempDir(), "test.zip")
131 
132         val resultFiles = processor.transform(setOf(FileMapping(inputFile, expectedFile)))
133 
134         // Take previous result & reverse it
135         val processor2 = Processor.createProcessor(
136             TEST_CONFIG,
137             rewritingSupportLib = true,
138             reversedMode = true)
139         val expectedFile2 = File(createTempDir(), "test2.zip")
140         val resultFiles2 = processor2.transform(setOf(
141             FileMapping(resultFiles.first(), expectedFile2)))
142 
143         testArchivesAreSame(resultFiles2.first(), File(javaClass.getResource(inputZipPath).file))
144 
145         tempDir.delete()
146     }
147 
testArchivesAreSamenull148     fun testArchivesAreSame(givenZip: File, expectedZip: File) {
149         testArchivesAreSame(Archive.Builder.extract(givenZip), Archive.Builder.extract(expectedZip))
150     }
151 
testArchivesAreSamenull152     fun testArchivesAreSame(givenZip: Archive, expectedZip: Archive) {
153         val givenFiles = ArchiveBrowser.grabAllPathsIn(givenZip)
154         val expectedFiles = ArchiveBrowser.grabAllPathsIn(expectedZip)
155         Truth.assertThat(givenFiles).containsExactlyElementsIn(expectedFiles)
156     }
157 
158     /**
159      * Just a helper utility to get all file paths in the archive.
160      */
161     class ArchiveBrowser : ArchiveItemVisitor {
162 
163         companion object {
grabAllPathsInnull164             fun grabAllPathsIn(archive: Archive): MutableSet<String> {
165                 val grabber = ArchiveBrowser()
166                 archive.accept(grabber)
167                 return grabber.allPaths
168             }
169         }
170 
171         val allPaths = mutableSetOf<String>()
172 
visitnull173         override fun visit(archiveFile: ArchiveFile) {
174             allPaths.add(archiveFile.relativePath.toString())
175             println("Visited ${archiveFile.relativePath}")
176         }
177 
visitnull178         override fun visit(archive: Archive) {
179             archive.files.forEach { it.accept(this) }
180         }
181     }
182 }
183