@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());
        CollectionRowPattern pattern = new CollectionRowPattern();
        pattern.collectionBlessing = collectionId.blessing;
        pattern.collectionName = collectionId.name;
        List<CollectionRowPattern> patterns = singletonList(pattern);
        Database.WatchPatterns(dbName, new byte[]{}, patterns,
                new Database.WatchPatternsCallbacks() {
            @Override
            public void onChange(WatchChange watchChange) {
                done.set(null);
            }
            @Override
            public void onError(VError vError) {
                assertEquals("v.io/v23/verror.Unknown", vError.id);
                assertEquals("context canceled", vError.message);
                assertEquals(0, vError.actionCode);                }
        });
        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(1, TimeUnit.SECONDS);
    } catch (InterruptedException|ExecutionException|TimeoutException e) {
        fail("Timeout waiting for onChange: " + e);
    }
}