Skip to content

Commit 4dee4a2

Browse files
committed
run command to disable system animations
removed frame timestamp check, as useless in that case upgraded androidx test dependency fixed doubleInitWithSameOption UI test by waiting for the last envelope moved lazy field load after old executor service shutdown removed saucelabs test devices (now run UI tests on 1 device only) wrapped SystemEventsBreadcrumbsIntegration.unregisterReceiver in try catch fixed UserFeedbackUiTest.userFeedbackSendEnvelope UI test by checking the replay was sent, too
1 parent e1a93be commit 4dee4a2

9 files changed

Lines changed: 78 additions & 75 deletions

File tree

.sauce/sentry-uitest-android-ui.yml

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,6 @@ suites:
2626
- name: ".*"
2727
platformVersion: "15"
2828

29-
- name: "Android 14 Ui test (api 34)"
30-
testOptions:
31-
clearPackageData: true
32-
useTestOrchestrator: true
33-
devices:
34-
- name: ".*"
35-
platformVersion: "14"
36-
37-
- name: "Android 13 Ui test (api 33)"
38-
testOptions:
39-
clearPackageData: true
40-
useTestOrchestrator: true
41-
devices:
42-
- name: ".*"
43-
platformVersion: "13"
44-
4529
# Controls what artifacts to fetch when the suite on Sauce Cloud has finished.
4630
artifacts:
4731
download:

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
apollo = "2.5.9"
33
androidxLifecycle = "2.2.0"
44
androidxNavigation = "2.4.2"
5-
androidxTestCore = "1.6.1"
5+
androidxTestCore = "1.7.0"
66
androidxCompose = "1.6.3"
77
composeCompiler = "1.5.14"
88
coroutines = "1.6.1"

sentry-android-core/src/main/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegration.java

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import java.util.HashMap;
4747
import java.util.List;
4848
import java.util.Map;
49+
import java.util.concurrent.RejectedExecutionException;
4950
import java.util.concurrent.atomic.AtomicBoolean;
5051
import org.jetbrains.annotations.NotNull;
5152
import org.jetbrains.annotations.Nullable;
@@ -181,26 +182,30 @@ private void registerReceiver(
181182
}
182183
}
183184

