Home | History | Annotate | Download | only in resource
      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.resource
     18 
     19 import com.android.tools.build.jetifier.core.PackageMap
     20 import com.android.tools.build.jetifier.core.config.Config
     21 import com.android.tools.build.jetifier.core.rule.RewriteRule
     22 import com.android.tools.build.jetifier.core.rule.RewriteRulesMap
     23 import com.android.tools.build.jetifier.core.type.JavaType
     24 import com.android.tools.build.jetifier.core.type.TypesMap
     25 import com.android.tools.build.jetifier.processor.archive.ArchiveFile
     26 import com.android.tools.build.jetifier.processor.transform.TransformationContext
     27 import com.google.common.truth.Truth
     28 import org.junit.Test
     29 import java.nio.charset.Charset
     30 import java.nio.file.Paths
     31 
     32 class XmlResourcesTransformerTest {
     33 
     34     @Test fun layout_noRule_noChange() {
     35         testRewriteToTheSame(
     36             givenAndExpectedXml =
     37                 "<android.support.v7.preference.Preference>\n" +
     38                 "</android.support.v7.preference.Preference>",
     39             prefixes = setOf("android/support/v7/"),
     40             map = mapOf(),
     41             errorsExpected = true
     42         )
     43     }
     44 
     45     @Test fun layout_notApplicablePrefix_shouldStillWork() {
     46         testRewrite(
     47             givenXml =
     48                 "<android.support.v7.preference.Preference>\n" +
     49                 "</android.support.v7.preference.Preference>",
     50             expectedXml =
     51                 "<android.test.pref.Preference>\n" +
     52                 "</android.test.pref.Preference>",
     53             prefixes = setOf("android/support/v14/"),
     54             typesMap = mapOf(
     55                 "android/support/v7/preference/Preference" to "android/test/pref/Preference"
     56             )
     57         )
     58     }
     59 
     60     @Test fun layout_notApplicablePrefix2_noChange() {
     61         testRewriteToTheSame(
     62             givenAndExpectedXml =
     63                 "<my.android.support.v7.preference.Preference>\n" +
     64                 "</my.android.support.v7.preference.Preference>",
     65             prefixes = setOf("android/support/v7/"),
     66             map = mapOf(
     67                 "android/support/v7/preference/Preference" to "android/test/pref/Preference"
     68             )
     69         )
     70     }
     71 
     72     @Test fun layout_notApplicableRule_noChange() {
     73         testRewriteToTheSame(
     74             givenAndExpectedXml =
     75                 "<android.support.v7.preference.Preference>\n" +
     76                 "</android.support.v7.preference.Preference>",
     77             prefixes = setOf("android/support/"),
     78             map = mapOf(
     79                 "android/support2/v7/preference/Preference" to "android/test/pref/Preference"
     80             ),
     81             errorsExpected = true
     82         )
     83     }
     84 
     85     @Test fun layout_onePrefix_oneRule_oneRewrite() {
     86         testRewrite(
     87             givenXml =
     88                 "<android.support.v7.preference.Preference/>",
     89             expectedXml =
     90                 "<android.test.pref.Preference/>",
     91             prefixes = setOf("android/support/"),
     92             typesMap = mapOf(
     93                 "android/support/v7/preference/Preference" to "android/test/pref/Preference"
     94             )
     95         )
     96     }
     97 
     98     @Test fun layout_onePrefix_oneRule_attribute_oneRewrite() {
     99         testRewrite(
    100             givenXml =
    101                 "<android.support.v7.preference.Preference \n" +
    102                 "    someAttribute=\"android.support.v7.preference.Preference\"/>",
    103             expectedXml =
    104                 "<android.test.pref.Preference \n" +
    105                 "    someAttribute=\"android.test.pref.Preference\"/>",
    106             prefixes = setOf("android/support/"),
    107             typesMap = mapOf(
    108                 "android/support/v7/preference/Preference" to "android/test/pref/Preference"
    109             )
    110         )
    111     }
    112 
    113     @Test fun layout_onePrefix_oneRule_twoRewrites() {
    114         testRewrite(
    115             givenXml =
    116                 "<android.support.v7.preference.Preference>\n" +
    117                 "</android.support.v7.preference.Preference>",
    118             expectedXml =
    119                 "<android.test.pref.Preference>\n" +
    120                 "</android.test.pref.Preference>",
    121             prefixes = setOf("android/support/"),
    122             typesMap = mapOf(
    123                 "android/support/v7/preference/Preference" to "android/test/pref/Preference"
    124             )
    125         )
    126     }
    127 
    128     @Test fun layout_onePrefix_oneRule_viewTag_simple() {
    129         testRewrite(
    130             givenXml =
    131                 "<view class=\"android.support.v7.preference.Preference\">",
    132             expectedXml =
    133                 "<view class=\"android.test.pref.Preference\">",
    134             prefixes = setOf("android/support/"),
    135             typesMap = mapOf(
    136                 "android/support/v7/preference/Preference" to "android/test/pref/Preference"
    137             )
    138         )
    139     }
    140 
    141     @Test fun layout_onePrefix_oneRule_viewInText() {
    142         testRewriteToTheSame(
    143             givenAndExpectedXml =
    144                 "<test attribute=\"view\" class=\"something.Else\">",
    145             prefixes = setOf("android/support/"),
    146             map = mapOf(
    147                 "android/support/v7/preference/Preference" to "android/test/pref/Preference"
    148             )
    149         )
    150     }
    151 
    152     @Test fun application_appComponentFactory() {
    153         testRewrite(
    154             givenXml =
    155                 "<application android:appComponentFactory=\"android.support.v7.Preference\" />",
    156             expectedXml =
    157                 "<application android:appComponentFactory=\"android.test.pref.Preference\" />",
    158             prefixes = setOf("android/support/"),
    159             typesMap = mapOf(
    160                 "android/support/v7/Preference" to "android/test/pref/Preference"
    161             )
    162         )
    163     }
    164 
    165     @Test fun layout_onePrefix_oneRule_identity() {
    166         testRewrite(
    167             givenXml =
    168                 "<android.support.v7.preference.Preference>\n" +
    169                 "</android.support.v7.preference.Preference>",
    170             expectedXml =
    171                 "<android.support.v7.preference.Preference>\n" +
    172                 "</android.support.v7.preference.Preference>",
    173             prefixes = setOf("android/support/"),
    174             typesMap = mapOf(
    175                 "android/support/v7/preference/Preference"
    176                     to "android/support/v7/preference/Preference"
    177             )
    178         )
    179     }
    180 
    181     @Test fun layout_twoPrefixes_threeRules_ignoreRule_multipleRewrites() {
    182         testRewrite(
    183             givenXml =
    184                 "<android.support.v7.preference.Preference>\n" +
    185                 "  <android.support.v14.preference.DialogPreference" +
    186                 "      someAttribute=\"someValue\"/>\n" +
    187                 "  <android.support.v14.preference.DialogPreference" +
    188                 "      someAttribute=\"someValue2\"/>\n" +
    189                 "  <!-- This one should be ignored --> \n" +
    190                 "  <android.support.v21.preference.DialogPreference" +
    191                 "      someAttribute=\"someValue2\"/>\n" +
    192                 "</android.support.v7.preference.Preference>\n" +
    193                 "\n" +
    194                 "<android.support.v7.preference.ListPreference/>",
    195             expectedXml =
    196                 "<android.test.pref.Preference>\n" +
    197                 "  <android.test14.pref.DialogPreference" +
    198                 "      someAttribute=\"someValue\"/>\n" +
    199                 "  <android.test14.pref.DialogPreference" +
    200                 "      someAttribute=\"someValue2\"/>\n" +
    201                 "  <!-- This one should be ignored --> \n" +
    202                 "  <android.support.v21.preference.DialogPreference" +
    203                 "      someAttribute=\"someValue2\"/>\n" +
    204                 "</android.test.pref.Preference>\n" +
    205                 "\n" +
    206                 "<android.test.pref.ListPref/>",
    207             prefixes = setOf(
    208                 "android/support/v7/",
    209                 "android/support/v14/"
    210             ),
    211             rulesMap = RewriteRulesMap(
    212                 RewriteRule(from = "android/support/v21/(.*)", to = "ignore")),
    213             typesMap = mapOf(
    214                 "android/support/v7/preference/ListPreference"
    215                     to "android/test/pref/ListPref",
    216                 "android/support/v7/preference/Preference"
    217                     to "android/test/pref/Preference",
    218                 "android/support/v14/preference/DialogPreference"
    219                     to "android/test14/pref/DialogPreference"
    220             )
    221         )
    222     }
    223 
    224     @Test fun manifestFile_packageRewrite() {
    225         testRewrite(
    226             givenXml =
    227                 "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    228                 "          package=\"android.support.v7.preference\">\n" +
    229                 "    <uses-sdk android:minSdkVersion=\"14\"/>\n" +
    230                 "</manifest>",
    231             expectedXml =
    232                 "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    233                 "          package=\"androidx.preference\">\n" +
    234                 "    <uses-sdk android:minSdkVersion=\"14\"/>\n" +
    235                 "</manifest>",
    236             prefixes = setOf(
    237                 "android/support"
    238             ),
    239             typesMap = mapOf(
    240             ),
    241             packageMap = PackageMap(listOf(
    242                 PackageMap.PackageRule(
    243                     from = "android/support/v7/preference",
    244                     to = "androidx/preference")
    245             )),
    246             rewritingSupportLib = true
    247         )
    248     }
    249 
    250     @Test fun manifestFile_packageRewrite_prefixMismatchShouldNotAffectRewrite() {
    251         testRewrite(
    252             givenXml =
    253                 "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    254                 "          package=\"android.support.v7.preference\">\n" +
    255                 "    <uses-sdk android:minSdkVersion=\"14\"/>\n" +
    256                 "</manifest>",
    257             expectedXml =
    258                 "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    259                 "          package=\"androidx.preference\">\n" +
    260                 "    <uses-sdk android:minSdkVersion=\"14\"/>\n" +
    261                 "</manifest>",
    262             prefixes = setOf(
    263                 "android/something/else"
    264             ),
    265             typesMap = mapOf(
    266             ),
    267             packageMap = PackageMap(listOf(
    268                 PackageMap.PackageRule(
    269                     from = "android/support/v7/preference",
    270                     to = "androidx/preference")
    271             )),
    272             rewritingSupportLib = true
    273         )
    274     }
    275 
    276     @Test fun manifestFile_packageRewrite_shouldIgnore() {
    277         testRewrite(
    278             givenXml =
    279                 "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    280                 "          package=\"android.support.test\">\n" +
    281                 "</manifest>",
    282             expectedXml =
    283                 "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    284                 "          package=\"android.support.test\">\n" +
    285                 "</manifest>",
    286             prefixes = setOf(
    287                 "android/support/"
    288             ),
    289             rulesMap = RewriteRulesMap(
    290                 RewriteRule("android/support/test/(.*)", "ignore")
    291             ),
    292             packageMap = PackageMap.EMPTY,
    293             rewritingSupportLib = true
    294         )
    295     }
    296 
    297     @Test fun generic_sample_provider() {
    298         testRewrite(
    299             givenXml =
    300                 "<provider\n" +
    301                 "  android:authorities=\"support.Something\"\n" +
    302                 "  android:name=\"support.Something\">\n" +
    303                 "  <meta-data android:name=\"support.Something\">\n" +
    304                 "</provider>",
    305             expectedXml =
    306                 "<provider\n" +
    307                 "  android:authorities=\"test.Something\"\n" +
    308                 "  android:name=\"test.Something\">\n" +
    309                 "  <meta-data android:name=\"test.Something\">\n" +
    310                 "</provider>",
    311             prefixes = setOf("support/"),
    312             typesMap = mapOf(
    313                 "support/Something" to "test/Something"
    314             )
    315         )
    316     }
    317 
    318     @Test fun generic_sample_intent() {
    319         testRewrite(
    320             givenXml =
    321                 "<activity android:name=\"some\" android:configChanges=\"orientation\">\n" +
    322                 "  <intent-filter>\n" +
    323                 "    <action android:name=\"support.Something\" />\n" +
    324                 "  </intent-filter>\n" +
    325                 "</activity>",
    326             expectedXml =
    327                 "<activity android:name=\"some\" android:configChanges=\"orientation\">\n" +
    328                 "  <intent-filter>\n" +
    329                 "    <action android:name=\"test.Something\" />\n" +
    330                 "  </intent-filter>\n" +
    331                 "</activity>",
    332             prefixes = setOf("support/"),
    333             typesMap = mapOf(
    334                 "support/Something" to "test/Something"
    335             )
    336         )
    337     }
    338 
    339     @Test fun generic_sample_style() {
    340         testRewrite(
    341             givenXml =
    342                 "<style name=\"AppCompat\" parent=\"Platform.AppCompat\">\n" +
    343                 "  <item name=\"viewInflaterClass\">support.Something</item>\n" +
    344                 "</style>",
    345             expectedXml =
    346                 "<style name=\"AppCompat\" parent=\"Platform.AppCompat\">\n" +
    347                 "  <item name=\"viewInflaterClass\">test.Something</item>\n" +
    348                 "</style>",
    349             prefixes = setOf("support/"),
    350             typesMap = mapOf(
    351                 "support/Something" to "test/Something"
    352             )
    353         )
    354     }
    355 
    356     @Test fun generic_sample_transition() {
    357         testRewrite(
    358             givenXml =
    359                 "<transition\n" +
    360                 "    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    361                 "    xmlns:lb=\"http://schemas.android.com/apk/res-auto\"\n" +
    362                 "    class=\"support.Something\"\n" +
    363                 "    lb:lb_slideEdge=\"top\" >\n" +
    364                 "</transition>",
    365             expectedXml =
    366                 "<transition\n" +
    367                 "    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    368                 "    xmlns:lb=\"http://schemas.android.com/apk/res-auto\"\n" +
    369                 "    class=\"test.Something\"\n" +
    370                 "    lb:lb_slideEdge=\"top\" >\n" +
    371                 "</transition>",
    372             prefixes = setOf("support/"),
    373             typesMap = mapOf(
    374                 "support/Something" to "test/Something"
    375             )
    376         )
    377     }
    378 
    379     private fun testRewriteToTheSame(
    380         givenAndExpectedXml: String,
    381         prefixes: Set<String>,
    382         map: Map<String, String>,
    383         errorsExpected: Boolean = false
    384     ) {
    385         testRewrite(givenAndExpectedXml, givenAndExpectedXml, prefixes, map,
    386             errorsExpected = errorsExpected)
    387     }
    388 
    389     private fun testRewrite(
    390         givenXml: String,
    391         expectedXml: String,
    392         prefixes: Set<String>,
    393         typesMap: Map<String, String> = emptyMap(),
    394         rulesMap: RewriteRulesMap = RewriteRulesMap.EMPTY,
    395         packageMap: PackageMap = PackageMap.EMPTY,
    396         rewritingSupportLib: Boolean = false,
    397         errorsExpected: Boolean = false
    398     ) {
    399         val given =
    400             "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
    401             "$givenXml\n"
    402 
    403         val expected =
    404             "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
    405             "$expectedXml\n"
    406 
    407         val typeMap = TypesMap(typesMap.map { JavaType(it.key) to JavaType(it.value) }.toMap())
    408         val config = Config.fromOptional(
    409             restrictToPackagePrefixes = prefixes,
    410             rulesMap = rulesMap,
    411             typesMap = typeMap,
    412             packageMap = packageMap
    413         )
    414         val context = TransformationContext(
    415             config,
    416             rewritingSupportLib = rewritingSupportLib,
    417             useFallbackIfTypeIsMissing = false)
    418         val processor = XmlResourcesTransformer(context)
    419         val fileName = Paths.get("random.xml")
    420         val file = ArchiveFile(fileName, given.toByteArray())
    421         processor.runTransform(file)
    422         val strResult = file.data.toString(Charset.defaultCharset())
    423 
    424         Truth.assertThat(strResult).isEqualTo(expected)
    425 
    426         if (errorsExpected) {
    427             Truth.assertThat(context.errorsTotal()).isAtLeast(1)
    428         } else {
    429             Truth.assertThat(context.errorsTotal()).isEqualTo(0)
    430         }
    431     }
    432 }
    433 
    434