blob: c86a48286224caa6dbe3f89687a1b846ef0e8b95 [file] [log] [blame]
/*
* Copyright (C) 2018 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.deployer;
import static com.android.tools.deployer.model.FileDiff.Status.CREATED;
import static com.android.tools.deployer.model.FileDiff.Status.MODIFIED;
import com.android.tools.deployer.model.Apk;
import com.android.tools.deployer.model.ApkEntry;
import com.android.tools.deployer.model.FileDiff;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
public class SwapVerifierTest {
@Test
public void testSimpleModifiedDex() throws DeployerException {
List<FileDiff> diffs = new ArrayList<>();
diffs.add(makeDiff("META-INF/CERT.SF ", MODIFIED));
diffs.add(makeDiff("META-INF/CERT.RSA", MODIFIED));
diffs.add(makeDiff("META-INF/MANIFEST.MF", MODIFIED));
diffs.add(makeDiff("classes.dex", MODIFIED));
new SwapVerifier().verify(diffs, false);
}
@Test
public void testModifiedSharedObject() {
List<FileDiff> diffs = new ArrayList<>();
diffs.add(makeDiff("META-INF/CERT.SF ", MODIFIED));
diffs.add(makeDiff("META-INF/CERT.RSA", MODIFIED));
diffs.add(makeDiff("META-INF/MANIFEST.MF", MODIFIED));
diffs.add(makeDiff("lib/arm64-v8a/libnative-lib.so", MODIFIED));
try {
new SwapVerifier().verify(diffs, false);
} catch (DeployerException e) {
Assert.assertEquals(DeployerException.Error.CANNOT_SWAP_STATIC_LIB, e.getError());
return;
}
Assert.fail("Exception not thrown");
}
@Test
public void testAddedSharedObject() throws DeployerException {
List<FileDiff> diffs = new ArrayList<>();
diffs.add(makeDiff("META-INF/CERT.SF ", MODIFIED));
diffs.add(makeDiff("META-INF/CERT.RSA", MODIFIED));
diffs.add(makeDiff("META-INF/MANIFEST.MF", MODIFIED));
diffs.add(makeDiff("classes.dex", MODIFIED));
diffs.add(makeDiff("lib/arm64-v8a/libnative-lib.so", CREATED));
// This is technically possible. User could have changed some init method that previous didn't load the .so but now swap in that
// Java method and potentially now load it. For that case, we need to let it swap and see if the VM is ok with the dex changes.
new SwapVerifier().verify(diffs, false);
}
@Test
public void testAddedDex() throws DeployerException {
List<FileDiff> diffs = new ArrayList<>();
diffs.add(makeDiff("META-INF/CERT.SF ", MODIFIED));
diffs.add(makeDiff("META-INF/CERT.RSA", MODIFIED));
diffs.add(makeDiff("META-INF/MANIFEST.MF", MODIFIED));
diffs.add(makeDiff("classes.dex", MODIFIED));
diffs.add(makeDiff("classes02.dex", CREATED));
// This is fine as long as the later dex comparison is ok with it. Added classes will not need to be swapped.
new SwapVerifier().verify(diffs, false);
}
@Test
public void testChangedManifest() {
List<FileDiff> diffs = new ArrayList<>();
diffs.add(makeDiff("META-INF/CERT.SF ", MODIFIED));
diffs.add(makeDiff("META-INF/CERT.RSA", MODIFIED));
diffs.add(makeDiff("META-INF/MANIFEST.MF", MODIFIED));
diffs.add(makeDiff("AndroidManifest.xml", MODIFIED));
try {
new SwapVerifier().verify(diffs, false);
} catch (DeployerException e) {
Assert.assertEquals(DeployerException.Error.CANNOT_SWAP_MANIFEST, e.getError());
return;
}
Assert.fail("Exception not thrown");
}
@Test
public void testChangedUnrelatedManifest() {
List<FileDiff> diffs = new ArrayList<>();
diffs.add(makeDiff("META-INF/CERT.SF ", MODIFIED));
diffs.add(makeDiff("META-INF/CERT.RSA", MODIFIED));
diffs.add(makeDiff("META-INF/MANIFEST.MF", MODIFIED));
diffs.add(makeDiff("Not-The-Real-AndroidManifest.xml", MODIFIED));
try {
new SwapVerifier().verify(diffs, false);
} catch (DeployerException e) {
Assert.assertEquals(DeployerException.Error.CANNOT_SWAP_RESOURCE, e.getError());
return;
}
Assert.fail("Exception not thrown");
}
@Test
public void testChangedResourcesCodeSwapOnly() throws DeployerException {
List<FileDiff> diffs = new ArrayList<>();
diffs.add(makeDiff("META-INF/CERT.SF ", MODIFIED));
diffs.add(makeDiff("META-INF/CERT.RSA", MODIFIED));
diffs.add(makeDiff("META-INF/MANIFEST.MF", MODIFIED));
diffs.add(makeDiff("Not-The-Real-AndroidManifest.xml", MODIFIED));
new SwapVerifier().verify(diffs, true);
}
@Test
public void testCrashlyticsBuildIdCodeSwap() throws DeployerException {
List<FileDiff> diffs = new ArrayList<>();
diffs.add(makeDiff("META-INF/CERT.SF ", MODIFIED));
diffs.add(makeDiff("META-INF/CERT.RSA", MODIFIED));
diffs.add(makeDiff("META-INF/MANIFEST.MF", MODIFIED));
diffs.add(makeDiff("assets/crashlytics-build.properties", MODIFIED));
try {
new SwapVerifier().verify(diffs, false);
} catch (DeployerException e) {
Assert.assertEquals(
DeployerException.Error.CANNOT_SWAP_CRASHLYTICS_PROPERTY, e.getError());
return;
}
Assert.fail("Exception not thrown");
}
private FileDiff makeDiff(String name, FileDiff.Status status) {
ApkEntry left =
new ApkEntry(name, 0, Apk.builder().setName("apk1").setChecksum("abcd").build());
ApkEntry right =
new ApkEntry(name, 0, Apk.builder().setName("apk2").setChecksum("abcd").build());
return new FileDiff(left, right, status);
}
}