/*
* Licensed to Cinchapi Inc, under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership. Cinchapi Inc. licenses this
* file to you 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 com.cinchapi.concourse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
import com.cinchapi.concourse.Timestamp;
import com.cinchapi.concourse.test.ConcourseIntegrationTest;
import com.cinchapi.concourse.test.Variables;
import com.cinchapi.concourse.time.Time;
import com.cinchapi.concourse.util.TestData;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
/**
* Tests new API named chronologize which returns a mapping from
* from each timestamp to each non-empty set of values over time.
*
* @author knd
*
*/
public class ChronologizeTest extends ConcourseIntegrationTest {
@Test
public void testChronologizeRangeSanityCheck(){
String key = "foo";
long record = 1;
client.add(key, 1, record);
client.add(key, 2, record);
client.add(key, 3, record);
Map<Timestamp, Set<Object>> chronology = client.chronologize(key, record);
Timestamp preStart = Iterables.get(chronology.keySet(), 0);
Timestamp start = Iterables.get(chronology.keySet(), 1);
chronology = client.chronologize(key, record, start, Timestamp.now());
assertFalse(chronology.keySet().contains(preStart));
assertEquals(2, chronology.size());
}
@Test
public void testChronologizeIsEmptyForNonExistingKeyInRecord() {
long record = Variables.register("record", Time.now());
String key = Variables.register("key", TestData.getSimpleString());
String diffKey = Variables.register("diffKey", null);
Object diffValue = Variables.register("diffValue", TestData.getObject());
while (diffKey == null || key.equals(diffKey)) {
diffKey = TestData.getSimpleString();
}
client.add(diffKey, diffValue, record);
assertTrue(client.chronologize(key, record).isEmpty());
}
@Test
public void testChronologizeWhenNoRemovalHasHappened() {
long record = Variables.register("record", Time.now());
String key = Variables.register("key", TestData.getSimpleString());
int testSize = Variables.register("testSize", 5);
Set<Object> initValues = Variables.register("initValues", Sets.newHashSet());
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
client.add(key, value, record);
}
Map<Timestamp, Set<Object>> result = client.chronologize(key, record);
assertEquals(testSize, result.size());
Iterator<Map.Entry<Timestamp, Set<Object>>> setIter = result.entrySet().iterator();
for (int i = 0; i < testSize; i++) {
assertEquals(i + 1, setIter.next().getValue().size());
}
}
@Test
public void testChronologizeWhenRemovalHasHappened() {
long record = Variables.register("record", Time.now());
String key = Variables.register("key", TestData.getSimpleString());
int testSize = Variables.register("testSize", 5);
Set<Object> initValues = Variables.register("initValues", Sets.newHashSet());
List<Object> listOfValues = new ArrayList<Object>();
Map<Timestamp, Set<Object>> result = null;
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
listOfValues.add(value);
client.add(key, value, record);
}
int expectedMapSize = testSize;
int expectedLastSetSize = testSize;
Set<Object> lastValueSet = null;
// remove 1 value
expectedMapSize += 1;
expectedLastSetSize -= 1;
client.remove(key, listOfValues.get(2), record);
result = client.chronologize(key, record);
assertEquals(expectedMapSize, result.size());
lastValueSet = Iterables.getLast((Iterable<Set<Object>>) result.values());
assertEquals(expectedLastSetSize, lastValueSet.size());
// remove 2 values
expectedMapSize += 2;
expectedLastSetSize -= 2;
client.remove(key, listOfValues.get(0), record);
client.remove(key, listOfValues.get(4), record);
result = client.chronologize(key, record);
assertEquals(expectedMapSize, result.size());
lastValueSet = Iterables.getLast((Iterable<Set<Object>>) result.values());
assertEquals(expectedLastSetSize, lastValueSet.size());
// add 1 value
expectedMapSize += 1;
expectedLastSetSize += 1;
client.add(key, listOfValues.get(2), record);
result = client.chronologize(key, record);
assertEquals(expectedMapSize, result.size());
lastValueSet = Iterables.getLast((Iterable<Set<Object>>) result.values());
assertEquals(expectedLastSetSize, lastValueSet.size());
// clear all values
expectedMapSize += expectedLastSetSize - 1; // last empty set filtered out
expectedLastSetSize = 1;
client.clear(key, record);
result = client.chronologize(key, record);
assertEquals(expectedMapSize, result.size());
lastValueSet = Iterables.getLast((Iterable<Set<Object>>) result.values());
assertEquals(expectedLastSetSize, lastValueSet.size());
}
@Test
public void testChronologizeWhenRemovalHasHappenedWithEmptyValues() {
long record = Variables.register("record", Time.now());
String key = Variables.register("key", TestData.getSimpleString());
int testSize = Variables.register("testSize", 5);
Set<Object> initValues = Variables.register("initValues", Sets.newHashSet());
List<Object> listOfValues = new ArrayList<Object>();
Map<Timestamp, Set<Object>> result = null;
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
listOfValues.add(value);
client.add(key, value, record);
}
client.remove(key, listOfValues.get(2), record);
client.remove(key, listOfValues.get(0), record);
client.remove(key, listOfValues.get(4), record);
client.add(key, listOfValues.get(2), record);
client.set(key, listOfValues.get(0), record);
client.add(key, listOfValues.get(1), record);
client.add(key, listOfValues.get(2), record);
client.set(key, listOfValues.get(3), record);
result = client.chronologize(key, record);
Variables.register("result", result);
Variables.register("audit", client.audit(key, record));
assertEquals(17, result.size());
assertEquals(5, Iterables.get(result.entrySet(), 4).getValue().size());
assertEquals(4, Iterables.get(result.entrySet(), 5).getValue().size());
assertEquals(3, Iterables.get(result.entrySet(), 6).getValue().size());
assertEquals(2, Iterables.get(result.entrySet(), 7).getValue().size());
assertEquals(3, Iterables.get(result.entrySet(), 8).getValue().size());
assertEquals(2, Iterables.get(result.entrySet(), 9).getValue().size());
assertEquals(1, Iterables.get(result.entrySet(), 10).getValue().size());
assertEquals(1, Iterables.get(result.entrySet(), 11).getValue().size());
assertEquals(2, Iterables.get(result.entrySet(), 12).getValue().size());
assertEquals(3, Iterables.get(result.entrySet(), 13).getValue().size());
assertEquals(2, Iterables.get(result.entrySet(), 14).getValue().size());
assertEquals(1, Iterables.get(result.entrySet(), 15).getValue().size());
assertEquals(1, Iterables.get(result.entrySet(), 16).getValue().size());
}
@Test
public void testChronologizeIsNotAffectedByAddingValueAlreadyInKeyInRecord() {
long record = Variables.register("record", Time.now());
String key = Variables.register("key", TestData.getSimpleString());
int testSize = Variables.register("testSize", 5);
Set<Object> initValues = Variables.register("initValues", Sets.newHashSet());
List<Object> listOfValues = new ArrayList<Object>();
Map<Timestamp, Set<Object>> result = null;
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
listOfValues.add(value);
client.add(key, value, record);
}
int expectedMapSize = testSize;
int expectedLastSetSize = testSize;
Set<Object> lastValueSet = null;
// add 1 already existed value
client.add(key, listOfValues.get(2), record);
result = client.chronologize(key, record);
assertEquals(expectedMapSize, result.size());
lastValueSet = Iterables.getLast((Iterable<Set<Object>>) result.values());
assertEquals(expectedLastSetSize, lastValueSet.size());
}
@Test
public void testChronologizeIsNotAffectedByRemovingValueNotInKeyInRecord() {
long record = Variables.register("record", Time.now());
String key = Variables.register("key", TestData.getSimpleString());
int testSize = Variables.register("testSize", 5);
Set<Object> initValues = Variables.register("initValues", Sets.newHashSet());
Map<Timestamp, Set<Object>> result = null;
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
client.add(key, value, record);
}
int expectedMapSize = testSize;
int expectedLastSetSize = testSize;
Set<Object> lastValueSet = null;
// remove 1 non-existing value
Object nonValue = null;
while (nonValue == null || initValues.contains(nonValue)) {
nonValue = TestData.getObject();
}
client.remove(key, nonValue, record);
result = client.chronologize(key, record);
assertEquals(expectedMapSize, result.size());
lastValueSet = Iterables.getLast((Iterable<Set<Object>>) result.values());
assertEquals(expectedLastSetSize, lastValueSet.size());
}
@Test
public void testChronologizeHasFilteredOutEmptyValueSets() {
long record = Variables.register("record", Time.now());
String key = Variables.register("key", TestData.getSimpleString());
int testSize = Variables.register("testSize", 5);
Set<Object> initValues = Variables.register("initValues", Sets.newHashSet());
Map<Timestamp, Set<Object>> result = null;
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
client.set(key, value, record);
}
result = client.chronologize(key, record);
for (Set<Object> values : result.values()) {
assertFalse(values.isEmpty());
}
}
@Test
public void testChronologizeWithStartTimestampAndEndTimestampBeforeAnyValuesChangeInKeyInRecord() {
long record = Variables.register("record", Time.now());
String key = Variables.register("key", TestData.getSimpleString());
int testSize = Variables.register("testSize", 5);
Set<Object> initValues = Variables.register("initValues", Sets.newHashSet());
Timestamp startTimestamp = Variables.register("startTimestamp", Timestamp.now());
Timestamp endTimestamp = Variables.register("endTimestamp", Timestamp.now());
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
client.add(key, value, record);
}
Map<Timestamp, Set<Object>> result = client.chronologize(key, record, startTimestamp, endTimestamp);
result = Variables.register("result", result);
assertTrue(result.isEmpty());
}
@Test
public void testChronologizeWithStartTimestampBeforeAndEndTimestampAfterAnyValuesChangeInKeyInRecord() {
long record = Variables.register("record", Time.now());
String key = Variables.register("key", TestData.getSimpleString());
int testSize = Variables.register("testSize", 5);
Set<Object> initValues = Variables.register("initValues", Sets.newHashSet());
Timestamp startTimestamp = Variables.register("startTimestamp", Timestamp.now());
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
client.add(key, value, record);
}
Timestamp endTimestamp = Variables.register("endTimestamp", Timestamp.now());
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
client.add(key, value, record);
}
Map<Timestamp, Set<Object>> result = client.chronologize(key, record, startTimestamp, endTimestamp);
Set<Object> lastResultSet = Iterables.getLast(result.values());
result = Variables.register("result", result);
assertEquals(testSize, result.size());
assertEquals(testSize, lastResultSet.size());
}
@Test
public void testChronologizeWithStartTimestampAndEndTimestampAfterAnyValuesChangeInKeyInRecord() {
long record = Variables.register("record", Time.now());
String key = Variables.register("key", TestData.getSimpleString());
int testSize = Variables.register("testSize", 5);
Set<Object> initValues = Variables.register("initValues", Sets.newHashSet());
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
client.add(key, value, record);
}
Timestamp startTimestamp = Variables.register("startTimestamp", Timestamp.now());
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
client.add(key, value, record);
}
Timestamp endTimestamp = Variables.register("endTimestamp", Timestamp.now());
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
client.add(key, value, record);
}
Map<Timestamp, Set<Object>> result = client.chronologize(key, record, startTimestamp, endTimestamp);
Set<Object> lastResultSet = Iterables.getLast(result.values());
assertEquals(testSize, result.size());
assertEquals(testSize * 2, lastResultSet.size());
}
@Test
public void testChronolgizeWithStartTimestampAsEpochAndEndTimestampAsNowInKeyInRecord() {
long record = Variables.register("record", Time.now());
String key = Variables.register("key", TestData.getSimpleString());
int testSize = Variables.register("testSize", 5);
Set<Object> initValues = Variables.register("initValues", Sets.newHashSet());
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
client.add(key, value, record);
}
client.set(key, TestData.getObject(), record);
Timestamp epoch = Variables.register("epochTimestamp", Timestamp.epoch());
Timestamp now = Variables.register("nowTimestamp", Timestamp.now());
Map<Timestamp, Set<Object>> result = client.chronologize(key, record, epoch, now);
result = Variables.register("result", result);
Set<Object> lastResultSet = Iterables.getLast(result.values());
assertEquals(testSize * 2, result.size());
assertEquals(1, lastResultSet.size());
}
@Test
public void testChronologizeWithEndTimestampIsExclusiveAtExactFirstValueChangeInKeyInRecord() {
long record = Variables.register("record", Time.now());
String key = Variables.register("key", TestData.getSimpleString());
int testSize = Variables.register("testSize", 5);
Set<Object> initValues = Variables.register("initValues", Sets.newHashSet());
List<Timestamp> timestamps = new ArrayList<Timestamp>();
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
client.add(key, value, record);
timestamps.add(Timestamp.now());
}
Map<Timestamp, Set<Object>> chronology = client.chronologize(key, record);
Timestamp exactStartTimestamp = Variables.register("exactStartTimestamp", Iterables.getFirst((Iterable<Timestamp>) chronology.keySet(), null));
Map<Timestamp, Set<Object>> result = client.chronologize(key, record, Timestamp.epoch(), exactStartTimestamp);
assertTrue(result.isEmpty());
}
@Test
public void testChronologizeWithEndTimestampIsExclusiveAfterFirstValueChangeInKeyInRecord() {
long record = Variables.register("record", Time.now());
String key = Variables.register("key", TestData.getSimpleString());
int testSize = Variables.register("testSize", 5);
Set<Object> initValues = Variables.register("initValues", Sets.newHashSet());
List<Timestamp> timestamps = new ArrayList<Timestamp>();
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
client.add(key, value, record);
timestamps.add(Timestamp.now());
}
Map<Timestamp, Set<Object>> result = client.chronologize(key, record, Timestamp.epoch(), timestamps.get(0));
Set<Object> lastResultSet = Iterables.getLast(result.values());
result = Variables.register("result", result);
assertEquals(1, result.size());
assertEquals(1, lastResultSet.size());
}
@Test
public void testChronologizeWithStartTimestampIsInclusiveAtExactFirstValueChangeInKeyInRecord() {
long record = Variables.register("record", Time.now());
String key = Variables.register("key", TestData.getSimpleString());
int testSize = Variables.register("testSize", 5);
Set<Object> initValues = Variables.register("initValues", Sets.newHashSet());
List<Timestamp> timestamps = new ArrayList<Timestamp>();
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
client.add(key, value, record);
timestamps.add(Timestamp.now());
}
Map<Timestamp, Set<Object>> chronology = client.chronologize(key, record);
Timestamp exactStartTimestamp = Variables.register("exactStartTimestamp", Iterables.getFirst((Iterable<Timestamp>) chronology.keySet(), null));
Map<Timestamp, Set<Object>> result = client.chronologize(key, record, exactStartTimestamp, timestamps.get(0));
Set<Object> lastResultSet = Iterables.getLast(result.values());
assertEquals(1, result.size());
assertEquals(1, lastResultSet.size());
}
@Test
public void testChronologizeWithStartTimestampIsInclusiveAtExactLastValueChangeInKeyInRecord() {
long record = Variables.register("record", Time.now());
String key = Variables.register("key", TestData.getSimpleString());
int testSize = Variables.register("testSize", 5);
Set<Object> initValues = Variables.register("initValues", Sets.newHashSet());
List<Timestamp> timestamps = new ArrayList<Timestamp>();
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
client.add(key, value, record);
timestamps.add(Timestamp.now());
}
Map<Timestamp, Set<Object>> chronologie = client.chronologize(key, record);
Timestamp exactEndTimestamp = Variables.register("exactEndTimestamp", Iterables.getLast((Iterable<Timestamp>) chronologie.keySet()));
Map<Timestamp, Set<Object>> result = client.chronologize(key, record, exactEndTimestamp, Timestamp.now());
Set<Object> lastResultSet = Iterables.getLast(result.values());
assertEquals(1, result.size());
assertEquals(testSize, lastResultSet.size());
}
@Test
public void testChronologizeWithStartTimestampEqualsEndTimestampBeforeFirstValueChangeInKeyInRecord() {
long record = Variables.register("record", Time.now());
String key = Variables.register("key", TestData.getSimpleString());
int testSize = Variables.register("testSize", 5);
Set<Object> initValues = Variables.register("initValues", Sets.newHashSet());
List<Timestamp> timestamps = new ArrayList<Timestamp>();
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
client.add(key, value, record);
timestamps.add(Timestamp.now());
}
// check same timestamps before initial add
Map<Timestamp, Set<Object>> result = client.chronologize(key, record, Timestamp.epoch(), Timestamp.epoch());
assertTrue(result.isEmpty());
}
@Test
public void testChronologizeWithStartTimestampGreaterThanEndTimestampInKeyInRecord() {
long record = Variables.register("record", Time.now());
String key = Variables.register("key", TestData.getSimpleString());
int testSize = Variables.register("testSize", 5);
Set<Object> initValues = Variables.register("initValues", Sets.newHashSet());
List<Timestamp> timestamps = new ArrayList<Timestamp>();
for (int i = 0; i < testSize; i++) {
Object value = null;
while (value == null || initValues.contains(value)) {
value = TestData.getObject();
}
initValues.add(value);
client.add(key, value, record);
timestamps.add(Timestamp.now());
}
client.chronologize(key, record, timestamps.get(3), timestamps.get(2));
}
}