Skip to content

Commit 3bd762c

Browse files
committed
Add tests for CrashHandlerConfiguration native lib resolution
1 parent 36d6def commit 3bd762c

File tree

1 file changed

+152
-0
lines changed

1 file changed

+152
-0
lines changed
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package backtraceio.library.crashHandler;
2+
3+
import static org.junit.Assert.assertEquals;
4+
5+
import androidx.test.ext.junit.runners.AndroidJUnit4;
6+
import androidx.test.platform.app.InstrumentationRegistry;
7+
8+
import org.junit.Test;
9+
import org.junit.runner.RunWith;
10+
11+
import java.io.File;
12+
import java.io.FileOutputStream;
13+
import java.util.List;
14+
import java.util.zip.ZipEntry;
15+
import java.util.zip.ZipOutputStream;
16+
17+
import android.content.pm.ApplicationInfo;
18+
19+
import backtraceio.library.common.AbiHelper;
20+
import backtraceio.library.models.nativeHandler.CrashHandlerConfiguration;
21+
22+
@RunWith(AndroidJUnit4.class)
23+
public class CrashHandlerNativeLibraryResolutionTest {
24+
25+
private static final String LIB = "libbacktrace-native.so";
26+
27+
private File tempDir(String name) {
28+
File cache = InstrumentationRegistry.getInstrumentation()
29+
.getTargetContext().getCacheDir();
30+
File d = new File(cache, name);
31+
//noinspection ResultOfMethodCallIgnored
32+
d.mkdirs();
33+
return d;
34+
}
35+
36+
private File makeApk(File dir, String name, String abi, boolean includeLib) throws Exception {
37+
File apk = new File(dir, name);
38+
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(apk))) {
39+
if (includeLib) {
40+
String entry = "lib/" + abi + "/" + LIB;
41+
zos.putNextEntry(new ZipEntry(entry));
42+
zos.write(new byte[]{1, 2, 3, 4});
43+
zos.closeEntry();
44+
} else {
45+
zos.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
46+
zos.write(0);
47+
zos.closeEntry();
48+
}
49+
}
50+
return apk;
51+
}
52+
53+
private static String getEnv(List<String> env, String key) {
54+
String prefix = key + "=";
55+
for (String kv : env) {
56+
if (kv.startsWith(prefix)) return kv.substring(prefix.length());
57+
}
58+
return null;
59+
}
60+
61+
@Test
62+
public void usesSplitWhenBaseDoesNotContainLib() throws Exception {
63+
final String abi = AbiHelper.getCurrentAbi();
64+
File root = tempDir("bt_split_pref");
65+
File base = makeApk(root, "base.apk", abi, false);
66+
File split = makeApk(root, "split_config." + abi + ".apk", abi, true);
67+
68+
ApplicationInfo ai = new ApplicationInfo();
69+
ai.sourceDir = base.getAbsolutePath();
70+
ai.splitSourceDirs = new String[]{split.getAbsolutePath()};
71+
ai.nativeLibraryDir = "/nonexistent";
72+
73+
CrashHandlerConfiguration cfg = new CrashHandlerConfiguration();
74+
List<String> env = cfg.getCrashHandlerEnvironmentVariables(ai);
75+
76+
String libPath = getEnv(env, CrashHandlerConfiguration.BACKTRACE_CRASH_HANDLER);
77+
String apkLib = split.getAbsolutePath() + "!/lib/" + abi + "/" + LIB;
78+
assertEquals(apkLib, libPath);
79+
80+
String classPath = getEnv(env, "CLASSPATH");
81+
assertEquals(base.getAbsolutePath(), classPath);
82+
}
83+
84+
@Test
85+
public void prefersExtractedOverApkContainers() throws Exception {
86+
final String abi = AbiHelper.getCurrentAbi();
87+
File root = tempDir("bt_extracted_pref");
88+
File base = makeApk(root, "base.apk", abi, false);
89+
File split = makeApk(root, "split_config." + abi + ".apk", abi, true);
90+
91+
File nativeDir = new File(root, "lib/" + abi);
92+
//noinspection ResultOfMethodCallIgnored
93+
nativeDir.mkdirs();
94+
File extracted = new File(nativeDir, LIB);
95+
try (FileOutputStream fos = new FileOutputStream(extracted)) {
96+
fos.write(new byte[]{9, 9, 9});
97+
}
98+
99+
ApplicationInfo ai = new ApplicationInfo();
100+
ai.sourceDir = base.getAbsolutePath();
101+
ai.splitSourceDirs = new String[]{split.getAbsolutePath()};
102+
ai.nativeLibraryDir = nativeDir.getAbsolutePath();
103+
104+
CrashHandlerConfiguration cfg = new CrashHandlerConfiguration();
105+
List<String> env = cfg.getCrashHandlerEnvironmentVariables(ai);
106+
107+
String libPath = getEnv(env, CrashHandlerConfiguration.BACKTRACE_CRASH_HANDLER);
108+
assertEquals(extracted.getAbsolutePath(), libPath);
109+
110+
String classPath = getEnv(env, "CLASSPATH");
111+
assertEquals(base.getAbsolutePath(), classPath);
112+
}
113+
114+
@Test
115+
public void prefersBaseWhenBaseContainsLib() throws Exception {
116+
final String abi = AbiHelper.getCurrentAbi();
117+
File root = tempDir("bt_base_pref");
118+
File base = makeApk(root, "base.apk", abi, true);
119+
File split = makeApk(root, "split_config." + abi + ".apk", abi, true);
120+
121+
ApplicationInfo ai = new ApplicationInfo();
122+
ai.sourceDir = base.getAbsolutePath();
123+
ai.splitSourceDirs = new String[]{split.getAbsolutePath()};
124+
ai.nativeLibraryDir = "/nonexistent";
125+
126+
CrashHandlerConfiguration cfg = new CrashHandlerConfiguration();
127+
List<String> env = cfg.getCrashHandlerEnvironmentVariables(ai);
128+
129+
String libPath = getEnv(env, CrashHandlerConfiguration.BACKTRACE_CRASH_HANDLER);
130+
String apkLib = base.getAbsolutePath() + "!/lib/" + abi + "/" + LIB;
131+
assertEquals(apkLib, libPath);
132+
}
133+
134+
@Test
135+
public void fallsBackToBasePathWhenNoContainerHasLib() throws Exception {
136+
final String abi = AbiHelper.getCurrentAbi();
137+
File root = tempDir("bt_fallback");
138+
File base = makeApk(root, "base.apk", abi, false);
139+
140+
ApplicationInfo ai = new ApplicationInfo();
141+
ai.sourceDir = base.getAbsolutePath();
142+
ai.splitSourceDirs = null;
143+
ai.nativeLibraryDir = "/nonexistent";
144+
145+
CrashHandlerConfiguration cfg = new CrashHandlerConfiguration();
146+
List<String> env = cfg.getCrashHandlerEnvironmentVariables(ai);
147+
148+
String libPath = getEnv(env, CrashHandlerConfiguration.BACKTRACE_CRASH_HANDLER);
149+
String apkLib = base.getAbsolutePath() + "!/lib/" + abi + "/" + LIB;
150+
assertEquals(apkLib, libPath);
151+
}
152+
}

0 commit comments

Comments
 (0)