Merge "Log when notifications in the RankingMap are not in the Collection" into tm-qpr-dev am: d7a0392228

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19744601

Change-Id: I3636fe1ba5682f67861304e56496fe5e6ead87ba
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Jeff DeCew
2022-08-29 14:08:35 +00:00
committed by Automerger Merge Worker
7 changed files with 385 additions and 143 deletions

View File

@@ -88,9 +88,9 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.En
import com.android.systemui.statusbar.notification.collection.notifcollection.EntryUpdatedEvent;
import com.android.systemui.statusbar.notification.collection.notifcollection.InitEntryEvent;
import com.android.systemui.statusbar.notification.collection.notifcollection.InternalNotifUpdater;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionInconsistencyTracker;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionLogger;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionLoggerKt;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifEvent;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
@@ -112,7 +112,6 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -151,6 +150,7 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
private final Executor mBgExecutor;
private final LogBufferEulogizer mEulogizer;
private final DumpManager mDumpManager;
private final NotifCollectionInconsistencyTracker mInconsistencyTracker;
private final Map<String, NotificationEntry> mNotificationSet = new ArrayMap<>();
private final Collection<NotificationEntry> mReadOnlyNotificationSet =
@@ -162,7 +162,6 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
private final List<NotifLifetimeExtender> mLifetimeExtenders = new ArrayList<>();
private final List<NotifDismissInterceptor> mDismissInterceptors = new ArrayList<>();
private Set<String> mNotificationsWithoutRankings = Collections.emptySet();
private Queue<NotifEvent> mEventQueue = new ArrayDeque<>();
@@ -188,6 +187,7 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
mBgExecutor = bgExecutor;
mEulogizer = logBufferEulogizer;
mDumpManager = dumpManager;
mInconsistencyTracker = new NotifCollectionInconsistencyTracker(mLogger);
}
/** Initializes the NotifCollection and registers it to receive notification events. */
@@ -199,6 +199,7 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
mAttached = true;
mDumpManager.registerDumpable(TAG, this);
groupCoalescer.setNotificationHandler(mNotifHandler);
mInconsistencyTracker.attach(mNotificationSet::keySet, groupCoalescer::getCoalescedKeySet);
}
/**
@@ -598,14 +599,9 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
}
}
}
NotifCollectionLoggerKt.maybeLogInconsistentRankings(
mLogger,
mNotificationsWithoutRankings,
currentEntriesWithoutRankings,
rankingMap
);
mNotificationsWithoutRankings = currentEntriesWithoutRankings == null
? Collections.emptySet() : currentEntriesWithoutRankings.keySet();
mInconsistencyTracker.logNewMissingNotifications(rankingMap);
mInconsistencyTracker.logNewInconsistentRankings(currentEntriesWithoutRankings, rankingMap);
if (currentEntriesWithoutRankings != null && mNotifPipelineFlags.removeUnrankedNotifs()) {
for (NotificationEntry entry : currentEntriesWithoutRankings.values()) {
entry.mCancellationReason = REASON_UNKNOWN;
@@ -864,10 +860,7 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
true,
"\t\t"));
pw.println("\n\tmNotificationsWithoutRankings: " + mNotificationsWithoutRankings.size());
for (String key : mNotificationsWithoutRankings) {
pw.println("\t * : " + key);
}
mInconsistencyTracker.dump(pw);
}
@Override

View File

@@ -39,9 +39,11 @@ import com.android.systemui.util.time.SystemClock;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
@@ -118,6 +120,11 @@ public class GroupCoalescer implements Dumpable, PipelineDumpable {
mHandler = handler;
}
/** @return the set of notification keys currently in the coalescer */
public Set<String> getCoalescedKeySet() {
return Collections.unmodifiableSet(mCoalescedEvents.keySet());
}
private final NotificationHandler mListener = new NotificationHandler() {
@Override
public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {

View File

@@ -0,0 +1,123 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.notification.collection.notifcollection
import android.service.notification.NotificationListenerService.RankingMap
import android.util.ArrayMap
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import java.io.PrintWriter
class NotifCollectionInconsistencyTracker(val logger: NotifCollectionLogger) {
fun attach(
collectedKeySetAccessor: () -> Set<String>,
coalescedKeySetAccessor: () -> Set<String>,
) {
if (attached) {
throw RuntimeException("attach() called twice")
}
attached = true
this.collectedKeySetAccessor = collectedKeySetAccessor
this.coalescedKeySetAccessor = coalescedKeySetAccessor
}
fun logNewMissingNotifications(rankingMap: RankingMap) {
val currentCollectedKeys = collectedKeySetAccessor()
val currentCoalescedKeys = coalescedKeySetAccessor()
val newMissingNotifications = rankingMap.orderedKeys.asSequence()
.filter { it !in currentCollectedKeys }
.filter { it !in currentCoalescedKeys }
.toSet()
maybeLogMissingNotifications(missingNotifications, newMissingNotifications)
missingNotifications = newMissingNotifications
}
@VisibleForTesting
fun maybeLogMissingNotifications(
oldMissingKeys: Set<String>,
newMissingKeys: Set<String>,
) {
if (oldMissingKeys.isEmpty() && newMissingKeys.isEmpty()) return
if (oldMissingKeys == newMissingKeys) return
(oldMissingKeys - newMissingKeys).sorted().let { justFound ->
if (justFound.isNotEmpty()) {
logger.logFoundNotifications(justFound, newMissingKeys.size)
}
}
(newMissingKeys - oldMissingKeys).sorted().let { goneMissing ->
if (goneMissing.isNotEmpty()) {
logger.logMissingNotifications(goneMissing, newMissingKeys.size)
}
}
}
fun logNewInconsistentRankings(
currentEntriesWithoutRankings: ArrayMap<String, NotificationEntry>?,
rankingMap: RankingMap,
) {
maybeLogInconsistentRankings(
notificationsWithoutRankings,
currentEntriesWithoutRankings ?: emptyMap(),
rankingMap
)
notificationsWithoutRankings = currentEntriesWithoutRankings?.keys ?: emptySet()
}
@VisibleForTesting
fun maybeLogInconsistentRankings(
oldKeysWithoutRankings: Set<String>,
newEntriesWithoutRankings: Map<String, NotificationEntry>,
rankingMap: RankingMap,
) {
if (oldKeysWithoutRankings.isEmpty() && newEntriesWithoutRankings.isEmpty()) return
if (oldKeysWithoutRankings == newEntriesWithoutRankings.keys) return
val newlyConsistent: List<String> = oldKeysWithoutRankings
.mapNotNull { key ->
key.takeIf { key !in newEntriesWithoutRankings }
.takeIf { key in rankingMap.orderedKeys }
}.sorted()
if (newlyConsistent.isNotEmpty()) {
val totalInconsistent: Int = newEntriesWithoutRankings.size
logger.logRecoveredRankings(newlyConsistent, totalInconsistent)
}
val newlyInconsistent: List<NotificationEntry> = newEntriesWithoutRankings
.mapNotNull { (key, entry) ->
entry.takeIf { key !in oldKeysWithoutRankings }
}.sortedBy { it.key }
if (newlyInconsistent.isNotEmpty()) {
val totalInconsistent: Int = newEntriesWithoutRankings.size
logger.logMissingRankings(newlyInconsistent, totalInconsistent, rankingMap)
}
}
fun dump(pw: PrintWriter) {
pw.println("notificationsWithoutRankings: ${notificationsWithoutRankings.size}")
for (key in notificationsWithoutRankings) {
pw.println("\t * : $key")
}
pw.println("missingNotifications: ${missingNotifications.size}")
for (key in missingNotifications) {
pw.println("\t * : $key")
}
}
private var attached: Boolean = false
private lateinit var collectedKeySetAccessor: (() -> Set<String>)
private lateinit var coalescedKeySetAccessor: (() -> Set<String>)
private var notificationsWithoutRankings = emptySet<String>()
private var missingNotifications = emptySet<String>()
}

View File

@@ -215,8 +215,9 @@ class NotifCollectionLogger @Inject constructor(
})
}
fun logRecoveredRankings(newlyConsistentKeys: List<String>) {
fun logRecoveredRankings(newlyConsistentKeys: List<String>, totalInconsistent: Int) {
buffer.log(TAG, INFO, {
int1 = totalInconsistent
int1 = newlyConsistentKeys.size
str1 = newlyConsistentKeys.joinToString { logKey(it) ?: "null" }
}, {
@@ -224,6 +225,32 @@ class NotifCollectionLogger @Inject constructor(
})
}
fun logMissingNotifications(
newlyMissingKeys: List<String>,
totalMissing: Int,
) {
buffer.log(TAG, WARNING, {
int1 = totalMissing
int2 = newlyMissingKeys.size
str1 = newlyMissingKeys.joinToString { logKey(it) ?: "null" }
}, {
"Collection missing $int1 entries in ranking update. Just lost $int2: $str1"
})
}
fun logFoundNotifications(
newlyFoundKeys: List<String>,
totalMissing: Int,
) {
buffer.log(TAG, INFO, {
int1 = totalMissing
int2 = newlyFoundKeys.size
str1 = newlyFoundKeys.joinToString { logKey(it) ?: "null" }
}, {
"Collection missing $int1 entries in ranking update. Just found $int2: $str1"
})
}
fun logRemoteExceptionOnNotificationClear(entry: NotificationEntry, e: RemoteException) {
buffer.log(TAG, WTF, {
str1 = entry.logKey
@@ -362,29 +389,4 @@ class NotifCollectionLogger @Inject constructor(
}
}
fun maybeLogInconsistentRankings(
logger: NotifCollectionLogger,
oldKeysWithoutRankings: Set<String>,
newEntriesWithoutRankings: Map<String, NotificationEntry>?,
rankingMap: RankingMap
) {
if (oldKeysWithoutRankings.isEmpty() && newEntriesWithoutRankings == null) return
val newlyConsistent: List<String> = oldKeysWithoutRankings
.mapNotNull { key ->
key.takeIf { key !in (newEntriesWithoutRankings ?: emptyMap()) }
.takeIf { key in rankingMap.orderedKeys }
}.sorted()
if (newlyConsistent.isNotEmpty()) {
logger.logRecoveredRankings(newlyConsistent)
}
val newlyInconsistent: List<NotificationEntry> = newEntriesWithoutRankings
?.mapNotNull { (key, entry) ->
entry.takeIf { key !in oldKeysWithoutRankings }
}?.sortedBy { it.key } ?: emptyList()
if (newlyInconsistent.isNotEmpty()) {
val totalInconsistent: Int = newEntriesWithoutRankings?.size ?: 0
logger.logMissingRankings(newlyInconsistent, totalInconsistent, rankingMap)
}
}
private const val TAG = "NotifCollection"

View File

@@ -1518,7 +1518,7 @@ public class NotifCollectionTest extends SysuiTestCase {
verify(mCollectionListener).onRankingApplied();
verifyNoMoreInteractions(mCollectionListener);
verify(mLogger).logMissingRankings(eq(List.of(entry1)), eq(1), any());
verify(mLogger, never()).logRecoveredRankings(any());
verify(mLogger, never()).logRecoveredRankings(any(), anyInt());
clearInvocations(mCollectionListener, mLogger);
// WHEN a ranking update includes key1 again
@@ -1530,7 +1530,7 @@ public class NotifCollectionTest extends SysuiTestCase {
verify(mCollectionListener).onRankingApplied();
verifyNoMoreInteractions(mCollectionListener);
verify(mLogger, never()).logMissingRankings(any(), anyInt(), any());
verify(mLogger).logRecoveredRankings(eq(List.of(key1)));
verify(mLogger).logRecoveredRankings(eq(List.of(key1)), eq(0));
}
@Test
@@ -1556,7 +1556,7 @@ public class NotifCollectionTest extends SysuiTestCase {
verify(mCollectionListener).onRankingApplied();
verifyNoMoreInteractions(mCollectionListener);
verify(mLogger).logMissingRankings(eq(List.of(entry1)), eq(1), any());
verify(mLogger, never()).logRecoveredRankings(any());
verify(mLogger, never()).logRecoveredRankings(any(), anyInt());
clearInvocations(mCollectionListener, mLogger);
// WHEN a ranking update includes key1 again
@@ -1568,7 +1568,7 @@ public class NotifCollectionTest extends SysuiTestCase {
verify(mCollectionListener).onRankingApplied();
verifyNoMoreInteractions(mCollectionListener);
verify(mLogger, never()).logMissingRankings(any(), anyInt(), any());
verify(mLogger).logRecoveredRankings(eq(List.of(key1)));
verify(mLogger).logRecoveredRankings(eq(List.of(key1)), eq(0));
}
@Test

View File

@@ -0,0 +1,215 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.notification.collection.notifcollection
import android.service.notification.NotificationListenerService.RankingMap
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
@SmallTest
@RunWith(AndroidTestingRunner::class)
@RunWithLooper
class NotifCollectionInconsistencyTrackerTest : SysuiTestCase() {
private val logger: NotifCollectionLogger = mock()
private val entry1: NotificationEntry = NotificationEntryBuilder().setId(1).build()
private val entry2: NotificationEntry = NotificationEntryBuilder().setId(2).build()
private val collectionSet = mutableSetOf<String>()
private val coalescedSet = mutableSetOf<String>()
private lateinit var inconsistencyTracker: NotifCollectionInconsistencyTracker
private fun mapOfEntries(vararg entries: NotificationEntry): Map<String, NotificationEntry> =
entries.associateBy { it.key }
private fun rankingMapOf(vararg entries: NotificationEntry): RankingMap =
RankingMap(entries.map { it.ranking }.toTypedArray())
@Before
fun setUp() {
inconsistencyTracker = NotifCollectionInconsistencyTracker(logger)
inconsistencyTracker.attach({ collectionSet }, { coalescedSet })
collectionSet.clear()
coalescedSet.clear()
}
@Test
fun maybeLogInconsistentRankings_logsNewlyInconsistentRanking() {
val rankingMap = rankingMapOf(entry1)
inconsistencyTracker.maybeLogInconsistentRankings(
oldKeysWithoutRankings = emptySet(),
newEntriesWithoutRankings = mapOfEntries(entry2),
rankingMap = rankingMap
)
verify(logger).logMissingRankings(
newlyInconsistentEntries = eq(listOf(entry2)),
totalInconsistent = eq(1),
rankingMap = eq(rankingMap),
)
verifyNoMoreInteractions(logger)
}
@Test
fun maybeLogInconsistentRankings_doesNotLogAlreadyInconsistentRanking() {
inconsistencyTracker.maybeLogInconsistentRankings(
oldKeysWithoutRankings = setOf(entry2.key),
newEntriesWithoutRankings = mapOfEntries(entry2),
rankingMap = rankingMapOf(entry1)
)
verifyNoMoreInteractions(logger)
}
@Test
fun maybeLogInconsistentRankings_logsWhenRankingIsAdded() {
inconsistencyTracker.maybeLogInconsistentRankings(
oldKeysWithoutRankings = setOf(entry2.key),
newEntriesWithoutRankings = mapOfEntries(),
rankingMap = rankingMapOf(entry1, entry2)
)
verify(logger).logRecoveredRankings(
newlyConsistentKeys = eq(listOf(entry2.key)),
totalInconsistent = eq(0),
)
verifyNoMoreInteractions(logger)
}
@Test
fun maybeLogInconsistentRankings_doesNotLogsWhenEntryIsRemoved() {
inconsistencyTracker.maybeLogInconsistentRankings(
oldKeysWithoutRankings = setOf(entry2.key),
newEntriesWithoutRankings = mapOfEntries(),
rankingMap = rankingMapOf(entry1)
)
verifyNoMoreInteractions(logger)
}
@Test
fun maybeLogMissingNotifications_logsNewlyMissingNotifications() {
inconsistencyTracker.maybeLogMissingNotifications(
oldMissingKeys = setOf("a"),
newMissingKeys = setOf("a", "b"),
)
verify(logger).logMissingNotifications(
newlyMissingKeys = eq(listOf("b")),
totalMissing = eq(2),
)
verifyNoMoreInteractions(logger)
}
@Test
fun maybeLogMissingNotifications_logsNoLongerMissingNotifications() {
inconsistencyTracker.maybeLogMissingNotifications(
oldMissingKeys = setOf("a", "b"),
newMissingKeys = setOf("a"),
)
verify(logger).logFoundNotifications(
newlyFoundKeys = eq(listOf("b")),
totalMissing = eq(1),
)
verifyNoMoreInteractions(logger)
}
@Test
fun maybeLogMissingNotifications_logsBothAtOnce() {
inconsistencyTracker.maybeLogMissingNotifications(
oldMissingKeys = setOf("a"),
newMissingKeys = setOf("b"),
)
verify(logger).logFoundNotifications(
newlyFoundKeys = eq(listOf("a")),
totalMissing = eq(1),
)
verify(logger).logMissingNotifications(
newlyMissingKeys = eq(listOf("b")),
totalMissing = eq(1),
)
verifyNoMoreInteractions(logger)
}
@Test
fun maybeLogMissingNotifications_logsNothingWhenNoChange() {
inconsistencyTracker.maybeLogMissingNotifications(
oldMissingKeys = setOf("a"),
newMissingKeys = setOf("a"),
)
verifyNoMoreInteractions(logger)
}
@Test
fun logNewMissingNotifications_doesNotLogForConsistentSets() {
inconsistencyTracker.logNewMissingNotifications(rankingMapOf())
verifyNoMoreInteractions(logger)
collectionSet.add(entry1.key)
inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1))
verifyNoMoreInteractions(logger)
coalescedSet.add(entry2.key)
inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1, entry2))
verifyNoMoreInteractions(logger)
coalescedSet.add(entry1.key)
inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1, entry2))
verifyNoMoreInteractions(logger)
coalescedSet.remove(entry1.key)
collectionSet.remove(entry1.key)
inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry2))
verifyNoMoreInteractions(logger)
coalescedSet.remove(entry2.key)
inconsistencyTracker.logNewMissingNotifications(rankingMapOf())
verifyNoMoreInteractions(logger)
}
@Test
fun logNewMissingNotifications_logsAsExpected() {
inconsistencyTracker.logNewMissingNotifications(rankingMapOf())
verifyNoMoreInteractions(logger)
collectionSet.add(entry1.key)
inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1, entry2))
verify(logger).logMissingNotifications(
newlyMissingKeys = eq(listOf(entry2.key)),
totalMissing = eq(1),
)
verifyNoMoreInteractions(logger)
clearInvocations(logger)
inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1, entry2))
verifyNoMoreInteractions(logger)
coalescedSet.add(entry2.key)
inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1, entry2))
verify(logger).logFoundNotifications(
newlyFoundKeys = eq(listOf(entry2.key)),
totalMissing = eq(0),
)
verifyNoMoreInteractions(logger)
clearInvocations(logger)
}
}

