
com.xtremelabs.robolectric.RobolectricConfig Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of robolectric Show documentation
Show all versions of robolectric Show documentation
An alternative Android testing framework.
The newest version!
package com.xtremelabs.robolectric;
import android.app.Application;
import com.xtremelabs.robolectric.internal.ClassNameResolver;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import static android.content.pm.ApplicationInfo.*;
import static com.xtremelabs.robolectric.Robolectric.DEFAULT_SDK_VERSION;
public class RobolectricConfig {
private final File androidManifestFile;
private final File resourceDirectory;
private final File assetsDirectory;
private String rClassName;
private String packageName;
private String processName;
private String applicationName;
private boolean manifestIsParsed = false;
private int sdkVersion;
private int minSdkVersion;
private boolean sdkVersionSpecified = true;
private boolean minSdkVersionSpecified = true;
private int applicationFlags;
private final List receivers = new ArrayList();
private boolean strictI18n = false;
private String valuesResQualifiers="";
private String oldValuesResQualifier="";
/**
* Creates a Robolectric configuration using default Android files relative to the specified base directory.
*
* The manifest will be baseDir/AndroidManifest.xml, res will be baseDir/res, and assets in baseDir/assets.
*
* @param baseDir the base directory of your Android project
*/
public RobolectricConfig(final File baseDir) {
this(new File(baseDir, "AndroidManifest.xml"), new File(baseDir, "res"), new File(baseDir, "assets"));
}
public RobolectricConfig(final File androidManifestFile, final File resourceDirectory) {
this(androidManifestFile, resourceDirectory, new File(resourceDirectory.getParent(), "assets"));
}
/**
* Creates a Robolectric configuration using specified locations.
*
* @param androidManifestFile location of the AndroidManifest.xml file
* @param resourceDirectory location of the res directory
* @param assetsDirectory location of the assets directory
*/
public RobolectricConfig(final File androidManifestFile, final File resourceDirectory, final File assetsDirectory) {
this.androidManifestFile = androidManifestFile;
this.resourceDirectory = resourceDirectory;
this.assetsDirectory = assetsDirectory;
}
public String getRClassName() throws Exception {
parseAndroidManifest();
return rClassName;
}
public void validate() throws FileNotFoundException {
if (!androidManifestFile.exists() || !androidManifestFile.isFile()) {
throw new FileNotFoundException(androidManifestFile.getAbsolutePath() + " not found or not a file; it should point to your project's AndroidManifest.xml");
}
if (!getResourceDirectory().exists() || !getResourceDirectory().isDirectory()) {
throw new FileNotFoundException(getResourceDirectory().getAbsolutePath() + " not found or not a directory; it should point to your project's res directory");
}
}
private void parseAndroidManifest() {
if (manifestIsParsed) {
return;
}
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder db = dbf.newDocumentBuilder();
Document manifestDocument = db.parse(androidManifestFile);
packageName = getTagAttributeText(manifestDocument, "manifest", "package");
rClassName = packageName + ".R";
applicationName = getTagAttributeText(manifestDocument, "application", "android:name");
Integer minSdkVer = getTagAttributeIntValue(manifestDocument, "uses-sdk", "android:minSdkVersion");
Integer sdkVer = getTagAttributeIntValue(manifestDocument, "uses-sdk", "android:targetSdkVersion");
if (minSdkVer == null) {
minSdkVersion = DEFAULT_SDK_VERSION;
minSdkVersionSpecified = false;
} else {
minSdkVersion = minSdkVer;
}
if (sdkVer == null) {
sdkVersion = DEFAULT_SDK_VERSION;
sdkVersionSpecified = false;
} else {
sdkVersion = sdkVer;
}
processName = getTagAttributeText(manifestDocument, "application", "android:process");
if (processName == null) {
processName = packageName;
}
parseApplicationFlags(manifestDocument);
parseReceivers(manifestDocument, packageName);
} catch (Exception ignored) {
}
manifestIsParsed = true;
}
private void parseReceivers(final Document manifestDocument, String packageName) {
Node application = manifestDocument.getElementsByTagName("application").item(0);
if (application == null) {
return;
}
for (Node receiverNode : getChildrenTags(application, "receiver")) {
Node namedItem = receiverNode.getAttributes().getNamedItem("android:name");
if (namedItem == null) {
continue;
}
String receiverName = namedItem.getTextContent();
if (receiverName.startsWith(".")) {
receiverName = packageName + receiverName;
}
for (Node intentFilterNode : getChildrenTags(receiverNode, "intent-filter")) {
List actions = new ArrayList();
for (Node actionNode : getChildrenTags(intentFilterNode, "action")) {
Node nameNode = actionNode.getAttributes().getNamedItem("android:name");
if (nameNode != null) {
actions.add(nameNode.getTextContent());
}
}
receivers.add(new ReceiverAndIntentFilter(receiverName, actions));
}
}
}
private List getChildrenTags(final Node node, final String tagName) {
List children = new ArrayList();
for (int i = 0; i < node.getChildNodes().getLength(); i++) {
Node childNode = node.getChildNodes().item(i);
if (childNode.getNodeName().equalsIgnoreCase(tagName)) {
children.add(childNode);
}
}
return children;
}
private void parseApplicationFlags(final Document manifestDocument) {
applicationFlags = getApplicationFlag(manifestDocument, "android:allowBackup", FLAG_ALLOW_BACKUP);
applicationFlags += getApplicationFlag(manifestDocument, "android:allowClearUserData", FLAG_ALLOW_CLEAR_USER_DATA);
applicationFlags += getApplicationFlag(manifestDocument, "android:allowTaskReparenting", FLAG_ALLOW_TASK_REPARENTING);
applicationFlags += getApplicationFlag(manifestDocument, "android:debuggable", FLAG_DEBUGGABLE);
applicationFlags += getApplicationFlag(manifestDocument, "android:hasCode", FLAG_HAS_CODE);
applicationFlags += getApplicationFlag(manifestDocument, "android:killAfterRestore", FLAG_KILL_AFTER_RESTORE);
applicationFlags += getApplicationFlag(manifestDocument, "android:persistent", FLAG_PERSISTENT);
applicationFlags += getApplicationFlag(manifestDocument, "android:resizeable", FLAG_RESIZEABLE_FOR_SCREENS);
applicationFlags += getApplicationFlag(manifestDocument, "android:restoreAnyVersion", FLAG_RESTORE_ANY_VERSION);
applicationFlags += getApplicationFlag(manifestDocument, "android:largeScreens", FLAG_SUPPORTS_LARGE_SCREENS);
applicationFlags += getApplicationFlag(manifestDocument, "android:normalScreens", FLAG_SUPPORTS_NORMAL_SCREENS);
applicationFlags += getApplicationFlag(manifestDocument, "android:anyDensity", FLAG_SUPPORTS_SCREEN_DENSITIES);
applicationFlags += getApplicationFlag(manifestDocument, "android:smallScreens", FLAG_SUPPORTS_SMALL_SCREENS);
applicationFlags += getApplicationFlag(manifestDocument, "android:testOnly", FLAG_TEST_ONLY);
applicationFlags += getApplicationFlag(manifestDocument, "android:vmSafeMode", FLAG_VM_SAFE_MODE);
}
private int getApplicationFlag(final Document doc, final String attribute, final int attributeValue) {
String flagString = getTagAttributeText(doc, "application", attribute);
return "true".equalsIgnoreCase(flagString) ? attributeValue : 0;
}
private Integer getTagAttributeIntValue(final Document doc, final String tag, final String attribute) {
return getTagAttributeIntValue(doc, tag, attribute, null);
}
private Integer getTagAttributeIntValue(final Document doc, final String tag, final String attribute, final Integer defaultValue) {
String valueString = getTagAttributeText(doc, tag, attribute);
if (valueString != null) {
return Integer.parseInt(valueString);
}
return defaultValue;
}
public String getApplicationName() {
parseAndroidManifest();
return applicationName;
}
public String getPackageName() {
parseAndroidManifest();
return packageName;
}
public int getMinSdkVersion() {
parseAndroidManifest();
return minSdkVersion;
}
public int getSdkVersion() {
parseAndroidManifest();
return sdkVersion;
}
public int getApplicationFlags() {
parseAndroidManifest();
return applicationFlags;
}
public String getProcessName() {
parseAndroidManifest();
return processName;
}
public File getResourceDirectory() {
return resourceDirectory;
}
public File getAssetsDirectory() {
return assetsDirectory;
}
public int getReceiverCount() {
parseAndroidManifest();
return receivers.size();
}
public String getReceiverClassName(final int receiverIndex) {
parseAndroidManifest();
return receivers.get(receiverIndex).getBroadcastReceiverClassName();
}
public List getReceiverIntentFilterActions(final int receiverIndex) {
parseAndroidManifest();
return receivers.get(receiverIndex).getIntentFilterActions();
}
public boolean getStrictI18n() {
return strictI18n;
}
public void setStrictI18n(boolean strict) {
strictI18n = strict;
}
public void setValuesResQualifiers( String qualifiers ){
this.oldValuesResQualifier = this.valuesResQualifiers;
this.valuesResQualifiers = qualifiers;
}
public String getValuesResQualifiers() {
return valuesResQualifiers;
}
public boolean isValuesResQualifiersChanged() {
return !valuesResQualifiers.equals( oldValuesResQualifier );
}
private static String getTagAttributeText(final Document doc, final String tag, final String attribute) {
NodeList elementsByTagName = doc.getElementsByTagName(tag);
for (int i = 0; i < elementsByTagName.getLength(); ++i) {
Node item = elementsByTagName.item(i);
Node namedItem = item.getAttributes().getNamedItem(attribute);
if (namedItem != null) {
return namedItem.getTextContent();
}
}
return null;
}
private static Application newApplicationInstance(final String packageName, final String applicationName) {
Application application;
try {
Class extends Application> applicationClass =
new ClassNameResolver(packageName, applicationName).resolve();
application = applicationClass.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
return application;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
RobolectricConfig that = (RobolectricConfig) o;
if (androidManifestFile != null ? !androidManifestFile.equals(that.androidManifestFile) : that.androidManifestFile != null) {
return false;
}
if (getAssetsDirectory() != null ? !getAssetsDirectory().equals(that.getAssetsDirectory()) : that.getAssetsDirectory() != null) {
return false;
}
if (getResourceDirectory() != null ? !getResourceDirectory().equals(that.getResourceDirectory()) : that.getResourceDirectory() != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = androidManifestFile != null ? androidManifestFile.hashCode() : 0;
result = 31 * result + (getResourceDirectory() != null ? getResourceDirectory().hashCode() : 0);
result = 31 * result + (getAssetsDirectory() != null ? getAssetsDirectory().hashCode() : 0);
return result;
}
public int getRealSdkVersion() {
parseAndroidManifest();
if (sdkVersionSpecified) {
return sdkVersion;
}
if (minSdkVersionSpecified) {
return minSdkVersion;
}
return sdkVersion;
}
private static class ReceiverAndIntentFilter {
private final List intentFilterActions;
private final String broadcastReceiverClassName;
public ReceiverAndIntentFilter(final String broadcastReceiverClassName, final List intentFilterActions) {
this.broadcastReceiverClassName = broadcastReceiverClassName;
this.intentFilterActions = intentFilterActions;
}
public String getBroadcastReceiverClassName() {
return broadcastReceiverClassName;
}
public List getIntentFilterActions() {
return intentFilterActions;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy