test_plugin.py 66 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232
  1. import zipfile
  2. from io import BytesIO
  3. from uuid import uuid4
  4. import pytest
  5. from django.core.files.uploadedfile import SimpleUploadedFile
  6. from django.urls import reverse
  7. from sentry.models.debugfile import ProjectDebugFile
  8. from sentry.models.files.file import File
  9. from sentry.testutils.cases import TransactionTestCase
  10. from sentry.testutils.helpers.datetime import before_now, iso_format
  11. from sentry.testutils.relay import RelayStoreHelper
  12. from sentry.utils import json
  13. PROGUARD_UUID = "6dc7fdb0-d2fb-4c8e-9d6b-bb1aa98929b1"
  14. PROGUARD_SOURCE = b"""\
  15. org.slf4j.helpers.Util$ClassContextSecurityManager -> org.a.b.g$a:
  16. 65:65:void <init>() -> <init>
  17. 67:67:java.lang.Class[] getClassContext() -> a
  18. 69:69:java.lang.Class[] getExtraClassContext() -> a
  19. 65:65:void <init>(org.slf4j.helpers.Util$1) -> <init>
  20. """
  21. PROGUARD_INLINE_UUID = "d748e578-b3d1-5be5-b0e5-a42e8c9bf8e0"
  22. PROGUARD_INLINE_SOURCE = b"""\
  23. # compiler: R8
  24. # compiler_version: 2.0.74
  25. # min_api: 16
  26. # pg_map_id: 5b46fdc
  27. # common_typos_disable
  28. $r8$backportedMethods$utility$Objects$2$equals -> a:
  29. boolean equals(java.lang.Object,java.lang.Object) -> a
  30. $r8$twr$utility -> b:
  31. void $closeResource(java.lang.Throwable,java.lang.Object) -> a
  32. android.support.v4.app.RemoteActionCompatParcelizer -> android.support.v4.app.RemoteActionCompatParcelizer:
  33. 1:1:void <init>():11:11 -> <init>
  34. io.sentry.sample.-$$Lambda$r3Avcbztes2hicEObh02jjhQqd4 -> e.a.c.a:
  35. io.sentry.sample.MainActivity f$0 -> b
  36. io.sentry.sample.MainActivity -> io.sentry.sample.MainActivity:
  37. 1:1:void <init>():15:15 -> <init>
  38. 1:1:boolean onCreateOptionsMenu(android.view.Menu):60:60 -> onCreateOptionsMenu
  39. 1:1:boolean onOptionsItemSelected(android.view.MenuItem):69:69 -> onOptionsItemSelected
  40. 2:2:boolean onOptionsItemSelected(android.view.MenuItem):76:76 -> onOptionsItemSelected
  41. 1:1:void bar():54:54 -> t
  42. 1:1:void foo():44 -> t
  43. 1:1:void onClickHandler(android.view.View):40 -> t
  44. """
  45. PROGUARD_BUG_UUID = "071207ac-b491-4a74-957c-2c94fd9594f2"
  46. PROGUARD_BUG_SOURCE = b"x"
  47. JVM_DEBUG_ID = "6dc7fdb0-d2fb-4c8e-9d6b-bb1aa98929b1"
  48. JVM_SOURCE = b"""\
  49. package io.sentry.samples
  50. import android.content.Intent
  51. import android.os.Bundle
  52. import androidx.activity.ComponentActivity
  53. class MainActivity : ComponentActivity() {
  54. override fun onCreate(savedInstanceState: Bundle?) {
  55. super.onCreate(savedInstanceState)
  56. setContentView(R.layout.activity_main)
  57. InnerClass().whoops()
  58. val list = findViewById<RecyclerView>(R.id.list)
  59. list.layoutManager = LinearLayoutManager(this)
  60. list.adapter = TrackAdapter()
  61. }
  62. class InnerClass {
  63. fun whoops() {
  64. AnotherInnerClass().whoops2()
  65. }
  66. }
  67. class AnotherInnerClass {
  68. fun whoops2() {
  69. AdditionalInnerClass().whoops3()
  70. }
  71. }
  72. class AdditionalInnerClass {
  73. fun whoops3() {
  74. OneMoreInnerClass().whoops4()
  75. }
  76. }
  77. class OneMoreInnerClass {
  78. fun whoops4() {
  79. throw RuntimeException("whoops")
  80. }
  81. }
  82. }
  83. """
  84. PROGUARD_SOURCE_LOOKUP_UUID = "05d96b1c-1786-477c-8615-d3cf83e027c7"
  85. PROGUARD_SOURCE_LOOKUP_SOURCE = b"""\
  86. io.sentry.samples.instrumentation.ui.EditActivity -> io.sentry.samples.instrumentation.ui.EditActivity:
  87. # {"id":"sourceFile","fileName":"EditActivity.kt"}
  88. int $r8$clinit -> a
  89. 0:65535:void <init>():15:15 -> <init>
  90. 1:6:void onCreate(android.os.Bundle):18:18 -> onCreate
  91. 7:12:void onCreate(android.os.Bundle):19:19 -> onCreate
  92. 13:22:void onCreate(android.os.Bundle):21:21 -> onCreate
  93. 23:32:void onCreate(android.os.Bundle):22:22 -> onCreate
  94. 33:42:void onCreate(android.os.Bundle):23:23 -> onCreate
  95. 43:49:void onCreate(android.os.Bundle):24:24 -> onCreate
  96. 50:71:void onCreate(android.os.Bundle):26:26 -> onCreate
  97. 72:73:java.lang.String io.sentry.samples.instrumentation.data.Track.getName():46:46 -> onCreate
  98. 72:73:void onCreate(android.os.Bundle):28 -> onCreate
  99. 74:76:void onCreate(android.os.Bundle):28:28 -> onCreate
  100. 77:78:java.lang.String io.sentry.samples.instrumentation.data.Track.getComposer():48:48 -> onCreate
  101. 77:78:void onCreate(android.os.Bundle):29 -> onCreate
  102. 79:81:void onCreate(android.os.Bundle):29:29 -> onCreate
  103. 82:83:long io.sentry.samples.instrumentation.data.Track.getMillis():51:51 -> onCreate
  104. 82:83:void onCreate(android.os.Bundle):30 -> onCreate
  105. 84:90:void onCreate(android.os.Bundle):30:30 -> onCreate
  106. 91:92:float io.sentry.samples.instrumentation.data.Track.getPrice():53:53 -> onCreate
  107. 91:92:void onCreate(android.os.Bundle):31 -> onCreate
  108. 93:102:void onCreate(android.os.Bundle):31:31 -> onCreate
  109. 103:119:void onCreate(android.os.Bundle):34:34 -> onCreate
  110. io.sentry.samples.instrumentation.ui.EditActivity$$ExternalSyntheticLambda0 -> io.sentry.samples.instrumentation.ui.g:
  111. # {"id":"sourceFile","fileName":"R8$$SyntheticClass"}
  112. # {"id":"com.android.tools.r8.synthesized"}
  113. android.widget.EditText io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.f$4 -> e
  114. android.widget.EditText io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.f$3 -> d
  115. android.widget.EditText io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.f$2 -> c
  116. io.sentry.samples.instrumentation.data.Track io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.f$0 -> a
  117. android.widget.EditText io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.f$1 -> b
  118. io.sentry.samples.instrumentation.ui.EditActivity io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.f$5 -> f
  119. void io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.<init>(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity) -> <init>
  120. # {"id":"com.android.tools.r8.synthesized"}
  121. 19:21:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):0:0 -> onMenuItemClick
  122. 19:21:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  123. # {"id":"com.android.tools.r8.synthesized"}
  124. 22:35:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):35:35 -> onMenuItemClick
  125. 22:35:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  126. # {"id":"com.android.tools.r8.synthesized"}
  127. 36:44:void io.sentry.samples.instrumentation.ui.AnotherClassInSameFile$AnotherInnerClass.helloOtherInner():26:26 -> onMenuItemClick
  128. 36:44:void io.sentry.samples.instrumentation.ui.AnotherClassInSameFile.otherFun():21 -> onMenuItemClick
  129. 36:44:void io.sentry.samples.instrumentation.ui.AnotherClassInSameFile.helloOther():17 -> onMenuItemClick
  130. 36:44:void io.sentry.samples.instrumentation.ui.SomeService$InnerClassOfSomeService.helloInner():10 -> onMenuItemClick
  131. 36:44:void io.sentry.samples.instrumentation.ui.SomeService.helloThere():5 -> onMenuItemClick
  132. 36:44:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):37 -> onMenuItemClick
  133. 36:44:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  134. # {"id":"com.android.tools.r8.synthesized"}
  135. 45:58:io.sentry.protocol.SentryId io.sentry.Sentry.captureException(java.lang.Throwable):433:433 -> onMenuItemClick
  136. 45:58:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):39 -> onMenuItemClick
  137. 45:58:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  138. # {"id":"com.android.tools.r8.synthesized"}
  139. 59:68:io.sentry.ITransaction io.sentry.Sentry.startTransaction(java.lang.String,java.lang.String,boolean):697:697 -> onMenuItemClick
  140. 59:68:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):42 -> onMenuItemClick
  141. 59:68:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  142. # {"id":"com.android.tools.r8.synthesized"}
  143. 69:71:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):42:42 -> onMenuItemClick
  144. 69:71:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  145. # {"id":"com.android.tools.r8.synthesized"}
  146. 72:79:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):48:48 -> onMenuItemClick
  147. 72:79:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  148. # {"id":"com.android.tools.r8.synthesized"}
  149. 80:87:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):49:49 -> onMenuItemClick
  150. 80:87:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  151. # {"id":"com.android.tools.r8.synthesized"}
  152. 88:95:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):50:50 -> onMenuItemClick
  153. 88:95:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  154. # {"id":"com.android.tools.r8.synthesized"}
  155. 96:103:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):51:51 -> onMenuItemClick
  156. 96:103:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  157. # {"id":"com.android.tools.r8.synthesized"}
  158. 104:125:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):52:52 -> onMenuItemClick
  159. 104:125:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  160. # {"id":"com.android.tools.r8.synthesized"}
  161. 126:142:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):53:53 -> onMenuItemClick
  162. 126:142:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  163. # {"id":"com.android.tools.r8.synthesized"}
  164. 143:164:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):54:54 -> onMenuItemClick
  165. 143:164:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  166. # {"id":"com.android.tools.r8.synthesized"}
  167. 165:175:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):64:64 -> onMenuItemClick
  168. 165:175:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  169. # {"id":"com.android.tools.r8.synthesized"}
  170. 176:187:void io.sentry.samples.instrumentation.ui.EditActivity.addNewTrack(java.lang.String,java.lang.String,long,float):84:84 -> onMenuItemClick
  171. 176:187:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):64 -> onMenuItemClick
  172. 176:187:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  173. # {"id":"com.android.tools.r8.synthesized"}
  174. 188:190:void io.sentry.samples.instrumentation.data.Track.<init>(long,java.lang.String,java.lang.Long,java.lang.String,java.lang.Long,java.lang.Long,long,java.lang.Long,float,int,kotlin.jvm.internal.DefaultConstructorMarker):43:43 -> onMenuItemClick
  175. 188:190:void io.sentry.samples.instrumentation.ui.EditActivity.addNewTrack(java.lang.String,java.lang.String,long,float):84 -> onMenuItemClick
  176. 188:190:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):64 -> onMenuItemClick
  177. 188:190:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  178. # {"id":"com.android.tools.r8.synthesized"}
  179. 191:198:void io.sentry.samples.instrumentation.ui.EditActivity.addNewTrack(java.lang.String,java.lang.String,long,float):94:94 -> onMenuItemClick
  180. 191:198:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):64 -> onMenuItemClick
  181. 191:198:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  182. # {"id":"com.android.tools.r8.synthesized"}
  183. 199:211:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):66:66 -> onMenuItemClick
  184. 199:211:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  185. # {"id":"com.android.tools.r8.synthesized"}
  186. 212:227:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):67:67 -> onMenuItemClick
  187. 212:227:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  188. # {"id":"com.android.tools.r8.synthesized"}
  189. 228:238:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):69:69 -> onMenuItemClick
  190. 228:238:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  191. # {"id":"com.android.tools.r8.synthesized"}
  192. 239:250:io.sentry.samples.instrumentation.data.Track io.sentry.samples.instrumentation.data.Track.copy$default(io.sentry.samples.instrumentation.data.Track,long,java.lang.String,java.lang.Long,java.lang.String,java.lang.Long,java.lang.Long,long,java.lang.Long,float,int,java.lang.Object):0:0 -> onMenuItemClick
  193. 239:250:void io.sentry.samples.instrumentation.ui.EditActivity.update(io.sentry.samples.instrumentation.data.Track,java.lang.String,java.lang.String,long,float):100 -> onMenuItemClick
  194. 239:250:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):69 -> onMenuItemClick
  195. 239:250:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  196. # {"id":"com.android.tools.r8.synthesized"}
  197. 251:265:io.sentry.samples.instrumentation.data.Track io.sentry.samples.instrumentation.data.Track.copy(long,java.lang.String,java.lang.Long,java.lang.String,java.lang.Long,java.lang.Long,long,java.lang.Long,float):0:0 -> onMenuItemClick
  198. 251:265:io.sentry.samples.instrumentation.data.Track io.sentry.samples.instrumentation.data.Track.copy$default(io.sentry.samples.instrumentation.data.Track,long,java.lang.String,java.lang.Long,java.lang.String,java.lang.Long,java.lang.Long,long,java.lang.Long,float,int,java.lang.Object):0 -> onMenuItemClick
  199. 251:265:void io.sentry.samples.instrumentation.ui.EditActivity.update(io.sentry.samples.instrumentation.data.Track,java.lang.String,java.lang.String,long,float):100 -> onMenuItemClick
  200. 251:265:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):69 -> onMenuItemClick
  201. 251:265:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  202. # {"id":"com.android.tools.r8.synthesized"}
  203. 266:273:void io.sentry.samples.instrumentation.ui.EditActivity.update(io.sentry.samples.instrumentation.data.Track,java.lang.String,java.lang.String,long,float):106:106 -> onMenuItemClick
  204. 266:273:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):69 -> onMenuItemClick
  205. 266:273:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  206. # {"id":"com.android.tools.r8.synthesized"}
  207. 274:286:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):71:71 -> onMenuItemClick
  208. 274:286:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  209. # {"id":"com.android.tools.r8.synthesized"}
  210. 287:301:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):72:72 -> onMenuItemClick
  211. 287:301:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  212. # {"id":"com.android.tools.r8.synthesized"}
  213. 302:306:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):74:74 -> onMenuItemClick
  214. 302:306:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  215. # {"id":"com.android.tools.r8.synthesized"}
  216. 307:312:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):75:75 -> onMenuItemClick
  217. 307:312:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  218. # {"id":"com.android.tools.r8.synthesized"}
  219. 313:316:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):56:56 -> onMenuItemClick
  220. 313:316:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  221. # {"id":"com.android.tools.r8.synthesized"}
  222. 317:320:boolean io.sentry.samples.instrumentation.ui.EditActivity.onCreate$lambda-1(io.sentry.samples.instrumentation.data.Track,android.widget.EditText,android.widget.EditText,android.widget.EditText,android.widget.EditText,io.sentry.samples.instrumentation.ui.EditActivity,android.view.MenuItem):61:61 -> onMenuItemClick
  223. 317:320:boolean io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0.onMenuItemClick(android.view.MenuItem):0 -> onMenuItemClick
  224. # {"id":"com.android.tools.r8.synthesized"}
  225. """
  226. EDIT_ACTIVITY_SOURCE = b"""\
  227. package io.sentry.samples.instrumentation.ui
  228. import android.os.Bundle
  229. import android.widget.EditText
  230. import android.widget.Toast
  231. import androidx.activity.ComponentActivity
  232. import androidx.appcompat.widget.Toolbar
  233. import io.sentry.Sentry
  234. import io.sentry.SpanStatus
  235. import io.sentry.samples.instrumentation.R
  236. import io.sentry.samples.instrumentation.SampleApp
  237. import io.sentry.samples.instrumentation.data.Track
  238. import kotlinx.coroutines.runBlocking
  239. class EditActivity : ComponentActivity() {
  240. override fun onCreate(savedInstanceState: Bundle?) {
  241. super.onCreate(savedInstanceState)
  242. setContentView(R.layout.activity_edit)
  243. val nameInput = findViewById<EditText>(R.id.track_name)
  244. val composerInput = findViewById<EditText>(R.id.track_composer)
  245. val durationInput = findViewById<EditText>(R.id.track_duration)
  246. val unitPriceInput = findViewById<EditText>(R.id.track_unit_price)
  247. val originalTrack: Track? = intent.getSerializableExtra(TRACK_EXTRA_KEY) as? Track
  248. originalTrack?.run {
  249. nameInput.setText(name)
  250. composerInput.setText(composer)
  251. durationInput.setText(millis.toString())
  252. unitPriceInput.setText(price.toString())
  253. }
  254. findViewById<Toolbar>(R.id.toolbar).setOnMenuItemClickListener {
  255. if (it.itemId == R.id.action_save) {
  256. try {
  257. SomeService().helloThere()
  258. } catch (e: Exception) {
  259. Sentry.captureException(e)
  260. }
  261. val transaction = Sentry.startTransaction(
  262. "Track Interaction",
  263. if (originalTrack == null) "ui.action.add" else "ui.action.edit",
  264. true
  265. )
  266. val name = nameInput.text.toString()
  267. val composer = composerInput.text.toString()
  268. val duration = durationInput.text.toString()
  269. val unitPrice = unitPriceInput.text.toString()
  270. if (name.isEmpty() || composer.isEmpty() ||
  271. duration.isEmpty() || duration.toLongOrNull() == null ||
  272. unitPrice.isEmpty() || unitPrice.toFloatOrNull() == null
  273. ) {
  274. Toast.makeText(
  275. this,
  276. "Some of the inputs are empty or have wrong format " +
  277. "(duration/unitprice not a number)",
  278. Toast.LENGTH_LONG
  279. ).show()
  280. } else {
  281. if (originalTrack == null) {
  282. addNewTrack(name, composer, duration.toLong(), unitPrice.toFloat())
  283. val createCount = SampleApp.analytics.getInt("create_count", 0) + 1
  284. SampleApp.analytics.edit().putInt("create_count", createCount).apply()
  285. } else {
  286. originalTrack.update(name, composer, duration.toLong(), unitPrice.toFloat())
  287. val editCount = SampleApp.analytics.getInt("edit_count", 0) + 1
  288. SampleApp.analytics.edit().putInt("edit_count", editCount).apply()
  289. }
  290. transaction.finish(SpanStatus.OK)
  291. finish()
  292. }
  293. return@setOnMenuItemClickListener true
  294. }
  295. return@setOnMenuItemClickListener false
  296. }
  297. }
  298. private fun addNewTrack(name: String, composer: String, duration: Long, unitPrice: Float) {
  299. val newTrack = Track(
  300. name = name,
  301. albumId = null,
  302. composer = composer,
  303. mediaTypeId = null,
  304. genreId = null,
  305. millis = duration,
  306. bytes = null,
  307. price = unitPrice
  308. )
  309. runBlocking {
  310. SampleApp.database.tracksDao().insert(newTrack)
  311. }
  312. }
  313. private fun Track.update(name: String, composer: String, duration: Long, unitPrice: Float) {
  314. val updatedTrack = copy(
  315. name = name,
  316. composer = composer,
  317. millis = duration,
  318. price = unitPrice
  319. )
  320. runBlocking {
  321. SampleApp.database.tracksDao().update(updatedTrack)
  322. }
  323. }
  324. companion object {
  325. const val TRACK_EXTRA_KEY = "EditActivity.Track"
  326. }
  327. }
  328. """
  329. SOME_SERVICE_SOURCE = b"""\
  330. package io.sentry.samples.instrumentation.ui
  331. class SomeService {
  332. fun helloThere() {
  333. InnerClassOfSomeService().helloInner()
  334. }
  335. class InnerClassOfSomeService {
  336. fun helloInner() {
  337. AnotherClassInSameFile().helloOther()
  338. }
  339. }
  340. }
  341. class AnotherClassInSameFile {
  342. fun helloOther() {
  343. otherFun()
  344. }
  345. private fun otherFun() {
  346. AnotherInnerClass().helloOtherInner()
  347. }
  348. class AnotherInnerClass {
  349. fun helloOtherInner() {
  350. throw RuntimeException("thrown on purpose to test ProGuard Android source context")
  351. }
  352. }
  353. }
  354. """
  355. @pytest.mark.django_db(transaction=True)
  356. class BasicResolvingIntegrationTest(RelayStoreHelper, TransactionTestCase):
  357. def upload_proguard_mapping(self, uuid, mapping_file_content):
  358. url = reverse(
  359. "sentry-api-0-dsym-files",
  360. kwargs={
  361. "organization_slug": self.project.organization.slug,
  362. "project_slug": self.project.slug,
  363. },
  364. )
  365. self.login_as(user=self.user)
  366. out = BytesIO()
  367. f = zipfile.ZipFile(out, "w")
  368. f.writestr("proguard/%s.txt" % uuid, mapping_file_content)
  369. f.writestr("ignored-file.txt", b"This is just some stuff")
  370. f.close()
  371. response = self.client.post(
  372. url,
  373. {
  374. "file": SimpleUploadedFile(
  375. "symbols.zip", out.getvalue(), content_type="application/zip"
  376. )
  377. },
  378. format="multipart",
  379. )
  380. assert response.status_code == 201, response.content
  381. assert len(response.json()) == 1
  382. def test_basic_resolving(self):
  383. self.upload_proguard_mapping(PROGUARD_UUID, PROGUARD_SOURCE)
  384. event_data = {
  385. "user": {"ip_address": "31.172.207.97"},
  386. "extra": {},
  387. "project": self.project.id,
  388. "platform": "java",
  389. "debug_meta": {"images": [{"type": "proguard", "uuid": PROGUARD_UUID}]},
  390. "exception": {
  391. "values": [
  392. {
  393. "stacktrace": {
  394. "frames": [
  395. {
  396. "function": "a",
  397. "abs_path": None,
  398. "module": "org.a.b.g$a",
  399. "filename": None,
  400. "lineno": 67,
  401. },
  402. {
  403. "function": "a",
  404. "abs_path": None,
  405. "module": "org.a.b.g$a",
  406. "filename": None,
  407. "lineno": 69,
  408. },
  409. ]
  410. },
  411. "module": "org.a.b",
  412. "type": "g$a",
  413. "value": "Attempt to invoke virtual method 'org.a.b.g$a.a' on a null object reference",
  414. }
  415. ]
  416. },
  417. "timestamp": iso_format(before_now(seconds=1)),
  418. }
  419. event = self.post_and_retrieve_event(event_data)
  420. if not self.use_relay():
  421. # We measure the number of queries after an initial post,
  422. # because there are many queries polluting the array
  423. # before the actual "processing" happens (like, auth_user)
  424. with self.assertWriteQueries(
  425. {
  426. "nodestore_node": 2,
  427. "sentry_eventuser": 1,
  428. "sentry_groupedmessage": 1,
  429. "sentry_userreport": 1,
  430. }
  431. ):
  432. self.post_and_retrieve_event(event_data)
  433. exc = event.interfaces["exception"].values[0]
  434. bt = exc.stacktrace
  435. frames = bt.frames
  436. assert exc.type == "Util$ClassContextSecurityManager"
  437. assert (
  438. exc.value
  439. == "Attempt to invoke virtual method 'org.slf4j.helpers.Util$ClassContextSecurityManager.getExtraClassContext' on a null object reference"
  440. )
  441. assert exc.module == "org.slf4j.helpers"
  442. assert frames[0].function == "getClassContext"
  443. assert frames[0].module == "org.slf4j.helpers.Util$ClassContextSecurityManager"
  444. assert frames[1].function == "getExtraClassContext"
  445. assert frames[1].module == "org.slf4j.helpers.Util$ClassContextSecurityManager"
  446. assert event.culprit == (
  447. "org.slf4j.helpers.Util$ClassContextSecurityManager " "in getExtraClassContext"
  448. )
  449. def test_resolving_does_not_fail_when_no_value(self):
  450. self.upload_proguard_mapping(PROGUARD_UUID, PROGUARD_SOURCE)
  451. event_data = {
  452. "user": {"ip_address": "31.172.207.97"},
  453. "extra": {},
  454. "project": self.project.id,
  455. "platform": "java",
  456. "debug_meta": {"images": [{"type": "proguard", "uuid": PROGUARD_UUID}]},
  457. "exception": {
  458. "values": [
  459. {
  460. "stacktrace": {
  461. "frames": [
  462. {
  463. "function": "a",
  464. "abs_path": None,
  465. "module": "org.a.b.g$a",
  466. "filename": None,
  467. "lineno": 67,
  468. },
  469. {
  470. "function": "a",
  471. "abs_path": None,
  472. "module": "org.a.b.g$a",
  473. "filename": None,
  474. "lineno": 69,
  475. },
  476. ]
  477. },
  478. "module": "org.a.b",
  479. "type": "g$a",
  480. }
  481. ]
  482. },
  483. "timestamp": iso_format(before_now(seconds=1)),
  484. }
  485. event = self.post_and_retrieve_event(event_data)
  486. if not self.use_relay():
  487. # We measure the number of queries after an initial post,
  488. # because there are many queries polluting the array
  489. # before the actual "processing" happens (like, auth_user)
  490. with self.assertWriteQueries(
  491. {
  492. "nodestore_node": 2,
  493. "sentry_eventuser": 1,
  494. "sentry_groupedmessage": 1,
  495. "sentry_userreport": 1,
  496. }
  497. ):
  498. self.post_and_retrieve_event(event_data)
  499. metrics = event.data["_metrics"]
  500. assert not metrics.get("flag.processing.error")
  501. def test_resolving_inline(self):
  502. self.upload_proguard_mapping(PROGUARD_INLINE_UUID, PROGUARD_INLINE_SOURCE)
  503. event_data = {
  504. "user": {"ip_address": "31.172.207.97"},
  505. "extra": {},
  506. "project": self.project.id,
  507. "platform": "java",
  508. "debug_meta": {"images": [{"type": "proguard", "uuid": PROGUARD_INLINE_UUID}]},
  509. "exception": {
  510. "values": [
  511. {
  512. "stacktrace": {
  513. "frames": [
  514. {
  515. "function": "onClick",
  516. "abs_path": None,
  517. "module": "e.a.c.a",
  518. "filename": None,
  519. "lineno": 2,
  520. },
  521. {
  522. "function": "t",
  523. "abs_path": None,
  524. "module": "io.sentry.sample.MainActivity",
  525. "filename": "MainActivity.java",
  526. "lineno": 1,
  527. },
  528. ]
  529. },
  530. "module": "org.a.b",
  531. "type": "g$a",
  532. "value": "Oh no",
  533. }
  534. ]
  535. },
  536. "timestamp": iso_format(before_now(seconds=1)),
  537. }
  538. event = self.post_and_retrieve_event(event_data)
  539. if not self.use_relay():
  540. # We measure the number of queries after an initial post,
  541. # because there are many queries polluting the array
  542. # before the actual "processing" happens (like, auth_user)
  543. with self.assertWriteQueries(
  544. {
  545. "nodestore_node": 2,
  546. "sentry_eventuser": 1,
  547. "sentry_groupedmessage": 1,
  548. "sentry_userreport": 1,
  549. }
  550. ):
  551. self.post_and_retrieve_event(event_data)
  552. exc = event.interfaces["exception"].values[0]
  553. bt = exc.stacktrace
  554. frames = bt.frames
  555. assert len(frames) == 4
  556. assert frames[0].function == "onClick"
  557. assert frames[0].module == "io.sentry.sample.-$$Lambda$r3Avcbztes2hicEObh02jjhQqd4"
  558. assert frames[1].filename == "MainActivity.java"
  559. assert frames[1].module == "io.sentry.sample.MainActivity"
  560. assert frames[1].function == "onClickHandler"
  561. assert frames[1].lineno == 40
  562. assert frames[2].function == "foo"
  563. assert frames[2].lineno == 44
  564. assert frames[3].function == "bar"
  565. assert frames[3].lineno == 54
  566. assert frames[3].filename == "MainActivity.java"
  567. assert frames[3].module == "io.sentry.sample.MainActivity"
  568. def test_error_on_resolving(self):
  569. url = reverse(
  570. "sentry-api-0-dsym-files",
  571. kwargs={
  572. "organization_slug": self.project.organization.slug,
  573. "project_slug": self.project.slug,
  574. },
  575. )
  576. self.login_as(user=self.user)
  577. out = BytesIO()
  578. f = zipfile.ZipFile(out, "w")
  579. f.writestr("proguard/%s.txt" % PROGUARD_BUG_UUID, PROGUARD_BUG_SOURCE)
  580. f.close()
  581. response = self.client.post(
  582. url,
  583. {
  584. "file": SimpleUploadedFile(
  585. "symbols.zip", out.getvalue(), content_type="application/zip"
  586. )
  587. },
  588. format="multipart",
  589. )
  590. assert response.status_code == 201, response.content
  591. assert len(response.json()) == 1
  592. event_data = {
  593. "user": {"ip_address": "31.172.207.97"},
  594. "extra": {},
  595. "project": self.project.id,
  596. "platform": "java",
  597. "debug_meta": {"images": [{"type": "proguard", "uuid": PROGUARD_BUG_UUID}]},
  598. "exception": {
  599. "values": [
  600. {
  601. "stacktrace": {
  602. "frames": [
  603. {
  604. "function": "a",
  605. "abs_path": None,
  606. "module": "org.a.b.g$a",
  607. "filename": None,
  608. "lineno": 67,
  609. },
  610. {
  611. "function": "a",
  612. "abs_path": None,
  613. "module": "org.a.b.g$a",
  614. "filename": None,
  615. "lineno": 69,
  616. },
  617. ]
  618. },
  619. "type": "RuntimeException",
  620. "value": "Oh no",
  621. }
  622. ]
  623. },
  624. "timestamp": iso_format(before_now(seconds=1)),
  625. }
  626. event = self.post_and_retrieve_event(event_data)
  627. assert len(event.data["errors"]) == 1
  628. assert event.data["errors"][0] == {
  629. "mapping_uuid": "071207ac-b491-4a74-957c-2c94fd9594f2",
  630. "type": "proguard_missing_lineno",
  631. }
  632. def upload_jvm_bundle(self, debug_id, source_files):
  633. files = {}
  634. for source_file in source_files:
  635. files[f"files/_/_/{source_file}"] = {"url": f"~/{source_file}"}
  636. manifest = {
  637. "org": self.project.organization.slug,
  638. "project": self.project.slug,
  639. "debug_id": debug_id,
  640. "files": files,
  641. }
  642. file_like = BytesIO()
  643. with zipfile.ZipFile(file_like, "w") as zip:
  644. for source_file in source_files:
  645. zip.writestr(f"files/_/_/{source_file}", source_files[source_file])
  646. zip.writestr("manifest.json", json.dumps(manifest))
  647. file_like.seek(0)
  648. file = File.objects.create(name="bundle.zip", type="artifact.bundle")
  649. file.putfile(file_like)
  650. ProjectDebugFile.objects.create(
  651. project_id=self.project.id,
  652. debug_id=debug_id,
  653. file=file,
  654. )
  655. def test_basic_source_lookup(self):
  656. debug_id = str(uuid4())
  657. self.upload_jvm_bundle(debug_id, {"io/sentry/samples/MainActivity.jvm": JVM_SOURCE})
  658. event_data = {
  659. "user": {"ip_address": "31.172.207.97"},
  660. "extra": {},
  661. "project": self.project.id,
  662. "platform": "java",
  663. "debug_meta": {"images": [{"type": "jvm", "debug_id": debug_id}]},
  664. "exception": {
  665. "values": [
  666. {
  667. "stacktrace": {
  668. "frames": [
  669. {
  670. "function": "otherMethod",
  671. "abs_path": "OtherActivity.java",
  672. "module": "OtherActivity",
  673. "filename": "OtherActivity.java",
  674. "lineno": 100,
  675. },
  676. {
  677. "function": "differentMethod",
  678. "abs_path": "DifferentActivity",
  679. "module": "DifferentActivity",
  680. "filename": "DifferentActivity",
  681. "lineno": 200,
  682. },
  683. {
  684. "function": "onCreate",
  685. "abs_path": None,
  686. "module": "io.sentry.samples.MainActivity",
  687. "filename": None,
  688. "lineno": 11,
  689. },
  690. {
  691. "function": "whoops",
  692. "abs_path": "MainActivity.kt",
  693. "module": "io.sentry.samples.MainActivity$InnerClass",
  694. "filename": "MainActivity.kt",
  695. "lineno": 20,
  696. },
  697. {
  698. "function": "whoops2",
  699. "abs_path": None,
  700. "module": "io.sentry.samples.MainActivity$AnotherInnerClass",
  701. "filename": None,
  702. "lineno": 26,
  703. },
  704. {
  705. "function": "whoops3",
  706. "abs_path": "MainActivity.kt",
  707. "module": "io.sentry.samples.MainActivity$AdditionalInnerClass",
  708. "filename": "MainActivity.kt",
  709. "lineno": 32,
  710. },
  711. {
  712. "function": "whoops4",
  713. "abs_path": "SourceFile",
  714. "module": "io.sentry.samples.MainActivity$OneMoreInnerClass",
  715. "filename": "SourceFile",
  716. "lineno": 38,
  717. },
  718. ]
  719. },
  720. "module": "io.sentry.samples",
  721. "type": "RuntimeException",
  722. "value": "whoops",
  723. }
  724. ]
  725. },
  726. "timestamp": iso_format(before_now(seconds=1)),
  727. }
  728. event = self.post_and_retrieve_event(event_data)
  729. if not self.use_relay():
  730. # We measure the number of queries after an initial post,
  731. # because there are many queries polluting the array
  732. # before the actual "processing" happens (like, auth_user)
  733. with self.assertWriteQueries(
  734. {
  735. "nodestore_node": 2,
  736. "sentry_eventuser": 1,
  737. "sentry_groupedmessage": 1,
  738. "sentry_userreport": 1,
  739. }
  740. ):
  741. self.post_and_retrieve_event(event_data)
  742. exc = event.interfaces["exception"].values[0]
  743. bt = exc.stacktrace
  744. frames = bt.frames
  745. assert exc.type == "RuntimeException"
  746. assert exc.value == "whoops"
  747. assert exc.module == "io.sentry.samples"
  748. assert frames[0].function == "otherMethod"
  749. assert frames[0].module == "OtherActivity"
  750. assert frames[0].lineno == 100
  751. assert frames[0].context_line is None
  752. assert frames[0].pre_context is None
  753. assert frames[0].post_context is None
  754. assert frames[1].function == "differentMethod"
  755. assert frames[1].module == "DifferentActivity"
  756. assert frames[1].lineno == 200
  757. assert frames[1].context_line is None
  758. assert frames[1].pre_context is None
  759. assert frames[1].post_context is None
  760. assert frames[2].function == "onCreate"
  761. assert frames[2].module == "io.sentry.samples.MainActivity"
  762. assert frames[2].lineno == 11
  763. assert frames[2].context_line == " InnerClass().whoops()"
  764. assert frames[2].pre_context == [
  765. "",
  766. "class MainActivity : ComponentActivity() {",
  767. " override fun onCreate(savedInstanceState: Bundle?) {",
  768. " super.onCreate(savedInstanceState)",
  769. " setContentView(R.layout.activity_main)",
  770. ]
  771. assert frames[2].post_context == [
  772. "",
  773. " val list = findViewById<RecyclerView>(R.id.list)",
  774. " list.layoutManager = LinearLayoutManager(this)",
  775. " list.adapter = TrackAdapter()",
  776. " }",
  777. ]
  778. assert frames[3].function == "whoops"
  779. assert frames[3].module == "io.sentry.samples.MainActivity$InnerClass"
  780. assert frames[3].lineno == 20
  781. assert frames[3].context_line == " AnotherInnerClass().whoops2()"
  782. assert frames[3].pre_context == [
  783. " list.adapter = TrackAdapter()",
  784. " }",
  785. "",
  786. " class InnerClass {",
  787. " fun whoops() {",
  788. ]
  789. assert frames[3].post_context == [
  790. " }",
  791. " }",
  792. "",
  793. " class AnotherInnerClass {",
  794. " fun whoops2() {",
  795. ]
  796. assert frames[4].function == "whoops2"
  797. assert frames[4].module == "io.sentry.samples.MainActivity$AnotherInnerClass"
  798. assert frames[4].lineno == 26
  799. assert frames[4].context_line == " AdditionalInnerClass().whoops3()"
  800. assert frames[4].pre_context == [
  801. " }",
  802. " }",
  803. "",
  804. " class AnotherInnerClass {",
  805. " fun whoops2() {",
  806. ]
  807. assert frames[4].post_context == [
  808. " }",
  809. " }",
  810. "",
  811. " class AdditionalInnerClass {",
  812. " fun whoops3() {",
  813. ]
  814. assert frames[5].function == "whoops3"
  815. assert frames[5].module == "io.sentry.samples.MainActivity$AdditionalInnerClass"
  816. assert frames[5].lineno == 32
  817. assert frames[5].context_line == " OneMoreInnerClass().whoops4()"
  818. assert frames[5].pre_context == [
  819. " }",
  820. " }",
  821. "",
  822. " class AdditionalInnerClass {",
  823. " fun whoops3() {",
  824. ]
  825. assert frames[5].post_context == [
  826. " }",
  827. " }",
  828. "",
  829. " class OneMoreInnerClass {",
  830. " fun whoops4() {",
  831. ]
  832. assert frames[6].function == "whoops4"
  833. assert frames[6].module == "io.sentry.samples.MainActivity$OneMoreInnerClass"
  834. assert frames[6].lineno == 38
  835. assert frames[6].context_line == ' throw RuntimeException("whoops")'
  836. assert frames[6].pre_context == [
  837. " }",
  838. " }",
  839. "",
  840. " class OneMoreInnerClass {",
  841. " fun whoops4() {",
  842. ]
  843. assert frames[6].post_context == [" }", " }", "}", ""]
  844. def test_source_lookup_with_proguard(self):
  845. self.upload_proguard_mapping(PROGUARD_SOURCE_LOOKUP_UUID, PROGUARD_SOURCE_LOOKUP_SOURCE)
  846. debug_id1 = str(uuid4())
  847. self.upload_jvm_bundle(
  848. debug_id1,
  849. {
  850. "io/sentry/samples/instrumentation/ui/EditActivity.jvm": EDIT_ACTIVITY_SOURCE,
  851. },
  852. )
  853. debug_id2 = str(uuid4())
  854. self.upload_jvm_bundle(
  855. debug_id2,
  856. {
  857. "io/sentry/samples/instrumentation/ui/SomeService.jvm": SOME_SERVICE_SOURCE,
  858. },
  859. )
  860. event_data = {
  861. "user": {"ip_address": "31.172.207.97"},
  862. "extra": {},
  863. "project": self.project.id,
  864. "platform": "java",
  865. "debug_meta": {
  866. "images": [
  867. {
  868. "type": "jvm",
  869. "debug_id": debug_id1,
  870. },
  871. {
  872. "type": "jvm",
  873. "debug_id": debug_id2,
  874. },
  875. {
  876. "type": "jvm",
  877. "debug_id": str(uuid4()),
  878. }, # does not exist
  879. {"type": "proguard", "uuid": PROGUARD_SOURCE_LOOKUP_UUID},
  880. {"type": "proguard", "uuid": str(uuid4())}, # does not exist
  881. ]
  882. },
  883. "exception": {
  884. "values": [
  885. {
  886. "type": "RuntimeException",
  887. "value": "thrown on purpose to test ProGuard Android source context",
  888. "module": "java.lang",
  889. "thread_id": 1,
  890. "stacktrace": {
  891. "frames": [
  892. {
  893. "filename": "ZygoteInit.java",
  894. "function": "main",
  895. "module": "com.android.internal.os.ZygoteInit",
  896. "lineno": 698,
  897. "native": False,
  898. },
  899. {
  900. "filename": "ZygoteInit.java",
  901. "function": "run",
  902. "module": "com.android.internal.os.ZygoteInit$MethodAndArgsCaller",
  903. "lineno": 903,
  904. "native": False,
  905. },
  906. {
  907. "filename": "Method.java",
  908. "function": "invoke",
  909. "module": "java.lang.reflect.Method",
  910. "lineno": 372,
  911. "native": False,
  912. },
  913. {
  914. "filename": "Method.java",
  915. "function": "invoke",
  916. "module": "java.lang.reflect.Method",
  917. "native": True,
  918. },
  919. {
  920. "filename": "ActivityThread.java",
  921. "function": "main",
  922. "module": "android.app.ActivityThread",
  923. "lineno": 5254,
  924. "native": False,
  925. },
  926. {
  927. "filename": "Looper.java",
  928. "function": "loop",
  929. "module": "android.os.Looper",
  930. "lineno": 135,
  931. "native": False,
  932. },
  933. {
  934. "filename": "Handler.java",
  935. "function": "dispatchMessage",
  936. "module": "android.os.Handler",
  937. "lineno": 95,
  938. "native": False,
  939. },
  940. {
  941. "filename": "Handler.java",
  942. "function": "handleCallback",
  943. "module": "android.os.Handler",
  944. "lineno": 739,
  945. "native": False,
  946. },
  947. {
  948. "filename": "View.java",
  949. "function": "run",
  950. "module": "android.view.View$PerformClick",
  951. "lineno": 19866,
  952. "native": False,
  953. },
  954. {
  955. "filename": "View.java",
  956. "function": "performClick",
  957. "module": "android.view.View",
  958. "lineno": 4780,
  959. "native": False,
  960. },
  961. {
  962. "filename": "ActionMenuItemView.java",
  963. "function": "onClick",
  964. "module": "androidx.appcompat.view.menu.ActionMenuItemView",
  965. "lineno": 7,
  966. "native": False,
  967. },
  968. {
  969. "filename": "ActionMenuView.java",
  970. "function": "invokeItem",
  971. "module": "androidx.appcompat.widget.ActionMenuView",
  972. "lineno": 4,
  973. "native": False,
  974. },
  975. {
  976. "filename": "MenuBuilder.java",
  977. "function": "performItemAction",
  978. "module": "androidx.appcompat.view.menu.MenuBuilder",
  979. "lineno": 1,
  980. "native": False,
  981. },
  982. {
  983. "filename": "MenuBuilder.java",
  984. "function": "performItemAction",
  985. "module": "androidx.appcompat.view.menu.MenuBuilder",
  986. "lineno": 4,
  987. "native": False,
  988. },
  989. {
  990. "filename": "MenuItemImpl.java",
  991. "function": "invoke",
  992. "module": "androidx.appcompat.view.menu.MenuItemImpl",
  993. "lineno": 15,
  994. "native": False,
  995. },
  996. {
  997. "filename": "MenuBuilder.java",
  998. "function": "dispatchMenuItemSelected",
  999. "module": "androidx.appcompat.view.menu.MenuBuilder",
  1000. "lineno": 5,
  1001. "native": False,
  1002. },
  1003. {
  1004. "filename": "ActionMenuView.java",
  1005. "function": "onMenuItemSelected",
  1006. "module": "androidx.appcompat.widget.ActionMenuView$MenuBuilderCallback",
  1007. "lineno": 7,
  1008. "native": False,
  1009. },
  1010. {
  1011. "filename": "Toolbar.java",
  1012. "function": "onMenuItemClick",
  1013. "module": "androidx.appcompat.widget.Toolbar$1",
  1014. "lineno": 7,
  1015. "native": False,
  1016. },
  1017. {
  1018. "filename": "R8$$SyntheticClass",
  1019. "function": "onMenuItemClick",
  1020. "module": "io.sentry.samples.instrumentation.ui.g",
  1021. "lineno": 40,
  1022. "in_app": True,
  1023. "native": False,
  1024. },
  1025. ]
  1026. },
  1027. }
  1028. ]
  1029. },
  1030. "timestamp": iso_format(before_now(seconds=1)),
  1031. }
  1032. event = self.post_and_retrieve_event(event_data)
  1033. if not self.use_relay():
  1034. # We measure the number of queries after an initial post,
  1035. # because there are many queries polluting the array
  1036. # before the actual "processing" happens (like, auth_user)
  1037. with self.assertWriteQueries(
  1038. {
  1039. "nodestore_node": 2,
  1040. "sentry_eventuser": 1,
  1041. "sentry_groupedmessage": 1,
  1042. "sentry_userreport": 1,
  1043. }
  1044. ):
  1045. self.post_and_retrieve_event(event_data)
  1046. exc = event.interfaces["exception"].values[0]
  1047. bt = exc.stacktrace
  1048. frames = bt.frames
  1049. assert exc.type == "RuntimeException"
  1050. assert exc.value == "thrown on purpose to test ProGuard Android source context"
  1051. assert exc.module == "java.lang"
  1052. assert frames[18].function == "onMenuItemClick"
  1053. assert (
  1054. frames[18].module
  1055. == "io.sentry.samples.instrumentation.ui.EditActivity$$InternalSyntheticLambda$1$ebaa538726b99bb77e0f5e7c86443911af17d6e5be2b8771952ae0caa4ff2ac7$0"
  1056. )
  1057. assert frames[18].lineno == 0
  1058. assert frames[18].context_line is None
  1059. assert frames[18].pre_context is None
  1060. assert frames[18].post_context is None
  1061. assert frames[19].function == "onCreate$lambda-1"
  1062. assert frames[19].module == "io.sentry.samples.instrumentation.ui.EditActivity"
  1063. assert frames[19].lineno == 37
  1064. assert frames[19].context_line == " SomeService().helloThere()"
  1065. assert frames[19].pre_context == [
  1066. " }",
  1067. "",
  1068. " findViewById<Toolbar>(R.id.toolbar).setOnMenuItemClickListener {",
  1069. " if (it.itemId == R.id.action_save) {",
  1070. " try {",
  1071. ]
  1072. assert frames[19].post_context == [
  1073. " } catch (e: Exception) {",
  1074. " Sentry.captureException(e)",
  1075. " }",
  1076. "",
  1077. " val transaction = Sentry.startTransaction(",
  1078. ]
  1079. assert frames[20].function == "helloThere"
  1080. assert frames[20].module == "io.sentry.samples.instrumentation.ui.SomeService"
  1081. assert frames[20].lineno == 5
  1082. assert frames[20].context_line == " InnerClassOfSomeService().helloInner()"
  1083. assert frames[20].pre_context == [
  1084. "package io.sentry.samples.instrumentation.ui",
  1085. "",
  1086. "class SomeService {",
  1087. " fun helloThere() {",
  1088. ]
  1089. assert frames[20].post_context == [
  1090. " }",
  1091. "",
  1092. " class InnerClassOfSomeService {",
  1093. " fun helloInner() {",
  1094. " AnotherClassInSameFile().helloOther()",
  1095. ]
  1096. assert frames[21].function == "helloInner"
  1097. assert (
  1098. frames[21].module
  1099. == "io.sentry.samples.instrumentation.ui.SomeService$InnerClassOfSomeService"
  1100. )
  1101. assert frames[21].lineno == 10
  1102. assert frames[21].context_line == " AnotherClassInSameFile().helloOther()"
  1103. assert frames[21].pre_context == [
  1104. " InnerClassOfSomeService().helloInner()",
  1105. " }",
  1106. "",
  1107. " class InnerClassOfSomeService {",
  1108. " fun helloInner() {",
  1109. ]
  1110. assert frames[21].post_context == [
  1111. " }",
  1112. " }",
  1113. "}",
  1114. "",
  1115. "class AnotherClassInSameFile {",
  1116. ]
  1117. assert frames[22].function == "helloOther"
  1118. assert frames[22].module == "io.sentry.samples.instrumentation.ui.AnotherClassInSameFile"
  1119. assert frames[22].lineno == 17
  1120. assert frames[22].context_line is None
  1121. assert frames[22].pre_context is None
  1122. assert frames[22].post_context is None
  1123. assert frames[23].function == "otherFun"
  1124. assert frames[23].module == "io.sentry.samples.instrumentation.ui.AnotherClassInSameFile"
  1125. assert frames[23].lineno == 21
  1126. assert frames[23].context_line is None
  1127. assert frames[23].pre_context is None
  1128. assert frames[23].post_context is None
  1129. assert frames[24].function == "helloOtherInner"
  1130. assert (
  1131. frames[24].module
  1132. == "io.sentry.samples.instrumentation.ui.AnotherClassInSameFile$AnotherInnerClass"
  1133. )
  1134. assert frames[24].lineno == 26
  1135. assert frames[24].context_line is None
  1136. assert frames[24].pre_context is None
  1137. assert frames[24].post_context is None