View File

@@ -1,98 +0,0 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.notification.collection.notifcollection
import android.service.notification.NotificationListenerService.RankingMap
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
@SmallTest
@RunWith(AndroidTestingRunner::class)
@RunWithLooper
class NotifCollectionLoggerTest : SysuiTestCase() {
private val logger: NotifCollectionLogger = mock()
private val entry1: NotificationEntry = NotificationEntryBuilder().setId(1).build()
private val entry2: NotificationEntry = NotificationEntryBuilder().setId(2).build()
private fun mapOfEntries(vararg entries: NotificationEntry): Map<String, NotificationEntry> =
entries.associateBy { it.key }
private fun rankingMapOf(vararg entries: NotificationEntry): RankingMap =
RankingMap(entries.map { it.ranking }.toTypedArray())
@Test
fun testMaybeLogInconsistentRankings_logsNewlyInconsistentRanking() {
val rankingMap = rankingMapOf(entry1)
maybeLogInconsistentRankings(
logger = logger,
oldKeysWithoutRankings = emptySet(),
newEntriesWithoutRankings = mapOfEntries(entry2),
rankingMap = rankingMap
)
verify(logger).logMissingRankings(
newlyInconsistentEntries = eq(listOf(entry2)),
totalInconsistent = eq(1),
rankingMap = eq(rankingMap),
)
verifyNoMoreInteractions(logger)
}
@Test
fun testMaybeLogInconsistentRankings_doesNotLogAlreadyInconsistentRanking() {
maybeLogInconsistentRankings(
logger = logger,
oldKeysWithoutRankings = setOf(entry2.key),
newEntriesWithoutRankings = mapOfEntries(entry2),
rankingMap = rankingMapOf(entry1)
)
verifyNoMoreInteractions(logger)
}
@Test
fun testMaybeLogInconsistentRankings_logsWhenRankingIsAdded() {
maybeLogInconsistentRankings(
logger = logger,
oldKeysWithoutRankings = setOf(entry2.key),
newEntriesWithoutRankings = mapOfEntries(),
rankingMap = rankingMapOf(entry1, entry2)
)
verify(logger).logRecoveredRankings(
newlyConsistentKeys = eq(listOf(entry2.key)),
)
verifyNoMoreInteractions(logger)
}
@Test
fun testMaybeLogInconsistentRankings_doesNotLogsWhenEntryIsRemoved() {
maybeLogInconsistentRankings(
logger = logger,
oldKeysWithoutRankings = setOf(entry2.key),
newEntriesWithoutRankings = mapOfEntries(),
rankingMap = rankingMapOf(entry1)
)
verifyNoMoreInteractions(logger)
}
}