test_plugin.py 64 KB

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