test_plugin.py 62 KB

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