blob: ba47ee0a0066039ab678cc48dd1c35459d1ebabb [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.nifi.distributed.cache.server.map;
import org.apache.nifi.distributed.cache.server.EvictionPolicy;
import org.junit.jupiter.api.Test;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class TestSimpleMapCache {
@Test
public void testBasicOperations() throws Exception {
final SimpleMapCache cache = new SimpleMapCache("service-id", 2, EvictionPolicy.FIFO);
final ByteBuffer key1 = ByteBuffer.wrap("key1".getBytes());
final ByteBuffer key2 = ByteBuffer.wrap("key2".getBytes());
final ByteBuffer key3 = ByteBuffer.wrap("key3".getBytes());
ByteBuffer value1 = ByteBuffer.wrap("value1-0".getBytes());
ByteBuffer value2 = ByteBuffer.wrap("value2-0".getBytes());
ByteBuffer value3 = ByteBuffer.wrap("value3-0".getBytes());
// Initial state.
assertNull(cache.get(key1));
assertNull(cache.fetch(key1));
// Put the 1st key.
MapPutResult putResult = cache.put(key1, value1);
assertTrue(putResult.isSuccessful());
assertNull(putResult.getExisting());
assertNull(putResult.getEvicted());
assertEquals(0, putResult.getRecord().getRevision());
// Update the same key.
value1 = ByteBuffer.wrap("value1-1".getBytes());
putResult = cache.put(key1, value1);
assertTrue(putResult.isSuccessful());
assertNotNull(putResult.getExisting());
assertEquals(1, putResult.getRecord().getRevision());
assertEquals(key1, putResult.getExisting().getKey());
assertEquals("value1-0", new String(putResult.getExisting().getValue().array()));
assertNull(putResult.getEvicted());
// Put the 2nd key.
putResult = cache.put(key2, value2);
assertTrue(putResult.isSuccessful());
assertNull(putResult.getExisting());
assertNull(putResult.getEvicted());
assertEquals(0, putResult.getRecord().getRevision());
// Put the 3rd key.
putResult = cache.put(key3, value3);
assertTrue(putResult.isSuccessful());
assertNull(putResult.getExisting());
assertNotNull(putResult.getEvicted(), "The first key should be evicted");
assertEquals("key1", new String(putResult.getEvicted().getKey().array()));
assertEquals("value1-1", new String(putResult.getEvicted().getValue().array()));
assertEquals(0, putResult.getRecord().getRevision());
// Delete 2nd key.
ByteBuffer removed = cache.remove(key2);
assertNotNull(removed);
assertEquals("value2-0", new String(removed.array()));
// Put the 2nd key again.
putResult = cache.put(key2, value2);
assertTrue(putResult.isSuccessful());
assertNull(putResult.getExisting());
assertNull(putResult.getEvicted());
assertEquals(0, putResult.getRecord().getRevision(), "Revision should start from 0");
// Get multiple keys
Map<ByteBuffer, ByteBuffer> results = cache.subMap(Arrays.asList(key1, key2, key3));
assertEquals(3, results.size());
}
@Test
public void testOptimisticLock() throws Exception {
final SimpleMapCache cache = new SimpleMapCache("service-id", 2, EvictionPolicy.FIFO);
final ByteBuffer key = ByteBuffer.wrap("key1".getBytes());
ByteBuffer valueC1 = ByteBuffer.wrap("valueC1-0".getBytes());
ByteBuffer valueC2 = ByteBuffer.wrap("valueC2-0".getBytes());
assertNull(cache.fetch(key), "If there's no existing key, fetch should return null.");
// Client 1 inserts the key.
MapCacheRecord c1 = new MapCacheRecord(key, valueC1);
MapPutResult putResult = cache.replace(c1);
assertTrue(putResult.isSuccessful(), "Replace should succeed if there's no existing key.");
MapCacheRecord c2 = new MapCacheRecord(key, valueC2);
putResult = cache.replace(c2);
assertFalse(putResult.isSuccessful(), "Replace should fail.");
// Client 1 and 2 fetch the key
c1 = cache.fetch(key);
c2 = cache.fetch(key);
assertEquals(0, c1.getRevision());
assertEquals(0, c2.getRevision());
// Client 1 replace
valueC1 = ByteBuffer.wrap("valueC1-1".getBytes());
putResult = cache.replace(new MapCacheRecord(key, valueC1, c1.getRevision()));
assertTrue(putResult.isSuccessful(), "Replace should succeed since revision matched.");
assertEquals(1, putResult.getRecord().getRevision());
// Client 2 replace with the old revision
valueC2 = ByteBuffer.wrap("valueC2-1".getBytes());
putResult = cache.replace(new MapCacheRecord(key, valueC2, c2.getRevision()));
assertFalse(putResult.isSuccessful(), "Replace should fail.");
}
}