Add test that detects persistent caches without defaults

The test detects that the following caches miss their defaults:
* comment_context
* gerrit_file_diff
* git_file_diff
* git_modified_files
* git_tags
* groups_byuuid_persisted
* modified_files

They were muted for the time being and defaults will be provided in the
follow up.

Bug: Issue 15865
Change-Id: I3c67bdcd6b2a570e97f3ba0328535d602b7e116c
diff --git a/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/CacheSerializers.java b/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/CacheSerializers.java
index 8546981..387391e 100644
--- a/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/CacheSerializers.java
+++ b/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/CacheSerializers.java
@@ -13,10 +13,12 @@
 // limitations under the License.
 package com.googlesource.gerrit.modules.cache.chroniclemap;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.gerrit.server.cache.PersistentCacheDef;
 import com.google.gerrit.server.cache.serialize.CacheSerializer;
 import com.google.inject.Singleton;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 @Singleton
@@ -30,16 +32,6 @@
     registerCacheValueSerializer(cacheName, def.valueSerializer());
   }
 
-  static <K, V> void registerCacheKeySerializer(
-      String cacheName, CacheSerializer<K> keySerializer) {
-    keySerializers.computeIfAbsent(cacheName, (name) -> keySerializer);
-  }
-
-  static <K, V> void registerCacheValueSerializer(
-      String cacheName, CacheSerializer<V> valueSerializer) {
-    valueSerializers.computeIfAbsent(cacheName, (name) -> valueSerializer);
-  }
-
   @SuppressWarnings("unchecked")
   public static <K> CacheSerializer<K> getKeySerializer(String name) {
     if (keySerializers.containsKey(name)) {
@@ -55,4 +47,29 @@
     }
     throw new IllegalStateException("Could not find value serializer for " + name);
   }
+
+  @VisibleForTesting
+  static <K, V> void registerCacheKeySerializer(
+      String cacheName, CacheSerializer<K> keySerializer) {
+    keySerializers.computeIfAbsent(cacheName, (name) -> keySerializer);
+  }
+
+  @VisibleForTesting
+  static <K, V> void registerCacheValueSerializer(
+      String cacheName, CacheSerializer<V> valueSerializer) {
+    valueSerializers.computeIfAbsent(cacheName, (name) -> valueSerializer);
+  }
+
+  @VisibleForTesting
+  static Set<String> getSerializersNames() {
+    // caches registration during Gerrit's start is performed through registerCacheDef hence there
+    // is no need to check both maps for all serializers names
+    return keySerializers.keySet();
+  }
+
+  @VisibleForTesting
+  static void clear() {
+    keySerializers.clear();
+    valueSerializers.clear();
+  }
 }
diff --git a/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapCacheConfig.java b/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapCacheConfig.java
index 3c7f380..429d2cc 100644
--- a/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapCacheConfig.java
+++ b/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapCacheConfig.java
@@ -16,6 +16,7 @@
 import static com.googlesource.gerrit.modules.cache.chroniclemap.ChronicleMapCacheFactory.PRUNE_DELAY;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.flogger.FluentLogger;
 import com.google.gerrit.common.Nullable;
@@ -217,7 +218,7 @@
     return duration != null ? duration.getSeconds() : 0;
   }
 
-  protected static class Defaults {
+  static class Defaults {
 
     public static final long DEFAULT_MAX_ENTRIES = 1000;
 
@@ -230,7 +231,8 @@
 
     public static final Duration DEFAULT_PERSIST_INDEX_EVERY = Duration.ofMinutes(15);
 
-    private static final ImmutableMap<String, DefaultConfig> defaultMap =
+    @VisibleForTesting
+    static final ImmutableMap<String, DefaultConfig> defaultMap =
         new ImmutableMap.Builder<String, DefaultConfig>()
             .put("web_sessions", DefaultConfig.create(45, 221, 1000, 1))
             .put("change_notes", DefaultConfig.create(36, 10240, 1000, 3))
diff --git a/src/test/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapCacheConfigDefaultsIT.java b/src/test/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapCacheConfigDefaultsIT.java
new file mode 100644
index 0000000..b3efa35
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapCacheConfigDefaultsIT.java
@@ -0,0 +1,61 @@
+// 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.googlesource.gerrit.modules.cache.chroniclemap;
+
+import static com.google.common.truth.Truth.assertThat;
+import static java.util.stream.Collectors.toSet;
+
+import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.UseLocalDisk;
+import com.google.gerrit.acceptance.UseSsh;
+import com.google.gerrit.acceptance.config.GerritConfig;
+import com.googlesource.gerrit.modules.cache.chroniclemap.ChronicleMapCacheConfig.Defaults;
+import java.util.Set;
+import org.junit.Test;
+
+@UseLocalDisk
+@UseSsh
+public class ChronicleMapCacheConfigDefaultsIT extends AbstractDaemonTest {
+  @Override
+  public ChronicleMapCacheModule createModule() {
+    // CacheSerializers is accumulating cache names from different test executions in CI therefore
+    // it has to be cleared before this test
+    CacheSerializers.clear();
+    return new ChronicleMapCacheModule();
+  }
+
+  @Test
+  // the following caches are not persisted by default hence `diskLimit` needs to be set so that
+  // Gerrit persists them
+  @GerritConfig(name = "cache.change_notes.diskLimit", value = "1")
+  @GerritConfig(name = "cache.external_ids_map.diskLimit", value = "1")
+  public void shouldAllPersistentCachesHaveDefaultConfiguration() throws Exception {
+    Set<String> allCaches = CacheSerializers.getSerializersNames();
+
+    // for the time being filter out all caches that have no defaults so that the test passes
+    Set<String> missingDefaults =
+        Set.of(
+            "comment_context",
+            "gerrit_file_diff",
+            "git_file_diff",
+            "git_modified_files",
+            "git_tags",
+            "groups_byuuid_persisted",
+            "modified_files");
+    Set<String> expected =
+        allCaches.stream().filter(cache -> !missingDefaults.contains(cache)).collect(toSet());
+    assertThat(Defaults.defaultMap.keySet()).containsExactlyElementsIn(expected);
+  }
+}