java: Implement the Database.WatchPatterns and Collection.Scan
I wasn't able to see that the onChange is called (which matches what
zinman@ also observed).
This change also contains two fixes to the ScanCallbacks interface:
- the onValue method is renamed to onKeyValue
- the onDone is updated to take a VError argument.
Due to some new "inconsistent definitions" I also had to move the
jFindClass from jni_util to jni.go. The bottom of the jni.go and the
jni_lib.go are also sorted.
MultiPart: 2/2
Change-Id: I4fba94a06b0398e46623ec39e1350ff179dec52a
diff --git a/syncbase/src/main/java/io/v/syncbase/internal/Collection.java b/syncbase/src/main/java/io/v/syncbase/internal/Collection.java
index 4710ece..4ba5e69 100644
--- a/syncbase/src/main/java/io/v/syncbase/internal/Collection.java
+++ b/syncbase/src/main/java/io/v/syncbase/internal/Collection.java
@@ -19,8 +19,8 @@
}
public interface ScanCallbacks {
- void onValue(KeyValue keyValue);
- void onDone();
+ void onKeyValue(KeyValue keyValue);
+ void onDone(VError vError);
}
public static native void Scan(String name, String batchHandle, byte[] start, byte[] limit, ScanCallbacks callbacks) throws VError;
diff --git a/syncbase/src/test/java/io/v/syncbase/internal/CollectionTest.java b/syncbase/src/test/java/io/v/syncbase/internal/CollectionTest.java
index 06f31d2..4a07d4f 100644
--- a/syncbase/src/test/java/io/v/syncbase/internal/CollectionTest.java
+++ b/syncbase/src/test/java/io/v/syncbase/internal/CollectionTest.java
@@ -4,14 +4,18 @@
package io.v.syncbase.internal;
+import com.google.common.util.concurrent.SettableFuture;
+
import org.junit.Before;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import static io.v.syncbase.internal.TestConstants.anyCollectionPermissions;
import static io.v.syncbase.internal.TestConstants.anyDbPermissions;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -146,4 +150,44 @@
fail(vError.toString());
}
}
+
+ @Test
+ public void scan() throws Exception {
+ Id dbId = new Id("idp:a:angrybirds", "scan_collection");
+ String dbName = dbId.encode();
+ Id collectionId = new Id("...", "collection");
+ String collectionName = Util.NamingJoin(Arrays.asList(dbName, collectionId.encode()));
+ final String keyName = Util.NamingJoin(Arrays.asList(collectionName, "key"));
+ // Reference: release/go/src/v.io/v23/vom/testdata/data81/vomdata.vdl
+ final byte[] vomValue = {(byte)0x81, 0x06, 0x03, 'a', 'b', 'c'};
+ try {
+ Database.Create(dbName, anyDbPermissions());
+ String batchHandle = Database.BeginBatch(dbId.encode(), null);
+ Collection.Create(collectionName, batchHandle, anyCollectionPermissions());
+ Row.Put(keyName, batchHandle, vomValue);
+ Database.Commit(dbName, batchHandle);
+
+ batchHandle = Database.BeginBatch(dbName, null);
+ assertTrue(Row.Exists(keyName, batchHandle));
+ final SettableFuture<Void> done = SettableFuture.create();
+ Collection.Scan(collectionName, batchHandle, new byte[]{}, new byte[]{},
+ new Collection.ScanCallbacks() {
+ @Override
+ public void onKeyValue(Collection.KeyValue keyValue) {
+ assertEquals("key", keyValue.key);
+ assertArrayEquals(vomValue, keyValue.value);
+ }
+
+ @Override
+ public void onDone(VError vError) {
+ assertEquals(null, vError);
+ done.set(null);
+ }
+ });
+ done.get(1, TimeUnit.SECONDS);
+ } catch (VError vError) {
+ vError.printStackTrace();
+ fail(vError.toString());
+ }
+ }
}
diff --git a/syncbase/src/test/java/io/v/syncbase/internal/DatabaseTest.java b/syncbase/src/test/java/io/v/syncbase/internal/DatabaseTest.java
index 9827359..d1b3955 100644
--- a/syncbase/src/test/java/io/v/syncbase/internal/DatabaseTest.java
+++ b/syncbase/src/test/java/io/v/syncbase/internal/DatabaseTest.java
@@ -4,6 +4,8 @@
package io.v.syncbase.internal;
+import com.google.common.util.concurrent.SettableFuture;
+
import org.junit.Before;
import org.junit.Test;
@@ -11,6 +13,9 @@
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import static io.v.syncbase.internal.TestConstants.anyCollectionPermissions;
import static io.v.syncbase.internal.TestConstants.anyDbPermissions;
@@ -299,4 +304,88 @@
}
assertTrue(exceptionThrown);
}
+
+ @Test
+ public void watchPattersEmptyPattern() {
+ Id dbId = new Id("idp:a:angrybirds", "watch_patterns_empty");
+ String dbName = dbId.encode();
+ final SettableFuture<Void> done = SettableFuture.create();
+ try {
+ Database.Create(dbName, anyDbPermissions());
+ String batchHandle = Database.BeginBatch(dbName, null);
+ byte[] marker = Database.GetResumeMarker(dbName, batchHandle);
+ List<Database.CollectionRowPattern> patterns =
+ Arrays.asList(new Database.CollectionRowPattern());
+ Database.WatchPatterns(dbName, marker, patterns, new Database.WatchPatternsCallbacks() {
+ @Override
+ public void onChange(Database.WatchChange watchChange) {
+ fail("Unexpected onChange: " + watchChange);
+ }
+
+ @Override
+ public void onError(VError vError) {
+ assertEquals("v.io/v23/verror.BadArg", vError.id);
+ done.set(null);
+ }
+ });
+ } catch (VError vError) {
+ vError.printStackTrace();
+ fail(vError.toString());
+ }
+ try {
+ done.get(1, TimeUnit.SECONDS);
+ } catch (InterruptedException | TimeoutException | ExecutionException e) {
+ fail("Timeout waiting for onError");
+ }
+ }
+
+ @Test
+ public void watchPatterns() {
+ Id dbId = new Id("idp:a:angrybirds", "watch_patterns");
+ String dbName = dbId.encode();
+ Id collectionId = new Id("...", "collection");
+ String collectionName = Util.NamingJoin(Arrays.asList(dbName, collectionId.encode()));
+ String keyName = Util.NamingJoin(Arrays.asList(collectionName, "key"));
+ // Reference: release/go/src/v.io/v23/vom/testdata/data81/vomdata.vdl
+ byte[] vomValue = {(byte)0x81, 0x06, 0x03, 'a', 'b', 'c'};
+ final SettableFuture<Void> done = SettableFuture.create();
+ try {
+ Database.Create(dbName, anyDbPermissions());
+ String batchHandle = Database.BeginBatch(dbName, null);
+ Collection.Create(collectionName, batchHandle, anyCollectionPermissions());
+ Database.CollectionRowPattern pattern = new Database.CollectionRowPattern();
+ pattern.collectionBlessing = collectionId.blessing;
+ pattern.collectionName = collectionId.name;
+ List<Database.CollectionRowPattern> patterns = Arrays.asList(pattern);
+ Database.WatchPatterns(dbName, new byte[]{}, patterns,
+ new Database.WatchPatternsCallbacks() {
+ @Override
+ public void onChange(Database.WatchChange watchChange) {
+ // TODO(razvanm): Really check the answer once the onChange starts working.
+ fail("Unexpected onChange: " + watchChange);
+ }
+
+ @Override
+ public void onError(VError vError) {
+ System.err.print(vError);
+ done.set(null);
+ }
+ });
+ Database.Commit(dbName, batchHandle);
+
+ batchHandle = Database.BeginBatch(dbName, null);
+ Row.Put(keyName, batchHandle, vomValue);
+ Database.Commit(dbName, batchHandle);
+ } catch (VError vError) {
+ vError.printStackTrace();
+ fail(vError.toString());
+ }
+ try {
+ done.get(10, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException|ExecutionException e) {
+ fail("Timeout waiting for onError");
+ } catch (TimeoutException e) {
+ // TODO(razvanm): Remove this after the onChange starts working.
+ }
+ }
}