@@ -57,83 +57,13 @@ class TombstoneParserTest {
5757 " /data/app/~~gu-2hA9_Zg6tfIuDAbLpKA==/io.sentry.samples.android-MFqmKAMnl9AjNlHcO3mejA==/lib/arm64"
5858
5959 @Test
60- fun `parses a snapshot tombstone into Event` () {
61- val tombstoneStream =
62- GZIPInputStream (TombstoneParserTest ::class .java.getResourceAsStream(" /tombstone.pb.gz" ))
63- val parser = TombstoneParser (tombstoneStream, inAppIncludes, inAppExcludes, nativeLibraryDir)
64- val event = parser.parse()
65-
66- // top-level data
67- assertNotNull(event.eventId)
68- assertEquals(
69- " Fatal signal SIGSEGV (11), SEGV_MAPERR (1), pid = 21891 (io.sentry.samples.android)" ,
70- event.message!! .formatted,
71- )
72- assertEquals(" native" , event.platform)
73- assertEquals(" FATAL" , event.level!! .name)
74-
75- // exception
76- // we only track one native exception (no nesting, one crashed thread)
77- assertEquals(1 , event.exceptions!! .size)
78- val exception = event.exceptions!! [0 ]
79- assertEquals(" SIGSEGV" , exception.type)
80- assertEquals(" Segfault" , exception.value)
81- val crashedThreadId = exception.threadId
82- assertNotNull(crashedThreadId)
83-
84- val mechanism = exception.mechanism
85- assertEquals(" Tombstone" , mechanism!! .type)
86- assertEquals(false , mechanism.isHandled)
87- assertEquals(true , mechanism.synthetic)
88- assertEquals(" SIGSEGV" , mechanism.meta!! [" name" ])
89- assertEquals(11 , mechanism.meta!! [" number" ])
90- assertEquals(" SEGV_MAPERR" , mechanism.meta!! [" code_name" ])
91- assertEquals(1 , mechanism.meta!! [" code" ])
92-
93- // threads
94- assertEquals(62 , event.threads!! .size)
95- for (thread in event.threads!! ) {
96- assertNotNull(thread.id)
97- if (thread.id == crashedThreadId) {
98- assert (thread.isCrashed == true )
99- }
100- assert (thread.stacktrace!! .frames!! .isNotEmpty())
101-
102- for (frame in thread.stacktrace!! .frames!! ) {
103- assertNotNull(frame.function)
104- if (frame.platform == " java" ) {
105- // Java frames have module instead of package/instructionAddr
106- assertNotNull(frame.module)
107- } else {
108- assertNotNull(frame.`package`)
109- assertNotNull(frame.instructionAddr)
110- }
111-
112- if (thread.id == crashedThreadId) {
113- if (frame.isInApp!! ) {
114- assert (
115- frame.module?.startsWith(inAppIncludes[0 ]) == true ||
116- frame.function!! .startsWith(inAppIncludes[0 ]) ||
117- frame.`package`?.startsWith(nativeLibraryDir) == true
118- )
119- }
120- }
121- }
122-
123- assert (thread.stacktrace!! .registers!! .keys.containsAll(expectedRegisters))
124- }
60+ fun `parses tombstone into Event` () {
61+ assertTombstoneParsesCorrectly(" /tombstone.pb.gz" )
62+ }
12563
126- // debug-meta
127- assertEquals(352 , event.debugMeta!! .images!! .size)
128- for (image in event.debugMeta!! .images!! ) {
129- assertEquals(" elf" , image.type)
130- assertNotNull(image.debugId)
131- assertNotNull(image.codeId)
132- assertNotNull(image.codeFile)
133- val imageAddress = image.imageAddr!! .removePrefix(" 0x" ).toLong(16 )
134- assert (imageAddress > 0 )
135- assert (image.imageSize!! > 0 )
136- }
64+ @Test
65+ fun `parses tombstone_r8 with OAT frames into Event` () {
66+ assertTombstoneParsesCorrectly(" /tombstone_r8.pb.gz" )
13767 }
13868
13969 @Test
@@ -436,32 +366,13 @@ class TombstoneParserTest {
436366 }
437367
438368 @Test
439- fun `java frames snapshot test for all threads` () {
440- val tombstoneStream =
441- GZIPInputStream (TombstoneParserTest ::class .java.getResourceAsStream(" /tombstone.pb.gz" ))
442- val parser = TombstoneParser (tombstoneStream, inAppIncludes, inAppExcludes, nativeLibraryDir)
443- val event = parser.parse()
444-
445- val logger = mock<ILogger >()
446- val writer = StringWriter ()
447- val jsonWriter = JsonObjectWriter (writer, 100 )
448- jsonWriter.beginObject()
449- for (thread in event.threads!! ) {
450- val javaFrames = thread.stacktrace!! .frames!! .filter { it.platform == " java" }
451- if (javaFrames.isEmpty()) continue
452- jsonWriter.name(thread.id.toString())
453- jsonWriter.beginArray()
454- for (frame in javaFrames) {
455- frame.serialize(jsonWriter, logger)
456- }
457- jsonWriter.endArray()
458- }
459- jsonWriter.endObject()
460-
461- val actualJson = writer.toString()
462- val expectedJson = readGzippedResourceFile(" /tombstone_java_frames.json.gz" )
369+ fun `java frames snapshot test` () {
370+ assertJavaFramesSnapshot(" /tombstone.pb.gz" , " /tombstone_java_frames.json.gz" )
371+ }
463372
464- assertEquals(expectedJson, actualJson)
373+ @Test
374+ fun `tombstone_r8 java frames snapshot test` () {
375+ assertJavaFramesSnapshot(" /tombstone_r8.pb.gz" , " /tombstone_r8_java_frames.json.gz" )
465376 }
466377
467378 @Test
@@ -577,6 +488,102 @@ class TombstoneParserTest {
577488 return parser.parse()
578489 }
579490
491+ private fun assertTombstoneParsesCorrectly (tombstoneResource : String ) {
492+ val tombstoneStream =
493+ GZIPInputStream (TombstoneParserTest ::class .java.getResourceAsStream(tombstoneResource))
494+ val parser = TombstoneParser (tombstoneStream, inAppIncludes, inAppExcludes, nativeLibraryDir)
495+ val event = parser.parse()
496+
497+ // top-level data
498+ assertNotNull(event.eventId)
499+ assertNotNull(event.message!! .formatted)
500+ assertEquals(" native" , event.platform)
501+ assertEquals(" FATAL" , event.level!! .name)
502+
503+ // exception
504+ assertEquals(1 , event.exceptions!! .size)
505+ val exception = event.exceptions!! [0 ]
506+ assertNotNull(exception.type)
507+ val crashedThreadId = exception.threadId
508+ assertNotNull(crashedThreadId)
509+
510+ val mechanism = exception.mechanism
511+ assertNotNull(mechanism)
512+ assertEquals(" Tombstone" , mechanism.type)
513+ assertEquals(false , mechanism.isHandled)
514+ assertEquals(true , mechanism.synthetic)
515+
516+ // threads
517+ assert (event.threads!! .isNotEmpty())
518+ var hasCrashedThread = false
519+ for (thread in event.threads!! ) {
520+ assertNotNull(thread.id)
521+ if (thread.id == crashedThreadId) {
522+ assert (thread.isCrashed == true )
523+ hasCrashedThread = true
524+ }
525+ assert (thread.stacktrace!! .frames!! .isNotEmpty())
526+
527+ for (frame in thread.stacktrace!! .frames!! ) {
528+ assertNotNull(frame.function)
529+ if (frame.platform == " java" ) {
530+ assertNotNull(frame.module)
531+ assert (frame.function!! .isNotEmpty()) {
532+ " Java frame has empty function name in thread ${thread.id} "
533+ }
534+ assertNotNull(frame.isInApp)
535+ } else {
536+ assertNotNull(frame.`package`)
537+ assertNotNull(frame.instructionAddr)
538+ }
539+ }
540+
541+ assertNotNull(thread.stacktrace!! .registers)
542+ }
543+ assert (hasCrashedThread) { " No crashed thread found matching exception threadId" }
544+
545+ // debug-meta
546+ assertNotNull(event.debugMeta)
547+ assert (event.debugMeta!! .images!! .isNotEmpty())
548+ for (image in event.debugMeta!! .images!! ) {
549+ assertEquals(" elf" , image.type)
550+ assertNotNull(image.debugId)
551+ assertNotNull(image.codeId)
552+ assertNotNull(image.codeFile)
553+ val imageAddress = image.imageAddr!! .removePrefix(" 0x" ).toLong(16 )
554+ assert (imageAddress > 0 )
555+ assert (image.imageSize!! > 0 )
556+ }
557+ }
558+
559+ private fun assertJavaFramesSnapshot (tombstoneResource : String , snapshotResource : String ) {
560+ val tombstoneStream =
561+ GZIPInputStream (TombstoneParserTest ::class .java.getResourceAsStream(tombstoneResource))
562+ val parser = TombstoneParser (tombstoneStream, inAppIncludes, inAppExcludes, nativeLibraryDir)
563+ val event = parser.parse()
564+
565+ val logger = mock<ILogger >()
566+ val writer = StringWriter ()
567+ val jsonWriter = JsonObjectWriter (writer, 100 )
568+ jsonWriter.beginObject()
569+ for (thread in event.threads!! ) {
570+ val javaFrames = thread.stacktrace!! .frames!! .filter { it.platform == " java" }
571+ if (javaFrames.isEmpty()) continue
572+ jsonWriter.name(thread.id.toString())
573+ jsonWriter.beginArray()
574+ for (frame in javaFrames) {
575+ frame.serialize(jsonWriter, logger)
576+ }
577+ jsonWriter.endArray()
578+ }
579+ jsonWriter.endObject()
580+
581+ val actualJson = writer.toString()
582+ val expectedJson = readGzippedResourceFile(snapshotResource)
583+
584+ assertEquals(expectedJson, actualJson)
585+ }
586+
580587 private fun serializeDebugMeta (debugMeta : DebugMeta ): String {
581588 val logger = mock<ILogger >()
582589 val writer = StringWriter ()
0 commit comments