blob: 5f9bb297cd44323623c8764ba87172b360fc4fb1 [file] [log] [blame]
/*
* Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tools.build.jetifier.processor.transform.resource
import com.android.tools.build.jetifier.core.PackageMap
import com.android.tools.build.jetifier.core.config.Config
import com.android.tools.build.jetifier.core.rule.RewriteRule
import com.android.tools.build.jetifier.core.rule.RewriteRulesMap
import com.android.tools.build.jetifier.core.type.JavaType
import com.android.tools.build.jetifier.core.type.TypesMap
import com.android.tools.build.jetifier.processor.archive.ArchiveFile
import com.android.tools.build.jetifier.processor.transform.TransformationContext
import com.google.common.truth.Truth
import org.junit.Test
import java.nio.charset.Charset
import java.nio.file.Paths
class XmlResourcesTransformerTest {
@Test fun layout_noRule_noChange() {
testRewriteToTheSame(
givenAndExpectedXml =
"<android.support.v7.preference.Preference>\n" +
"</android.support.v7.preference.Preference>",
prefixes = setOf("android/support/v7/"),
map = mapOf(),
errorsExpected = true
)
}
@Test fun layout_notApplicablePrefix_shouldStillWork() {
testRewrite(
givenXml =
"<android.support.v7.preference.Preference>\n" +
"</android.support.v7.preference.Preference>",
expectedXml =
"<android.test.pref.Preference>\n" +
"</android.test.pref.Preference>",
prefixes = setOf("android/support/v14/"),
typesMap = mapOf(
"android/support/v7/preference/Preference" to "android/test/pref/Preference"
)
)
}
@Test fun layout_notApplicablePrefix2_noChange() {
testRewriteToTheSame(
givenAndExpectedXml =
"<my.android.support.v7.preference.Preference>\n" +
"</my.android.support.v7.preference.Preference>",
prefixes = setOf("android/support/v7/"),
map = mapOf(
"android/support/v7/preference/Preference" to "android/test/pref/Preference"
)
)
}
@Test fun layout_notApplicableRule_noChange() {
testRewriteToTheSame(
givenAndExpectedXml =
"<android.support.v7.preference.Preference>\n" +
"</android.support.v7.preference.Preference>",
prefixes = setOf("android/support/"),
map = mapOf(
"android/support2/v7/preference/Preference" to "android/test/pref/Preference"
),
errorsExpected = true
)
}
@Test fun layout_onePrefix_oneRule_oneRewrite() {
testRewrite(
givenXml =
"<android.support.v7.preference.Preference/>",
expectedXml =
"<android.test.pref.Preference/>",
prefixes = setOf("android/support/"),
typesMap = mapOf(
"android/support/v7/preference/Preference" to "android/test/pref/Preference"
)
)
}
@Test fun layout_onePrefix_oneRule_attribute_oneRewrite() {
testRewrite(
givenXml =
"<android.support.v7.preference.Preference \n" +
" someAttribute=\"android.support.v7.preference.Preference\"/>",
expectedXml =
"<android.test.pref.Preference \n" +
" someAttribute=\"android.test.pref.Preference\"/>",
prefixes = setOf("android/support/"),
typesMap = mapOf(
"android/support/v7/preference/Preference" to "android/test/pref/Preference"
)
)
}
@Test fun layout_onePrefix_oneRule_twoRewrites() {
testRewrite(
givenXml =
"<android.support.v7.preference.Preference>\n" +
"</android.support.v7.preference.Preference>",
expectedXml =
"<android.test.pref.Preference>\n" +
"</android.test.pref.Preference>",
prefixes = setOf("android/support/"),
typesMap = mapOf(
"android/support/v7/preference/Preference" to "android/test/pref/Preference"
)
)
}
@Test fun layout_onePrefix_oneRule_viewTag_simple() {
testRewrite(
givenXml =
"<view class=\"android.support.v7.preference.Preference\">",
expectedXml =
"<view class=\"android.test.pref.Preference\">",
prefixes = setOf("android/support/"),
typesMap = mapOf(
"android/support/v7/preference/Preference" to "android/test/pref/Preference"
)
)
}
@Test fun layout_onePrefix_oneRule_viewInText() {
testRewriteToTheSame(
givenAndExpectedXml =
"<test attribute=\"view\" class=\"something.Else\">",
prefixes = setOf("android/support/"),
map = mapOf(
"android/support/v7/preference/Preference" to "android/test/pref/Preference"
)
)
}
@Test fun application_appComponentFactory() {
testRewrite(
givenXml =
"<application android:appComponentFactory=\"android.support.v7.Preference\" />",
expectedXml =
"<application android:appComponentFactory=\"android.test.pref.Preference\" />",
prefixes = setOf("android/support/"),
typesMap = mapOf(
"android/support/v7/Preference" to "android/test/pref/Preference"
)
)
}
@Test fun layout_onePrefix_oneRule_identity() {
testRewrite(
givenXml =
"<android.support.v7.preference.Preference>\n" +
"</android.support.v7.preference.Preference>",
expectedXml =
"<android.support.v7.preference.Preference>\n" +
"</android.support.v7.preference.Preference>",
prefixes = setOf("android/support/"),
typesMap = mapOf(
"android/support/v7/preference/Preference"
to "android/support/v7/preference/Preference"
)
)
}
@Test fun layout_twoPrefixes_threeRules_ignoreRule_multipleRewrites() {
testRewrite(
givenXml =
"<android.support.v7.preference.Preference>\n" +
" <android.support.v14.preference.DialogPreference" +
" someAttribute=\"someValue\"/>\n" +
" <android.support.v14.preference.DialogPreference" +
" someAttribute=\"someValue2\"/>\n" +
" <!-- This one should be ignored --> \n" +
" <android.support.v21.preference.DialogPreference" +
" someAttribute=\"someValue2\"/>\n" +
"</android.support.v7.preference.Preference>\n" +
"\n" +
"<android.support.v7.preference.ListPreference/>",
expectedXml =
"<android.test.pref.Preference>\n" +
" <android.test14.pref.DialogPreference" +
" someAttribute=\"someValue\"/>\n" +
" <android.test14.pref.DialogPreference" +
" someAttribute=\"someValue2\"/>\n" +
" <!-- This one should be ignored --> \n" +
" <android.support.v21.preference.DialogPreference" +
" someAttribute=\"someValue2\"/>\n" +
"</android.test.pref.Preference>\n" +
"\n" +
"<android.test.pref.ListPref/>",
prefixes = setOf(
"android/support/v7/",
"android/support/v14/"
),
rulesMap = RewriteRulesMap(
RewriteRule(from = "android/support/v21/(.*)", to = "ignore")),
typesMap = mapOf(
"android/support/v7/preference/ListPreference"
to "android/test/pref/ListPref",
"android/support/v7/preference/Preference"
to "android/test/pref/Preference",
"android/support/v14/preference/DialogPreference"
to "android/test14/pref/DialogPreference"
)
)
}
@Test fun link_withoutSuffix_shouldRewrite() {
testRewrite(
givenXml =
"<!-- Comment {@link android.support.Test} -->\n" +
"<attr name=\"someAttribute\">",
expectedXml =
"<!-- Comment {@link androidx.Test} -->\n" +
"<attr name=\"someAttribute\">",
prefixes = setOf("android/support/"),
typesMap = mapOf(
"android/support/Test"
to "androidx/Test"
)
)
}
@Test fun link_withInnerClass_shouldRewrite() {
testRewrite(
givenXml =
"<!-- Comment {@link android.support.Test\$R#get(Context, int)} -->\n" +
"<attr name=\"someAttribute\">",
expectedXml =
"<!-- Comment {@link androidx.Test\$R#get(Context, int)} -->\n" +
"<attr name=\"someAttribute\">",
prefixes = setOf("android/support/"),
typesMap = mapOf(
"android/support/Test"
to "androidx/Test"
)
)
}
@Test fun link_shouldRewrite() {
testRewrite(
givenXml =
"<!-- Comment {@link android.support.Test#get(Context, int)} -->\n" +
"<attr name=\"someAttribute\">",
expectedXml =
"<!-- Comment {@link androidx.Test#get(Context, int)} -->\n" +
"<attr name=\"someAttribute\">",
prefixes = setOf("android/support/"),
typesMap = mapOf(
"android/support/Test"
to "androidx/Test"
)
)
}
@Test fun link_lineBreak_shouldRewrite() {
testRewrite(
givenXml =
"<!-- Comment {@link \n" +
"android.support.Test#get(Context, int)} -->\n" +
"<attr name=\"someAttribute\">",
expectedXml =
"<!-- Comment {@link \n" +
"androidx.Test#get(Context, int)} -->\n" +
"<attr name=\"someAttribute\">",
prefixes = setOf("android/support/"),
typesMap = mapOf(
"android/support/Test"
to "androidx/Test"
)
)
}
@Test fun link_lineBreak2_shouldRewrite() {
testRewrite(
givenXml =
"<!-- Comment {@link android.support.Test#get(Context, int)" +
"} -->\n" +
"<attr name=\"someAttribute\">",
expectedXml =
"<!-- Comment {@link androidx.Test#get(Context, int)" +
"} -->\n" +
"<attr name=\"someAttribute\">",
prefixes = setOf("android/support/"),
typesMap = mapOf(
"android/support/Test"
to "androidx/Test"
)
)
}
@Test fun manifestFile_packageRewrite() {
testRewrite(
givenXml =
"<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
" package=\"android.support.v7.preference\">\n" +
" <uses-sdk android:minSdkVersion=\"14\"/>\n" +
"</manifest>",
expectedXml =
"<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
" package=\"androidx.preference\">\n" +
" <uses-sdk android:minSdkVersion=\"14\"/>\n" +
"</manifest>",
prefixes = setOf(
"android/support"
),
typesMap = mapOf(),
packageMap = PackageMap(listOf(
PackageMap.PackageRule(
from = "android/support/v7/preference",
to = "androidx/preference")
)),
rewritingSupportLib = true
)
}
@Test fun manifestFile_packageRewrite_prefixMismatchShouldNotAffectRewrite() {
testRewrite(
givenXml =
"<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
" package=\"android.support.v7.preference\">\n" +
" <uses-sdk android:minSdkVersion=\"14\"/>\n" +
"</manifest>",
expectedXml =
"<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
" package=\"androidx.preference\">\n" +
" <uses-sdk android:minSdkVersion=\"14\"/>\n" +
"</manifest>",
prefixes = setOf(
"android/something/else"
),
typesMap = mapOf(),
packageMap = PackageMap(listOf(
PackageMap.PackageRule(
from = "android/support/v7/preference",
to = "androidx/preference")
)),
rewritingSupportLib = true
)
}
@Test fun manifestFile_packageRewrite_shouldIgnore() {
testRewrite(
givenXml =
"<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
" package=\"androidx.test\">\n" +
"</manifest>",
expectedXml =
"<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
" package=\"androidx.test\">\n" +
"</manifest>",
prefixes = setOf(
"android/support/"
),
rulesMap = RewriteRulesMap(
RewriteRule("androidx.test/(.*)", "ignore")
),
packageMap = PackageMap.EMPTY,
rewritingSupportLib = true
)
}
@Test fun generic_sample_provider() {
testRewrite(
givenXml =
"<provider\n" +
" android:authorities=\"support.Something\"\n" +
" android:name=\"support.Something\">\n" +
" <meta-data android:name=\"support.Something\">\n" +
"</provider>",
expectedXml =
"<provider\n" +
" android:authorities=\"test.Something\"\n" +
" android:name=\"test.Something\">\n" +
" <meta-data android:name=\"test.Something\">\n" +
"</provider>",
prefixes = setOf("support/"),
typesMap = mapOf(
"support/Something" to "test/Something"
)
)
}
@Test fun generic_sample_intent() {
testRewrite(
givenXml =
"<activity android:name=\"some\" android:configChanges=\"orientation\">\n" +
" <intent-filter>\n" +
" <action android:name=\"support.Something\" />\n" +
" </intent-filter>\n" +
"</activity>",
expectedXml =
"<activity android:name=\"some\" android:configChanges=\"orientation\">\n" +
" <intent-filter>\n" +
" <action android:name=\"test.Something\" />\n" +
" </intent-filter>\n" +
"</activity>",
prefixes = setOf("support/"),
typesMap = mapOf(
"support/Something" to "test/Something"
)
)
}
@Test fun generic_sample_style() {
testRewrite(
givenXml =
"<style name=\"AppCompat\" parent=\"Platform.AppCompat\">\n" +
" <item name=\"viewInflaterClass\">support.Something</item>\n" +
"</style>",
expectedXml =
"<style name=\"AppCompat\" parent=\"Platform.AppCompat\">\n" +
" <item name=\"viewInflaterClass\">test.Something</item>\n" +
"</style>",
prefixes = setOf("support/"),
typesMap = mapOf(
"support/Something" to "test/Something"
)
)
}
@Test fun generic_sample_transition() {
testRewrite(
givenXml =
"<transition\n" +
" xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
" xmlns:lb=\"http://schemas.android.com/apk/res-auto\"\n" +
" class=\"support.Something\"\n" +
" lb:lb_slideEdge=\"top\" >\n" +
"</transition>",
expectedXml =
"<transition\n" +
" xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
" xmlns:lb=\"http://schemas.android.com/apk/res-auto\"\n" +
" class=\"test.Something\"\n" +
" lb:lb_slideEdge=\"top\" >\n" +
"</transition>",
prefixes = setOf("support/"),
typesMap = mapOf(
"support/Something" to "test/Something"
)
)
}
@Test fun generic_sample_slices() {
testRewriteToTheSame(
givenAndExpectedXml =
"<LinearLayout\n" +
" xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
" android:layout_width=\"match_parent\"\n" +
" android:layout_height=\"wrap_content\"\n" +
" android:paddingStart=\"16dp\"\n" +
" android:paddingEnd=\"16dp\"\n" +
" android:orientation=\"vertical\">\n" +
"\n" +
" <TextView\n" +
" android:id=\"@+id/text2\"\n" +
" android:layout_width=\"match_parent\"\n" +
" android:layout_height=\"wrap_content\"\n" +
" android:paddingTop=\"8dp\"\n" +
" android:paddingStart=\"8dp\"\n" +
" android:textAppearance=\"?android:attr/textAppearanceMedium\"\n" +
" android:text=\"@string/abc_slice_permission_text_1\" />\n" +
"\n" +
" <TextView\n" +
" android:id=\"@+id/text1\"\n" +
" android:layout_width=\"match_parent\"\n" +
" android:layout_height=\"wrap_content\"\n" +
" android:paddingStart=\"8dp\"\n" +
" android:textAppearance=\"?android:attr/textAppearanceMedium\"\n" +
" android:paddingBottom=\"16dp\"\n" +
" android:text=\"@string/abc_slice_permission_text_2\" />\n" +
"\n" +
"</LinearLayout>",
prefixes = setOf("support/"),
map = mapOf()
)
}
@Test fun generic_sample_slices_dejetification() {
testRewriteToTheSame(
givenAndExpectedXml =
"<LinearLayout\n" +
" xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
" android:layout_width=\"match_parent\"\n" +
" android:layout_height=\"wrap_content\"\n" +
" android:paddingStart=\"16dp\"\n" +
" android:paddingEnd=\"16dp\"\n" +
" android:orientation=\"vertical\">\n" +
"\n" +
" <TextView\n" +
" android:id=\"@+id/text2\"\n" +
" android:layout_width=\"match_parent\"\n" +
" android:layout_height=\"wrap_content\"\n" +
" android:paddingTop=\"8dp\"\n" +
" android:paddingStart=\"8dp\"\n" +
" android:textAppearance=\"?android:attr/textAppearanceMedium\"\n" +
" android:text=\"@string/abc_slice_permission_text_1\" />\n" +
"\n" +
" <TextView\n" +
" android:id=\"@+id/text1\"\n" +
" android:layout_width=\"match_parent\"\n" +
" android:layout_height=\"wrap_content\"\n" +
" android:paddingStart=\"8dp\"\n" +
" android:textAppearance=\"?android:attr/textAppearanceMedium\"\n" +
" android:paddingBottom=\"16dp\"\n" +
" android:text=\"@string/abc_slice_permission_text_2\" />\n" +
"\n" +
"</LinearLayout>",
prefixes = setOf("support/"),
rewritingSupportLib = true,
map = mapOf()
)
}
private fun testRewriteToTheSame(
givenAndExpectedXml: String,
prefixes: Set<String>,
map: Map<String, String>,
errorsExpected: Boolean = false,
rewritingSupportLib: Boolean = false
) {
testRewrite(
givenXml = givenAndExpectedXml,
expectedXml = givenAndExpectedXml,
prefixes = prefixes,
typesMap = map,
errorsExpected = errorsExpected,
rewritingSupportLib = rewritingSupportLib
)
}
private fun testRewrite(
givenXml: String,
expectedXml: String,
prefixes: Set<String>,
typesMap: Map<String, String> = emptyMap(),
rulesMap: RewriteRulesMap = RewriteRulesMap.EMPTY,
packageMap: PackageMap = PackageMap.EMPTY,
rewritingSupportLib: Boolean = false,
errorsExpected: Boolean = false
) {
val given =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"$givenXml\n"
val expected =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"$expectedXml\n"
val typeMap = TypesMap(typesMap.map { JavaType(it.key) to JavaType(it.value) }.toMap())
val config = Config.fromOptional(
restrictToPackagePrefixes = prefixes,
rulesMap = rulesMap,
typesMap = typeMap,
packageMap = packageMap
)
val context = TransformationContext(
config,
rewritingSupportLib = rewritingSupportLib,
useFallbackIfTypeIsMissing = false)
val processor = XmlResourcesTransformer(context)
val fileName = Paths.get("random.xml")
val file = ArchiveFile(fileName, given.toByteArray())
processor.runTransform(file)
val strResult = file.data.toString(Charset.defaultCharset())
Truth.assertThat(strResult).isEqualTo(expected)
if (errorsExpected) {
Truth.assertThat(context.errorsTotal()).isAtLeast(1)
} else {
Truth.assertThat(context.errorsTotal()).isEqualTo(0)
}
}
}