Skip to content

Commit 5c9e199

Browse files
authored
Merge f52eb9c into 10dd21c
2 parents 10dd21c + f52eb9c commit 5c9e199

4 files changed

Lines changed: 139 additions & 124 deletions

File tree

sentry-android-core/src/test/java/io/sentry/android/core/internal/tombstone/TombstoneParserTest.kt

Lines changed: 131 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -19,41 +19,40 @@ import org.mockito.kotlin.mock
1919
class TombstoneParserTest {
2020
val expectedRegisters =
2121
setOf(
22+
"x0",
23+
"x1",
24+
"x2",
25+
"x3",
26+
"x4",
27+
"x5",
28+
"x6",
29+
"x7",
2230
"x8",
2331
"x9",
24-
"esr",
25-
"lr",
26-
"pst",
2732
"x10",
28-
"x12",
2933
"x11",
30-
"x14",
34+
"x12",
3135
"x13",
32-
"x16",
36+
"x14",
3337
"x15",
34-
"sp",
35-
"x18",
38+
"x16",
3639
"x17",
40+
"x18",
3741
"x19",
38-
"pc",
39-
"x21",
4042
"x20",
41-
"x0",
42-
"x23",
43-
"x1",
43+
"x21",
4444
"x22",
45-
"x2",
46-
"x25",
47-
"x3",
45+
"x23",
4846
"x24",
49-
"x4",
50-
"x27",
51-
"x5",
47+
"x25",
5248
"x26",
53-
"x6",
54-
"x29",
55-
"x7",
49+
"x27",
5650
"x28",
51+
"x29",
52+
"lr",
53+
"sp",
54+
"pc",
55+
"pst",
5756
)
5857

5958
val inAppIncludes = arrayListOf("io.sentry.samples.android")
@@ -64,84 +63,13 @@ class TombstoneParserTest {
6463
val parser = TombstoneParser(inAppIncludes, inAppExcludes, nativeLibraryDir)
6564

6665
@Test
67-
fun `parses a snapshot tombstone into Event`() {
68-
val tombstoneStream =
69-
GZIPInputStream(TombstoneParserTest::class.java.getResourceAsStream("/tombstone.pb.gz"))
70-
val streamParser =
71-
TombstoneParser(tombstoneStream, inAppIncludes, inAppExcludes, nativeLibraryDir)
72-
val event = streamParser.parse()
73-
74-
// top-level data
75-
assertNotNull(event.eventId)
76-
assertEquals(
77-
"Fatal signal SIGSEGV (11), SEGV_MAPERR (1), pid = 21891 (io.sentry.samples.android)",
78-
event.message!!.formatted,
79-
)
80-
assertEquals("native", event.platform)
81-
assertEquals("FATAL", event.level!!.name)
82-
83-
// exception
84-
// we only track one native exception (no nesting, one crashed thread)
85-
assertEquals(1, event.exceptions!!.size)
86-
val exception = event.exceptions!![0]
87-
assertEquals("SIGSEGV", exception.type)
88-
assertEquals("Segfault", exception.value)
89-
val crashedThreadId = exception.threadId
90-
assertNotNull(crashedThreadId)
91-
92-
val mechanism = exception.mechanism
93-
assertEquals("Tombstone", mechanism!!.type)
94-
assertEquals(false, mechanism.isHandled)
95-
assertEquals(true, mechanism.synthetic)
96-
assertEquals("SIGSEGV", mechanism.meta!!["name"])
97-
assertEquals(11, mechanism.meta!!["number"])
98-
assertEquals("SEGV_MAPERR", mechanism.meta!!["code_name"])
99-
assertEquals(1, mechanism.meta!!["code"])
100-
101-
// threads
102-
assertEquals(62, event.threads!!.size)
103-
for (thread in event.threads!!) {
104-
assertNotNull(thread.id)
105-
if (thread.id == crashedThreadId) {
106-
assert(thread.isCrashed == true)
107-
}
108-
assert(thread.stacktrace!!.frames!!.isNotEmpty())
109-
110-
for (frame in thread.stacktrace!!.frames!!) {
111-
assertNotNull(frame.function)
112-
if (frame.platform == "java") {
113-
// Java frames have module instead of package/instructionAddr
114-
assertNotNull(frame.module)
115-
} else {
116-
assertNotNull(frame.`package`)
117-
assertNotNull(frame.instructionAddr)
118-
}
119-
120-
if (thread.id == crashedThreadId) {
121-
if (frame.isInApp!!) {
122-
assert(
123-
frame.module?.startsWith(inAppIncludes[0]) == true ||
124-
frame.function!!.startsWith(inAppIncludes[0]) ||
125-
frame.`package`?.startsWith(nativeLibraryDir) == true
126-
)
127-
}
128-
}
129-
}
130-
131-
assert(thread.stacktrace!!.registers!!.keys.containsAll(expectedRegisters))
132-
}
66+
fun `parses tombstone into Event`() {
67+
assertTombstoneParsesCorrectly("/tombstone.pb.gz")
68+
}
13369

134-
// debug-meta
135-
assertEquals(352, event.debugMeta!!.images!!.size)
136-
for (image in event.debugMeta!!.images!!) {
137-
assertEquals("elf", image.type)
138-
assertNotNull(image.debugId)
139-
assertNotNull(image.codeId)
140-
assertNotNull(image.codeFile)
141-
val imageAddress = image.imageAddr!!.removePrefix("0x").toLong(16)
142-
assert(imageAddress > 0)
143-
assert(image.imageSize!! > 0)
144-
}
70+
@Test
71+
fun `parses tombstone_r8 with OAT frames into Event`() {
72+
assertTombstoneParsesCorrectly("/tombstone_r8.pb.gz")
14573
}
14674

14775
@Test
@@ -425,32 +353,13 @@ class TombstoneParserTest {
425353
}
426354

427355
@Test
428-
fun `java frames snapshot test for all threads`() {
429-
val tombstoneStream =
430-
GZIPInputStream(TombstoneParserTest::class.java.getResourceAsStream("/tombstone.pb.gz"))
431-
val parser = TombstoneParser(tombstoneStream, inAppIncludes, inAppExcludes, nativeLibraryDir)
432-
val event = parser.parse()
433-
434-
val logger = mock<ILogger>()
435-
val writer = StringWriter()
436-
val jsonWriter = JsonObjectWriter(writer, 100)
437-
jsonWriter.beginObject()
438-
for (thread in event.threads!!) {
439-
val javaFrames = thread.stacktrace!!.frames!!.filter { it.platform == "java" }
440-
if (javaFrames.isEmpty()) continue
441-
jsonWriter.name(thread.id.toString())
442-
jsonWriter.beginArray()
443-
for (frame in javaFrames) {
444-
frame.serialize(jsonWriter, logger)
445-
}
446-
jsonWriter.endArray()
447-
}
448-
jsonWriter.endObject()
449-
450-
val actualJson = writer.toString()
451-
val expectedJson = readGzippedResourceFile("/tombstone_java_frames.json.gz")
356+
fun `java frames snapshot test`() {
357+
assertJavaFramesSnapshot("/tombstone.pb.gz", "/tombstone_java_frames.json.gz")
358+
}
452359

453-
assertEquals(expectedJson, actualJson)
360+
@Test
361+
fun `tombstone_r8 java frames snapshot test`() {
362+
assertJavaFramesSnapshot("/tombstone_r8.pb.gz", "/tombstone_r8_java_frames.json.gz")
454363
}
455364

456365
@Test
@@ -566,6 +475,104 @@ class TombstoneParserTest {
566475
return parser.parse()
567476
}
568477

478+
private fun assertTombstoneParsesCorrectly(tombstoneResource: String) {
479+
val tombstoneStream =
480+
GZIPInputStream(TombstoneParserTest::class.java.getResourceAsStream(tombstoneResource))
481+
val parser = TombstoneParser(tombstoneStream, inAppIncludes, inAppExcludes, nativeLibraryDir)
482+
val event = parser.parse()
483+
484+
// top-level data
485+
assertNotNull(event.eventId)
486+
assertNotNull(event.message!!.formatted)
487+
assertEquals("native", event.platform)
488+
assertEquals("FATAL", event.level!!.name)
489+
490+
// exception
491+
assertEquals(1, event.exceptions!!.size)
492+
val exception = event.exceptions!![0]
493+
assertNotNull(exception.type)
494+
val crashedThreadId = exception.threadId
495+
assertNotNull(crashedThreadId)
496+
497+
val mechanism = exception.mechanism
498+
assertNotNull(mechanism)
499+
assertEquals("Tombstone", mechanism.type)
500+
assertEquals(false, mechanism.isHandled)
501+
assertEquals(true, mechanism.synthetic)
502+
503+
// threads
504+
assert(event.threads!!.isNotEmpty())
505+
var hasCrashedThread = false
506+
for (thread in event.threads!!) {
507+
assertNotNull(thread.id)
508+
if (thread.id == crashedThreadId) {
509+
assert(thread.isCrashed == true)
510+
hasCrashedThread = true
511+
}
512+
assert(thread.stacktrace!!.frames!!.isNotEmpty())
513+
514+
for (frame in thread.stacktrace!!.frames!!) {
515+
assertNotNull(frame.function)
516+
if (frame.platform == "java") {
517+
assertNotNull(frame.module)
518+
assert(frame.function!!.isNotEmpty()) {
519+
"Java frame has empty function name in thread ${thread.id}"
520+
}
521+
assertNotNull(frame.isInApp)
522+
} else {
523+
assertNotNull(frame.`package`)
524+
assertNotNull(frame.instructionAddr)
525+
}
526+
}
527+
528+
assert(thread.stacktrace!!.registers!!.keys.containsAll(expectedRegisters)) {
529+
"Thread ${thread.id} is missing registers: ${expectedRegisters - thread.stacktrace!!.registers!!.keys}"
530+
}
531+
}
532+
assert(hasCrashedThread) { "No crashed thread found matching exception threadId" }
533+
534+
// debug-meta
535+
assertNotNull(event.debugMeta)
536+
assert(event.debugMeta!!.images!!.isNotEmpty())
537+
for (image in event.debugMeta!!.images!!) {
538+
assertEquals("elf", image.type)
539+
assertNotNull(image.debugId)
540+
assertNotNull(image.codeId)
541+
assertNotNull(image.codeFile)
542+
val imageAddress = image.imageAddr!!.removePrefix("0x").toLong(16)
543+
assert(imageAddress > 0)
544+
assert(image.imageSize!! > 0)
545+
}
546+
}
547+
548+
private fun assertJavaFramesSnapshot(tombstoneResource: String, snapshotResource: String) {
549+
val tombstoneStream =
550+
GZIPInputStream(TombstoneParserTest::class.java.getResourceAsStream(tombstoneResource))
551+
val parser = TombstoneParser(tombstoneStream, inAppIncludes, inAppExcludes, nativeLibraryDir)
552+
val event = parser.parse()
553+
554+
val logger = mock<ILogger>()
555+
val writer = StringWriter()
556+
val jsonWriter = JsonObjectWriter(writer, 100)
557+
jsonWriter.beginObject()
558+
for (thread in event.threads!!) {
559+
val javaFrames = thread.stacktrace!!.frames!!.filter { it.platform == "java" }
560+
if (javaFrames.isEmpty()) continue
561+
jsonWriter.name(thread.id.toString())
562+
jsonWriter.beginArray()
563+
for (frame in javaFrames) {
564+
frame.serialize(jsonWriter, logger)
565+
}
566+
jsonWriter.endArray()
567+
}
568+
jsonWriter.endObject()
569+
570+
val actualJson = writer.toString()
571+
val expectedJson = readGzippedResourceFile(snapshotResource)
572+
573+
assertEquals(expectedJson, actualJson)
574+
}
575+
569576
private fun serializeDebugMeta(debugMeta: DebugMeta): String {
570577
val logger = mock<ILogger>()
571578
val writer = StringWriter()
64.4 KB
Binary file not shown.
Binary file not shown.

sentry-samples/sentry-samples-android/build.gradle.kts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ plugins {
77
id("com.android.application")
88
alias(libs.plugins.kotlin.android)
99
alias(libs.plugins.kotlin.compose)
10+
alias(libs.plugins.sentry)
1011
}
1112

1213
android {
@@ -116,6 +117,13 @@ android {
116117
@Suppress("UnstableApiUsage") packagingOptions { jniLibs { useLegacyPackaging = true } }
117118
}
118119

120+
sentry {
121+
autoUploadProguardMapping = false
122+
autoUploadNativeSymbols = false
123+
autoUploadSourceContext = false
124+
autoInstallation { enabled = false }
125+
}
126+
119127
dependencies {
120128
implementation(
121129
kotlin(Config.kotlinStdLib, org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION)

0 commit comments

Comments
 (0)