/**
* Copyright 2016 LinkedIn Corp. All rights reserved.
*
* Licensed 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.
*/
package com.github.ambry.store;
import com.github.ambry.utils.ByteBufferInputStream;
import com.github.ambry.utils.TestUtils;
import com.github.ambry.utils.Utils;
import java.io.DataInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Tests for {@link Offset}.
*/
public class OffsetTest {
/**
* Tests serialization and deserialization of an {@link Offset} class.
* @throws IOException
*/
@Test
public void offsetSerDeTest() throws IOException {
long pos = Utils.getRandomLong(TestUtils.RANDOM, 1000);
long gen = Utils.getRandomLong(TestUtils.RANDOM, 1000);
String name = LogSegmentNameHelper.getName(pos, gen);
long offset = Utils.getRandomLong(new Random(), Long.MAX_VALUE);
Offset logOffset = new Offset(name, offset);
byte[] serialized = logOffset.toBytes();
Offset deserializedOffset =
Offset.fromBytes(new DataInputStream(new ByteBufferInputStream(ByteBuffer.wrap(serialized))));
assertEquals("Original offset 'name' does not match with the deserialized offset", name,
deserializedOffset.getName());
assertEquals("Original offset 'offset' does not match with the deserialized offset", offset,
deserializedOffset.getOffset());
// equals test
assertEquals("Original offset does not match with the deserialized offset", logOffset, deserializedOffset);
// hashcode test
assertEquals("Hashcode doesn't match", logOffset.hashCode(), deserializedOffset.hashCode());
}
/**
* Tests the constructor and {@link Offset#fromBytes(DataInputStream)} function with bad input.
* @throws IOException
*/
@Test
public void offsetBadInputTest() throws IOException {
doBadOffsetInputTest(null, 10);
doBadOffsetInputTest("1_11_log", -1);
Offset offset = new Offset("1_11_log", 10);
byte[] serialized = offset.toBytes();
// mess with a version byte
serialized[0] = serialized[0] == (byte) 1 ? (byte) 2 : (byte) 1;
try {
Offset.fromBytes(new DataInputStream(new ByteBufferInputStream(ByteBuffer.wrap(serialized))));
fail("Version check should have failed");
} catch (IllegalArgumentException e) {
// expected.
}
}
/**
* Tests {@link Offset#compareTo(Offset)}.
*/
@Test
public void compareToTest() {
List<Offset> offsets = new ArrayList<>();
offsets.add(new Offset("0_0", 0));
offsets.add(new Offset("0_0", 1));
offsets.add(new Offset("0_1", 0));
offsets.add(new Offset("0_1", 1));
offsets.add(new Offset("1_0", 0));
offsets.add(new Offset("1_0", 1));
for (int i = 0; i < offsets.size(); i++) {
for (int j = 0; j < offsets.size(); j++) {
int expectCompare = i == j ? 0 : i > j ? 1 : -1;
assertEquals("Unexpected value on compare", expectCompare, offsets.get(i).compareTo(offsets.get(j)));
assertEquals("Unexpected value on compare", -1 * expectCompare, offsets.get(j).compareTo(offsets.get(i)));
}
}
}
/**
* Tests for {@link Offset#equals(Object)} and {@link Offset#hashCode()}.
*/
@Test
public void equalsAndHashCodeTest() {
Offset o1 = new Offset("1_1", 2);
Offset o2 = new Offset("1_1", 2);
Offset o3 = new Offset("1_1", 3);
Offset o4 = new Offset("1_2", 2);
assertTrue("Offset should be equal to itself", o1.equals(o1));
assertFalse("Offset should not be equal to null", o1.equals(null));
assertFalse("Offset should not be equal to random Object", o1.equals(new Object()));
assertTrue("Offsets should be declared equal", o1.equals(o2));
assertEquals("Hashcode mismatch", o1.hashCode(), o2.hashCode());
assertFalse("Offsets should be declared unequal", o1.equals(o3));
assertFalse("Offsets should be declared unequal", o1.equals(o4));
}
// helpers
// offsetBadInputTest()
/**
* Tests constructor of {@link Offset} with bad input.
* @param name the name to use.
* @param offset the offset to use.
*/
private void doBadOffsetInputTest(String name, long offset) {
try {
new Offset(name, offset);
fail("Should have thrown because one of the inputs is invalid");
} catch (IllegalArgumentException e) {
// expected.
}
}
}