Add UnsignedLongBitmap
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / test / java / org / opendaylight / controller / cluster / datastore / utils / UnsignedLongBitmapTest.java
1 /*
2  * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.cluster.datastore.utils;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertNotEquals;
13 import static org.junit.Assert.assertSame;
14 import static org.junit.Assert.assertThrows;
15 import static org.junit.Assert.assertTrue;
16 import static org.mockito.Mockito.mock;
17
18 import com.google.common.base.VerifyException;
19 import com.google.common.io.ByteStreams;
20 import com.google.common.primitives.UnsignedLong;
21 import java.io.DataOutput;
22 import java.io.IOException;
23 import java.util.Map;
24 import org.junit.Test;
25 import org.junit.runner.RunWith;
26 import org.mockito.junit.MockitoJUnitRunner;
27 import org.opendaylight.controller.cluster.datastore.utils.UnsignedLongBitmap.Regular;
28 import org.opendaylight.yangtools.concepts.WritableObjects;
29
30 @RunWith(MockitoJUnitRunner.StrictStubs.class)
31 public class UnsignedLongBitmapTest {
32     @Test
33     public void testEmpty() throws IOException {
34         final var empty = UnsignedLongBitmap.of();
35         assertTrue(empty.isEmpty());
36         assertEquals(empty, empty);
37         assertSame(empty, UnsignedLongBitmap.copyOf(Map.of()));
38         assertEquals(Map.of(), empty.mutableCopy());
39         assertEquals("{}", empty.toString());
40         assertEquals(0, empty.hashCode());
41
42         final var ex = assertThrows(IOException.class, () -> empty.writeEntriesTo(mock(DataOutput.class), 1));
43         assertEquals("Mismatched size: expected 0, got 1", ex.getMessage());
44
45         // Should not do anything
46         empty.writeEntriesTo(mock(DataOutput.class), 0);
47
48         assertSame(empty, assertWriteToReadFrom(empty));
49     }
50
51     @Test
52     public void testSingleton() {
53         final var one = UnsignedLongBitmap.of(0, false);
54         assertFalse(one.isEmpty());
55         assertEquals(1, one.size());
56         assertEquals(one, one);
57         assertEquals(one, UnsignedLongBitmap.of(0, false));
58         assertEquals(one, UnsignedLongBitmap.copyOf(Map.of(UnsignedLong.ZERO, false)));
59         assertEquals(Map.of(UnsignedLong.ZERO, false), one.mutableCopy());
60         assertEquals("{0=false}", one.toString());
61         assertEquals(1237, one.hashCode());
62
63         final var ex = assertThrows(IOException.class, () -> one.writeEntriesTo(mock(DataOutput.class), 0));
64         assertEquals("Mismatched size: expected 1, got 0", ex.getMessage());
65
66         assertEquals(one, UnsignedLongBitmap.of(0, false));
67         assertNotEquals(one, UnsignedLongBitmap.of(0, true));
68         assertNotEquals(one, UnsignedLongBitmap.of(1, false));
69         assertNotEquals(UnsignedLongBitmap.of(), one);
70         assertNotEquals(one, UnsignedLongBitmap.of());
71
72         assertWriteToReadFrom(one);
73     }
74
75     @Test
76     public void testRegular() {
77         final var one = UnsignedLongBitmap.copyOf(Map.of(UnsignedLong.ZERO, false, UnsignedLong.ONE, true));
78         assertFalse(one.isEmpty());
79         assertEquals(2, one.size());
80         assertEquals(one, one);
81         assertEquals(one, UnsignedLongBitmap.copyOf(Map.of(UnsignedLong.ONE, true, UnsignedLong.ZERO, false)));
82         assertEquals(Map.of(UnsignedLong.ZERO, false, UnsignedLong.ONE, true), one.mutableCopy());
83
84         assertNotEquals(one,
85             UnsignedLongBitmap.copyOf(Map.of(UnsignedLong.ZERO, false, UnsignedLong.valueOf(2), true)));
86         assertEquals("{0=false, 1=true}", one.toString());
87         assertEquals(40345, one.hashCode());
88
89         final var ex = assertThrows(IOException.class, () -> one.writeEntriesTo(mock(DataOutput.class), 1));
90         assertEquals("Mismatched size: expected 2, got 1", ex.getMessage());
91
92         final var two = UnsignedLongBitmap.copyOf(Map.of(UnsignedLong.ZERO, true, UnsignedLong.ONE, false));
93         assertFalse(two.isEmpty());
94         assertEquals(2, two.size());
95         assertEquals(two, two);
96         assertEquals(two, UnsignedLongBitmap.copyOf(Map.of(UnsignedLong.ZERO, true, UnsignedLong.ONE, false)));
97         assertEquals("{0=true, 1=false}", two.toString());
98         assertEquals(40549, two.hashCode());
99
100         assertNotEquals(one, two);
101         assertNotEquals(two, one);
102
103         assertWriteToReadFrom(one);
104         assertWriteToReadFrom(two);
105     }
106
107     private static UnsignedLongBitmap assertWriteToReadFrom(final UnsignedLongBitmap orig) {
108         final var dos = ByteStreams.newDataOutput();
109         try {
110             orig.writeEntriesTo(dos);
111         } catch (IOException e) {
112             throw new AssertionError(e);
113         }
114
115         final UnsignedLongBitmap copy;
116         try {
117             final var dis = ByteStreams.newDataInput(dos.toByteArray());
118             copy = UnsignedLongBitmap.readFrom(dis, orig.size());
119             assertThrows(IllegalStateException.class, () -> dis.readByte());
120         } catch (IOException e) {
121             throw new AssertionError(e);
122         }
123
124         assertEquals(orig, copy);
125         return copy;
126     }
127
128     @Test
129     public void testKeyOrder() throws IOException {
130         assertInvalidKey(0);
131         assertInvalidKey(1);
132     }
133
134     private static void assertInvalidKey(final long second) throws IOException {
135         final var out = ByteStreams.newDataOutput();
136         WritableObjects.writeLong(out, 1);
137         out.writeBoolean(false);
138         WritableObjects.writeLong(out, second);
139         out.writeBoolean(true);
140
141         final var ex = assertThrows(IOException.class,
142             () -> UnsignedLongBitmap.readFrom(ByteStreams.newDataInput(out.toByteArray()), 2));
143         assertEquals("Key " + second + " may not be used after key 1", ex.getMessage());
144     }
145
146     @Test
147     public void testInvalidArrays() {
148         assertThrows(VerifyException.class, () -> new Regular(new long[0], new boolean[] { false, false }));
149     }
150 }