/* * Copyright 2012-2014 eBay Software Foundation and selendroid committers. * * 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 io.selendroid.standalone.builder; import io.selendroid.standalone.SelendroidConfiguration; import io.selendroid.standalone.android.AndroidApp; import io.selendroid.standalone.android.AndroidSdk; import io.selendroid.standalone.android.impl.DefaultAndroidApp; import io.selendroid.standalone.builder.SelendroidServerBuilder; import io.selendroid.standalone.io.ShellCommand; import java.io.File; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.commons.exec.CommandLine; import org.apache.commons.io.FileUtils; import org.junit.Assert; import org.junit.Test; public class SelendroidServerBuilderTest { public static final String APK_FILE = "src/test/resources/selendroid-test-app.apk"; public static final String SELENDROID_PREBUILD_SERVER = "src/test/resources/selendroid-server.apk"; public static final String ANDROID_APPLICATION_XML_TEMPLATE = "src/test/resources/AndroidManifest.xml"; public static SelendroidConfiguration selendroidConfiguration = null; @Test public void testShouldBeAbleToCreateCustomizedSelendroidServerAndCleantTUp() throws Exception { SelendroidServerBuilder builder = getDefaultBuilder(); builder.init(new DefaultAndroidApp(new File(APK_FILE))); builder.cleanUpPrebuildServer(); // Verify apk, if the files have been removed CommandLine cmd = new CommandLine(AndroidSdk.aapt()); cmd.addArgument("list", false); cmd.addArgument(builder.getSelendroidServer().getAbsolutePath(), false); String output = ShellCommand.exec(cmd); assertResultDoesNotContainFile(output, "META-INF/CERT.RSA"); assertResultDoesNotContainFile(output, "META-INF/CERT.SF"); assertResultDoesNotContainFile(output, "AndroidManifest.xml"); // just double check that dexed classes are there assertResultDoesContainFile(output, "classes.dex"); } @Test public void testShouldBeAbleToCreateCustomizedAndroidApplicationXML() throws Exception { SelendroidServerBuilder builder = getDefaultBuilder(); builder.init(new DefaultAndroidApp(new File(APK_FILE))); builder.cleanUpPrebuildServer(); File file = builder.createAndAddCustomizedAndroidManifestToSelendroidServer(); ZipFile zipFile = new ZipFile(file); ZipArchiveEntry entry = zipFile.getEntry("AndroidManifest.xml"); Assert.assertEquals(entry.getName(), "AndroidManifest.xml"); Assert.assertTrue("Expecting non empty AndroidManifest.xml file", entry.getSize() > 700); // Verify that apk is not yet signed CommandLine cmd = new CommandLine(AndroidSdk.aapt()); cmd.addArgument("list", false); cmd.addArgument(builder.getSelendroidServer().getAbsolutePath(), false); String output = ShellCommand.exec(cmd); assertResultDoesNotContainFile(output, "META-INF/CERT.RSA"); assertResultDoesNotContainFile(output, "META-INF/CERT.SF"); } @Test public void testShouldBeAbleToResignAnSignedApp() throws Exception { SelendroidServerBuilder builder = getDefaultBuilder(); File androidApp = File.createTempFile("testapp", ".apk"); FileUtils.copyFile(new File(APK_FILE), androidApp); AndroidApp resignedApp = builder.resignApp(androidApp); assertResignedApp(resignedApp, androidApp); // Verify that apk is signed CommandLine cmd = new CommandLine(AndroidSdk.aapt()); cmd.addArgument("list", false); cmd.addArgument(resignedApp.getAbsolutePath(), false); String output = ShellCommand.exec(cmd); assertResultDoesNotContainFile(output, "META-INF/CERT.RSA"); assertResultDoesNotContainFile(output, "META-INF/CERT.SF"); assertResultDoesContainFile(output, "META-INF/ANDROIDD.SF"); assertResultDoesContainFile(output, "META-INF/ANDROIDD.RSA"); assertResultDoesContainFile(output, "AndroidManifest.xml"); } @Test public void testShouldBeAbleToResignAnSignedAppWithCustomKeystore() throws Exception { SelendroidServerBuilder builder = getDefaultBuilderWithCustomKeystore(); File androidApp = File.createTempFile("testapp", ".apk"); System.out.println("App name: " + androidApp.getName()); FileUtils.copyFile(new File(APK_FILE), androidApp); AndroidApp resignedApp = builder.resignApp(androidApp); assertResignedApp(resignedApp, androidApp); // Verify that apk is signed CommandLine cmd = new CommandLine(AndroidSdk.aapt()); cmd.addArgument("list", false); cmd.addArgument(resignedApp.getAbsolutePath(), false); String output = ShellCommand.exec(cmd); String sigFileName = selendroidConfiguration.getKeystoreAlias().toUpperCase(); if(sigFileName.length() > 8) { sigFileName = sigFileName.substring(0, 8); } assertResultDoesNotContainFile(output, "META-INF/CERT.RSA"); assertResultDoesNotContainFile(output, "META-INF/CERT.SF"); assertResultDoesContainFile(output, "META-INF/"+ sigFileName + ".SF"); assertResultDoesContainFile(output, "META-INF/" + sigFileName + ".RSA"); assertResultDoesContainFile(output, "AndroidManifest.xml"); } @Test public void testShouldBeAbleToCreateASignedSelendroidServer() throws Exception { SelendroidServerBuilder builder = getDefaultBuilder(); builder.init(new DefaultAndroidApp(new File(APK_FILE))); builder.cleanUpPrebuildServer(); File file = File.createTempFile("testserver", "apk"); builder.signTestServer(builder.createAndAddCustomizedAndroidManifestToSelendroidServer(), file); // Verify that apk is signed CommandLine cmd = new CommandLine(AndroidSdk.aapt()); cmd.addArgument("list", false); cmd.addArgument(file.getAbsolutePath(), false); String output = ShellCommand.exec(cmd); assertResultDoesNotContainFile(output, "META-INF/CERT.RSA"); assertResultDoesNotContainFile(output, "META-INF/CERT.SF"); assertResultDoesContainFile(output, "META-INF/ANDROIDD.SF"); assertResultDoesContainFile(output, "META-INF/ANDROIDD.RSA"); assertResultDoesContainFile(output, "AndroidManifest.xml"); } @Test public void testShouldBeAbleToCreateASignedSelendroidServerWithCustomKeystore() throws Exception { SelendroidServerBuilder builder = getDefaultBuilderWithCustomKeystore(); builder.init(new DefaultAndroidApp(new File(APK_FILE))); builder.cleanUpPrebuildServer(); File file = File.createTempFile("testserver1", "apk"); builder.signTestServer(builder.createAndAddCustomizedAndroidManifestToSelendroidServer(), file); // Verify that apk is signed CommandLine cmd = new CommandLine(AndroidSdk.aapt()); cmd.addArgument("list", false); cmd.addArgument(file.getAbsolutePath(), false); String output = ShellCommand.exec(cmd); String sigFileName = selendroidConfiguration.getKeystoreAlias().toUpperCase(); if(sigFileName.length() > 8) { sigFileName = sigFileName.substring(0, 8); } assertResultDoesNotContainFile(output, "META-INF/CERT.RSA"); assertResultDoesNotContainFile(output, "META-INF/CERT.SF"); assertResultDoesContainFile(output, "META-INF/"+ sigFileName + ".SF"); assertResultDoesContainFile(output, "META-INF/" + sigFileName + ".RSA"); assertResultDoesContainFile(output, "AndroidManifest.xml"); } void assertResultDoesNotContainFile(String output, String file) { if (output.contains(file)) { Assert.fail("Output does contain the file: " + file); } } void assertResultDoesContainFile(String output, String file) { if (!output.contains(file)) { Assert.fail("Output does not contain the file: " + file); } } private static void assertResignedApp(AndroidApp resignedApp, File originalApp) { String resignedName = new File(resignedApp.getAbsolutePath()).getName(); Assert.assertTrue(resignedName.startsWith("resigned-")); Assert.assertTrue(resignedName.endsWith(originalApp.getName())); } public static SelendroidServerBuilder getDefaultBuilder() { return new SelendroidServerBuilder(SELENDROID_PREBUILD_SERVER, ANDROID_APPLICATION_XML_TEMPLATE); } public static SelendroidServerBuilder getDefaultBuilderWithCustomKeystore() { selendroidConfiguration = new SelendroidConfiguration(); selendroidConfiguration.setKeystore("src/test/resources/selendriodtest1.keystore"); selendroidConfiguration.setKeystorePassword("selendroid"); selendroidConfiguration.setKeystoreAlias("selendroid1"); return new SelendroidServerBuilder(SELENDROID_PREBUILD_SERVER, ANDROID_APPLICATION_XML_TEMPLATE,selendroidConfiguration); } }