blob: 5d0ba59ee5d76ae253fe2064f2a4123c06ae48ce [file] [log] [blame]
/*
* Copyright (C) 2014 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.manifmerger;
import com.android.utils.ILogger;
import junit.framework.TestCase;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.xml.sax.SAXException;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
/**
* Tests for the {@link ActionRecorder} class
*/
public class ActionRecorderTest extends TestCase {
private static final String REFERENCE = ""
+ "<manifest\n"
+ " xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
+ " xmlns:tools=\"http://schemas.android.com/apk/res/android/tools\"\n"
+ " package=\"com.example.lib3\">\n"
+ "\n"
+ " <activity android:name=\"activityOne\">\n"
+ " <intent-filter android:label=\"@string/foo\"/>\n"
+ " </activity>\n"
+ "\n"
+ "</manifest>";
// this will be used as the source location for the "reference" xml string.
private static final String REFEFENCE_DOCUMENT = "ref_doc";
@Mock ILogger mLoggerMock;
ActionRecorder mActionRecorderBuilder = new ActionRecorder();
@Override
protected void setUp() throws Exception {
super.setUp();
MockitoAnnotations.initMocks(this);
}
public void testDoNothing() {
Actions actions = mActionRecorderBuilder.build();
actions.log(mLoggerMock);
Mockito.verify(mLoggerMock).verbose(Actions.HEADER);
Mockito.verifyNoMoreInteractions(mLoggerMock);
assertTrue(actions.getNodeKeys().isEmpty());
}
public void testSingleElement_withoutAttributes()
throws ParserConfigurationException, SAXException, IOException {
XmlDocument xmlDocument = TestUtils.xmlDocumentFromString(
new TestUtils.TestSourceLocation(getClass(),
REFEFENCE_DOCUMENT), REFERENCE);
XmlElement xmlElement = xmlDocument.getRootNode().getNodeByTypeAndKey(
ManifestModel.NodeTypes.ACTIVITY, "com.example.lib3.activityOne").get();
// added during the initial file loading
mActionRecorderBuilder.recordNodeAction(xmlElement, Actions.ActionType.ADDED);
Actions actions = mActionRecorderBuilder.build();
assertEquals(1, actions.getNodeKeys().size());
assertEquals(1, actions.getNodeRecords(xmlElement.getId()).size());
assertEquals(0, actions.getRecordedAttributeNames(xmlElement.getId()).size());
actions.log(mLoggerMock);
// check that output is consistent with spec.
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(Actions.HEADER)
.append(xmlElement.getId()).append("\n");
appendNode(stringBuilder, Actions.ActionType.ADDED, REFEFENCE_DOCUMENT, 6, 5);
Mockito.verify(mLoggerMock).verbose(stringBuilder.toString());
Mockito.verifyNoMoreInteractions(mLoggerMock);
}
public void testSingleElement_withoutAttributes_withRejection()
throws ParserConfigurationException, SAXException, IOException {
String other = ""
+ "<manifest\n"
+ " xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
+ " xmlns:tools=\"http://schemas.android.com/apk/res/android/tools\"\n"
+ " package=\"com.example.lib3\">\n"
+ "\n"
+ " <activity android:name=\"activityOne\" "
+ " android:configChanges=\"locale\"/>\n"
+ "\n"
+ "</manifest>";
XmlDocument xmlDocument = TestUtils.xmlDocumentFromString(
new TestUtils.TestSourceLocation(getClass(),
REFEFENCE_DOCUMENT), REFERENCE);
XmlDocument otherDocument = TestUtils.xmlDocumentFromString(
new TestUtils.TestSourceLocation(getClass(),
"other_document"), other);
XmlElement xmlElement = xmlDocument.getRootNode().getNodeByTypeAndKey(
ManifestModel.NodeTypes.ACTIVITY, "com.example.lib3.activityOne").get();
// added during initial document loading
mActionRecorderBuilder.recordNodeAction(xmlElement, Actions.ActionType.ADDED);
// rejected during second document merging.
mActionRecorderBuilder.recordNodeAction(xmlElement, Actions.ActionType.REJECTED,
otherDocument.getRootNode().getNodeByTypeAndKey(
ManifestModel.NodeTypes.ACTIVITY, "com.example.lib3.activityOne").get());
Actions actions = mActionRecorderBuilder.build();
assertEquals(1, actions.getNodeKeys().size());
assertEquals(2, actions.getNodeRecords(xmlElement.getId()).size());
assertEquals(Actions.ActionType.ADDED,
actions.getNodeRecords(xmlElement.getId()).get(0).mActionType);
assertEquals(Actions.ActionType.REJECTED,
actions.getNodeRecords(xmlElement.getId()).get(1).mActionType);
assertEquals(0, actions.getRecordedAttributeNames(xmlElement.getId()).size());
actions.log(mLoggerMock);
// check that output is consistent with spec.
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(Actions.HEADER)
.append(xmlElement.getId()).append("\n");
appendNode(stringBuilder, Actions.ActionType.ADDED, REFEFENCE_DOCUMENT, 6, 5);
appendNode(stringBuilder, Actions.ActionType.REJECTED, "other_document", 6, 5);
Mockito.verify(mLoggerMock).verbose(stringBuilder.toString());
Mockito.verifyNoMoreInteractions(mLoggerMock);
}
public void testSingleElement_withNoNamespaceAttributes()
throws ParserConfigurationException, SAXException, IOException {
XmlDocument xmlDocument = TestUtils.xmlDocumentFromString(
new TestUtils.TestSourceLocation(getClass(),
REFEFENCE_DOCUMENT), REFERENCE);
XmlElement xmlElement = xmlDocument.getRootNode().getNodeByTypeAndKey(
ManifestModel.NodeTypes.ACTIVITY, "com.example.lib3.activityOne").get();
// added during the initial file loading
mActionRecorderBuilder.recordNodeAction(xmlElement, Actions.ActionType.ADDED);
mActionRecorderBuilder.recordAttributeAction(
xmlElement.getAttribute(XmlNode.fromXmlName("android:name")).get(),
Actions.ActionType.ADDED, AttributeOperationType.STRICT);
Actions actions = mActionRecorderBuilder.build();
assertEquals(1, actions.getNodeKeys().size());
assertEquals(1, actions.getNodeRecords(xmlElement.getId()).size());
assertEquals(1, actions.getRecordedAttributeNames(xmlElement.getId()).size());
actions.log(mLoggerMock);
// check that output is consistent with spec.
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(Actions.HEADER)
.append(xmlElement.getId()).append("\n");
appendNode(stringBuilder, Actions.ActionType.ADDED, REFEFENCE_DOCUMENT, 6, 5);
appendAttribute(stringBuilder,
XmlNode.unwrapName(xmlElement.getXml().getAttributeNode("android:name")),
Actions.ActionType.ADDED,
REFEFENCE_DOCUMENT,
6,
15);
Mockito.verify(mLoggerMock).verbose(stringBuilder.toString());
Mockito.verifyNoMoreInteractions(mLoggerMock);
}
public void testSingleElement_withNamespaceAttributes()
throws ParserConfigurationException, SAXException, IOException {
XmlDocument xmlDocument = TestUtils.xmlDocumentFromString(
new TestUtils.TestSourceLocation(getClass(),
REFEFENCE_DOCUMENT), REFERENCE);
XmlElement xmlElement = xmlDocument.getRootNode();
// added during the initial file loading
mActionRecorderBuilder.recordNodeAction(xmlElement, Actions.ActionType.ADDED);
mActionRecorderBuilder.recordAttributeAction(
xmlElement.getAttribute(XmlNode.fromXmlName("package")).get(),
Actions.ActionType.ADDED, AttributeOperationType.STRICT);
Actions actions = mActionRecorderBuilder.build();
assertEquals(1, actions.getNodeKeys().size());
assertEquals(1, actions.getNodeRecords(xmlElement.getId()).size());
assertEquals(1, actions.getRecordedAttributeNames(xmlElement.getId()).size());
actions.log(mLoggerMock);
// check that output is consistent with spec.
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(Actions.HEADER)
.append(xmlElement.getId()).append("\n");
appendNode(stringBuilder, Actions.ActionType.ADDED, REFEFENCE_DOCUMENT, 1, 1);
appendAttribute(stringBuilder,
XmlNode.unwrapName(xmlElement.getXml().getAttributeNode("package")),
Actions.ActionType.ADDED,
REFEFENCE_DOCUMENT,
4,
5);
Mockito.verify(mLoggerMock).verbose(stringBuilder.toString());
Mockito.verifyNoMoreInteractions(mLoggerMock);
}
public void testMultipleElements_withRejection()
throws ParserConfigurationException, SAXException, IOException {
String other = ""
+ "<manifest\n"
+ " xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
+ " xmlns:tools=\"http://schemas.android.com/apk/res/android/tools\"\n"
+ " package=\"com.example.lib3\">\n"
+ "\n"
+ " <activity android:name=\"activityOne\""
+ " android:configChanges=\"locale\"/>\n"
+ " <application android:name=\"applicationOne\"/>"
+ "\n"
+ "</manifest>";
XmlDocument xmlDocument = TestUtils.xmlDocumentFromString(
new TestUtils.TestSourceLocation(getClass(),
REFEFENCE_DOCUMENT), REFERENCE);
XmlDocument otherDocument = TestUtils.xmlDocumentFromString(
new TestUtils.TestSourceLocation(getClass(),
"other_document"), other);
XmlElement activityElement = xmlDocument.getRootNode().getNodeByTypeAndKey(
ManifestModel.NodeTypes.ACTIVITY, "com.example.lib3.activityOne").get();
// added during initial document loading
mActionRecorderBuilder.recordNodeAction(activityElement, Actions.ActionType.ADDED);
// rejected during second document merging.
mActionRecorderBuilder.recordNodeAction(activityElement, Actions.ActionType.REJECTED,
otherDocument.getRootNode().getNodeByTypeAndKey(
ManifestModel.NodeTypes.ACTIVITY, "com.example.lib3.activityOne").get());
XmlElement applicationElement = otherDocument.getRootNode().getNodeByTypeAndKey(
ManifestModel.NodeTypes.APPLICATION, null).get();
mActionRecorderBuilder.recordNodeAction(applicationElement, Actions.ActionType.ADDED);
Actions actions = mActionRecorderBuilder.build();
assertEquals(2, actions.getNodeKeys().size());
assertEquals(2, actions.getNodeRecords(activityElement.getId()).size());
assertEquals(Actions.ActionType.ADDED,
actions.getNodeRecords(activityElement.getId()).get(0).mActionType);
assertEquals(Actions.ActionType.REJECTED,
actions.getNodeRecords(activityElement.getId()).get(1).mActionType);
assertEquals(0, actions.getRecordedAttributeNames(activityElement.getId()).size());
assertEquals(1, actions.getNodeRecords(applicationElement.getId()).size());
assertEquals(0, actions.getRecordedAttributeNames(applicationElement.getId()).size());
actions.log(mLoggerMock);
// check that output is consistent with spec.
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(Actions.HEADER)
.append(activityElement.getId()).append("\n");
appendNode(stringBuilder, Actions.ActionType.ADDED, REFEFENCE_DOCUMENT, 6, 5);
appendNode(stringBuilder, Actions.ActionType.REJECTED, "other_document", 6, 5);
stringBuilder.append(applicationElement.getId()).append("\n");
appendNode(stringBuilder, Actions.ActionType.ADDED, "other_document", 7, 5);
Mockito.verify(mLoggerMock).verbose(stringBuilder.toString());
Mockito.verifyNoMoreInteractions(mLoggerMock);
}
private void appendNode(StringBuilder out,
Actions.ActionType actionType,
String docString,
int lineNumber,
int columnNumber) {
out.append(actionType.toString())
.append(" from ")
.append(getClass().getSimpleName()).append('#').append(docString)
.append(":").append(lineNumber).append(":").append(columnNumber).append("\n");
}
private void appendAttribute(StringBuilder out,
XmlNode.NodeName attributeName,
Actions.ActionType actionType,
String docString,
int lineNumber,
int columnNumber) {
out.append("\t")
.append(attributeName.toString())
.append("\n\t\t")
.append(actionType.toString())
.append(" from ")
.append(getClass().getSimpleName()).append('#').append(docString)
.append(":").append(lineNumber)
.append(":").append(columnNumber).append("\n");
}
}