Skip to content

Commit

Permalink
RUMM-2497 SnapshotProcessor - do not write anything if there was no m…
Browse files Browse the repository at this point in the history
…utation resolved
  • Loading branch information
mariusc83 committed Sep 12, 2022
1 parent 6178adb commit 35c40fb
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 65 deletions.
1 change: 1 addition & 0 deletions detekt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1039,6 +1039,7 @@ datadog:
- "kotlin.collections.List.forEach(kotlin.Function1)"
- "kotlin.collections.List.getOrNull(kotlin.Int)"
- "kotlin.collections.List.isEmpty()"
- "kotlin.collections.List.isNotEmpty()"
- "kotlin.collections.List.joinToString(kotlin.CharSequence, kotlin.CharSequence, kotlin.CharSequence, kotlin.Int, kotlin.CharSequence, kotlin.Function1?)"
- "kotlin.collections.List.lastOrNull()"
- "kotlin.collections.List.lastOrNull(kotlin.Function1)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal class MutationResolver {
fun resolveMutations(
prevSnapshot: List<MobileSegment.Wireframe>,
currentSnapshot: List<MobileSegment.Wireframe>
): MobileSegment.MobileIncrementalData.MobileMutationData {
): MobileSegment.MobileIncrementalData.MobileMutationData? {
val prevSnapshotAsMap = prevSnapshot.associateBy { it.id() }.toMutableMap()
val updates: MutableList<MobileSegment.WireframeUpdateMutation> = LinkedList()
val adds: MutableList<MobileSegment.Add> = LinkedList()
Expand All @@ -31,11 +31,16 @@ internal class MutationResolver {
prevWireframe = currentWireframe
}
val removes = prevSnapshotAsMap.map { MobileSegment.Remove(it.key) }
return MobileSegment.MobileIncrementalData.MobileMutationData(
adds = adds,
removes = removes,
updates = updates
)

return if (adds.isNotEmpty() || removes.isNotEmpty() || updates.isNotEmpty()) {
MobileSegment.MobileIncrementalData.MobileMutationData(
adds = adds,
removes = removes,
updates = updates
)
} else {
null
}
}

private fun resolveUpdateMutation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,20 +137,27 @@ internal class SnapshotProcessor(
records.add(focusRecord)
}

val record = if (fullSnapshotRequired) {
MobileSegment.MobileRecord.MobileFullSnapshotRecord(
timestamp,
MobileSegment.Data(wireframes)
if (fullSnapshotRequired) {
records.add(
MobileSegment.MobileRecord.MobileFullSnapshotRecord(
timestamp,
MobileSegment.Data(wireframes)
)
)
} else {
MobileSegment.MobileRecord.MobileIncrementalSnapshotRecord(
timestamp,
mutationResolver.resolveMutations(prevSnapshot, wireframes)
)
mutationResolver.resolveMutations(prevSnapshot, wireframes)?.let {
records.add(
MobileSegment.MobileRecord.MobileIncrementalSnapshotRecord(
timestamp,
it
)
)
}
}
records.add(record)
prevSnapshot = wireframes
writer.write(bundleRecordInEnrichedRecord(newRumContext, records))
if (records.isNotEmpty()) {
writer.write(bundleRecordInEnrichedRecord(newRumContext, records))
}
}

private fun isLastFullSnapshotTime(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.datadog.android.sessionreplay.utils.ForgeConfigurator
import fr.xgouchet.elmyr.Forge
import fr.xgouchet.elmyr.junit5.ForgeConfiguration
import fr.xgouchet.elmyr.junit5.ForgeExtension
import java.util.ArrayList
import java.util.LinkedList
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
Expand Down Expand Up @@ -60,9 +61,9 @@ internal class MutationResolverTest {
)

// Then
assertThat(mutations.adds).isEqualTo(expectedAdditions)
assertThat(mutations.removes).isNullOrEmpty()
assertThat(mutations.updates).isNullOrEmpty()
assertThat(mutations?.adds).isEqualTo(expectedAdditions)
assertThat(mutations?.removes).isNullOrEmpty()
assertThat(mutations?.updates).isNullOrEmpty()
}

@Test
Expand All @@ -87,9 +88,9 @@ internal class MutationResolverTest {
)

// Then
assertThat(mutations.adds).isEqualTo(expectedAdds)
assertThat(mutations.removes).isNullOrEmpty()
assertThat(mutations.updates).isNullOrEmpty()
assertThat(mutations?.adds).isEqualTo(expectedAdds)
assertThat(mutations?.removes).isNullOrEmpty()
assertThat(mutations?.updates).isNullOrEmpty()
}

// endregion
Expand All @@ -115,9 +116,9 @@ internal class MutationResolverTest {
)

