Skip to content

Commit e6df0ad

Browse files
committed
add tests for lazy init, rework SentryId to cache string result
1 parent debd140 commit e6df0ad

File tree

3 files changed

+108
-21
lines changed

3 files changed

+108
-21
lines changed

sentry/src/main/java/io/sentry/protocol/SentryId.java

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,62 +16,55 @@ public final class SentryId implements JsonSerializable {
1616

1717
public static final SentryId EMPTY_ID = new SentryId(new UUID(0, 0));
1818

19-
private final @NotNull LazyEvaluator<UUID> lazyValue;
19+
private final @NotNull LazyEvaluator<String> lazyStringValue;
2020

2121
public SentryId() {
2222
this((UUID) null);
2323
}
2424

2525
public SentryId(@Nullable UUID uuid) {
2626
if (uuid != null) {
27-
this.lazyValue = new LazyEvaluator<>(() -> uuid);
27+
this.lazyStringValue = new LazyEvaluator<>(() -> uuidToSentryIdString(uuid));
2828
} else {
29-
this.lazyValue = new LazyEvaluator<>(UUID::randomUUID);
29+
this.lazyStringValue = new LazyEvaluator<>(() -> uuidToSentryIdString(UUID.randomUUID()));
3030
}
3131
}
3232

3333
public SentryId(final @NotNull String sentryIdString) {
34-
if (sentryIdString.length() != 32 && sentryIdString.length() != 36) {
34+
String normalized = StringUtils.normalizeUUID(sentryIdString);
35+
if (normalized.length() != 32 && normalized.length() != 36) {
3536
throw new IllegalArgumentException(
3637
"String representation of SentryId has either 32 (UUID no dashes) "
3738
+ "or 36 characters long (completed UUID). Received: "
3839
+ sentryIdString);
3940
}
40-
this.lazyValue =
41-
new LazyEvaluator<>(() -> fromStringSentryId(StringUtils.normalizeUUID(sentryIdString)));
41+
this.lazyStringValue = new LazyEvaluator<>(() -> uuidStringToSentryIdString(normalized));
4242
}
4343

4444
@Override
4545
public String toString() {
46-
return StringUtils.normalizeUUID(lazyValue.getValue().toString()).replace("-", "");
46+
return lazyStringValue.getValue();
4747
}
4848

4949
@Override
5050
public boolean equals(final @Nullable Object o) {
5151
if (this == o) return true;
5252
if (o == null || getClass() != o.getClass()) return false;
5353
SentryId sentryId = (SentryId) o;
54-
return lazyValue.getValue().compareTo(sentryId.lazyValue.getValue()) == 0;
54+
return lazyStringValue.getValue().compareTo(sentryId.lazyStringValue.getValue()) == 0;
5555
}
5656

5757
@Override
5858
public int hashCode() {
59-
return lazyValue.getValue().hashCode();
59+
return lazyStringValue.getValue().hashCode();
6060
}
6161

62-
private @NotNull UUID fromStringSentryId(@NotNull String sentryIdString) {
63-
if (sentryIdString.length() == 32) {
64-
// expected format, SentryId is a UUID without dashes
65-
sentryIdString =
66-
new StringBuilder(sentryIdString)
67-
.insert(8, "-")
68-
.insert(13, "-")
69-
.insert(18, "-")
70-
.insert(23, "-")
71-
.toString();
72-
}
62+
private @NotNull String uuidToSentryIdString(@NotNull UUID uuid) {
63+
return uuidStringToSentryIdString(uuid.toString());
64+
}
7365

74-
return UUID.fromString(sentryIdString);
66+
private @NotNull String uuidStringToSentryIdString(@NotNull String uuidString) {
67+
return StringUtils.normalizeUUID(uuidString).replace("-", "");
7568
}
7669

7770
// JsonSerializable

sentry/src/test/java/io/sentry/protocol/SentryIdTest.kt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package io.sentry.protocol
22

3+
import io.sentry.util.StringUtils
4+
import org.mockito.Mockito
5+
import org.mockito.kotlin.any
6+
import org.mockito.kotlin.never
7+
import org.mockito.kotlin.times
8+
import java.util.*
39
import kotlin.test.Test
410
import kotlin.test.assertEquals
511

@@ -10,4 +16,41 @@ class SentryIdTest {
1016
val id = SentryId("0000-0000")
1117
assertEquals("00000000000000000000000000000000", id.toString())
1218
}
19+
20+
@Test
21+
fun `UUID is not generated on initialization`() {
22+
val uuid = UUID.randomUUID()
23+
Mockito.mockStatic(UUID::class.java).use { utils ->
24+
utils.`when`<UUID> { UUID.randomUUID() }.thenReturn(uuid)
25+
val ignored = SentryId()
26+
utils.verify({ UUID.randomUUID() }, never())
27+
}
28+
}
29+
30+
@Test
31+
fun `UUID is generated only once`() {
32+
val uuid = UUID.randomUUID()
33+
Mockito.mockStatic(UUID::class.java).use { utils ->
34+
utils.`when`<UUID> { UUID.randomUUID() }.thenReturn(uuid)
35+
val sentryId = SentryId()
36+
val uuid1 = sentryId.toString()
37+
val uuid2 = sentryId.toString()
38+
39+
assertEquals(uuid1, uuid2)
40+
utils.verify({ UUID.randomUUID() }, times(1))
41+
}
42+
}
43+
44+
@Test
45+
fun `normalizeUUID is only called once`() {
46+
Mockito.mockStatic(StringUtils::class.java).use { utils ->
47+
utils.`when`<Any> { StringUtils.normalizeUUID(any()) }.thenReturn("00000000000000000000000000000000")
48+
val sentryId = SentryId()
49+
val uuid1 = sentryId.toString()
50+
val uuid2 = sentryId.toString()
51+
52+
assertEquals(uuid1, uuid2)
53+
utils.verify({ StringUtils.normalizeUUID(any()) }, times(1))
54+
}
55+
}
1356
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package io.sentry.protocol
2+
3+
import io.sentry.SpanId
4+
import io.sentry.util.StringUtils
5+
import org.mockito.Mockito
6+
import org.mockito.kotlin.any
7+
import org.mockito.kotlin.never
8+
import org.mockito.kotlin.times
9+
import java.util.*
10+
import kotlin.test.Test
11+
import kotlin.test.assertEquals
12+
13+
class SpanIdTest {
14+
15+
@Test
16+
fun `UUID is not generated on initialization`() {
17+
val uuid = UUID.randomUUID()
18+
Mockito.mockStatic(UUID::class.java).use { utils ->
19+
utils.`when`<UUID> { UUID.randomUUID() }.thenReturn(uuid)
20+
val ignored = SpanId()
21+
utils.verify({ UUID.randomUUID() }, never())
22+
}
23+
}
24+
25+
@Test
26+
fun `UUID is generated only once`() {
27+
val uuid = UUID.randomUUID()
28+
Mockito.mockStatic(java.util.UUID::class.java).use { utils ->
29+
utils.`when`<UUID> { UUID.randomUUID() }.thenReturn(uuid)
30+
val spanId = SpanId()
31+
val uuid1 = spanId.toString()
32+
val uuid2 = spanId.toString()
33+
34+
assertEquals(uuid1, uuid2)
35+
utils.verify({ UUID.randomUUID() }, times(1))
36+
}
37+
}
38+
39+
@Test
40+
fun `normalizeUUID is only called once`() {
41+
Mockito.mockStatic(StringUtils::class.java).use { utils ->
42+
utils.`when`<Any> { StringUtils.normalizeUUID(any()) }.thenReturn("00000000000000000000000000000000")
43+
val spanId = SpanId()
44+
val uuid1 = spanId.toString()
45+
val uuid2 = spanId.toString()
46+
47+
assertEquals(uuid1, uuid2)
48+
utils.verify({ StringUtils.normalizeUUID(any()) }, times(1))
49+
}
50+
}
51+
}

0 commit comments

Comments
 (0)