Java tutorial
/** * Copyright (c) 2016, All Contributors (see CONTRIBUTORS file) * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package com.eventsourcing.hlc; import com.eventsourcing.layout.Layout; import com.eventsourcing.layout.ObjectDeserializer; import com.eventsourcing.layout.ObjectSerializer; import com.eventsourcing.layout.Property; import com.eventsourcing.layout.binary.BinarySerialization; import com.google.common.util.concurrent.AbstractService; import lombok.SneakyThrows; import org.apache.commons.net.ntp.TimeStamp; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.nio.ByteBuffer; import java.util.Date; import java.util.List; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; public class HybridTimestampTest { class TestPhysicalTimeProvider extends AbstractService implements PhysicalTimeProvider { private long physicalTime = 0; @Override public long getPhysicalTime() { return physicalTime; } public void setPhysicalTime(long physicalTime) { this.physicalTime = physicalTime; } @Override protected void doStart() { notifyStarted(); } @Override protected void doStop() { notifyStopped(); } } ; private TestPhysicalTimeProvider physicalTimeProvider; @BeforeClass public void setup() { physicalTimeProvider = new TestPhysicalTimeProvider(); } @Test public void initialTimestamp() { HybridTimestamp timestamp = new HybridTimestamp(physicalTimeProvider); TimeStamp ntpTime = new TimeStamp(timestamp.getLogicalTime()); assertEquals(ntpTime.getDate(), new Date(0)); } @Test public void testTimestamp() { HybridTimestamp timestamp = new HybridTimestamp(physicalTimeProvider); timestamp.update(); timestamp.update(); assertTrue(timestamp.getLogicalCounter() > 0); HybridTimestamp timestamp1 = new HybridTimestamp(physicalTimeProvider, timestamp.getLogicalTime(), timestamp.getLogicalCounter()); assertEquals(timestamp1.getLogicalCounter(), timestamp.getLogicalCounter()); } @Test @SneakyThrows public void layout() { Layout<HybridTimestamp> layout = Layout.forClass(HybridTimestamp.class); List<Property<HybridTimestamp>> properties = layout.getProperties(); assertEquals(properties.size(), 2); assertTrue(properties.stream().anyMatch(p -> p.getName().contentEquals("logicalTime"))); assertTrue(properties.stream().anyMatch(p -> p.getName().contentEquals("logicalCounter"))); HybridTimestamp timestamp = new HybridTimestamp(physicalTimeProvider); timestamp.update(); BinarySerialization serialization = BinarySerialization.getInstance(); ObjectSerializer<HybridTimestamp> serializer = serialization.getSerializer(HybridTimestamp.class); ObjectDeserializer<HybridTimestamp> deserializer = serialization.getDeserializer(HybridTimestamp.class); ByteBuffer buffer = serializer.serialize(timestamp); buffer.rewind(); HybridTimestamp timestamp1 = deserializer.deserialize(buffer); assertEquals(timestamp1.compareTo(timestamp), 0); } @Test public void test() { long ts, ts_; HybridTimestamp timestamp = new HybridTimestamp(physicalTimeProvider, 0, 0); ts = (long) 1 << 32 | 0; physicalTimeProvider.setPhysicalTime(ts); timestamp.update(); assertEquals(ts, timestamp.getLogicalTime()); assertEquals(0, timestamp.getLogicalCounter()); // clock didn't move ts = (long) 1 << 32 | 0; physicalTimeProvider.setPhysicalTime(ts); timestamp.update(); assertEquals(ts, timestamp.getLogicalTime()); assertEquals(1, timestamp.getLogicalCounter()); // clock moved back ts = (long) 0 << 32 | 1; physicalTimeProvider.setPhysicalTime(ts); ts_ = timestamp.getLogicalTime(); timestamp.update(); assertEquals(ts_, timestamp.getLogicalTime()); assertEquals(2, timestamp.getLogicalCounter()); // clock moved ahead ts = (long) 2 << 32 | 0; physicalTimeProvider.setPhysicalTime(ts); timestamp.update(); assertEquals(ts, timestamp.getLogicalTime()); assertEquals(0, timestamp.getLogicalCounter()); // event happens, but wall ahead ts = (long) 3 << 32 | 0; physicalTimeProvider.setPhysicalTime(ts); timestamp.update((long) 1 << 32 | 2, 3); assertEquals(ts, timestamp.getLogicalTime()); assertEquals(0, timestamp.getLogicalCounter()); // event happens, wall ahead but unchanged ts = (long) 3 << 32 | 0; physicalTimeProvider.setPhysicalTime(ts); timestamp.update((long) 1 << 32 | 2, 3); assertEquals(ts, timestamp.getLogicalTime()); assertEquals(1, timestamp.getLogicalCounter()); // event happens at wall, which is still unchanged ts = (long) 3 << 32 | 0; physicalTimeProvider.setPhysicalTime(ts); timestamp.update((long) 3 << 32 | 0, 1); assertEquals(ts, timestamp.getLogicalTime()); assertEquals(2, timestamp.getLogicalCounter()); // event with larger logical, wall unchaged ts = (long) 3 << 32 | 0; physicalTimeProvider.setPhysicalTime(ts); timestamp.update((long) 3 << 32 | 0, 99); assertEquals(ts, timestamp.getLogicalTime()); assertEquals(100, timestamp.getLogicalCounter()); // event with larger wall, our wall behind ts = (long) 3 << 32 | 5; physicalTimeProvider.setPhysicalTime(ts); timestamp.update((long) 4 << 32 | 4, 100); assertEquals((long) 4 << 32 | 4, timestamp.getLogicalTime()); assertEquals(101, timestamp.getLogicalCounter()); // event behind wall, but ahead of previous state ts = (long) 5 << 32 | 0; physicalTimeProvider.setPhysicalTime(ts); timestamp.update((long) 4 << 32 | 5, 0); assertEquals(ts, timestamp.getLogicalTime()); assertEquals(0, timestamp.getLogicalCounter()); ts = (long) 4 << 32 | 9; physicalTimeProvider.setPhysicalTime(ts); timestamp.update((long) 5 << 32 | 0, 99); assertEquals((long) 5 << 32 | 0, timestamp.getLogicalTime()); assertEquals(100, timestamp.getLogicalCounter()); // event at state, lower logical than state ts = (long) 0 << 32 | 0; physicalTimeProvider.setPhysicalTime(ts); timestamp.update((long) 5 << 32 | 0, 50); assertEquals((long) 5 << 32 | 0, timestamp.getLogicalTime()); assertEquals(101, timestamp.getLogicalCounter()); // another update API timestamp.update(timestamp); assertEquals((long) 5 << 32 | 0, timestamp.getLogicalTime()); assertEquals(102, timestamp.getLogicalCounter()); } }