blob: bf2de43a363d1aca564f279d596d72b109ae0f20 [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
*
* 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.manifmerger;
import com.android.annotations.NonNull;
import com.android.manifmerger.IMergerLog.FileAndLine;
import com.android.sdklib.mock.MockLog;
import junit.framework.TestCase;
import org.w3c.dom.Document;
import java.io.File;
public class ManifestMergerSourceLinkTest extends TestCase {
public void testSourceLinks() throws Exception {
MockLog log = new MockLog();
IMergerLog mergerLog = MergerLog.wrapSdkLog(log);
ManifestMerger merger = new ManifestMerger(mergerLog, new ICallback() {
@Override
public int queryCodenameApiLevel(@NonNull String codename) {
if ("ApiCodename1".equals(codename)) {
return 1;
} else if ("ApiCodename10".equals(codename)) {
return 10;
}
return ICallback.UNKNOWN_CODENAME;
}
});
merger.setInsertSourceMarkers(true);
Document mainDoc = MergerXmlUtils.parseDocument(""
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
+ " xmlns:tools=\"http://schemas.android.com/tools\"\n"
+ " package=\"com.example.app1\"\n"
+ " android:versionCode=\"100\"\n"
+ " android:versionName=\"1.0.0\">\n"
+ "\n"
+ " <uses-sdk android:minSdkVersion=\"3\" android:targetSdkVersion=\"11\"/>\n"
+ "\n"
+ " <application\n"
+ " android:name=\"TheApp\"\n"
+ " android:backupAgent=\".MyBackupAgent\" >\n"
+ " <activity android:name=\".MainActivity\" />\n"
+ " <receiver android:name=\"AppReceiver\" />\n"
+ " <activity android:name=\"com.example.lib2.LibActivity\" />\n"
+ "\n"
+ " <!-- This key is defined in the main application. -->\n"
+ " <meta-data\n"
+ " android:name=\"name.for.yet.another.api.key\"\n"
+ " android:value=\"your_yet_another_api_key\"/>\n"
+ "\n"
+ " <!-- Merged elements will be appended here at the end. -->\n"
+ " </application>\n"
+ "\n"
+ "</manifest>",
mergerLog, new FileAndLine("main", 1));
assertNotNull(mainDoc);
Document library1 = MergerXmlUtils.parseDocument(""
+ "<manifest\n"
+ " xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
+ " package=\"com.example.app1\">\n"
+ "\n"
+ " <application android:name=\"TheApp\" >\n"
+ " <activity android:name=\".Library1\" />\n"
+ "\n"
+ " <!-- The library maps API key gets merged in the main application. -->\n"
+ " <meta-data\n"
+ " android:name=\"name.for.maps.api.key\"\n"
+ " android:value=\"your_maps_api_key\"/>\n"
+ "\n"
+ " <!-- The library backup key gets merged in the main application. -->\n"
+ " <meta-data\n"
+ " android:name=\"name.for.backup.api.key\"\n"
+ " android:value=\"your_backup_api_key\" />\n"
+ " </application>\n"
+ "\n"
+ "</manifest>",
mergerLog, new FileAndLine("library1", 1));
assertNotNull(library1);
Document library2 = MergerXmlUtils.parseDocument(""
+ "<manifest\n"
+ " xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
+ " package=\"com.example.lib3\">\n"
+ "\n"
+ " <!-- This comment is ignored. -->\n"
+ "\n"
+ " <application android:label=\"@string/lib_name\" >\n"
+ "\n"
+ " <!-- The first comment just before the element\n"
+ " is carried over as-is.\n"
+ " -->\n"
+ " <!-- Formatting is preserved. -->\n"
+ " <!-- All consecutive comments are taken together. -->\n"
+ "\n"
+ " <activity-alias\n"
+ " android:name=\"com.example.alias.MyActivity\"\n"
+ " android:targetActivity=\"com.example.MainActivity\"\n"
+ " android:label=\"@string/alias_name\"\n"
+ " android:icon=\"@drawable/alias_icon\"\n"
+ " >\n"
+ " <intent-filter>\n"
+ " <action android:name=\"android.intent.action.MAIN\" />\n"
+ " <category android:name=\"android.intent.category.LAUNCHER\" />\n"
+ " </intent-filter>\n"
+ " </activity-alias>\n"
+ "\n"
+ " <!-- This is a dup of the 2nd activity in lib2 -->\n"
+ " <activity\n"
+ " android:name=\"com.example.LibActivity2\"\n"
+ " android:label=\"@string/lib_activity_name\"\n"
+ " android:icon=\"@drawable/lib_activity_icon\"\n"
+ " android:theme=\"@style/Lib.Theme\">\n"
+ " <intent-filter>\n"
+ " <action android:name=\"android.intent.action.MAIN\" />\n"
+ " <category android:name=\"android.intent.category.LAUNCHER\" />\n"
+ " </intent-filter>\n"
+ " </activity>\n"
+ "\n"
+ " </application>\n"
+ "\n"
+ "</manifest>",
mergerLog, new FileAndLine("library2", 1));
assertNotNull(library2);
Document library3 = MergerXmlUtils.parseDocument(""
+ "<manifest\n"
+ " xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
+ " package=\"com.example.lib3\">\n"
+ "\n"
+ " <application android:label=\"@string/lib_name\" >\n"
+ " <activity\n"
+ " android:name=\"com.example.LibActivity3\"\n"
+ " android:label=\"@string/lib_activity_name3\"\n"
+ " android:icon=\"@drawable/lib_activity_icon3\"\n"
+ " android:theme=\"@style/Lib.Theme\">\n"
+ " <intent-filter>\n"
+ " <action android:name=\"android.intent.action.MAIN\" />\n"
+ " <category android:name=\"android.intent.category.LAUNCHER\" />\n"
+ " </intent-filter>\n"
+ " </activity>\n"
+ "\n"
+ " </application>\n"
+ "\n"
+ "</manifest>",
mergerLog, new FileAndLine("library3", 1));
assertNotNull(library3);
MergerXmlUtils.setSource(mainDoc, new File("/path/to/main/doc"));
MergerXmlUtils.setSource(library1, new File("/path/to/library1"));
MergerXmlUtils.setSource(library2, new File("/path/to/library2"));
MergerXmlUtils.setSource(library3, new File("/path/to/library3"));
boolean ok = merger.process(mainDoc, library1, library2, library3);
assertTrue(ok);
String actual = MergerXmlUtils.printXmlString(mainDoc, mergerLog);
assertEquals("Encountered unexpected errors/warnings", "[]", log.toString());
String expected = ""
+ "<!-- From: file:/path/to/main/doc -->\n"
+ "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" android:versionCode=\"100\" android:versionName=\"1.0.0\" package=\"com.example.app1\">\n"
+ "\n"
+ " <uses-sdk android:minSdkVersion=\"3\" android:targetSdkVersion=\"11\"/>\n"
+ "\n"
+ " <application android:backupAgent=\"com.example.app1.MyBackupAgent\" android:name=\"com.example.app1.TheApp\">\n"
+ " <activity android:name=\"com.example.app1.MainActivity\"/>\n"
+ " <receiver android:name=\"com.example.app1.AppReceiver\"/>\n"
+ " <activity android:name=\"com.example.lib2.LibActivity\"/>\n"
+ "\n"
+ " <!-- This key is defined in the main application. -->\n"
+ " <meta-data android:name=\"name.for.yet.another.api.key\" android:value=\"your_yet_another_api_key\"/>\n"
+ "\n"
+ " <!-- Merged elements will be appended here at the end. -->\n"
+ " <!-- From: file:/path/to/library1 -->\n"
+ " <activity android:name=\"com.example.app1.Library1\"/>\n"
+ "\n"
+ " <!-- The library maps API key gets merged in the main application. -->\n"
+ " <meta-data android:name=\"name.for.maps.api.key\" android:value=\"your_maps_api_key\"/>\n"
+ "\n"
+ " <!-- The library backup key gets merged in the main application. -->\n"
+ " <meta-data android:name=\"name.for.backup.api.key\" android:value=\"your_backup_api_key\"/>\n"
+ "\n"
+ " <!-- From: file:/path/to/library2 -->\n"
+ " <!-- This is a dup of the 2nd activity in lib2 -->\n"
+ " <activity android:icon=\"@drawable/lib_activity_icon\" android:label=\"@string/lib_activity_name\" android:name=\"com.example.LibActivity2\" android:theme=\"@style/Lib.Theme\">\n"
+ " <intent-filter>\n"
+ " <action android:name=\"android.intent.action.MAIN\"/>\n"
+ " <category android:name=\"android.intent.category.LAUNCHER\"/>\n"
+ " </intent-filter>\n"
+ " </activity>\n"
+ "\n"
+ " <!-- The first comment just before the element\n"
+ " is carried over as-is.\n"
+ " -->\n"
+ " <!-- Formatting is preserved. -->\n"
+ " <!-- All consecutive comments are taken together. -->\n"
+ "\n"
+ " <activity-alias android:icon=\"@drawable/alias_icon\" android:label=\"@string/alias_name\" android:name=\"com.example.alias.MyActivity\" android:targetActivity=\"com.example.MainActivity\">\n"
+ " <intent-filter>\n"
+ " <action android:name=\"android.intent.action.MAIN\"/>\n"
+ " <category android:name=\"android.intent.category.LAUNCHER\"/>\n"
+ " </intent-filter>\n"
+ " </activity-alias>\n"
+ " <!-- From: file:/path/to/library3 -->\n"
+ " <activity android:icon=\"@drawable/lib_activity_icon3\" android:label=\"@string/lib_activity_name3\" android:name=\"com.example.LibActivity3\" android:theme=\"@style/Lib.Theme\">\n"
+ " <intent-filter>\n"
+ " <action android:name=\"android.intent.action.MAIN\"/>\n"
+ " <category android:name=\"android.intent.category.LAUNCHER\"/>\n"
+ " </intent-filter>\n"
+ " </activity>\n"
+ " <!-- From: file:/path/to/main/doc -->\n"
+ " \n"
+ " </application>\n"
+ "\n"
+ "</manifest>\n";
if (!expected.equals(actual)) {
// DOM implementations vary slightly whether they'll insert a newline for comment
// inserted outside document
// JDK 7 doesn't, JDK 6 does
int index = expected.indexOf('\n');
assertTrue(index != -1);
expected = expected.substring(0, index) + expected.substring(index + 1);
}
assertEquals(expected, actual);
}
}