Created
May 19, 2014 04:48
-
-
Save t3hmrman/5dcc25a1cf2c199c8d0d to your computer and use it in GitHub Desktop.
NodeJS Test fixtures for RethinkDB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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