// Then
assertThat(mutations.adds).isNullOrEmpty()
assertThat(mutations.removes).isEqualTo(expectedRemovals)
assertThat(mutations.updates).isNullOrEmpty()
assertThat(mutations?.adds).isNullOrEmpty()
assertThat(mutations?.removes).isEqualTo(expectedRemovals)
assertThat(mutations?.updates).isNullOrEmpty()
}

// endregion
Expand Down Expand Up @@ -150,9 +151,9 @@ internal class MutationResolverTest {
)

// Then
assertThat(mutations.adds).isNullOrEmpty()
assertThat(mutations.removes).isNullOrEmpty()
assertThat(mutations.updates).isEqualTo(expectedUpdates)
assertThat(mutations?.adds).isNullOrEmpty()
assertThat(mutations?.removes).isNullOrEmpty()
assertThat(mutations?.updates).isEqualTo(expectedUpdates)
}

@Test
Expand Down Expand Up @@ -181,9 +182,9 @@ internal class MutationResolverTest {
)

// Then
assertThat(mutations.adds).isNullOrEmpty()
assertThat(mutations.removes).isNullOrEmpty()
assertThat(mutations.updates).isEqualTo(expectedUpdates)
assertThat(mutations?.adds).isNullOrEmpty()
assertThat(mutations?.removes).isNullOrEmpty()
assertThat(mutations?.updates).isEqualTo(expectedUpdates)
}

@Test
Expand Down Expand Up @@ -218,9 +219,9 @@ internal class MutationResolverTest {
)

// Then
assertThat(mutations.adds).isNullOrEmpty()
assertThat(mutations.removes).isNullOrEmpty()
assertThat(mutations.updates).isEqualTo(expectedUpdates)
assertThat(mutations?.adds).isNullOrEmpty()
assertThat(mutations?.removes).isNullOrEmpty()
assertThat(mutations?.updates).isEqualTo(expectedUpdates)
}

@Test
Expand Down Expand Up @@ -256,9 +257,9 @@ internal class MutationResolverTest {
)

// Then
assertThat(mutations.adds).isNullOrEmpty()
assertThat(mutations.removes).isNullOrEmpty()
assertThat(mutations.updates).isEqualTo(expectedUpdates)
assertThat(mutations?.adds).isNullOrEmpty()
assertThat(mutations?.removes).isNullOrEmpty()
assertThat(mutations?.updates).isEqualTo(expectedUpdates)
}

@Test
Expand All @@ -284,9 +285,9 @@ internal class MutationResolverTest {
)

// Then
assertThat(mutations.adds).isNullOrEmpty()
assertThat(mutations.removes).isNullOrEmpty()
assertThat(mutations.updates).isNullOrEmpty()
assertThat(mutations?.adds).isNullOrEmpty()
assertThat(mutations?.removes).isNullOrEmpty()
assertThat(mutations?.updates).isNullOrEmpty()
}

// endregion
Expand Down Expand Up @@ -319,9 +320,9 @@ internal class MutationResolverTest {
)

// Then
assertThat(mutations.adds).isNullOrEmpty()
assertThat(mutations.removes).isNullOrEmpty()
assertThat(mutations.updates).isEqualTo(expectedUpdates)
assertThat(mutations?.adds).isNullOrEmpty()
assertThat(mutations?.removes).isNullOrEmpty()
assertThat(mutations?.updates).isEqualTo(expectedUpdates)
}

@Test
Expand Down Expand Up @@ -350,9 +351,9 @@ internal class MutationResolverTest {
)

// Then
assertThat(mutations.adds).isNullOrEmpty()
assertThat(mutations.removes).isNullOrEmpty()
assertThat(mutations.updates).isEqualTo(expectedUpdates)
assertThat(mutations?.adds).isNullOrEmpty()
assertThat(mutations?.removes).isNullOrEmpty()
assertThat(mutations?.updates).isEqualTo(expectedUpdates)
}

@Test
Expand Down Expand Up @@ -387,9 +388,9 @@ internal class MutationResolverTest {
)

// Then
assertThat(mutations.adds).isNullOrEmpty()
assertThat(mutations.removes).isNullOrEmpty()
assertThat(mutations.updates).isEqualTo(expectedUpdates)
assertThat(mutations?.adds).isNullOrEmpty()
assertThat(mutations?.removes).isNullOrEmpty()
assertThat(mutations?.updates).isEqualTo(expectedUpdates)
}

@Test
Expand Down Expand Up @@ -425,9 +426,9 @@ internal class MutationResolverTest {
)

// Then
assertThat(mutations.adds).isNullOrEmpty()
assertThat(mutations.removes).isNullOrEmpty()
assertThat(mutations.updates).isEqualTo(expectedUpdates)
assertThat(mutations?.adds).isNullOrEmpty()
assertThat(mutations?.removes).isNullOrEmpty()
assertThat(mutations?.updates).isEqualTo(expectedUpdates)
}

@Test
Expand Down Expand Up @@ -455,9 +456,9 @@ internal class MutationResolverTest {
)

