/* * 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 })); } }