package com.jivesoftware.os.amza.client.http;
import com.google.common.primitives.UnsignedBytes;
import com.jivesoftware.os.amza.api.stream.KeyValueStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import org.testng.Assert;
import org.testng.annotations.Test;
/**
* @author jonathan.colt
*/
public class QuorumScanNGTest {
@Test
public void testSomeMethod() throws Exception {
List<byte[]> outputPrefixes = new ArrayList<>();
List<byte[]> outputKeys = new ArrayList<>();
List<byte[]> outputValues = new ArrayList<>();
List<Long> outputTimestamps = new ArrayList<>();
List<Boolean> outputTombstones = new ArrayList<>();
List<Long> outputVersions = new ArrayList<>();
int numStreams = 10;
KeyValueStream capture = (prefix, key, value, timestamp, tombstoned, version) -> {
outputPrefixes.add(prefix);
outputKeys.add(key);
outputValues.add(value);
outputTimestamps.add(timestamp);
outputTombstones.add(tombstoned);
outputVersions.add(version);
System.out.println("\tOUTPUT -> prefix:" + null
+ " key:" + Arrays.toString(key)
+ " value:" + Arrays.toString(value)
+ " timestamp:" + timestamp
+ " tombstoned:" + tombstoned
+ " version:" + version);
return true;
};
QuorumScan quorumScannable = new QuorumScan(numStreams);
Random r = new Random();
Set<Byte> expectedKeys = new HashSet<>();
Map<Byte, ValueTimestampVersion> expectedTimestamp = new HashMap<>();
int[] v = new int[numStreams];
for (int i = 0; i < v.length; i++) {
v[i] = i * 128;
}
int done = 0;
byte[] lastKey = new byte[numStreams];
while (done < numStreams) {
for (int i = 0; i < lastKey.length; i++) {
if (!quorumScannable.used(i)) {
continue;
}
int advance = (byte) (1 + r.nextInt(32));
if (advance + lastKey[i] < 127) {
lastKey[i] += advance;
expectedKeys.add(lastKey[i]);
byte[] key = new byte[] { lastKey[i] };
byte[] value = new byte[] { (byte) r.nextInt(127) };
long timestamp = r.nextInt(numStreams);
boolean tombstoned = r.nextBoolean();
long version = v[i];
System.out.println("INPUT -> index:" + i + " prefix:" + null
+ " key:" + Arrays.toString(key)
+ " value:" + Arrays.toString(value)
+ " timestamp:" + timestamp
+ " tombstoned:" + tombstoned
+ " version:" + version);
quorumScannable.fill(i, null, key, value, timestamp, tombstoned, version);
expectedTimestamp.compute(lastKey[i], (k, vv) -> {
if (vv == null) {
return new ValueTimestampVersion(value, timestamp, tombstoned, version);
} else {
int c = Long.compare(timestamp, vv.timestamp);
if (c == 0) {
c = Long.compare(version, vv.version);
if (c == 0) {
throw new RuntimeException("Test bug");
} else if (c < 0) {
return vv;
}
} else if (c < 0) {
return vv;
}
return new ValueTimestampVersion(value, timestamp, tombstoned, version);
}
});
v[i]++;
} else {
if (lastKey[i] != 127) {
lastKey[i] = 127;
done++;
}
}
}
int wi = quorumScannable.findWinningIndex();
if (wi != -1) {
if (!quorumScannable.stream(wi, capture)) {
throw new IllegalStateException("Shouldn't be false.");
}
}
}
int wi;
while ((wi = quorumScannable.findWinningIndex()) > -1) {
if (!quorumScannable.stream(wi, capture)) {
throw new IllegalStateException("Shouldn't be false.");
}
}
for (int j = 0; j < outputKeys.size(); j++) {
System.out.println("OUTPUT -> prefix:" + Arrays.toString(outputPrefixes.get(j))
+ " key:" + Arrays.toString(outputKeys.get(j))
+ " value:" + Arrays.toString(outputValues.get(j))
+ " timestamp:" + outputTimestamps.get(j)
+ " version:" + outputVersions.get(j));
}
int i = 0;
ValueTimestampVersion expected = expectedTimestamp.get(outputKeys.get(i)[0]);
Assert.assertEquals(outputValues.get(i), expected.value);
Assert.assertEquals((long) outputTimestamps.get(i), expected.timestamp);
Assert.assertEquals((boolean) outputTombstones.get(i), expected.tombstoned);
Assert.assertEquals((long) outputVersions.get(i), expected.version);
Assert.assertTrue(expectedKeys.remove(outputKeys.get(i)[0]));
i++;
for (; i < outputKeys.size(); i++) {
expected = expectedTimestamp.get(outputKeys.get(i)[0]);
Assert.assertEquals(outputValues.get(i), expected.value);
Assert.assertEquals((long) outputTimestamps.get(i), expected.timestamp);
Assert.assertEquals((boolean) outputTombstones.get(i), expected.tombstoned);
Assert.assertEquals((long) outputVersions.get(i), expected.version);
Assert.assertTrue(expectedKeys.remove(outputKeys.get(i)[0]), "expectedKeys lacks key:" + outputKeys.get(i)[0]);
Assert.assertTrue(UnsignedBytes.lexicographicalComparator().compare(outputKeys.get(i - 1), outputKeys.get(i)) < 0, "key ordering failed");
}
Assert.assertTrue(expectedKeys.isEmpty());
}
private static class ValueTimestampVersion {
public final byte[] value;
public final long timestamp;
public final boolean tombstoned;
public final long version;
public ValueTimestampVersion(byte[] value, long timestamp, boolean tombstoned, long version) {
this.value = value;
this.timestamp = timestamp;
this.tombstoned = tombstoned;
this.version = version;
}
}
}