// Then
assertThat(mutations.adds).isNullOrEmpty()
assertThat(mutations.removes).isNullOrEmpty()
assertThat(mutations.updates).isEqualTo(expectedUpdates)
assertThat(mutations?.adds).isNullOrEmpty()
assertThat(mutations?.removes).isNullOrEmpty()
assertThat(mutations?.updates).isEqualTo(expectedUpdates)
}

@Test
Expand Down Expand Up @@ -493,9 +494,9 @@ internal class MutationResolverTest {
)

// Then
assertThat(mutations.adds).isNullOrEmpty()
assertThat(mutations.removes).isNullOrEmpty()
assertThat(mutations.updates).isEqualTo(expectedUpdates)
assertThat(mutations?.adds).isNullOrEmpty()
assertThat(mutations?.removes).isNullOrEmpty()
assertThat(mutations?.updates).isEqualTo(expectedUpdates)
}

@Test
Expand Down Expand Up @@ -542,13 +543,13 @@ internal class MutationResolverTest {
)

// Then
assertThat(mutations.adds).isNullOrEmpty()
assertThat(mutations.removes).isNullOrEmpty()
assertThat(mutations.updates).isEqualTo(expectedUpdates)
assertThat(mutations?.adds).isNullOrEmpty()
assertThat(mutations?.removes).isNullOrEmpty()
assertThat(mutations?.updates).isEqualTo(expectedUpdates)
}

@Test
fun `M return empty mutations W resolveMutation {Text wireframes types are not matching }`(
fun `M return null W resolveMutation {Text wireframes types are not matching }`(
forge: Forge
) {
// Given
Expand All @@ -570,9 +571,53 @@ internal class MutationResolverTest {
)

// Then
assertThat(mutations.adds).isNullOrEmpty()
assertThat(mutations.removes).isNullOrEmpty()
assertThat(mutations.updates).isNullOrEmpty()
assertThat(mutations).isNull()
}

// endregion

// region no mutation

@Test
fun `M return null W resolveMutation { Text wireframes, no mutation }`(
forge: Forge
) {
// Given
val fakePrevSnapshot = forge.aList(size = forge.anInt(min = 2, max = 10)) {
forge.getForgery(MobileSegment.Wireframe.TextWireframe::class.java)
}

val fakeCurrentSnapshot = ArrayList(fakePrevSnapshot)

// When
val mutations = testedMutationResolver.resolveMutations(
fakePrevSnapshot,
fakeCurrentSnapshot
)

// Then
assertThat(mutations).isNull()
}

@Test
fun `M return null W resolveMutation { Shape wireframes, no mutation }`(
forge: Forge
) {
// Given
val fakePrevSnapshot = forge.aList(size = forge.anInt(min = 2, max = 10)) {
forge.getForgery(MobileSegment.Wireframe.ShapeWireframe::class.java)
}

val fakeCurrentSnapshot = ArrayList(fakePrevSnapshot)

// When
val mutations = testedMutationResolver.resolveMutations(
fakePrevSnapshot,
fakeCurrentSnapshot
)

// Then
assertThat(mutations).isNull()
}

// endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,38 @@ internal class SnapshotProcessorTest {
assertThat(incrementalSnapshotRecord.data).isEqualTo(fakeMutationData)
}

@Test
fun `M do nothing W process { no mutation was detected }`(forge: Forge) {
// Given
val fakeSnapshot1 = forge.aSingleLevelSnapshot()
val fakeSnapshot2 = fakeSnapshot1.copy()
val fakeFlattenedSnapshot1 = forge.aList {
getForgery(MobileSegment.Wireframe::class.java)
}
val fakeFlattenedSnapshot2 = ArrayList(fakeFlattenedSnapshot1)
whenever(mockNodeFlattener.flattenNode(fakeSnapshot1)).thenReturn(fakeFlattenedSnapshot1)
whenever(mockNodeFlattener.flattenNode(fakeSnapshot2)).thenReturn(fakeFlattenedSnapshot2)
whenever(
mockMutationResolver.resolveMutations(
fakeFlattenedSnapshot1,
fakeFlattenedSnapshot2
)
).thenReturn(null)
testedProcessor.process(fakeSnapshot1)

// When
testedProcessor.process(fakeSnapshot2)

// Then
// We should only send the FullSnapshotRecord. The IncrementalSnapshotRecord will not be
// send as there was no mutation data detected.
val captor = argumentCaptor<EnrichedRecord>()
verify(mockWriter, times(1)).write(captor.capture())
assertThat(captor.firstValue.records.size).isEqualTo(3)
assertThat(captor.firstValue.records[2])
.isInstanceOf(MobileSegment.MobileRecord.MobileFullSnapshotRecord::class.java)
}

// region TouchData

@Test
Expand Down

0 comments on commit 35c40fb

Please sign in to comment.