@Test
public void testPutIfNotExists() throws Exception {

    final Random random = new Random();
    final String name = "dir_" + Math.abs(random.nextInt());
    final Long id;
    ScopedValue<String> scopedName = globalScope.wrap(name);
    FDBReverseDirectoryCache rdc = fdb.getReverseDirectoryCache();
    try (FDBRecordContext context = openContext()) {
        Transaction tr = context.ensureActive();
        id = Tuple.fromBytes(DirectoryLayer.getDefault().createOrOpen(tr, PathUtil.from(name)).get().pack()).getLong(0);
        commit(context);
    }
    // Initial store should be considered a hard miss
    try (FDBRecordContext context = openContext()) {
        rdc.putIfNotExists(context, scopedName, id).get();
        // A few more calls to make sure that we only put it in once
        rdc.putIfNotExists(context, scopedName, id).get();
        rdc.putIfNotExists(context, scopedName, id).get();
        rdc.putIfNotExists(context, scopedName, id).get();
        assertEquals(3L, rdc.getPersistentCacheHitCount());
        assertEquals(1L, rdc.getPersistentCacheMissCount());
        assertEquals(3L, context.getTimer().getCount(FDBStoreTimer.Counts.REVERSE_DIR_PERSISTENT_CACHE_HIT_COUNT));
        assertEquals(1L, context.getTimer().getCount(FDBStoreTimer.Counts.REVERSE_DIR_PERSISTENT_CACHE_MISS_COUNT));
        commit(context);
    }
    // Second attempt should miss the in-memory cache but hit the persistent cache
    rdc.clearStats();
    try (FDBRecordContext context = openContext()) {
        rdc.putIfNotExists(context, scopedName, id).get();
        assertEquals(1L, rdc.getPersistentCacheHitCount());
        assertEquals(0L, rdc.getPersistentCacheMissCount());
        assertEquals(1L, context.getTimer().getCount(FDBStoreTimer.Counts.REVERSE_DIR_PERSISTENT_CACHE_HIT_COUNT));
        assertEquals(0L, context.getTimer().getCount(FDBStoreTimer.Counts.REVERSE_DIR_PERSISTENT_CACHE_MISS_COUNT));
        commit(context);
    }
}