test_plugin.py 62 KB

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