184-
private void unregisterReceiver() {
185+
@SuppressWarnings("Convert2MethodRef") // older AGP versions do not support method references
186+
private void scheduleUnregisterReceiver() {
185187
if (options == null) {
186188
return;
187189
}
188190

189-
options
190-
.getExecutorService()
191-
.submit(
192-
() -> {
193-
final @Nullable SystemEventsBroadcastReceiver receiverRef;
194-
try (final @NotNull ISentryLifecycleToken ignored = receiverLock.acquire()) {
195-
isStopped = true;
196-
receiverRef = receiver;
197-
receiver = null;
198-
}
191+
try {
192+
options.getExecutorService().submit(() -> unregisterReceiver());
193+
} catch (RejectedExecutionException e) {
194+
unregisterReceiver();
195+
}
196+
}
199197

200-
if (receiverRef != null) {
201-
context.unregisterReceiver(receiverRef);
202-
}
203-
});
198+
private void unregisterReceiver() {
199+
final @Nullable SystemEventsBroadcastReceiver receiverRef;
200+
try (final @NotNull ISentryLifecycleToken ignored = receiverLock.acquire()) {
201+
isStopped = true;
202+
receiverRef = receiver;
203+
receiver = null;
204+
}
205+
206+
if (receiverRef != null) {
207+
context.unregisterReceiver(receiverRef);
208+
}
204209
}
205210

206211
@Override
@@ -215,7 +220,7 @@ public void close() throws IOException {
215220
}
216221

217222
AppState.getInstance().removeAppStateListener(this);
218-
unregisterReceiver();
223+
scheduleUnregisterReceiver();
219224

220225
if (options != null) {
221226
options.getLogger().log(SentryLevel.DEBUG, "SystemEventsBreadcrumbsIntegration removed.");
@@ -264,7 +269,7 @@ public void onForeground() {
264269

265270
@Override
266271
public void onBackground() {
267-
unregisterReceiver();
272+
scheduleUnregisterReceiver();
268273
}
269274

270275
final class SystemEventsBroadcastReceiver extends BroadcastReceiver {

sentry-android-integration-tests/sentry-uitest-android/src/androidTest/java/io/sentry/uitest/android/BaseUiTest.kt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ abstract class BaseUiTest {
5050
/** Mock relay server that receives all envelopes sent during the test. */
5151
protected val relay = MockRelay(false, relayIdlingResource)
5252

53-
private fun disableDontKeepActivities() {
53+
private fun runCommand(cmd: String) {
5454
val automation = InstrumentationRegistry.getInstrumentation().uiAutomation
55-
val pfd = automation.executeShellCommand("settings put global always_finish_activities 0")
55+
val pfd = automation.executeShellCommand(cmd)
5656
try {
5757
FileInputStream(pfd.fileDescriptor).readBytes()
5858
} catch (e: Throwable) {
@@ -61,6 +61,16 @@ abstract class BaseUiTest {
6161
pfd.close()
6262
}
6363

64+
private fun disableDontKeepActivities() {
65+
runCommand("settings put global always_finish_activities 0")
66+
}
67+
68+
fun disableSystemAnimations() {
69+
runCommand("settings put global window_animation_scale 0")
70+
runCommand("settings put global transition_animation_scale 0")
71+
runCommand("settings put global animator_duration_scale 0")
72+
}
73+
6474
@BeforeTest
6575
fun baseSetUp() {
6676
runner = InstrumentationRegistry.getInstrumentation() as AndroidJUnitRunner
@@ -70,6 +80,7 @@ abstract class BaseUiTest {
7080
relay.start()
7181
mockDsn = relay.createMockDsn()
7282
disableDontKeepActivities()
83+
disableSystemAnimations()
7384
}
7485

7586
@AfterTest

sentry-android-integration-tests/sentry-uitest-android/src/androidTest/java/io/sentry/uitest/android/EnvelopeTests.kt

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ class EnvelopeTests : BaseUiTest() {
5656

5757
relayIdlingResource.increment()
5858
IdlingRegistry.getInstance().register(ProfilingSampleActivity.scrollingIdlingResource)
59-
Thread.sleep(1000)
6059
val transaction = Sentry.startTransaction("profiledTransaction", "test1")
6160
val sampleScenario = launchActivity<ProfilingSampleActivity>()
6261
swipeList(1)
@@ -171,15 +170,17 @@ class EnvelopeTests : BaseUiTest() {
171170
values.last().relativeStartNs.toLong() <= maxTimestampAllowed,
172171
"Last measurement value for '$name' is outside bounds (was: ${values.last().relativeStartNs.toLong()}ns, max: ${maxTimestampAllowed}ns",
173172
)
174-
}
175173

176-
// Timestamps of measurements should differ at least 10 milliseconds from each other
177-
(1 until values.size).forEach { i ->
178-
assertTrue(
179-
values[i].relativeStartNs.toLong() >=
180-
values[i - 1].relativeStartNs.toLong() + TimeUnit.MILLISECONDS.toNanos(10),
181-
"Measurement value timestamp for '$name' does not differ at least 10ms",
182-
)
174+
// Timestamps of measurements should differ at least 10 milliseconds from each other
175+
(1 until values.size).forEach { i ->
176+
val measurementTimestampDiff =
177+
values[i].relativeStartNs.toLong() - values[i - 1].relativeStartNs.toLong()
178+
179+
assertTrue(
180+
measurementTimestampDiff >= TimeUnit.MILLISECONDS.toNanos(10),
181+
"Measurement value timestamp for '$name' should differ at least 10ms, but was $measurementTimestampDiff",
182+
)
183+
}
183184
}
184185
}
185186

sentry-android-integration-tests/sentry-uitest-android/src/androidTest/java/io/sentry/uitest/android/SdkInitTests.kt

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,16 @@ class SdkInitTests : BaseUiTest() {
5656
}
5757
val transaction = Sentry.startTransaction("e2etests", "testInit")
5858
val sampleScenario = launchActivity<EmptyActivity>()
59+
5960
initSentry(true) {
6061
it.tracesSampleRate = 1.0
6162
it.profilesSampleRate = 1.0
6263
// We use the same executorService before and after closing the SDK
6364
it.executorService = options.executorService
6465
it.isDebug = true
6566
}
67+
68+
relayIdlingResource.increment()
6669
relayIdlingResource.increment()
6770
relayIdlingResource.increment()
6871
transaction.finish()
@@ -79,9 +82,19 @@ class SdkInitTests : BaseUiTest() {
7982
it.assertNoOtherItems()
8083
assertEquals("e2etests", transactionItem.transaction)
8184
}
82-
}
8385

84-
relay.assert {
86+
findEnvelope {
87+
assertEnvelopeTransaction(it.items.toList(), AndroidLogger()).transaction ==
88+
"EmptyActivity"
89+
}
90+
.assert {
91+
val transactionItem: SentryTransaction = it.assertTransaction()
92+
// Transaction-based Profiling is already in e2etests transaction, so it won't run again
93+
// here
94+
it.assertNoOtherItems()
95+
assertEquals("EmptyActivity", transactionItem.transaction)
96+
}
97+
8598
findEnvelope {
8699
assertEnvelopeTransaction(it.items.toList(), AndroidLogger()).transaction == "e2etests2"
87100
}
@@ -97,14 +110,6 @@ class SdkInitTests : BaseUiTest() {
97110
}
98111
}
99112

100-
@Test
101-
fun doubleInitDoesNotWait2() {
102-
repeat(150) {
103-
println("Run number $it")
104-
doubleInitDoesNotWait()
105-
}
106-
}
107-
108113
@Test
109114
fun doubleInitDoesNotWait() {
110115
relayIdlingResource.increment()

sentry-android-integration-tests/sentry-uitest-android/src/androidTest/java/io/sentry/uitest/android/UserFeedbackUiTest.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
2323
import io.sentry.Sentry
2424
import io.sentry.SentryEvent
2525
import io.sentry.SentryFeedbackOptions.SentryFeedbackCallback
26+
import io.sentry.SentryItemType
2627
import io.sentry.SentryOptions
2728
import io.sentry.android.core.AndroidLogger
2829
import io.sentry.android.core.R
@@ -471,6 +472,7 @@ class UserFeedbackUiTest : BaseUiTest() {
471472
// because it would block the espresso interactions (button click)
472473
it.feedbackOptions.onSubmitSuccess = SentryFeedbackCallback {
473474
relayIdlingResource.increment()
475+
relayIdlingResource.increment()
474476
}
475477
// Let's capture a replay, so we can check the replayId in the feedback
476478
if (enableReplay) {
@@ -511,6 +513,8 @@ class UserFeedbackUiTest : BaseUiTest() {
511513
)
512514
}
513515
}
516+
findEnvelope { it.items.first().header.type == SentryItemType.ReplayVideo }
517+
assertNoOtherEnvelopes()
514518
}
515519
}
516520

sentry-android-integration-tests/sentry-uitest-android/src/androidTest/java/io/sentry/uitest/android/mockservers/RelayAsserter.kt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
package io.sentry.uitest.android.mockservers
22

33
import io.sentry.EnvelopeReader
4-
import io.sentry.JsonSerializer
5-
import io.sentry.ProfilingTraceData
64
import io.sentry.Sentry
75
import io.sentry.SentryEnvelope
8-
import io.sentry.SentryEvent
9-
import io.sentry.SentryItemType
10-
import io.sentry.SentryOptions
11-
import io.sentry.protocol.SentryTransaction
126
import io.sentry.uitest.android.describeForTest
137
import java.io.IOException
148
import java.util.zip.GZIPInputStream

sentry/src/main/java/io/sentry/Sentry.java

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -311,18 +311,6 @@ private static void init(final @NotNull SentryOptions options, final boolean glo
311311
"Sentry has been already initialized. Previous configuration will be overwritten.");
312312
}
313313

314-
// load lazy fields of the options in a separate thread
315-
try {
316-
options.getExecutorService().submit(() -> options.loadLazyFields());
317-
} catch (RejectedExecutionException e) {
318-
options
319-
.getLogger()
320-
.log(
321-
SentryLevel.DEBUG,
322-
"Failed to call the executor. Lazy fields will not be loaded. Did you call Sentry.close()?",
323-
e);
324-
}
325-
326314
final IScopes scopes = getCurrentScopes();
327315
scopes.close(true);
328316

@@ -340,13 +328,24 @@ private static void init(final @NotNull SentryOptions options, final boolean glo
340328
globalScope.bindClient(new SentryClient(options));
341329

342330
// If the executorService passed in the init is the same that was previously closed, we have
343-
// to
344-
// set a new one
331+
// to set a new one
345332
if (options.getExecutorService().isClosed()) {
346333
options.setExecutorService(new SentryExecutorService(options));
347334
options.getExecutorService().prewarm();
348335
}
349336

337+
// load lazy fields of the options in a separate thread
338+
try {
339+
options.getExecutorService().submit(() -> options.loadLazyFields());
340+
} catch (RejectedExecutionException e) {
341+
options
342+
.getLogger()
343+
.log(
344+
SentryLevel.DEBUG,
345+
"Failed to call the executor. Lazy fields will not be loaded. Did you call Sentry.close()?",
346+
e);
347+
}
348+
350349
movePreviousSession(options);
351350
// when integrations are registered on Scopes ctor and async integrations are fired,
352351
// it might and actually happened that integrations called captureSomething

0 commit comments

Comments
 (0)