/**
* 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.queries;
import com.eventsourcing.*;
import com.eventsourcing.hlc.HybridTimestamp;
import com.eventsourcing.index.Index;
import com.eventsourcing.index.SimpleIndex;
import com.googlecode.cqengine.query.Query;
import com.googlecode.cqengine.resultset.ResultSet;
import lombok.EqualsAndHashCode;
import lombok.SneakyThrows;
import lombok.Value;
import lombok.experimental.Accessors;
import org.testng.annotations.Test;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import static com.eventsourcing.index.IndexEngine.IndexFeature.EQ;
import static com.eventsourcing.index.IndexEngine.IndexFeature.GT;
import static com.eventsourcing.index.IndexEngine.IndexFeature.LT;
import static com.eventsourcing.queries.QueryFactory.*;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
public class MinMaxTest extends RepositoryUsingTest {
@Value
@EqualsAndHashCode(callSuper = false)
@Accessors(fluent = true)
public static class TestEvent extends StandardEvent {
String prop;
public final static SimpleIndex<TestEvent, String> PROP = SimpleIndex.as(TestEvent::prop);
@Index({EQ, LT, GT})
public final static SimpleIndex<TestEvent, HybridTimestamp> TIMESTAMP = SimpleIndex.as(StandardEntity::timestamp);
}
@Value
@EqualsAndHashCode(callSuper = false)
@Accessors(fluent = true)
public static class TestCommand extends StandardCommand<UUID, HybridTimestamp> {
String prop;
@Override public EventStream<UUID> events() throws Exception {
TestEvent event = new TestEvent(prop);
return EventStream.ofWithState(event.uuid(), event);
}
@Override public HybridTimestamp result(UUID state, Repository repository) {
return repository.getJournal().get(state).get().timestamp();
}
}
public MinMaxTest() {
super(Min.class.getPackage());
}
@Test
@SneakyThrows
public void test() {
HybridTimestamp ts1 = repository.publish(new TestCommand("test")).get();
HybridTimestamp ts2 = repository.publish(new TestCommand("test")).get();
HybridTimestamp ts3 = repository.publish(new TestCommand("test")).get();
try (ResultSet<EntityHandle<TestEvent>> rs = repository.query(TestEvent.class, min(TestEvent.TIMESTAMP))) {
assertEquals(rs.uniqueResult().get().timestamp(), ts1);
}
try (ResultSet<EntityHandle<TestEvent>> rs = repository.query(TestEvent.class, max(TestEvent.TIMESTAMP))) {
assertEquals(rs.uniqueResult().get().timestamp(), ts3);
}
}
@Test
@SneakyThrows
public void empty() {
try (ResultSet<EntityHandle<TestEvent>> rs = repository.query(TestEvent.class, min(TestEvent.TIMESTAMP))) {
assertTrue(rs.isEmpty());
}
}
@Test @SneakyThrows
public void testMassive() {
UUID uuid = UUID.randomUUID();
for (int i = 0; i < 100000; i++ ) {
repository.publish(new IsLatestEntityTest.TestCommand("test" + (i + 1), uuid)).get();
}
Query<EntityHandle<IsLatestEntityTest.TestEvent>> query = scoped(equal(IsLatestEntityTest.TestEvent
.REFERENCE_ID, uuid),
max(IsLatestEntityTest.TestEvent.TIMESTAMP));
long t1 = System.nanoTime();
try (ResultSet<EntityHandle<IsLatestEntityTest.TestEvent>> resultSet = repository.query(IsLatestEntityTest.TestEvent.class, query)) {
assertEquals(resultSet.size(), 1);
assertEquals(resultSet.uniqueResult().get().test(), "test100000");
long t2 = System.nanoTime();
long time = TimeUnit.SECONDS.convert(t2 - t1, TimeUnit.NANOSECONDS);
if (time > 1) {
System.err.println("Warning: [MinMaxTest.testMassive] is slow, took " + time +
" seconds");
}
}
}
}