Skip to content

Instantly share code, notes, and snippets.

@t3hmrman
Created May 19, 2014
Embed
What would you like to do?
NodeJS Test fixtures for RethinkDB
/* Test fixtures and example objects for various tests to use */
var os = require('os'),
fs = require('fs'),
temp = require('temp'),
u = require('underscore'),
portfinder = require('portfinder'),
child_process = require('child_process'),
Q = require('q'),
rdb = require('rethinkdb'),
should = require('should');
// Track temporary files & cleanup at exit by default, disable if needed
temp.track()
var pGetTempDirectory = Q.denodeify(temp.mkdir);
var pGetPort = Q.denodeify(portfinder.getPort);
var pExec = Q.denodeify(child_process.exec);
// Execute mocha test after setting up a test rethinkdb database
function withTestRethinkDBInstance(options,done,callback) {
// Disable temp file cleanup for debug if specified
if (!u.isUndefined(options) && u.has(options,'no_cleanup') && !options.no_cleanup) {
temp.track(false)
}
// Create a new temp directory, and rethinkdb instance
pGetTempDirectory('switchboard_discovery_mocha_test_' + process.env.USER + '_' + process.pid)
.then(function(temp_dir) {
// After creating a temp directory, get an open port that can be used
console.log("INFO: Temp directory successfully created:",temp_dir);
return pGetPort().then(function(temp_cluster_port) {
// After getting an port for clustering, get a port for driver connections
console.log("INFO: Found cluster port: " + temp_cluster_port);
portfinder.basePort = temp_cluster_port + 1;
return pGetPort().then(function(temp_driver_port) {
// After getting an port for driver connections, initialize rethinkdb in the temp dir
console.log("INFO: Found driver port: " + temp_driver_port);
var new_data_path = temp_dir + "/rethinkdb_data";
console.log("INFO: Attempting to initialize new rethinkdb instace at [" + new_data_path + "]");
child_process.exec("rethinkdb create -d " + new_data_path,{cwd:temp_dir},function(err,stdout,stderr) {
if (err) throw err
console.log("INFO: Initialized rethinkdb database");
// Start rethinkdb
console.log("INFO: About to start rethinkdb child process");
var rdb_args = ['serve',
'--driver-port',temp_driver_port,
'--cluster-port',temp_cluster_port,
'--directory', new_data_path,
'--no-http-admin'];
console.log("CMD: rethinkdb " + rdb_args.join(" "));
var rdb_process = child_process.spawn('rethinkdb',rdb_args,{cwd:temp_dir});
process.on('exit',function() {
rdb_process.kill();
});
process.on('uncaughtException',function() {
rdb_process.kill();
});
// Alert the user if DB process quits/crashesn
rdb_process.on('close', function (code) {
console.log('WARNING: Test RethinkDB child process exited with code ' + code);
});
// Watch rethinkdb process output until it says that rethinkdb is ready for connections
rdb_process.stderr.on('data', function (data) {
if (data.toString().match(/Server ready/)) {
// Connect to the instance and pass a connection
var rdb_config = {host: 'localhost',
port: temp_driver_port};
rdb.connect(rdb_config,function(err,conn) {
if (err) throw err
// Pass along instance and process information
var info = {rdb_process: {dir: temp_dir,
cluster_port: temp_cluster_port,
driver_port: temp_driver_port,
process: rdb_process},
rdb_conn: conn,
done: done};
callback(info);
});
}
});
}); // /rethinkdb create command
});
});
});
};
exports.withTestRethinkDBInstance = withTestRethinkDBInstance;
// Function for testing the temp rethinkdb instance creation fixture function
describe('withTestRethinkDBInstance',function() {
it('should create a usable test rethinkdb instance',function(done) {
withTestRethinkDBInstance({},done, function(db_info) {
console.log("INFO: Successfully created a temporary rethinkdb instance!");
db_info.rdb_conn.should.be.ok;
db_info.done();
});
});
});
// Execute a mocha test after setting up a test rethinkdb database
function withTestDBCreated(rdb_info,options,done,callback) {
// Ensure valid rdb connection is used
if (u.isUndefined(rdb_info) || !u.has(rdb_info,'rdb_conn') ||
u.isNull(rdb_info.rdb_conn) || u.isUndefined(rdb_info.rdb_conn)) {
throw Error("rdb_info object is expected to contain a valid RethinkDB connection");
}
// Generate test database name
var test_db_name = "";
if (!u.isUndefined(options) && u.has(options,'db_name')) {
test_db_name = options.db_name;
} else {
var test_db_name = ['_mocha_test_db',process.env.USER,process.pid,Date.now()].join('_');
}
// Create test database
rdb.dbCreate(test_db_name).run(rdb_info.rdb_conn,function(err,qres) {
if (err) throw err
if (qres.created == 1) {
console.log("Successfully created test database [" + test_db_name + "]");
} else {
throw Error("Failed to create rethinkdb temp database!");
}
// Augment the info object that was passed to us
rdb_info = u.extend(rdb_info,{db_name: test_db_name});
if (u.isUndefined(options) && u.has(options,'no_teardown') && options.no_teardown) {
rdb_info.done = done;
} else {
// If no_teardown was not specified, wrap done function in a teardown function
rdb_info.done = function() {
rdb.dbDrop(test_db_name).run(rdb_info.rdb_conn,function(err,deleted) {
if (err) throw err
console.log("Successfully dropped test db [" + test_db_name + "]");
done();
});
}
}
// Call the given callback
callback(rdb_info);
});
};
exports.withTestDBCreated = withTestDBCreated;
describe('withTestDBCreated',function() {
it("should create a test database when given a test database",function(done) {
// Create a test rethinkdb instance
withTestRethinkDBInstance({},done,function(rdb_info) {
// Create a test DB (rdb_infos are augmented along the way by the functions)
withTestDBCreated(rdb_info,{},rdb_info.done,function(rdb_info) {
// Ensure the test DB exists
rdb.dbList().run(rdb_info.rdb_conn,function(err,dbs) {
if (err) throw err
dbs.should.containEql(rdb_info.db_name);
// Always call the most recent done function
rdb_info.done();
});
});
});
});
});
// Execute a mocha test after setting up a test rethinkdb table
function withTestTableCreated(rdb_info,options,done,callback) {
// Ensure valid rdb connection is used
if (u.isUndefined(rdb_info) || !u.has(rdb_info,'rdb_conn') ||
u.isNull(rdb_info.rdb_conn) || u.isUndefined(rdb_info.rdb_conn)) {
throw Error("rdb_info object is expected to contain a valid RethinkDB connection");
}
// Generate test table name (unless one is specified in options)
var test_table_name = ""
if (!u.isUndefined(options) && u.has(options,'table_name')) {
test_table_name = options.table_name;
} else {
var test_table_name = ['_mocha_test_table',process.env.USER,process.pid,Date.now()].join('_');
}
// Create the test table
console.log("Attempting to create test table [" + test_table_name + "]");
rdb.db(rdb_info.db_name).tableCreate(test_table_name).run(rdb_info.rdb_conn,function(err,created) {
if (err) throw err
console.log("Successfully created test table [" + test_table_name + "]");
rdb_info = u.extend(rdb_info,{table_name: test_table_name});
if (u.isUndefined(options) && u.has(options,'no_teardown') && options.no_teardown) {
// if no_teardown was specified, done function should not do anything to teardown table
rdb_info.done = done;
} else {
// If no_teardown was not specified, wrap done function in a teardown function
rdb_info.done = function() {
rdb.db(rdb_info.db_name).tableDrop(test_table_name).run(rdb_info.rdb_conn,function(err,deleted) {
if (err) throw err
console.log("Successfully dropped test table [" + test_table_name + "]");
done();
});
}
}
// Call the given callback
callback(rdb_info);
});
};
exports.withTestTableCreated = withTestTableCreated;
describe('withTestTableCreated',function() {
it("should create a named test table in a tempDB",function(done){
withTestRethinkDBInstance({},done,function(rdb_info) {
withTestDBCreated(rdb_info,{},rdb_info.done,function(rdb_info) {
withTestTableCreated(rdb_info,{},rdb_info.done,function(rdb_info) {
rdb.db(rdb_info.db_name).tableList().run(rdb_info.rdb_conn,function(err,tables) {
if(err) throw err
tables.should.containEql(rdb_info.table_name);
rdb_info.done();
});
});
});
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment