Add UnsignedLongBitmap
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / test / java / org / opendaylight / controller / cluster / datastore / utils / UnsignedLongBitmapTest.java
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/UnsignedLongBitmapTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/UnsignedLongBitmapTest.java
new file mode 100644 (file)
index 0000000..fc0b490
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.cluster.datastore.utils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import com.google.common.base.VerifyException;
+import com.google.common.io.ByteStreams;
+import com.google.common.primitives.UnsignedLong;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Map;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.opendaylight.controller.cluster.datastore.utils.UnsignedLongBitmap.Regular;
+import org.opendaylight.yangtools.concepts.WritableObjects;
+
+@RunWith(MockitoJUnitRunner.StrictStubs.class)
+public class UnsignedLongBitmapTest {
+    @Test
+    public void testEmpty() throws IOException {
+        final var empty = UnsignedLongBitmap.of();
+        assertTrue(empty.isEmpty());
+        assertEquals(empty, empty);
+        assertSame(empty, UnsignedLongBitmap.copyOf(Map.of()));
+        assertEquals(Map.of(), empty.mutableCopy());
+        assertEquals("{}", empty.toString());
+        assertEquals(0, empty.hashCode());
+
+        final var ex = assertThrows(IOException.class, () -> empty.writeEntriesTo(mock(DataOutput.class), 1));
+        assertEquals("Mismatched size: expected 0, got 1", ex.getMessage());
+
+        // Should not do anything
+        empty.writeEntriesTo(mock(DataOutput.class), 0);
+
+        assertSame(empty, assertWriteToReadFrom(empty));
+    }
+
+    @Test
+    public void testSingleton() {
+        final var one = UnsignedLongBitmap.of(0, false);
+        assertFalse(one.isEmpty());
+        assertEquals(1, one.size());
+        assertEquals(one, one);
+        assertEquals(one, UnsignedLongBitmap.of(0, false));
+        assertEquals(one, UnsignedLongBitmap.copyOf(Map.of(UnsignedLong.ZERO, false)));
+        assertEquals(Map.of(UnsignedLong.ZERO, false), one.mutableCopy());
+        assertEquals("{0=false}", one.toString());
+        assertEquals(1237, one.hashCode());
+
+        final var ex = assertThrows(IOException.class, () -> one.writeEntriesTo(mock(DataOutput.class), 0));
+        assertEquals("Mismatched size: expected 1, got 0", ex.getMessage());
+
+        assertEquals(one, UnsignedLongBitmap.of(0, false));
+        assertNotEquals(one, UnsignedLongBitmap.of(0, true));
+        assertNotEquals(one, UnsignedLongBitmap.of(1, false));
+        assertNotEquals(UnsignedLongBitmap.of(), one);
+        assertNotEquals(one, UnsignedLongBitmap.of());
+
+        assertWriteToReadFrom(one);
+    }
+
+    @Test
+    public void testRegular() {
+        final var one = UnsignedLongBitmap.copyOf(Map.of(UnsignedLong.ZERO, false, UnsignedLong.ONE, true));
+        assertFalse(one.isEmpty());
+        assertEquals(2, one.size());
+        assertEquals(one, one);
+        assertEquals(one, UnsignedLongBitmap.copyOf(Map.of(UnsignedLong.ONE, true, UnsignedLong.ZERO, false)));
+        assertEquals(Map.of(UnsignedLong.ZERO, false, UnsignedLong.ONE, true), one.mutableCopy());
+
+        assertNotEquals(one,
+            UnsignedLongBitmap.copyOf(Map.of(UnsignedLong.ZERO, false, UnsignedLong.valueOf(2), true)));
+        assertEquals("{0=false, 1=true}", one.toString());
+        assertEquals(40345, one.hashCode());
+
+        final var ex = assertThrows(IOException.class, () -> one.writeEntriesTo(mock(DataOutput.class), 1));
+        assertEquals("Mismatched size: expected 2, got 1", ex.getMessage());
+
+        final var two = UnsignedLongBitmap.copyOf(Map.of(UnsignedLong.ZERO, true, UnsignedLong.ONE, false));
+        assertFalse(two.isEmpty());
+        assertEquals(2, two.size());
+        assertEquals(two, two);
+        assertEquals(two, UnsignedLongBitmap.copyOf(Map.of(UnsignedLong.ZERO, true, UnsignedLong.ONE, false)));
+        assertEquals("{0=true, 1=false}", two.toString());
+        assertEquals(40549, two.hashCode());
+
+        assertNotEquals(one, two);
+        assertNotEquals(two, one);
+
+        assertWriteToReadFrom(one);
+        assertWriteToReadFrom(two);
+    }
+
+    private static UnsignedLongBitmap assertWriteToReadFrom(final UnsignedLongBitmap orig) {
+        final var dos = ByteStreams.newDataOutput();
+        try {
+            orig.writeEntriesTo(dos);
+        } catch (IOException e) {
+            throw new AssertionError(e);
+        }
+
+        final UnsignedLongBitmap copy;
+        try {
+            final var dis = ByteStreams.newDataInput(dos.toByteArray());
+            copy = UnsignedLongBitmap.readFrom(dis, orig.size());
+            assertThrows(IllegalStateException.class, () -> dis.readByte());
+        } catch (IOException e) {
+            throw new AssertionError(e);
+        }
+
+        assertEquals(orig, copy);
+        return copy;
+    }
+
+    @Test
+    public void testKeyOrder() throws IOException {
+        assertInvalidKey(0);
+        assertInvalidKey(1);
+    }
+
+    private static void assertInvalidKey(final long second) throws IOException {
+        final var out = ByteStreams.newDataOutput();
+        WritableObjects.writeLong(out, 1);
+        out.writeBoolean(false);
+        WritableObjects.writeLong(out, second);
+        out.writeBoolean(true);
+
+        final var ex = assertThrows(IOException.class,
+            () -> UnsignedLongBitmap.readFrom(ByteStreams.newDataInput(out.toByteArray()), 2));
+        assertEquals("Key " + second + " may not be used after key 1", ex.getMessage());
+    }
+
+    @Test
+    public void testInvalidArrays() {
+        assertThrows(VerifyException.class, () -> new Regular(new long[0], new boolean[] { false, false }));
+    }
+}