mirror of
https://github.com/revanced/Apktool.git
synced 2025-04-29 21:54:25 +02:00

* refactor: ApkDecoder & ApkBuilder overhaul A major rewrite of ApkDecoder and ApkBuilder classes to make them managable. Removed many instances of redundancy and improved syntaxed and indentation. Modifying the stock Apktool source to our needs have become too difficult, so I'm pushing the general (not specific to our needs) changes upstream. I'd change a lot more, but I wanted to make sure all tests pass as expected, despite some of them being wierd, outdated or unnecessary. This also fixes certain files in META-INF being lost during recompile when the -c/--copy-original option isn't used. This has been tweaked and tested for several days and I vouch for its stablity. * style: fix more redundancy * style: fix more redundancy * tweak: consistent case-sensitivity for cmd and options * refactor: tracking unknownFiles via apkInfo is redundant 1) We take advantage of the fact that doNotCompress already tracks uncompressed files, including those separated into "unknown". With this change the "unknownFiles" is simply ignored, so it's backward-compatible with existing decoded APK dirs. Tweaked a few tests to match the removal of "unknownFiles". 2) Passing doNotCompress to AAPT is redundant, Apktool extracts the temp APK packed by AAPT to build/apk and then repackages it anyway, so it serves no purpose. * refactor: fix minSdkVersion from baksmali + clean up more redundancy * Regression: minSdkVersion inferred from baksmali was not stored properly. * The arsc extension can be generalized for simplicity as seen in AOSP source. https://cs.android.com/android/platform/superproject/main/+/main:external/deqp/scripts/android/build_apk.py;l=644?q=apk%20pack&ss=android%2Fplatform%2Fsuperproject%2Fmain:external%2F Note: NO_COMPRESS_EXT_PATTERN only collapses paths to a common extension. It does NOT force these extensions to be always uncompressed. doNotCompress is the one determining files/extensions that should be uncompressed. (no funcionality was changed) * resourcesAreCompressed in apkInfo is redundant. It was only used in invokeAapt, but not ApkBuilder. Its value is also never set by Apktool, only read. Like with doNotCompress, passing any kind of compression rules to AAPT is pointless, since we don't use the temp APK packed by AAPT directly - it's extracted and repacked by ApkBuilder, where doNotCompress already determines whether resources.arsc should or should not be compressed in the final APK. (no funcionality was changed) * style: optional args come after required args * style: optional args come after required args * style: sdkInfo as a normal field for consistency * style: some formatting tweaks
583 lines
18 KiB
Java
583 lines
18 KiB
Java
/*
|
|
* Copyright (C) 2010 Ryszard Wiśniewski <brut.alll@gmail.com>
|
|
* Copyright (C) 2010 Connor Tumbleson <connor.tumbleson@gmail.com>
|
|
*
|
|
* 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
|
|
*
|
|
* https://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 brut.androlib.aapt1;
|
|
|
|
import brut.androlib.*;
|
|
import brut.androlib.apk.ApkInfo;
|
|
import brut.common.BrutException;
|
|
import brut.directory.ExtFile;
|
|
import brut.util.OS;
|
|
import brut.util.OSDetection;
|
|
import org.junit.AfterClass;
|
|
import org.junit.BeforeClass;
|
|
import org.junit.Test;
|
|
|
|
import javax.imageio.ImageIO;
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.util.Map;
|
|
|
|
import static org.junit.Assert.*;
|
|
import static org.junit.Assume.assumeTrue;
|
|
|
|
public class BuildAndDecodeTest extends BaseTest {
|
|
|
|
@BeforeClass
|
|
public static void beforeClass() throws Exception {
|
|
TestUtils.cleanFrameworkFile();
|
|
|
|
sTmpDir = new ExtFile(OS.createTempDirectory());
|
|
sTestOrigDir = new ExtFile(sTmpDir, "testapp-orig");
|
|
sTestNewDir = new ExtFile(sTmpDir, "testapp-new");
|
|
LOGGER.info("Unpacking testapp...");
|
|
TestUtils.copyResourceDir(BuildAndDecodeTest.class, "aapt1/testapp/", sTestOrigDir);
|
|
|
|
LOGGER.info("Building testapp.apk...");
|
|
ExtFile testApk = new ExtFile(sTmpDir, "testapp.apk");
|
|
Config config = Config.getDefaultConfig();
|
|
config.aaptVersion = 1;
|
|
new ApkBuilder(sTestOrigDir, config).build(testApk);
|
|
|
|
LOGGER.info("Decoding testapp.apk...");
|
|
ApkDecoder apkDecoder = new ApkDecoder(testApk);
|
|
apkDecoder.decode(sTestNewDir);
|
|
}
|
|
|
|
@AfterClass
|
|
public static void afterClass() throws BrutException {
|
|
OS.rmdir(sTmpDir);
|
|
}
|
|
|
|
@Test
|
|
public void buildAndDecodeTest() {
|
|
assertTrue(sTestNewDir.isDirectory());
|
|
}
|
|
|
|
@Test
|
|
public void manifestTaggingNotSupressed() throws BrutException {
|
|
compareXmlFiles("AndroidManifest.xml");
|
|
}
|
|
|
|
@Test
|
|
public void valuesAnimsTest() throws BrutException {
|
|
compareValuesFiles("values-mcc001/anims.xml");
|
|
}
|
|
|
|
@Test
|
|
public void valuesArraysTest() throws BrutException {
|
|
compareValuesFiles("values-mcc001/arrays.xml");
|
|
}
|
|
|
|
@Test
|
|
public void valuesArraysCastingTest() throws BrutException {
|
|
compareValuesFiles("values-mcc002/arrays.xml");
|
|
compareValuesFiles("values-mcc003/arrays.xml");
|
|
}
|
|
|
|
@Test
|
|
public void valuesAttrsTest() throws BrutException {
|
|
compareValuesFiles("values/attrs.xml");
|
|
}
|
|
|
|
@Test
|
|
public void valuesBoolsTest() throws BrutException {
|
|
compareValuesFiles("values-mcc001/bools.xml");
|
|
}
|
|
|
|
@Test
|
|
public void valuesColorsTest() throws BrutException {
|
|
compareValuesFiles("values-mcc001/colors.xml");
|
|
}
|
|
|
|
@Test
|
|
public void bug702Test() throws BrutException {
|
|
compareValuesFiles("values-mcc001-mnc00/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void valuesDimensTest() throws BrutException {
|
|
compareValuesFiles("values-mcc001/dimens.xml");
|
|
}
|
|
|
|
@Test
|
|
public void valuesDrawablesTest() throws BrutException {
|
|
compareValuesFiles("values-mcc001/drawables.xml");
|
|
}
|
|
|
|
@Test
|
|
public void valuesIdsTest() throws BrutException {
|
|
compareValuesFiles("values-mcc001/ids.xml");
|
|
}
|
|
|
|
@Test
|
|
public void valuesIntegersTest() throws BrutException {
|
|
compareValuesFiles("values-mcc001/integers.xml");
|
|
}
|
|
|
|
@Test
|
|
public void valuesLayoutsTest() throws BrutException {
|
|
compareValuesFiles("values-mcc001/layouts.xml");
|
|
}
|
|
|
|
@Test
|
|
public void xmlPluralsTest() throws BrutException {
|
|
compareValuesFiles("values-mcc001/plurals.xml");
|
|
}
|
|
|
|
@Test
|
|
public void miuiRegressionTest() throws BrutException {
|
|
compareValuesFiles("values-godzillaui/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void valuesStringsTest() throws BrutException {
|
|
compareValuesFiles("values-mcc001/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void valuesStylesTest() throws BrutException {
|
|
compareValuesFiles("values-mcc001/styles.xml");
|
|
}
|
|
|
|
@Test
|
|
public void valuesReferencesTest() throws BrutException {
|
|
compareValuesFiles("values-mcc002/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void valuesExtraLongTest() throws BrutException {
|
|
compareValuesFiles("values-en/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void valuesExtraLongExactLengthTest() throws BrutException {
|
|
Map<String, String> strs = TestUtils.parseStringsXml(new File(sTestNewDir, "res/values-en/strings.xml"));
|
|
|
|
// long_string6 should be exactly 0x8888 chars of "a"
|
|
// the valuesExtraLongTest() should handle this
|
|
// but such an edge case, want a specific test
|
|
String aaaa = strs.get("long_string6");
|
|
assertEquals(0x8888, aaaa.length());
|
|
}
|
|
|
|
@Test
|
|
public void storedMp3FilesAreNotCompressedTest() throws BrutException {
|
|
ExtFile extFile = new ExtFile(sTmpDir, "testapp.apk");
|
|
Integer built = extFile.getDirectory().getCompressionLevel("res/raw/rain.mp3");
|
|
assertEquals(Integer.valueOf(0), built);
|
|
}
|
|
|
|
@Test
|
|
public void crossTypeTest() throws BrutException {
|
|
compareValuesFiles("values-mcc003/strings.xml");
|
|
compareValuesFiles("values-mcc003/integers.xml");
|
|
compareValuesFiles("values-mcc003/bools.xml");
|
|
}
|
|
|
|
@Test
|
|
public void xmlLiteralsTest() throws BrutException {
|
|
compareXmlFiles("res/xml/literals.xml");
|
|
}
|
|
|
|
@Test
|
|
public void xmlReferencesTest() throws BrutException {
|
|
compareXmlFiles("res/xml/references.xml");
|
|
}
|
|
|
|
@Test
|
|
public void xmlAccessibilityTest() throws BrutException {
|
|
compareXmlFiles("res/xml/accessibility_service_config.xml");
|
|
}
|
|
|
|
@Test
|
|
public void xmlXsdFileTest() throws BrutException {
|
|
compareXmlFiles("res/xml/ww_box_styles_schema.xsd");
|
|
}
|
|
|
|
@Test
|
|
public void xmlIdsEmptyTest() throws BrutException {
|
|
compareXmlFiles("res/values/ids.xml");
|
|
}
|
|
|
|
@Test
|
|
public void xmlReferenceAttributeTest() throws BrutException {
|
|
compareXmlFiles("res/layout/issue1040.xml");
|
|
}
|
|
|
|
@Test
|
|
public void xmlCustomAttributeTest() throws BrutException {
|
|
compareXmlFiles("res/layout/issue1063.xml");
|
|
}
|
|
|
|
@Test
|
|
public void xmlSmallNumbersDontEscapeTest() throws BrutException {
|
|
compareXmlFiles("res/layout/issue1130.xml");
|
|
}
|
|
|
|
@Test
|
|
public void xmlUniformAutoTextTest() throws BrutException {
|
|
compareXmlFiles("res/layout/issue1674.xml");
|
|
}
|
|
|
|
@Test(expected = AssertionError.class)
|
|
public void xmlFillParentBecomesMatchTest() throws BrutException {
|
|
compareXmlFiles("res/layout/issue1274.xml");
|
|
}
|
|
|
|
@Test
|
|
public void xmlCustomAttrsNotAndroidTest() throws BrutException {
|
|
compareXmlFiles("res/layout/issue1157.xml");
|
|
}
|
|
|
|
@Test
|
|
public void qualifiersTest() throws BrutException {
|
|
compareValuesFiles("values-mcc004-mnc4-en-rUS-ldrtl-sw100dp-w200dp-h300dp"
|
|
+ "-long-round-highdr-land-desk-night-xhdpi-finger-keyssoft-12key"
|
|
+ "-navhidden-dpad-v26/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void shortendedMncTest() throws BrutException {
|
|
compareValuesFiles("values-mcc001-mnc1/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void shortMncHtcTest() throws BrutException {
|
|
compareValuesFiles("values-mnc1/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void shortMncv2Test() throws BrutException {
|
|
compareValuesFiles("values-mcc238-mnc6/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void longMncTest() throws BrutException {
|
|
compareValuesFiles("values-mcc238-mnc870/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void anyDpiTest() throws BrutException {
|
|
compareValuesFiles("values-watch/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void packed3CharsTest() throws BrutException {
|
|
compareValuesFiles("values-ast-rES/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void rightToLeftTest() throws BrutException {
|
|
compareValuesFiles("values-ldrtl/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void scriptBcp47Test() throws BrutException {
|
|
compareValuesFiles("values-b+en+Latn+US/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void threeLetterLangBcp47Test() throws BrutException {
|
|
compareValuesFiles("values-ast/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void androidOStringTest() throws BrutException {
|
|
compareValuesFiles("values-ast/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void twoLetterNotHandledAsBcpTest() {
|
|
checkFolderExists("res/values-fr");
|
|
}
|
|
|
|
@Test
|
|
public void twoLetterLangBcp47Test() throws BrutException {
|
|
compareValuesFiles("values-en-rUS/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void variantBcp47Test() throws BrutException {
|
|
compareValuesFiles("values-b+en+US+POSIX/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void fourpartBcp47Test() throws BrutException {
|
|
compareValuesFiles("values-b+ast+Latn+IT+AREVELA/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void RegionLocaleBcp47Test() throws BrutException {
|
|
compareValuesFiles("values-b+en+Latn+419/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void numericalRegionBcp47Test() throws BrutException {
|
|
compareValuesFiles("values-b+eng+419/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void api23ConfigurationsTest() throws BrutException {
|
|
compareValuesFiles("values-round/strings.xml");
|
|
compareValuesFiles("values-notround/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void api26ConfigurationsTest() throws BrutException {
|
|
compareValuesFiles("values-widecg-v26/strings.xml");
|
|
compareValuesFiles("values-lowdr-v26/strings.xml");
|
|
compareValuesFiles("values-nowidecg-v26/strings.xml");
|
|
compareValuesFiles("values-vrheadset-v26/strings.xml");
|
|
}
|
|
|
|
@Test
|
|
public void fontTest() throws BrutException {
|
|
File fontXml = new File((sTestNewDir + "/res/font"), "lobster.xml");
|
|
File fontFile = new File((sTestNewDir + "/res/font"), "lobster_regular.otf");
|
|
|
|
// Per #1662, ensure font file is not encoded.
|
|
assertTrue(fontXml.isFile());
|
|
compareXmlFiles("/res/font/lobster.xml");
|
|
|
|
// If we properly skipped decoding the font (otf) file, this file should not exist
|
|
assertFalse((new File((sTestNewDir + "/res/values"), "fonts.xml")).isFile());
|
|
assertTrue(fontFile.isFile());
|
|
}
|
|
|
|
@Test
|
|
public void drawableNoDpiTest() throws BrutException, IOException {
|
|
compareResFolder("drawable-nodpi");
|
|
}
|
|
|
|
@Test
|
|
public void drawableAnyDpiTest() throws BrutException, IOException {
|
|
compareResFolder("drawable-anydpi");
|
|
}
|
|
|
|
@Test
|
|
public void drawableNumberedDpiTest() throws BrutException, IOException {
|
|
compareResFolder("drawable-534dpi");
|
|
}
|
|
|
|
@Test
|
|
public void drawableLdpiTest() throws BrutException, IOException {
|
|
compareResFolder("drawable-ldpi");
|
|
}
|
|
|
|
@Test
|
|
public void drawableMdpiTest() throws BrutException, IOException {
|
|
compareResFolder("drawable-mdpi");
|
|
}
|
|
|
|
@Test
|
|
public void drawableTvdpiTest() throws BrutException, IOException {
|
|
compareResFolder("drawable-tvdpi");
|
|
}
|
|
|
|
@Test
|
|
public void drawableXhdpiTest() throws BrutException, IOException {
|
|
compareResFolder("drawable-xhdpi");
|
|
}
|
|
|
|
@Test
|
|
public void ninePatchImageColorTest() throws IOException {
|
|
char slash = File.separatorChar;
|
|
String location = slash + "res" + slash + "drawable-xhdpi" + slash;
|
|
|
|
File control = new File((sTestOrigDir + location), "9patch.9.png");
|
|
File test = new File((sTestNewDir + location), "9patch.9.png");
|
|
|
|
BufferedImage controlImage = ImageIO.read(control);
|
|
BufferedImage testImage = ImageIO.read(test);
|
|
|
|
// lets start with 0,0 - empty
|
|
assertEquals(controlImage.getRGB(0, 0), testImage.getRGB(0, 0));
|
|
|
|
// then with 30, 0 - black
|
|
assertEquals(controlImage.getRGB(30, 0), testImage.getRGB(30, 0));
|
|
|
|
// then 30, 30 - blue
|
|
assertEquals(controlImage.getRGB(30, 30), testImage.getRGB(30, 30));
|
|
}
|
|
|
|
@Test
|
|
public void issue1508Test() throws IOException {
|
|
char slash = File.separatorChar;
|
|
String location = slash + "res" + slash + "drawable-xhdpi" + slash;
|
|
|
|
File control = new File((sTestOrigDir + location), "btn_zoom_up_normal.9.png");
|
|
File test = new File((sTestNewDir + location), "btn_zoom_up_normal.9.png");
|
|
|
|
BufferedImage controlImage = ImageIO.read(control);
|
|
BufferedImage testImage = ImageIO.read(test);
|
|
|
|
// 0, 0 = clear
|
|
assertEquals(controlImage.getRGB(0, 0), testImage.getRGB(0, 0));
|
|
|
|
// 30, 0 = black line
|
|
assertEquals(controlImage.getRGB(0, 30), testImage.getRGB(0, 30));
|
|
|
|
// 30, 30 = greyish button
|
|
assertEquals(controlImage.getRGB(30, 30), testImage.getRGB(30, 30));
|
|
}
|
|
|
|
@Test
|
|
public void issue1511Test() throws IOException {
|
|
char slash = File.separatorChar;
|
|
String location = slash + "res" + slash + "drawable-xxhdpi" + slash;
|
|
|
|
File control = new File((sTestOrigDir + location), "textfield_activated_holo_dark.9.png");
|
|
File test = new File((sTestNewDir + location), "textfield_activated_holo_dark.9.png");
|
|
|
|
BufferedImage controlImage = ImageIO.read(control);
|
|
BufferedImage testImage = ImageIO.read(test);
|
|
|
|
// Check entire image as we cannot mess this up
|
|
final int w = controlImage.getWidth(),
|
|
h = controlImage.getHeight();
|
|
|
|
final int[] controlImageGrid = controlImage.getRGB(0, 0, w, h, null, 0, w);
|
|
final int[] testImageGrid = testImage.getRGB(0, 0, w, h, null, 0, w);
|
|
|
|
for (int i = 0; i < controlImageGrid.length; i++) {
|
|
assertEquals("Image lost Optical Bounds at i = " + i, controlImageGrid[i], testImageGrid[i]);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void robust9patchTest() throws IOException {
|
|
String[] ninePatches = {"ic_notification_overlay.9.png", "status_background.9.png",
|
|
"search_bg_transparent.9.png", "screenshot_panel.9.png", "recents_lower_gradient.9.png"};
|
|
|
|
char slash = File.separatorChar;
|
|
String location = slash + "res" + slash + "drawable-xxhdpi" + slash;
|
|
|
|
for (String ninePatch : ninePatches) {
|
|
File control = new File((sTestOrigDir + location), ninePatch);
|
|
File test = new File((sTestNewDir + location), ninePatch);
|
|
|
|
BufferedImage controlImage = ImageIO.read(control);
|
|
BufferedImage testImage = ImageIO.read(test);
|
|
|
|
int w = controlImage.getWidth(), h = controlImage.getHeight();
|
|
|
|
// Check the entire horizontal line
|
|
for (int i = 1; i < w; i++) {
|
|
if (isTransparent(controlImage.getRGB(i, 0))) {
|
|
assertTrue(isTransparent(testImage.getRGB(i, 0)));
|
|
} else {
|
|
assertEquals("Image lost npTc chunk on image " + ninePatch + " at (x, y) (" + i + "," + 0 + ")",
|
|
controlImage.getRGB(i, 0), testImage.getRGB(i, 0));
|
|
}
|
|
}
|
|
|
|
// Check the entire vertical line
|
|
for (int i = 1; i < h; i++) {
|
|
if (isTransparent(controlImage.getRGB(0, i))) {
|
|
assertTrue(isTransparent(testImage.getRGB(0, i)));
|
|
} else {
|
|
assertEquals("Image lost npTc chunk on image " + ninePatch + " at (x, y) (" + 0 + "," + i + ")",
|
|
controlImage.getRGB(0, i), testImage.getRGB(0, i));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void confirmZeroByteFileExtensionIsNotStored() throws BrutException {
|
|
ApkInfo apkInfo = ApkInfo.load(sTestNewDir);
|
|
|
|
for (String item : apkInfo.doNotCompress) {
|
|
assertNotEquals("jpg", item);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void confirmZeroByteFileIsStored() throws BrutException {
|
|
ApkInfo apkInfo = ApkInfo.load(sTestNewDir);
|
|
assertTrue(apkInfo.doNotCompress.contains("assets/0byte_file.jpg"));
|
|
}
|
|
|
|
@Test
|
|
public void drawableXxhdpiTest() throws BrutException, IOException {
|
|
compareResFolder("drawable-xxhdpi");
|
|
}
|
|
|
|
@Test
|
|
public void drawableQualifierXxhdpiTest() throws BrutException, IOException {
|
|
compareResFolder("drawable-xxhdpi-v4");
|
|
}
|
|
|
|
@Test
|
|
public void drawableXxxhdpiTest() throws BrutException, IOException {
|
|
compareResFolder("drawable-xxxhdpi");
|
|
}
|
|
|
|
@Test
|
|
public void resRawTest() throws BrutException, IOException {
|
|
compareResFolder("raw");
|
|
}
|
|
|
|
@Test
|
|
public void libsTest() throws BrutException, IOException {
|
|
compareLibsFolder("libs");
|
|
compareLibsFolder("lib");
|
|
}
|
|
|
|
@Test
|
|
public void unknownFolderTest() throws BrutException, IOException {
|
|
compareUnknownFiles();
|
|
}
|
|
|
|
@Test
|
|
public void fileAssetTest() throws BrutException, IOException {
|
|
compareAssetsFolder("txt");
|
|
}
|
|
|
|
@Test
|
|
public void unicodeAssetTest() throws BrutException, IOException {
|
|
assumeTrue(! OSDetection.isWindows());
|
|
compareAssetsFolder("unicode-txt");
|
|
}
|
|
|
|
@Test
|
|
public void multipleDexTest() throws BrutException, IOException {
|
|
compareBinaryFolder("/smali_classes2", false);
|
|
compareBinaryFolder("/smali_classes3", false);
|
|
|
|
File classes2Dex = new File(sTestOrigDir, "build/apk/classes2.dex");
|
|
File classes3Dex = new File(sTestOrigDir, "build/apk/classes3.dex");
|
|
|
|
assertTrue(classes2Dex.isFile());
|
|
assertTrue(classes3Dex.isFile());
|
|
}
|
|
|
|
@Test
|
|
public void singleDexTest() throws BrutException, IOException {
|
|
compareBinaryFolder("/smali", false);
|
|
|
|
File classesDex = new File(sTestOrigDir, "build/apk/classes.dex");
|
|
assertTrue(classesDex.isFile());
|
|
}
|
|
|
|
@Test
|
|
public void confirmKotlinFolderPersistsTest() {
|
|
checkFolderExists("/kotlin");
|
|
}
|
|
}
|