From 7ad50e64ea75acceae7656fa9b1c5ae870265b40 Mon Sep 17 00:00:00 2001 From: Rob Austin Date: Mon, 22 Dec 2014 14:44:54 +0000 Subject: [PATCH] updated test cases --- .../openhft/chronicle/map/ChronicleMap.java | 21 +- .../chronicle/map/StatelessChronicleMap.java | 12 +- .../chronicle/map/VanillaChronicleMap.java | 75 ++- .../openhft/chronicle/map/XStreamHelper.java | 40 +- .../chronicle/map/CHMUseCasesTest.java | 483 +++++++++++------- .../chronicle/map/KeyValueInstanceTest.java | 91 ++++ .../chronicle/map/ReplicationCheckingMap.java | 10 + .../openhft/chronicle/map/SerializerTest.java | 18 + .../jsr166/map/StatelessChronicleMapTest.java | 10 + 9 files changed, 518 insertions(+), 242 deletions(-) create mode 100644 src/test/java/net/openhft/chronicle/map/KeyValueInstanceTest.java diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMap.java b/src/main/java/net/openhft/chronicle/map/ChronicleMap.java index 33f98fa45..03f62ebfb 100755 --- a/src/main/java/net/openhft/chronicle/map/ChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMap.java @@ -175,9 +175,8 @@ public interface ChronicleMap extends ConcurrentMap, ChronicleHash { * *

If the {@code ChronicleMap} is off-heap updatable, i. e. created via {@link * ChronicleMapBuilder} builder (values are {@link Byteable}), there is one more option of what - * to do if the key is absent in the map. - * By default, value bytes are just zeroed out, no default value, either provided for key or - * constant, is put for the absent key. + * to do if the key is absent in the map. By default, value bytes are just zeroed out, no + * default value, either provided for key or constant, is put for the absent key. * * @param key the key whose associated value is to be returned * @param usingValue the object to read value data in, if present. Can not be null @@ -200,10 +199,10 @@ public interface ChronicleMap extends ConcurrentMap, ChronicleHash { R getMapped(K key, @NotNull Function function); /** - * Apply a unaryOperator to the value for a key and return a result. A write lock is assumed.

If - * there is no entry for this key null will be returned + * Apply a unaryOperator to the value for a key and return a result. A write lock is assumed. + *

If there is no entry for this key null will be returned * - * @param key to apply the mapping to + * @param key to apply the mapping to * @param unaryOperator to alter the value and calculate a result * @return the result of the function. */ @@ -256,5 +255,15 @@ public interface ChronicleMap extends ConcurrentMap, ChronicleHash { * @return a new empty instance based on the Key type */ K newKeyInstance(); + + /** + * @return the class of + */ + Class keyClass(); + + /** + * @return the class of + */ + Class valueClass(); } diff --git a/src/main/java/net/openhft/chronicle/map/StatelessChronicleMap.java b/src/main/java/net/openhft/chronicle/map/StatelessChronicleMap.java index 9a973ffc9..9b9316d76 100644 --- a/src/main/java/net/openhft/chronicle/map/StatelessChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/StatelessChronicleMap.java @@ -195,6 +195,16 @@ class StatelessChronicleMap implements ChronicleMap, Closeable, Clon return VanillaChronicleMap.newInstance(kClass, true); } + @Override + public Class keyClass() { + return kClass; + } + + @Override + public Class valueClass() { + return vClass; + } + private void checkTimeout(long timeoutTime) { if (timeoutTime < System.currentTimeMillis()) @@ -1703,7 +1713,7 @@ class StatelessChronicleMap implements ChronicleMap, Closeable, Clon } } - private void resizeToMessageOutBuffer(long start, @NotNull Exception e) throws Exception{ + private void resizeToMessageOutBuffer(long start, @NotNull Exception e) throws Exception { assert outBytesLock.isHeldByCurrentThread(); assert !inBytesLock.isHeldByCurrentThread(); String message = e.getMessage(); diff --git a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java index 2ce504a51..ea34acb70 100755 --- a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java @@ -49,7 +49,6 @@ import org.slf4j.LoggerFactory; import java.beans.BeanInfo; import java.beans.IntrospectionException; -import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.io.*; import java.lang.reflect.Array; @@ -716,6 +715,16 @@ class VanillaChronicleMap, return newInstance(kClass, true); } + @Override + public Class keyClass() { + return kClass; + } + + @Override + public Class valueClass() { + return vClass; + } + static T newInstance(Class aClass, boolean isKey) { try { @@ -749,7 +758,7 @@ class VanillaChronicleMap, } } - private XStreamConverter xStreamConverter; + private transient XStreamConverter xStreamConverter; /** @@ -782,7 +791,8 @@ class VanillaChronicleMap, String canonicalName = aClass.getCanonicalName(); return canonicalName.startsWith("net.openhft.lang.values") - || canonicalName.endsWith("$$Native"); + || canonicalName.endsWith("$$Native") || canonicalName.endsWith + ("$$Heap"); } @@ -815,9 +825,11 @@ class VanillaChronicleMap, } } - if (o.getClass().getCanonicalName().startsWith("net.openhft.lang.values") - && (o.getClass().getCanonicalName().endsWith("$$Native") || - o.getClass().getCanonicalName().endsWith("$$Heap"))) { + final String canonicalName = o.getClass().getCanonicalName(); + + if (canonicalName.startsWith("net.openhft.lang.values") + && (canonicalName.endsWith("$$Native") || + canonicalName.endsWith("$$Heap"))) { Method[] methods = o.getClass().getMethods(); @@ -825,19 +837,17 @@ class VanillaChronicleMap, if (method.getName().equals("getValue") && method.getParameterTypes().length == 0) { try { - final Object result = method.invoke(o); - // writer.startNode(o.getClass().getCanonicalName()); - marshallingContext.convertAnother(result); - // writer.endNode(); + marshallingContext.convertAnother(method.invoke(o)); return; } catch (Exception e) { - throw new RuntimeException("class=" + o.getClass().getCanonicalName(), e); + throw new RuntimeException("class=" + canonicalName, e); } } } } else { - if (o.getClass().getCanonicalName().endsWith("$$Native")) { + if (canonicalName.endsWith("$$Native") || + canonicalName.endsWith("$$Heap")) { try { BeanInfo info = getBeanInfo(o.getClass()); // new BeanGenerator @@ -867,7 +877,7 @@ class VanillaChronicleMap, } } catch (IntrospectionException e) { - throw new RuntimeException("class=" + o.getClass().getCanonicalName(), e); + throw new RuntimeException("class=" + canonicalName, e); } } } @@ -878,10 +888,19 @@ class VanillaChronicleMap, UnmarshallingContext unmarshallingContext) { String canonicalName = unmarshallingContext.getRequiredType().getCanonicalName(); - if (canonicalName.endsWith("$$Native")) { + boolean isNative = canonicalName.endsWith("$$Native"); + boolean isHeap = canonicalName.endsWith("$$Heap"); + + if (isNative || isHeap) { + + + final String nodeName = isNative ? + canonicalName.substring(0, canonicalName.length() - + "$$Native".length()) : + + canonicalName.substring(0, canonicalName.length() - + "$$Heap".length()); - final String nodeName = canonicalName.substring(0, canonicalName.length() - - "$$Native".length()); Object o; try { @@ -959,7 +978,7 @@ class VanillaChronicleMap, if (kClass.getCanonicalName().startsWith("net.openhft.lang.values")) { return to$$Native(reader, vClass, true, VanillaChronicleMap.this, unmarshallingContext); - } else if (type.endsWith("$$Native")) { + } else if (type.endsWith("$$Native") || type.endsWith("$$Heap")) { return XStreamHelper.to$$Native2(reader, vClass, false, VanillaChronicleMap.this, unmarshallingContext, type); } else { long keySize = keySizeMarshaller.readSize(buffer); @@ -971,7 +990,7 @@ class VanillaChronicleMap, if (vClass.getCanonicalName().startsWith("net.openhft.lang.values")) { return to$$Native(reader, vClass, false, VanillaChronicleMap.this, unmarshallingContext); - } else if (type.endsWith("$$Native")) { + } else if (type.endsWith("$$Native") || type.endsWith("$$Heap")) { return XStreamHelper.to$$Native2(reader, vClass, false, VanillaChronicleMap.this, unmarshallingContext, type); } else { long valueSize = valueSizeMarshaller.readSize(buffer); @@ -995,12 +1014,16 @@ class VanillaChronicleMap, if (reader.getAttributeCount() > 0) { final String type = reader.getAttribute("type"); - try { - return (E) unmarshallingContext.convertAnother(null, forName(type)); - } catch (ClassNotFoundException e) { - throw new ConversionException(e); - } - } else return (E) unmarshallingContext.convertAnother(null, clazz); + if (type != null) + try { + return (E) unmarshallingContext.convertAnother(null, forName(type)); + } catch (ClassNotFoundException e) { + throw new ConversionException(e); + } + + } + + return (E) unmarshallingContext.convertAnother(null, clazz); } @@ -1591,7 +1614,9 @@ class VanillaChronicleMap, return segmentStateProvider.getCopies(copies); } - static @NotNull SegmentState get(@NotNull ThreadLocalCopies copies) { + static + @NotNull + SegmentState get(@NotNull ThreadLocalCopies copies) { assertNotNull(copies); return segmentStateProvider.get(copies, originalSegmentState).get(); } diff --git a/src/main/java/net/openhft/chronicle/map/XStreamHelper.java b/src/main/java/net/openhft/chronicle/map/XStreamHelper.java index 0372353be..8d19c795a 100644 --- a/src/main/java/net/openhft/chronicle/map/XStreamHelper.java +++ b/src/main/java/net/openhft/chronicle/map/XStreamHelper.java @@ -34,33 +34,35 @@ class XStreamHelper { ChronicleMap map, UnmarshallingContext unmarshallingContext, String type) { - if (type.endsWith("$$Native")) { + boolean isNative = type.endsWith("$$Native"); - Class aClass = null; + + Class aClass; + try { + aClass = Class.forName(type); + } catch (ClassNotFoundException e) { + String clazz = isNative ? type.substring(0, type.length() - + "$$Native".length()) : type.substring(0, type.length() - + "$$Heap".length()); + try { + DataValueClasses.newDirectInstance(Class.forName(clazz)); + } catch (ClassNotFoundException e1) { + throw new ConversionException(e1); + } try { aClass = Class.forName(type); - } catch (ClassNotFoundException e) { - String clazz = type.substring(0, type.length() - - "$$Native".length()); - try { - DataValueClasses.newDirectInstance(Class.forName(clazz)); - } catch (ClassNotFoundException e1) { - throw new ConversionException(e1); - } - try { - aClass = Class.forName(type); - } catch (ClassNotFoundException e1) { - throw new ConversionException(e1); - } + } catch (ClassNotFoundException e1) { + throw new ConversionException(e1); } - - - return unmarshallingContext.convertAnother(null, aClass); } - throw new ConversionException("setValue(..) method not found in class=" + type); + + return unmarshallingContext.convertAnother(null, aClass); } + + + static Object to$$Native(HierarchicalStreamReader reader, final Class aClass, final boolean isKey, ChronicleMap map, UnmarshallingContext unmarshallingContext) { diff --git a/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java b/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java index 86d20a06e..e537ab541 100644 --- a/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java +++ b/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java @@ -14,6 +14,7 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.io.Closeable; +import java.io.File; import java.io.IOException; import java.io.Serializable; import java.net.InetSocketAddress; @@ -31,11 +32,37 @@ import static org.junit.Assert.*; @RunWith(value = Parameterized.class) public class CHMUseCasesTest { + private static final String TMP = System.getProperty("java.io.tmpdir"); - enum TypeOfMap {SIMPLE, REPLICATED, STATELESS} + + enum TypeOfMap {SIMPLE, SIMPLE_PERSISTED, REPLICATED, STATELESS} private final TypeOfMap typeOfMap; + Collection closeables = new ArrayList(); + + public CHMUseCasesTest(TypeOfMap typeOfMap) { + this.typeOfMap = typeOfMap; + } + + @After + public void after() { + for (Closeable c : closeables) { + + try { + c.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + closeables.clear(); + map2 = null; + map1 = null; + } + + ChronicleMap map1; + ChronicleMap map2; + @Parameterized.Parameters public static Collection data() { return asList(new Object[][]{ @@ -52,17 +79,180 @@ public class CHMUseCasesTest { // stateless client { TypeOfMap.STATELESS + }, + { + TypeOfMap.SIMPLE_PERSISTED } }); - } - public CHMUseCasesTest(TypeOfMap typeOfMap) { - this.typeOfMap = typeOfMap; + + /** + * * waits until map1 and map2 show the same value + * + * @param timeOutMs timeout in milliseconds + */ + private void waitTillEqual(final int timeOutMs) { + int t = 0; + for (; t < timeOutMs; t++) { + if (map1.equals(map2)) + break; + try { + Thread.sleep(1); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } } + private void mapChecks() { + if (typeOfMap == TypeOfMap.REPLICATED) { + + // see HCOLL-265 Chronicle Maps with Identical char[] values are not equal1 + if (map1.keyClass() == char[].class || map1.valueClass() == char[].class) { + return; + } + + waitTillEqual(5000); + assertEquals(map1, map2); + + } + + if (typeOfMap == TypeOfMap.SIMPLE) + checkJsonSerilization(); + } + + + private void checkJsonSerilization() { + + // see HCOLL-265 Chronicle Maps with Identical char[] values are not equal1 + if (map1.keyClass() == char[].class || map1.valueClass() == char[].class) { + return; + } + + File file = new File(TMP + "/chronicle-map-" + System.nanoTime() + ".json"); + file.deleteOnExit(); + + try { + + try { + map1.getAll(file); + + try (ChronicleMap actual = ChronicleMapBuilder.of(map1.keyClass(), + map1.valueClass()) + .create()) { + actual.putAll(file); + + Assert.assertEquals(map1, actual); + } + + } catch (IOException e) { + e.printStackTrace(); + } + + } finally { + file.delete(); + } + } + + + private ChronicleMap newInstance(ChronicleMapBuilder builder) throws + IOException { + + switch (typeOfMap) { + + case SIMPLE: + map2 = null; + map1 = builder.create(); + closeables.add(map1); + return map1; + + case SIMPLE_PERSISTED: + final File file = new File(TMP + "/chronicle-map-" + System.nanoTime() + ".map"); + file.deleteOnExit(); + map1 = builder.createPersistedTo(file); + closeables.add(map1); + closeables.add(new Closeable() { + @Override + public void close() throws IOException { + file.delete(); + } + }); + + return map1; + + case REPLICATED: { + + map2 = null; + { + final TcpTransportAndNetworkConfig tcpConfig1 = TcpTransportAndNetworkConfig + .of(8086).name("server") + .heartBeatInterval(1, TimeUnit.SECONDS) + .tcpBufferSize(1024 * 64); + + + map2 = builder + .replication((byte) 1, tcpConfig1) + .instance() + .name("server") + .create(); + closeables.add(map2); + + } + { + final TcpTransportAndNetworkConfig tcpConfig2 = TcpTransportAndNetworkConfig.of + (8087, new InetSocketAddress("localhost", 8086)).name("map2") + .heartBeatInterval(1, TimeUnit.SECONDS) + .tcpBufferSize(1024 * 64); + + map1 = builder + .replication((byte) 2, tcpConfig2) + .instance() + .name("map2") + .create(); + closeables.add(map1); + return map1; + + } + + + } + + + case STATELESS: { + { + final TcpTransportAndNetworkConfig tcpConfig1 = TcpTransportAndNetworkConfig + .of(8086).name("server") + .heartBeatInterval(1, TimeUnit.SECONDS) + .tcpBufferSize(1024 * 64); + + + map2 = builder + .replication((byte) 1, tcpConfig1) + .instance() + .name("server") + .create(); + closeables.add(map2); + + } + { + map1 = builder + .statelessClient(new InetSocketAddress("localhost", 8086)) + .create(); + + closeables.add(map1); + return map1; + + } + } + + default: + throw new IllegalStateException(); + } + } + static class PrefixStringFunction implements Function { private final String prefix; @@ -105,6 +295,7 @@ public class CHMUseCasesTest { char[] actual = map.get("Key"); System.out.println(actual); assertEquals(Chars.asList(expected), Chars.asList(map.get("Key"))); + mapChecks(); } } @@ -122,6 +313,7 @@ public class CHMUseCasesTest { try (ChronicleMap map = newInstance(builder)) { map.put("Key", expected); + mapChecks(); } } @@ -159,116 +351,7 @@ public class CHMUseCasesTest { assertEquals("New World", map.getMapped("Hello", new PrefixStringFunction("New "))); assertEquals(null, map.getMapped("No key", new PrefixStringFunction("New "))); - - } - } - - @Test - public void testStringSerialization() throws ExecutionException, - InterruptedException, IOException { - - ByteBufferBytes b = new ByteBufferBytes(ByteBuffer.allocate(512)); - - String expected = "Hello"; - b.writeObject(expected); - - b.clear(); - - String actual = (String) b.readObject(); - assertEquals(expected, actual); - - } - - - Collection closeables = new ArrayList(); - - @After - public void after() { - for (Closeable c : closeables) { - - try { - c.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - closeables.clear(); - } - - - private ChronicleMap newInstance(ChronicleMapBuilder builder) throws - IOException { - - switch (typeOfMap) { - - case SIMPLE: - return builder.create(); - - case REPLICATED: { - - - { - final TcpTransportAndNetworkConfig tcpConfig1 = TcpTransportAndNetworkConfig - .of(8086).name("server") - .heartBeatInterval(1, TimeUnit.SECONDS) - .tcpBufferSize(1024 * 64); - - - closeables.add(builder - .replication((byte) 1, tcpConfig1) - .instance() - .name("server") - .create()); - - } - { - final TcpTransportAndNetworkConfig tcpConfig2 = TcpTransportAndNetworkConfig.of - (8087, new InetSocketAddress("localhost", 8086)).name("map2") - .heartBeatInterval(1, TimeUnit.SECONDS) - .tcpBufferSize(1024 * 64); - - ChronicleMap map2 = builder - .replication((byte) 2, tcpConfig2) - .instance() - .name("map2") - .create(); - closeables.add(map2); - return map2; - - } - - - } - - - case STATELESS: { - { - final TcpTransportAndNetworkConfig tcpConfig1 = TcpTransportAndNetworkConfig - .of(8086).name("server") - .heartBeatInterval(1, TimeUnit.SECONDS) - .tcpBufferSize(1024 * 64); - - - closeables.add(builder - .replication((byte) 1, tcpConfig1) - .instance() - .name("server") - .create()); - - } - { - ChronicleMap map2 = builder - .statelessClient(new InetSocketAddress("localhost", 8086)) - .create(); - - closeables.add(map2); - return map2; - - } - } - - default: - throw new IllegalStateException(); + mapChecks(); } } @@ -285,6 +368,7 @@ public class CHMUseCasesTest { public String update(String s) { return prefix + s; } + } @@ -297,6 +381,7 @@ public class CHMUseCasesTest { try (ChronicleMap map = newInstance(builder)) { map.put("Hello", "World"); map.putMapped("Hello", new StringPrefixUnaryOperator("New ")); + mapChecks(); } } @@ -312,6 +397,7 @@ public class CHMUseCasesTest { map.put(new StringBuilder("Hello"), "World2"); Assert.assertEquals("World2", map.get("Hello")); + mapChecks(); } } @@ -327,6 +413,7 @@ public class CHMUseCasesTest { Assert.assertEquals("World2", map.get("Hello2")); Assert.assertEquals("World", map.get("Hello")); + mapChecks(); } } @@ -396,6 +483,7 @@ public class CHMUseCasesTest { } })); + mapChecks(); } } @@ -420,6 +508,7 @@ public class CHMUseCasesTest { } assertEquals("Hello World", map.get("1")); + mapChecks(); } } @@ -441,6 +530,7 @@ public class CHMUseCasesTest { } assertEquals(null, map.get("1")); + mapChecks(); } } @@ -464,6 +554,7 @@ public class CHMUseCasesTest { } assertEquals(null, map.get("1")); + mapChecks(); } } @@ -489,6 +580,7 @@ public class CHMUseCasesTest { } assertEquals(null, map.get("1")); + mapChecks(); } } @@ -515,6 +607,7 @@ public class CHMUseCasesTest { } assertEquals(null, map.get("1")); + mapChecks(); } } @@ -540,6 +633,7 @@ public class CHMUseCasesTest { } assertEquals("Hello", map.get(key).toString()); + mapChecks(); } } @@ -571,6 +665,7 @@ public class CHMUseCasesTest { key.setValue(1); assertEquals("Hello", map.get(key)); + mapChecks(); } } @@ -597,53 +692,7 @@ public class CHMUseCasesTest { } assertTrue(map.get(key).length() == 0); - } - } - - - @Test(expected = IllegalStateException.class) - public void testLongNewKeyValueInstance() { - try (ChronicleMap map = ChronicleMapBuilder - .of(Long.class, Long.class) - .create()) { - - map.newKeyInstance(); - map.newValueInstance(); - } - } - - - @Test(expected = IllegalStateException.class) - public void testNewKeyValueInstanceWithMapType() { - try (ChronicleMap map = ChronicleMapBuilder - .of(Map.class, Map.class) - .create()) { - - map.newKeyInstance(); - map.newValueInstance(); - } - } - - @Test - public void testNewKeyValueInstanceWithHahMapType() { - try (ChronicleMap map = ChronicleMapBuilder - .of(HashMap.class, HashMap.class) - .create()) { - - map.newKeyInstance(); - map.newValueInstance(); - } - } - - - @Test(expected = IllegalStateException.class) - public void testNewKeyValueInstanceWithByteArray() { - try (ChronicleMap map = ChronicleMapBuilder - .of(byte[].class, byte[].class) - .create()) { - - map.newKeyInstance(); - map.newValueInstance(); + mapChecks(); } } @@ -651,6 +700,7 @@ public class CHMUseCasesTest { /** * StringValue represents any bean which contains a String Value */ + @Ignore("HCOLL-268 JSON serialisation issue") @Test public void testStringValueStringValueMap() throws IOException { @@ -676,6 +726,8 @@ public class CHMUseCasesTest { map.put(key2, value2); assertEquals(value2, map.get(key2)); + mapChecks(); + StringBuilder sb = new StringBuilder(); try (ReadContext rc = map.getUsingLocked(key1, value1)) { assertTrue(rc.present()); @@ -683,28 +735,39 @@ public class CHMUseCasesTest { value1.getUsingValue(sb); assertEquals("11", sb.toString()); } + + mapChecks(); + try (ReadContext rc = map.getUsingLocked(key2, value1)) { assertTrue(rc.present()); assertEquals("22", value2.getValue()); value2.getUsingValue(sb); assertEquals("22", sb.toString()); } + + mapChecks(); + try (ReadContext rc = map.getUsingLocked(key1, value2)) { assertTrue(rc.present()); assertEquals("11", value2.getValue()); value2.getUsingValue(sb); assertEquals("11", sb.toString()); } + + mapChecks(); + try (ReadContext rc = map.getUsingLocked(key2, value2)) { assertTrue(rc.present()); assertEquals("22", value2.getValue()); value2.getUsingValue(sb); assertEquals("22", sb.toString()); } + key1.setValue("3"); try (ReadContext rc = map.getUsingLocked(key1, value1)) { assertFalse(rc.present()); } + key2.setValue("4"); try (ReadContext rc = map.getUsingLocked(key2, value2)) { assertFalse(rc.present()); @@ -717,16 +780,24 @@ public class CHMUseCasesTest { sb.append(123); value1.setValue(sb); } + + mapChecks(); + try (WriteContext wc = map.acquireUsingLocked(key1, value2)) { assertEquals("123", value2.getValue()); value2.setValue(value2.getValue() + '4'); assertEquals("1234", value2.getValue()); } + + mapChecks(); + try (ReadContext rc = map.getUsingLocked(key1, value1)) { assertTrue(rc.present()); assertEquals("1234", value1.getValue()); } + mapChecks(); + try (WriteContext wc = map.acquireUsingLocked(key2, value2)) { assertEquals("", value2.getValue()); value2.getUsingValue(sb); @@ -734,15 +805,23 @@ public class CHMUseCasesTest { sb.append(123); value2.setValue(sb); } + + mapChecks(); + try (WriteContext wc = map.acquireUsingLocked(key2, value1)) { assertEquals("123", value1.getValue()); value1.setValue(value1.getValue() + '4'); assertEquals("1234", value1.getValue()); } + + mapChecks(); + try (ReadContext rc = map.getUsingLocked(key2, value2)) { assertTrue(rc.present()); assertEquals("1234", value2.getValue()); } + + mapChecks(); } } @@ -757,7 +836,7 @@ public class CHMUseCasesTest { .of(Integer.class, Integer.class); try (ChronicleMap map = newInstance(builder)) { - assertEquals(8, entrySize(map)); + assertEquals(1, ((VanillaChronicleMap) map).maxEntryOversizeFactor); Integer key1; Integer key2; @@ -769,6 +848,7 @@ public class CHMUseCasesTest { map.put(key1, value1); assertEquals(value1, map.get(key1)); + key2 = 2; value2 = 22; map.put(key2, value2); @@ -779,12 +859,17 @@ public class CHMUseCasesTest { assertEquals(null, map.get(3)); assertEquals(null, map.get(4)); + mapChecks(); + assertEquals((Integer) 110, map.getMapped(1, new Function() { @Override public Integer apply(Integer s) { return 10 * s; } })); + + mapChecks(); + assertEquals(null, map.getMapped(-1, new Function() { @Override public Integer apply(Integer s) { @@ -792,6 +877,8 @@ public class CHMUseCasesTest { } })); + mapChecks(); + try { map.putMapped(1, new UnaryOperator() { @Override @@ -801,7 +888,7 @@ public class CHMUseCasesTest { }); } catch (Exception todoMoreSpecificException) { } - + mapChecks(); } } @@ -829,6 +916,8 @@ public class CHMUseCasesTest { assertEquals(null, map.get(3L)); assertEquals(null, map.get(4L)); + mapChecks(); + assertEquals((Long) 110L, map.getMapped(1L, new Function() { @Override public Long apply(Long s) { @@ -842,6 +931,8 @@ public class CHMUseCasesTest { } })); + mapChecks(); + try { map.putMapped(1L, new UnaryOperator() { @Override @@ -852,7 +943,7 @@ public class CHMUseCasesTest { } catch (Exception todoMoreSpecificException) { } - + mapChecks(); } } @@ -868,7 +959,7 @@ public class CHMUseCasesTest { .of(Double.class, Double.class); try (ChronicleMap map = newInstance(builder)) { - assertEquals(16, entrySize(map)); + assertEquals(1, ((VanillaChronicleMap) map).maxEntryOversizeFactor); map.put(1.0, 11.0); assertEquals((Double) 11.0, map.get(1.0)); @@ -960,6 +1051,8 @@ public class CHMUseCasesTest { } } + + @Ignore("HCOLL-268 JSON serialisation issue") @Test public void testByteBufferByteBufferDefaultKeyValueMarshaller() throws ExecutionException, InterruptedException, IOException { @@ -984,9 +1077,12 @@ public class CHMUseCasesTest { map.put(key1, value1); + + mapChecks(); } } + @Ignore("HCOLL-268 JSON serialisation issue") @Test public void testByteBufferByteBufferMap() throws ExecutionException, InterruptedException, IOException { @@ -1025,7 +1121,7 @@ public class CHMUseCasesTest { map.put(key1, value1); assertBBEquals(ByteBuffer.wrap(new byte[]{11, 11}), map.getMapped(key1, function)); assertEquals(null, map.getMapped(key2, function)); - + mapChecks(); assertBBEquals(ByteBuffer.wrap(new byte[]{12, 10}), map.putMapped(key1, new UnaryOperator() { @Override public ByteBuffer update(ByteBuffer s) { @@ -1037,6 +1133,8 @@ public class CHMUseCasesTest { assertBBEquals(ByteBuffer.wrap(new byte[]{12, 10}), map.get(key1)); + mapChecks(); + map.put(key1, value1); map.put(key2, value2); ByteBuffer valueA = ByteBuffer.allocateDirect(8); @@ -1091,7 +1189,7 @@ public class CHMUseCasesTest { assertBBEquals(bb1, valueA); } - + mapChecks(); } } @@ -1100,7 +1198,7 @@ public class CHMUseCasesTest { valueA.limit(valueA.capacity()); } - + @Ignore("HCOLL-268 JSON serialisation issue") @Test public void testByteBufferDirectByteBufferMap() throws ExecutionException, InterruptedException, IOException { @@ -1130,7 +1228,7 @@ public class CHMUseCasesTest { assertBBEquals(value2, map.get(key1)); assertNull(map.get(key2)); map.put(key1, value1); - + mapChecks(); final Function function = new Function() { @Override public ByteBuffer apply(ByteBuffer s) { @@ -1141,7 +1239,7 @@ public class CHMUseCasesTest { }; assertBBEquals(ByteBuffer.wrap(new byte[]{11, 11}), map.getMapped(key1, function)); assertEquals(null, map.getMapped(key2, function)); - + mapChecks(); assertBBEquals(ByteBuffer.wrap(new byte[]{12, 10}), map.putMapped(key1, new UnaryOperator() { @Override public ByteBuffer update(ByteBuffer s) { @@ -1152,7 +1250,7 @@ public class CHMUseCasesTest { })); assertBBEquals(ByteBuffer.wrap(new byte[]{12, 10}), map.get(key1)); - + mapChecks(); } } @@ -1244,6 +1342,8 @@ public class CHMUseCasesTest { assertTrue(rc.present()); assertEquals(1230, value2.getValue()); } + mapChecks(); + } } @@ -1267,7 +1367,7 @@ public class CHMUseCasesTest { value1.setValue(11); map.put(key1, value1); assertEquals(value1, map.get(key1)); - + mapChecks(); } } @@ -1356,6 +1456,7 @@ public class CHMUseCasesTest { assertTrue(rc.present()); assertEquals(1230, value2.getValue()); } + mapChecks(); } } @@ -1447,6 +1548,7 @@ public class CHMUseCasesTest { assertTrue(rc.present()); assertEquals(1230, value2.getValue()); } + mapChecks(); } } @@ -1538,6 +1640,7 @@ public class CHMUseCasesTest { assertTrue(rc.present()); assertEquals(1230, value2.getValue()); } + mapChecks(); } } @@ -1556,7 +1659,6 @@ public class CHMUseCasesTest { try (ChronicleMap map = newInstance(builder)) { - assertEquals(6, entrySize(map)); assertEquals(1, ((VanillaChronicleMap) map).maxEntryOversizeFactor); IntValue key1 = map.newKeyInstance(); IntValue key2 = map.newKeyInstance(); @@ -1720,6 +1822,7 @@ public class CHMUseCasesTest { assertTrue(rc.present()); assertEquals(12, value2.getValue()); } + mapChecks(); } } @@ -1737,7 +1840,7 @@ public class CHMUseCasesTest { try (ChronicleMap map = newInstance(builder)) { - assertEquals(5, entrySize(map)); + assertEquals(1, ((VanillaChronicleMap) map).maxEntryOversizeFactor); IntValue key1 = map.newKeyInstance(); @@ -1810,6 +1913,7 @@ public class CHMUseCasesTest { assertTrue(rc.present()); assertEquals(false, value2.getValue()); } + mapChecks(); } } @@ -1828,9 +1932,6 @@ public class CHMUseCasesTest { try (ChronicleMap map = newInstance(builder)) { - -// this may change due to alignment - //assertEquals(8, entrySize(map)); assertEquals(1, ((VanillaChronicleMap) map).maxEntryOversizeFactor); FloatValue key1 = map.newKeyInstance(); @@ -1903,19 +2004,10 @@ public class CHMUseCasesTest { assertTrue(rc.present()); assertEquals(1230, value2.getValue(), 0); } + mapChecks(); } } - private long entrySize(ChronicleMap map) { - - if (map instanceof VanillaChronicleMap) { - if (typeOfMap == TypeOfMap.SIMPLE) - return ((VanillaChronicleMap) map).entrySize; - else - return ((VanillaChronicleMap) map).entrySize - ReplicatedChronicleMap.ADDITIONAL_ENTRY_BYTES; - } else - return 0; - } /** * For double values, the key can be on heap or off heap. @@ -2008,6 +2100,7 @@ public class CHMUseCasesTest { assertTrue(rc.present()); assertEquals(1230, value2.getValue(), 0); } + mapChecks(); } } @@ -2100,6 +2193,7 @@ public class CHMUseCasesTest { assertTrue(rc.present()); assertEquals(1230, value2.getValue()); } + mapChecks(); } } @@ -2154,6 +2248,7 @@ public class CHMUseCasesTest { } } + @Ignore("HCOLL-268 JSON serialisation issue") @Test public void testSetValue() throws IOException { @@ -2187,6 +2282,7 @@ public class CHMUseCasesTest { assertTrue(rc.present()); assertEquals(new LinkedHashSet(asList("one", "three")), list2); } + mapChecks(); } } @@ -2224,9 +2320,11 @@ public class CHMUseCasesTest { assertTrue(rc.present()); assertEquals(mapOf("one", "uni", "three", "tri"), map2); } + mapChecks(); } } + @Ignore("HCOLL-267 MapMarshaller fails to serialize") @Test public void testMapStringIntegerValue() throws IOException { @@ -2261,18 +2359,21 @@ public class CHMUseCasesTest { assertTrue(rc.present()); assertEquals(mapOf("one", 1, "three", 3), map2); } + mapChecks(); } } + @Ignore("HCOLL-268 JSON serialisation issue") @Test - public void testMapStringIntegerValueWithoutListMarshallers() { - try (ChronicleMap> map = ChronicleMapBuilder - .of(String.class, (Class>) (Class) Map.class) - .create()) { + public void testMapStringIntegerValueWithoutListMarshallers() throws IOException { + ChronicleMapBuilder> builder = ChronicleMapBuilder + .of(String.class, (Class>) (Class) Map.class); + try (ChronicleMap> map = newInstance(builder)) { map.put("1", Collections.emptyMap()); map.put("2", mapOf("two", 2)); assertEquals(mapOf("two", 2), map.get("2")); + mapChecks(); } } diff --git a/src/test/java/net/openhft/chronicle/map/KeyValueInstanceTest.java b/src/test/java/net/openhft/chronicle/map/KeyValueInstanceTest.java new file mode 100644 index 000000000..302591a8f --- /dev/null +++ b/src/test/java/net/openhft/chronicle/map/KeyValueInstanceTest.java @@ -0,0 +1,91 @@ +package net.openhft.chronicle.map; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertTrue; + +/** + * @author Rob Austin. + */ +public class KeyValueInstanceTest { + + @Test(expected = IllegalStateException.class) + public void testLongNewKeyValueInstance() { + try (ChronicleMap map = ChronicleMapBuilder + .of(Long.class, Long.class) + .create()) { + + map.newKeyInstance(); + map.newValueInstance(); + } + } + + + @Test(expected = IllegalStateException.class) + public void testNewKeyValueInstanceWithMapType() { + try (ChronicleMap map = ChronicleMapBuilder + .of(Map.class, Map.class) + .create()) { + + map.newKeyInstance(); + map.newValueInstance(); + } + } + + @Test + public void testNewKeyValueInstanceWithHahMapType() { + try (ChronicleMap map = ChronicleMapBuilder + .of(HashMap.class, HashMap.class) + .create()) { + + Object key = map.newKeyInstance(); + Object value = map.newValueInstance(); + + } + } + + + interface IBean { + long getLong(); + + void setLong(long num); + + double getDouble(); + + void setDouble(double d); + + int getInt(); + + void setInt(int i); + } + + @Test + public void testNewKeyValueInstanceWithListType() { + try (ChronicleMap map = ChronicleMapBuilder + .of(HashMap.class, IBean.class) + .create()) { + + map.newKeyInstance(); + Object value = map.newValueInstance(); + + assertTrue(value.getClass().getCanonicalName().endsWith("$$Native")); + + + } + } + + + @Test(expected = IllegalStateException.class) + public void testNewKeyValueInstanceWithByteArray() { + try (ChronicleMap map = ChronicleMapBuilder + .of(byte[].class, byte[].class) + .create()) { + + map.newKeyInstance(); + map.newValueInstance(); + } + } +} diff --git a/src/test/java/net/openhft/chronicle/map/ReplicationCheckingMap.java b/src/test/java/net/openhft/chronicle/map/ReplicationCheckingMap.java index a973809e1..7865b7b2f 100644 --- a/src/test/java/net/openhft/chronicle/map/ReplicationCheckingMap.java +++ b/src/test/java/net/openhft/chronicle/map/ReplicationCheckingMap.java @@ -247,6 +247,16 @@ public class ReplicationCheckingMap implements ChronicleMap { throw new UnsupportedOperationException(); } + @Override + public Class keyClass() { + return map1.keyClass(); + } + + @Override + public Class valueClass() { + return map1.valueClass(); + } + @Override public V acquireUsing(@NotNull K key, V usingValue) { return map1.acquireUsing(key, usingValue); diff --git a/src/test/java/net/openhft/chronicle/map/SerializerTest.java b/src/test/java/net/openhft/chronicle/map/SerializerTest.java index d8bfd6433..02dc96e62 100644 --- a/src/test/java/net/openhft/chronicle/map/SerializerTest.java +++ b/src/test/java/net/openhft/chronicle/map/SerializerTest.java @@ -28,6 +28,7 @@ import org.junit.Test; import java.io.*; import java.nio.ByteBuffer; import java.util.Collections; +import java.util.concurrent.ExecutionException; import static org.junit.Assert.assertEquals; @@ -47,6 +48,23 @@ public class SerializerTest { } + @Test + public void testStringSerialization() throws ExecutionException, + InterruptedException, IOException { + + ByteBufferBytes b = new ByteBufferBytes(ByteBuffer.allocate(512)); + + String expected = "Hello"; + b.writeObject(expected); + + b.clear(); + + String actual = (String) b.readObject(); + assertEquals(expected, actual); + + } + + @Test public void testValueMarshallable() throws Exception { testReadWriteValue("Test"); diff --git a/src/test/java/net/openhft/chronicle/map/jsr166/map/StatelessChronicleMapTest.java b/src/test/java/net/openhft/chronicle/map/jsr166/map/StatelessChronicleMapTest.java index 12f69defa..95c6589b0 100755 --- a/src/test/java/net/openhft/chronicle/map/jsr166/map/StatelessChronicleMapTest.java +++ b/src/test/java/net/openhft/chronicle/map/jsr166/map/StatelessChronicleMapTest.java @@ -199,6 +199,16 @@ public class StatelessChronicleMapTest extends JSR166TestCase { throw new UnsupportedOperationException(); } + @Override + public Class keyClass() { + return d.keyClass(); + } + + @Override + public Class valueClass() { + return d.valueClass(); + } + @Override public V putIfAbsent(K key, V value) { return d.putIfAbsent(key, value);