/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.bson.types;
import org.junit.Test;
import java.util.Date;
import java.util.Random;
import java.nio.ByteBuffer;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class ObjectIdTest {
@Test
public void testToBytes() {
ObjectId objectId = new ObjectId(0x5106FC9A, 0x00BC8237, (short) 0x5581, 0x0036D289);
byte[] expectedBytes = new byte[]{81, 6, -4, -102, -68, -126, 55, 85, -127, 54, -46, -119};
assertArrayEquals(expectedBytes, objectId.toByteArray());
ByteBuffer buffer = ByteBuffer.allocate(12);
objectId.putToByteBuffer(buffer);
assertArrayEquals(expectedBytes, buffer.array());
}
@Test
public void testFromBytes() {
byte[] bytes = new byte[]{81, 6, -4, -102, -68, -126, 55, 85, -127, 54, -46, -119};
ObjectId objectId1 = new ObjectId(bytes);
assertEquals(0x5106FC9A, objectId1.getTimestamp());
assertEquals(0x00BC8237, objectId1.getMachineIdentifier());
assertEquals((short) 0x5581, objectId1.getProcessIdentifier());
assertEquals(0x0036D289, objectId1.getCounter());
ObjectId objectId2 = new ObjectId(ByteBuffer.wrap(bytes));
assertEquals(0x5106FC9A, objectId2.getTimestamp());
assertEquals(0x00BC8237, objectId2.getMachineIdentifier());
assertEquals((short) 0x5581, objectId2.getProcessIdentifier());
assertEquals(0x0036D289, objectId2.getCounter());
}
@Test
public void testBytesRoundtrip() {
ObjectId expected = new ObjectId();
ObjectId actual = new ObjectId(expected.toByteArray());
assertEquals(expected, actual);
byte[] b = new byte[12];
Random r = new Random(17);
for (int i = 0; i < b.length; i++) {
b[i] = (byte) (r.nextInt());
}
expected = new ObjectId(b);
assertEquals(expected, new ObjectId(expected.toByteArray()));
assertEquals("41d91c58988b09375cc1fe9f", expected.toString());
}
@Test
public void testTime() {
long a = System.currentTimeMillis();
long b = (new ObjectId()).getDate().getTime();
assertTrue(Math.abs(b - a) < 3000);
}
@Test
public void testDateCons() {
Date d = new Date();
ObjectId a = new ObjectId(d);
assertEquals(d.getTime() / 1000, a.getDate().getTime() / 1000);
}
@Test
public void testMachineIdentifier() {
assertTrue(ObjectId.getGeneratedMachineIdentifier() > 0);
assertEquals(0, ObjectId.getGeneratedMachineIdentifier() & 0xff000000);
assertEquals(5, new ObjectId(0, 5, (short) 0, 0).getMachineIdentifier());
assertEquals(0x00ffffff, new ObjectId(0, 0x00ffffff, (short) 0, 0).getMachineIdentifier());
assertEquals(ObjectId.getGeneratedMachineIdentifier(), new ObjectId().getMachineIdentifier());
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowIfMachineIdentifierIsTooLarge() {
new ObjectId(0, 0x00ffffff + 1, (short) 0, 0);
}
@Test
public void testProcessIdentifier() {
assertEquals(5, new ObjectId(0, 0, (short) 5, 0).getProcessIdentifier());
assertEquals(ObjectId.getGeneratedProcessIdentifier(), new ObjectId().getProcessIdentifier());
}
@Test
public void testCounter() {
assertEquals(new ObjectId().getCounter() + 1, new ObjectId().getCounter());
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowIfCounterIsTooLarge() {
new ObjectId(0, 0, (short) 0, 0x00ffffff + 1);
}
@Test
public void testHexStringConstructor() {
ObjectId id = new ObjectId();
assertEquals(id, new ObjectId(id.toHexString()));
}
@Test
public void testCompareTo() {
assertEquals(-1, new ObjectId(0, 0, (short) 0, 0).compareTo(new ObjectId(1, 0, (short) 0, 0)));
assertEquals(-1, new ObjectId(0, 0, (short) 0, 0).compareTo(new ObjectId(0, 1, (short) 0, 0)));
assertEquals(-1, new ObjectId(0, 0, (short) 0, 0).compareTo(new ObjectId(0, 0, (short) 1, 0)));
assertEquals(-1, new ObjectId(0, 0, (short) 1, 0).compareTo(new ObjectId(0, 0, (short) -1, 0)));
assertEquals(-1, new ObjectId(0, 0, (short) 0, 0).compareTo(new ObjectId(0, 0, (short) 0, 1)));
assertEquals(0, new ObjectId(0, 0, (short) 0, 0).compareTo(new ObjectId(0, 0, (short) 0, 0)));
assertEquals(1, new ObjectId(1, 0, (short) 0, 0).compareTo(new ObjectId(0, 0, (short) 0, 0)));
assertEquals(1, new ObjectId(0, 1, (short) 0, 0).compareTo(new ObjectId(0, 0, (short) 0, 0)));
assertEquals(1, new ObjectId(0, 0, (short) 1, 0).compareTo(new ObjectId(0, 0, (short) 0, 0)));
assertEquals(1, new ObjectId(0, 0, (short) -1, 0).compareTo(new ObjectId(0, 0, (short) 1, 0)));
assertEquals(1, new ObjectId(0, 0, (short) 0, 1).compareTo(new ObjectId(0, 0, (short) 0, 0)));
}
@Test
public void testToHexString() {
assertEquals("000000000000000000000000", new ObjectId(0, 0, (short) 0, 0).toHexString());
assertEquals("7fffffff007fff7fff007fff",
new ObjectId(Integer.MAX_VALUE, Short.MAX_VALUE, Short.MAX_VALUE, Short.MAX_VALUE).toHexString());
}
@SuppressWarnings("deprecation")
@Test
public void testDeprecatedMethods() {
ObjectId id = new ObjectId();
assertEquals(id.getTimestamp(), id.getTimeSecond());
assertEquals(id.getDate().getTime(), id.getTime());
assertEquals(id.toHexString(), id.toStringMongod());
assertArrayEquals(new byte[]{0x12, 0x34, 0x56, 0x78, 0x43, 0x21, 0xffffff87, 0x65, 0x74, 0xffffff92, 0xffffff87, 0x56},
new ObjectId(0x12345678, 0x43218765, 0x74928756).toByteArray());
}
// Got these values from 2.12.0 driver. This test is ensuring that we properly round-trip old and new format ObjectIds.
@Test
public void testCreateFromLegacy() {
assertArrayEquals(new byte[]{82, 23, -82, -78, -80, -58, -95, -92, -75, -38, 118, -16},
ObjectId.createFromLegacyFormat(1377283762, -1329159772, -1243973904).toByteArray());
}
}