syncbase.js: Add Exists rpc method to app, db, table, row.
Mirrors v.io/c/13470
Change-Id: Iaa225dbc8146cfe5a02bb4fa803188e69478a450
diff --git a/src/app.js b/src/app.js
index 9452023..3357eae 100644
--- a/src/app.js
+++ b/src/app.js
@@ -52,6 +52,12 @@
this._wire(ctx).delete(ctx, cb);
};
+// exists returns true only if this app exists. Insufficient permissions cause
+// exists to return false instead of an error.
+App.prototype.exists = function(ctx, cb) {
+ this._wire(ctx).exists(ctx, cb);
+};
+
App.prototype.getPermissions = function(ctx, cb) {
this._wire(ctx).getPermissions(ctx, cb);
};
diff --git a/src/gen-vdl/v.io/syncbase/v23/services/syncbase/index.js b/src/gen-vdl/v.io/syncbase/v23/services/syncbase/index.js
index 812ab36..3777938 100644
--- a/src/gen-vdl/v.io/syncbase/v23/services/syncbase/index.js
+++ b/src/gen-vdl/v.io/syncbase/v23/services/syncbase/index.js
@@ -133,6 +133,11 @@
};
+App.prototype.exists = function(ctx, serverCall) {
+ throw new Error('Method Exists not implemented');
+};
+
+
App.prototype.setPermissions = function(ctx, serverCall, perms, version) {
throw new Error('Method SetPermissions not implemented');
};
@@ -185,6 +190,22 @@
{
+ name: 'Exists',
+ doc: "// Exists returns true only if this App exists. Insufficient permissions\n// cause Exists to return false instead of an error.",
+ inArgs: [],
+ outArgs: [{
+ name: '',
+ doc: "",
+ type: vdl.types.BOOL
+ },
+ ],
+ inStream: null,
+ outStream: null,
+ tags: [canonicalize.reduce(new access.Tag("Read", true), new access.Tag()._type), ]
+ },
+
+
+ {
name: 'SetPermissions',
doc: "// SetPermissions replaces the current Permissions for an object. version\n// allows for optional, optimistic concurrency control. If non-empty,\n// version's value must come from GetPermissions. If any client has\n// successfully called SetPermissions in the meantime, the version will be\n// stale and SetPermissions will fail. If empty, SetPermissions performs an\n// unconditional update.\n//\n// Permissions objects are expected to be small. It is up to the\n// implementation to define the exact limit, though it should probably be\n// around 100KB. Large lists of principals can be represented concisely using\n// blessings.\n//\n// There is some ambiguity when calling SetPermissions on a mount point.\n// Does it affect the mount itself or does it affect the service endpoint\n// that the mount points to? The chosen behavior is that it affects the\n// service endpoint. To modify the mount point's Permissions, use\n// ResolveToMountTable to get an endpoint and call SetPermissions on that.\n// This means that clients must know when a name refers to a mount point to\n// change its Permissions.",
inArgs: [{
diff --git a/src/gen-vdl/v.io/syncbase/v23/services/syncbase/nosql/index.js b/src/gen-vdl/v.io/syncbase/v23/services/syncbase/nosql/index.js
index 18bc481..af0ea54 100644
--- a/src/gen-vdl/v.io/syncbase/v23/services/syncbase/nosql/index.js
+++ b/src/gen-vdl/v.io/syncbase/v23/services/syncbase/nosql/index.js
@@ -382,6 +382,11 @@
};
+Database.prototype.exists = function(ctx, serverCall) {
+ throw new Error('Method Exists not implemented');
+};
+
+
Database.prototype.beginBatch = function(ctx, serverCall, bo) {
throw new Error('Method BeginBatch not implemented');
};
@@ -504,8 +509,24 @@
{
+ name: 'Exists',
+ doc: "// Exists returns true only if this Database exists. Insufficient permissions\n// cause Exists to return false instead of an error.\n// TODO(ivanpi): Exists may fail with an error if higher levels of hierarchy\n// do not exist.",
+ inArgs: [],
+ outArgs: [{
+ name: '',
+ doc: "",
+ type: vdl.types.BOOL
+ },
+ ],
+ inStream: null,
+ outStream: null,
+ tags: [canonicalize.reduce(new access.Tag("Read", true), new access.Tag()._type), ]
+ },
+
+
+ {
name: 'BeginBatch',
- doc: "// BeginBatch creates a new batch. It returns an App-relative name for a\n// Database handle bound to this batch. If this Database is already bound to a\n// batch, BeginBatch() will fail with ErrBoundToBatch.\n//\n// Concurrency semantics are documented in model.go.",
+ doc: "// BeginBatch creates a new batch. It returns an App-relative name for a\n// Database handle bound to this batch. If this Database is already bound to a\n// batch, BeginBatch() will fail with ErrBoundToBatch. Concurrency semantics\n// are documented in model.go.",
inArgs: [{
name: 'bo',
doc: "",
@@ -537,7 +558,7 @@
{
name: 'Exec',
- doc: "// Exec executes a syncQL query and returns all results as specified by\n// in the query's select clause. The returned stream reads\n// from a consistent snapshot taken at the time of the Exec RPC.",
+ doc: "// Exec executes a syncQL query and returns all results as specified by in the\n// query's select clause. Concurrency semantics are documented in model.go.",
inArgs: [{
name: 'query',
doc: "",
@@ -821,6 +842,11 @@
};
+Table.prototype.exists = function(ctx, serverCall) {
+ throw new Error('Method Exists not implemented');
+};
+
+
Table.prototype.deleteRowRange = function(ctx, serverCall, start, limit) {
throw new Error('Method DeleteRowRange not implemented');
};
@@ -831,13 +857,13 @@
};
-Table.prototype.setPermissions = function(ctx, serverCall, prefix, perms) {
- throw new Error('Method SetPermissions not implemented');
+Table.prototype.getPermissions = function(ctx, serverCall, key) {
+ throw new Error('Method GetPermissions not implemented');
};
-Table.prototype.getPermissions = function(ctx, serverCall, key) {
- throw new Error('Method GetPermissions not implemented');
+Table.prototype.setPermissions = function(ctx, serverCall, prefix, perms) {
+ throw new Error('Method SetPermissions not implemented');
};
@@ -883,8 +909,24 @@
{
+ name: 'Exists',
+ doc: "// Exists returns true only if this Table exists. Insufficient permissions\n// cause Exists to return false instead of an error.\n// TODO(ivanpi): Exists may fail with an error if higher levels of hierarchy\n// do not exist.",
+ inArgs: [],
+ outArgs: [{
+ name: '',
+ doc: "",
+ type: vdl.types.BOOL
+ },
+ ],
+ inStream: null,
+ outStream: null,
+ tags: [canonicalize.reduce(new access.Tag("Read", true), new access.Tag()._type), ]
+ },
+
+
+ {
name: 'DeleteRowRange',
- doc: "// Delete deletes all rows in the given half-open range [start, limit). If\n// limit is \"\", all rows with keys >= start are included. If the last row that\n// is covered by a prefix from SetPermissions is deleted, that (prefix, perms)\n// pair is removed.\n// TODO(sadovsky): Automatic GC interacts poorly with sync. Revisit this API.",
+ doc: "// Delete deletes all rows in the given half-open range [start, limit). If\n// limit is \"\", all rows with keys >= start are included.",
inArgs: [{
name: 'start',
doc: "",
@@ -905,7 +947,7 @@
{
name: 'Scan',
- doc: "// Scan returns all rows in the given half-open range [start, limit). If limit\n// is \"\", all rows with keys >= start are included. The returned stream reads\n// from a consistent snapshot taken at the time of the Scan RPC.",
+ doc: "// Scan returns all rows in the given half-open range [start, limit). If limit\n// is \"\", all rows with keys >= start are included. Concurrency semantics are\n// documented in model.go.",
inArgs: [{
name: 'start',
doc: "",
@@ -929,27 +971,6 @@
{
- name: 'SetPermissions',
- doc: "// SetPermissions sets the permissions for all current and future rows with\n// the given prefix. If the prefix overlaps with an existing prefix, the\n// longest prefix that matches a row applies. For example:\n// SetPermissions(ctx, Prefix(\"a/b\"), perms1)\n// SetPermissions(ctx, Prefix(\"a/b/c\"), perms2)\n// The permissions for row \"a/b/1\" are perms1, and the permissions for row\n// \"a/b/c/1\" are perms2.\n//\n// SetPermissions will fail if called with a prefix that does not match any\n// rows.",
- inArgs: [{
- name: 'prefix',
- doc: "",
- type: vdl.types.STRING
- },
- {
- name: 'perms',
- doc: "",
- type: new access.Permissions()._type
- },
- ],
- outArgs: [],
- inStream: null,
- outStream: null,
- tags: [canonicalize.reduce(new access.Tag("Admin", true), new access.Tag()._type), ]
- },
-
-
- {
name: 'GetPermissions',
doc: "// GetPermissions returns an array of (prefix, perms) pairs. The array is\n// sorted from longest prefix to shortest, so element zero is the one that\n// applies to the row with the given key. The last element is always the\n// prefix \"\" which represents the table's permissions -- the array will always\n// have at least one element.",
inArgs: [{
@@ -971,6 +992,27 @@
{
+ name: 'SetPermissions',
+ doc: "// SetPermissions sets the permissions for all current and future rows with\n// the given prefix. If the prefix overlaps with an existing prefix, the\n// longest prefix that matches a row applies. For example:\n// SetPermissions(ctx, Prefix(\"a/b\"), perms1)\n// SetPermissions(ctx, Prefix(\"a/b/c\"), perms2)\n// The permissions for row \"a/b/1\" are perms1, and the permissions for row\n// \"a/b/c/1\" are perms2.",
+ inArgs: [{
+ name: 'prefix',
+ doc: "",
+ type: vdl.types.STRING
+ },
+ {
+ name: 'perms',
+ doc: "",
+ type: new access.Permissions()._type
+ },
+ ],
+ outArgs: [],
+ inStream: null,
+ outStream: null,
+ tags: [canonicalize.reduce(new access.Tag("Admin", true), new access.Tag()._type), ]
+ },
+
+
+ {
name: 'DeletePermissions',
doc: "// DeletePermissions deletes the permissions for the specified prefix. Any\n// rows covered by this prefix will use the next longest prefix's permissions\n// (see the array returned by GetPermissions).",
inArgs: [{
@@ -995,6 +1037,11 @@
+Row.prototype.exists = function(ctx, serverCall) {
+ throw new Error('Method Exists not implemented');
+};
+
+
Row.prototype.get = function(ctx, serverCall) {
throw new Error('Method Get not implemented');
};
@@ -1020,6 +1067,22 @@
{
+ name: 'Exists',
+ doc: "// Exists returns true only if this Row exists. Insufficient permissions\n// cause Exists to return false instead of an error.\n// TODO(ivanpi): Exists may fail with an error if higher levels of hierarchy\n// do not exist.",
+ inArgs: [],
+ outArgs: [{
+ name: '',
+ doc: "",
+ type: vdl.types.BOOL
+ },
+ ],
+ inStream: null,
+ outStream: null,
+ tags: [canonicalize.reduce(new access.Tag("Read", true), new access.Tag()._type), ]
+ },
+
+
+ {
name: 'Get',
doc: "// Get returns the value for this Row.",
inArgs: [],
diff --git a/src/nosql/database.js b/src/nosql/database.js
index 76386a7..1e01c67 100644
--- a/src/nosql/database.js
+++ b/src/nosql/database.js
@@ -78,6 +78,18 @@
};
/**
+ * Returns true only if this Database exists.
+ * Insufficient permissions cause exists to return false instead of an error.
+ * TODO(ivanpi): exists may fail with an error if higher levels of hierarchy
+ * do not exist.
+ * @param {module:vanadium.context.Context} ctx Vanadium context.
+ * @param {function} cb Callback.
+ */
+Database.prototype.exists = function(ctx, cb) {
+ this._wire(ctx).exists(ctx, cb);
+};
+
+/**
* Executes a syncQL query.
*
* Returns a stream of rows. The first row contains an array of headers (i.e.
diff --git a/src/nosql/row.js b/src/nosql/row.js
index a748c7d..ba9f633 100644
--- a/src/nosql/row.js
+++ b/src/nosql/row.js
@@ -74,6 +74,18 @@
};
/**
+ * Returns true only if this Row exists.
+ * Insufficient permissions cause exists to return false instead of an error.
+ * TODO(ivanpi): exists may fail with an error if higher levels of hierarchy
+ * do not exist.
+ * @param {module:vanadium.context.Context} ctx Vanadium context.
+ * @param {function} cb Callback.
+ */
+Row.prototype.exists = function(ctx, cb) {
+ this._wire(ctx).exists(ctx, cb);
+};
+
+/**
* Returns the value for this Row.
* @param {module:vanadium.context.Context} ctx Vanadium context.
* @param {function} cb Callback.
diff --git a/src/nosql/table.js b/src/nosql/table.js
index 384a1f7..824f816 100644
--- a/src/nosql/table.js
+++ b/src/nosql/table.js
@@ -58,6 +58,18 @@
};
/**
+ * Returns true only if this Table exists.
+ * Insufficient permissions cause exists to return false instead of an error.
+ * TODO(ivanpi): exists may fail with an error if higher levels of hierarchy
+ * do not exist.
+ * @param {module:vanadium.context.Context} ctx Vanadium context.
+ * @param {function} cb Callback.
+ */
+Table.prototype.exists = function(ctx, cb) {
+ this._wire(ctx).exists(ctx, cb);
+};
+
+/**
* Creates a row the given primary key in this table.
* @param {string} key Primary key for the row.
* @return {module:syncbase.row.Row} Row object.
diff --git a/test/integration/test-app.js b/test/integration/test-app.js
index 73838c2..597a569 100644
--- a/test/integration/test-app.js
+++ b/test/integration/test-app.js
@@ -9,7 +9,6 @@
var syncbase = require('../..');
var testUtil = require('./util');
-var appExists = testUtil.appExists;
var setupApp = testUtil.setupApp;
var setupService = testUtil.setupService;
var uniqueName = testUtil.uniqueName;
@@ -52,22 +51,51 @@
uniqueName('app'),
uniqueName('app')
];
- async.forEach(appNames, function(appName, cb) {
- o.service.app(appName).create(o.ctx, {}, cb);
- }, function(err) {
- if (err) {
- t.error(err);
- return o.teardown(t.end);
- }
- // Verify each app exists.
- async.map(appNames, function(appName, cb) {
- appExists(o.ctx, o.service, appName, cb);
- }, function(err, existsArray) {
- t.error(err);
- t.deepEqual(existsArray, [true, true, true], 'all apps exist');
- o.teardown(t.end);
- });
+ async.waterfall([
+ // Verify none of the apps exist using exists().
+ async.apply(async.map, appNames, function(appName, cb) {
+ o.service.app(appName).exists(o.ctx, cb);
+ }),
+ function(existsArray, cb) {
+ t.deepEqual(existsArray, [false, false, false],
+ 'exists: no apps exist');
+ cb(null);
+ },
+
+ // Verify none of the apps exist using listApps().
+ o.service.listApps.bind(o.service, o.ctx),
+ function(appList, cb) {
+ t.deepEqual(appList, [],
+ 'listApps: no apps exist');
+ cb(null);
+ },
+
+ // Create all apps.
+ async.apply(async.forEach, appNames, function(appName, cb) {
+ o.service.app(appName).create(o.ctx, {}, cb);
+ }),
+
+ // Verify each app exists using exists().
+ async.apply(async.map, appNames, function(appName, cb) {
+ o.service.app(appName).exists(o.ctx, cb);
+ }),
+ function(existsArray, cb) {
+ t.deepEqual(existsArray, [true, true, true],
+ 'exists: all apps exist');
+ cb(null);
+ },
+
+ // Verify all the apps exist using listApps().
+ o.service.listApps.bind(o.service, o.ctx),
+ function(appList, cb) {
+ t.deepEqual(appList.sort(), appNames.sort(),
+ 'listApps: all apps exist');
+ cb(null);
+ }
+ ], function(err) {
+ t.error(err);
+ o.teardown(t.end);
});
});
});
@@ -78,17 +106,26 @@
return t.end(err);
}
- o.app.delete(o.ctx, function(err) {
- if (err) {
- t.error(err);
- return o.teardown(t.end);
- }
+ async.waterfall([
+ // Verify app exists.
+ o.app.exists.bind(o.app, o.ctx),
+ function(exists, cb) {
+ t.ok(exists, 'app exists');
+ cb(null);
+ },
- appExists(o.ctx, o.service, o.app.name, function(err, exists) {
- t.error(err);
+ // Delete app.
+ o.app.delete.bind(o.app, o.ctx),
+
+ // Verify app no longer exists.
+ o.app.exists.bind(o.app, o.ctx),
+ function(exists, cb) {
t.notok(exists, 'app no longer exists');
- o.teardown(t.end);
- });
+ cb(null);
+ }
+ ], function(err, arg) {
+ t.error(err);
+ o.teardown(t.end);
});
});
});
diff --git a/test/integration/test-database.js b/test/integration/test-database.js
index 9bba2ee..af5a0f1 100644
--- a/test/integration/test-database.js
+++ b/test/integration/test-database.js
@@ -16,8 +16,6 @@
var Table = require('../../src/nosql/table');
var testUtil = require('./util');
-var databaseExists = testUtil.databaseExists;
-var tableExists = testUtil.tableExists;
var setupApp = testUtil.setupApp;
var setupDatabase = testUtil.setupDatabase;
var setupTable = testUtil.setupTable;
@@ -71,18 +69,55 @@
}
var db = o.app.noSqlDatabase(uniqueName('db'));
+ var db2 = o.app.noSqlDatabase(uniqueName('db'));
- db.create(o.ctx, {}, function(err) {
- if (err) {
- t.error(err);
- return o.teardown(t.end);
- }
+ async.waterfall([
+ // Verify database does not exist yet.
+ db.exists.bind(db, o.ctx),
+ function(exists, cb) {
+ t.notok(exists, 'exists: database doesn\'t exist yet');
+ cb(null);
+ },
- databaseExists(o.ctx, o.app, db.name, function(err, exists) {
- t.error(err);
- t.ok(exists, 'database exists');
- o.teardown(t.end);
- });
+ // Verify database list is empty.
+ o.app.listDatabases.bind(o.app, o.ctx),
+ function(dbList, cb) {
+ t.deepEqual(dbList, [],
+ 'listDatabases: no databases exist');
+ cb(null);
+ },
+
+ // Create database.
+ db.create.bind(db, o.ctx, {}),
+
+ // Verify database exists.
+ db.exists.bind(db, o.ctx),
+ function(exists, cb) {
+ t.ok(exists, 'exists: database exists');
+ cb(null);
+ },
+
+ // Verify database list contains the database.
+ o.app.listDatabases.bind(o.app, o.ctx),
+ function(dbList, cb) {
+ t.deepEqual(dbList, [db.name],
+ 'listDatabases: database exists');
+ cb(null);
+ },
+
+ // Create another database.
+ db2.create.bind(db2, o.ctx, {}),
+
+ // Verify database list contains both databases.
+ o.app.listDatabases.bind(o.app, o.ctx),
+ function(dbList, cb) {
+ t.deepEqual(dbList.sort(), [db.name, db2.name].sort(),
+ 'listDatabases: both databases exist');
+ cb(null);
+ },
+ ], function(err, arg) {
+ t.error(err);
+ o.teardown(t.end);
});
});
});
@@ -119,24 +154,29 @@
var db = o.app.noSqlDatabase(uniqueName('db'));
- db.create(o.ctx, {}, function(err) {
- if (err) {
- t.error(err);
- return o.teardown(t.end);
- }
+ async.waterfall([
+ // Create database.
+ db.create.bind(db, o.ctx, {}),
- db.delete(o.ctx, function(err) {
- if (err) {
- t.error(err);
- return o.teardown(t.end);
- }
+ // Verify database exists.
+ db.exists.bind(db, o.ctx),
+ function(exists, cb) {
+ t.ok(exists, 'database exists');
+ cb(null);
+ },
- databaseExists(o.ctx, o.app, db.name, function(err, exists) {
- t.error(err);
- t.notok(exists, 'database does not exist');
- o.teardown(t.end);
- });
- });
+ // Delete database.
+ db.delete.bind(db, o.ctx),
+
+ // Verify database no longer exists.
+ db.exists.bind(db, o.ctx),
+ function(exists, cb) {
+ t.notok(exists, 'database no longer exists');
+ cb(null);
+ },
+ ], function(err, arg) {
+ t.error(err);
+ o.teardown(t.end);
});
});
});
@@ -183,19 +223,56 @@
}
var db = o.database;
+ var table = db.table(uniqueName('table'));
+ var table2 = db.table(uniqueName('table'));
- var tableName = uniqueName('table');
- db.createTable(o.ctx, tableName, {}, function(err) {
- if (err) {
- t.error(err);
- return o.teardown(t.end);
- }
+ async.waterfall([
+ // Verify table does not exist yet.
+ table.exists.bind(table, o.ctx),
+ function(exists, cb) {
+ t.notok(exists, 'exists: table doesn\'t exist yet');
+ cb(null);
+ },
- tableExists(o.ctx, db, tableName, function(err, exists) {
- t.error(err);
- t.ok(exists, 'table exists');
- o.teardown(t.end);
- });
+ // Verify table list is empty.
+ db.listTables.bind(db, o.ctx),
+ function(tableList, cb) {
+ t.deepEqual(tableList, [],
+ 'listTables: no tables exist');
+ cb(null);
+ },
+
+ // Create table.
+ db.createTable.bind(db, o.ctx, table.name, {}),
+
+ // Verify table exists.
+ table.exists.bind(table, o.ctx),
+ function(exists, cb) {
+ t.ok(exists, 'exists: table exists');
+ cb(null);
+ },
+
+ // Verify table list contains the table.
+ db.listTables.bind(db, o.ctx),
+ function(tableList, cb) {
+ t.deepEqual(tableList, [table.name],
+ 'listTables: table exists');
+ cb(null);
+ },
+
+ // Create another table.
+ db.createTable.bind(db, o.ctx, table2.name, {}),
+
+ // Verify table list contains both tables.
+ db.listTables.bind(db, o.ctx),
+ function(tableList, cb) {
+ t.deepEqual(tableList.sort(), [table.name, table2.name].sort(),
+ 'listTables: both tables exist');
+ cb(null);
+ },
+ ], function(err, arg) {
+ t.error(err);
+ o.teardown(t.end);
});
});
});
@@ -207,26 +284,31 @@
}
var db = o.database;
+ var table = db.table(uniqueName('table'));
- var tableName = uniqueName('table');
- db.createTable(o.ctx, tableName, {}, function(err) {
- if (err) {
- t.error(err);
- return o.teardown(t.end);
- }
+ async.waterfall([
+ // Create table.
+ db.createTable.bind(db, o.ctx, table.name, {}),
- db.deleteTable(o.ctx, tableName, function(err) {
- if (err) {
- t.error(err);
- return o.teardown(t.end);
- }
+ // Verify table exists.
+ table.exists.bind(table, o.ctx),
+ function(exists, cb) {
+ t.ok(exists, 'table exists');
+ cb(null);
+ },
- tableExists(o.ctx, db, tableName, function(err, exists) {
- t.error(err);
- t.notok(exists, 'table does not exist');
- o.teardown(t.end);
- });
- });
+ // Delete table.
+ db.deleteTable.bind(db, o.ctx, table.name),
+
+ // Verify table no longer exists.
+ table.exists.bind(table, o.ctx),
+ function(exists, cb) {
+ t.notok(exists, 'table no longer exists');
+ cb(null);
+ },
+ ], function(err, arg) {
+ t.error(err);
+ o.teardown(t.end);
});
});
});
diff --git a/test/integration/test-table.js b/test/integration/test-table.js
index 3714eba..7e924f8 100644
--- a/test/integration/test-table.js
+++ b/test/integration/test-table.js
@@ -53,16 +53,46 @@
var value = uniqueName(ROW_VAL);
var table = o.table;
- table.put(o.ctx, key, value, deleteRow);
+ var row = o.table.row(key);
- function deleteRow() {
- table.row(key).delete(o.ctx, function() {
- table.get(o.ctx, key, function(err, val) {
- t.ok(err, 'get should error after row is deleted');
- o.teardown(t.end);
- });
+ async.waterfall([
+ // Verify row doesn't exist yet.
+ row.exists.bind(row, o.ctx),
+ function(exists, cb) {
+ t.notok(exists, 'row doesn\'t exist yet');
+ cb(null);
+ },
+
+ // Put row.
+ table.put.bind(table, o.ctx, key, value),
+
+ // Verify row exists.
+ row.exists.bind(row, o.ctx),
+ function(exists, cb) {
+ t.ok(exists, 'row exists');
+ cb(null);
+ },
+
+ // Delete row.
+ row.delete.bind(row, o.ctx),
+
+ // Verify row no longer exists.
+ row.exists.bind(row, o.ctx),
+ function(exists, cb) {
+ t.notok(exists, 'row no longer exists');
+ cb(null);
+ },
+ ], function(err, arg) {
+ if (err) {
+ t.error(err);
+ return o.teardown(t.end);
+ }
+
+ table.get(o.ctx, key, function(err, val) {
+ t.ok(err, 'get should error after row is deleted');
+ o.teardown(t.end);
});
- }
+ });
});
});
diff --git a/test/integration/util.js b/test/integration/util.js
index 50b6563..7242f07 100644
--- a/test/integration/util.js
+++ b/test/integration/util.js
@@ -3,10 +3,6 @@
// license that can be found in the LICENSE file.
module.exports = {
- appExists: appExists,
- databaseExists: databaseExists,
- tableExists: tableExists,
-
setupApp: setupApp,
setupDatabase: setupDatabase,
setupService: setupService,
@@ -223,36 +219,6 @@
});
}
-function appExists(ctx, service, name, cb) {
- service.listApps(ctx, function(err, names) {
- if (err) {
- return cb(err);
- }
-
- cb(null, names.indexOf(name) >= 0);
- });
-}
-
-function databaseExists(ctx, app, name, cb) {
- app.listDatabases(ctx, function(err, names) {
- if (err) {
- return cb(err);
- }
-
- cb(null, names.indexOf(name) >= 0);
- });
-}
-
-function tableExists(ctx, db, name, cb) {
- db.listTables(ctx, function(err, names) {
- if (err) {
- return cb(err);
- }
-
- cb(null, names.indexOf(name) >= 0);
- });
-}
-
function compareRows(r1, r2) {
if (r1.key > r2.key) {
return 1;