Permalink
Browse files

Logging, callbacks and testing basic tools.

  • Loading branch information...
1 parent 8e2b6de commit a9d340d44fe42ca80cdd488ae038e26759af17dc Pierre committed Mar 22, 2010
View
661 LICENSE

Large diffs are not rendered by default.

Oops, something went wrong.
View
32 README
@@ -0,0 +1,32 @@
+
+## Setup
+How to use these libraries / tools :
+
+In your .bashrc (or whatever rc) file, set the bin dir in your PATH env variable:
+export PATH=$PATH:/path/to/nodetk/bin
+
+and the src dir in your NODE_PATH env variable:
+export NODE_PATH=$NODE_PATH:/path/to/nodetk/src
+
+You should then be able to use the nodetk modules with something like:
+var callbacks = require("nodetk/orchestration/callbacks");
+
+You now have the following available commands:
+nodetests [-v]
+
+
+## License
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see [http://www.fsf.org/licensing/licenses/agpl-3.0.html](http://www.fsf.org/licensing/licenses/agpl-3.0.html)
+
View
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+BASEDIR=`dirname $0`
+node $BASEDIR/../src/nodetk/testing/nodetests.js $*
+
View
@@ -0,0 +1,13 @@
+/* Provides debug function, wrapper around sys.puts, [de]activable on demand.
+ */
+
+var sys = require("sys");
+
+var debug_active = false;
+exports.debug = function(/* stuff to print*/) {
+ if(debug_active) sys.puts.apply(this, arguments);
+};
+
+exports.debug.on = function() {debug_active=true};
+exports.debug.off = function() {debug_active=false};
+
@@ -0,0 +1,60 @@
+// Some function to handle lists (or files) of callbacks
+
+
+exports.get_waiter = function(calls_needed, callback){
+ /* Returns a function which will call the given
+ * callback once she has been called calls_needed times.
+ * If calls_needed is 0, then the callback is immediatly called.
+ */
+ !calls_needed && callback();
+ return function(){
+ !--calls_needed && callback();
+ }
+};
+
+
+exports.empty_awaiting_callbacks = function(awaiting_callbacks, key, data){
+ /* Takes the list of functions present in awaiting_callbacks[key],
+ * calls them with data, and delete awaiting_callbacks[key] */
+ var to_call = awaiting_callbacks[key] || [];
+ // Important! The delete must be done BEFORE the call
+ // of the following callbacks (callback at the end!)
+ delete awaiting_callbacks[key];
+ to_call.forEach(function(callback){
+ callback && callback(data);
+ });
+};
+
+
+exports.add_awaiting_callbacks = function(awaiting_callbacks, keys, callback){
+ /* Add (push) the given callback to every awaiting_callbacks[key] for key in keys.
+ * If awaiting_callbacks[key] does not exist, define it as the list [callback].
+ */
+ keys.forEach(function(key){
+ if(awaiting_callbacks[key] == undefined) awaiting_callbacks[key] = [callback];
+ else awaiting_callbacks[key].push(callback);
+ });
+};
+
+
+var sync_calls = function(fct, args, callback, i/*optional*/) {
+ /* Runs the fct synchronously for each given set of args in args.
+ * The last arguments of the fct is a callback, called when fct finishes.
+ * Callback is called when the last call finished.
+ *
+ * Arguments:
+ * - args: array of single values (one argument for each call) or
+ * array of arrays (the inside arrays being the arguments).
+ */
+ if(i === undefined) i = 0;
+ if(i < args.length) {
+ var args_fct = args[i];
+ if (args_fct.forEach === undefined) args_fct = [args_fct];
+ fct.apply(this, args_fct.concat([function(){
+ sync_calls(fct, args, callback, i+1);
+ }]));
+ }
+ else callback && callback();
+};
+exports.sync_calls = sync_calls;
+
@@ -0,0 +1,26 @@
+/* Wraps assert functions to call a callback, and display a dot (.) when success */
+
+var assert = require('assert');
+var sys = require('sys');
+
+// will be called after each assert
+var callback = function(){};
+
+
+for(var attr in assert)
+ if(typeof assert[attr] == 'function' && attr != 'AssertionError') {
+ (function(func) {
+ exports[func] = function() {
+ assert[func].apply(this, arguments);
+ sys.print('.');
+ callback();
+ };
+ })(attr);
+}
+
+exports._set_assert_callback = function(clbck){
+ /* Set a callback to call after each assert.
+ */
+ callback = clbck;
+};
+
@@ -0,0 +1,51 @@
+/* Run all tests present in files 'test_*.js' present in given directory or sub dirs.
+ * Search recursivly for test files.
+ */
+
+var fs = require('fs');
+var sys = require('sys');
+
+var tests_runner = require('nodetk/testing/tests_runner');
+
+var run_tests = function() {
+ var args = {};
+ var tests_dir = '.';
+
+ process.argv.shift(); // remove 'node'
+ process.argv.shift(); // remove 'nodetests.js'
+
+ process.argv.forEach(function(e){
+ if(e[0] == '-') args[e]=true;
+ else tests_dir = e;
+ });
+
+ if(tests_dir[0] != '/') tests_dir = process.cwd() + '/' + tests_dir;
+ sys.puts("Run tests in " + tests_dir);
+
+ to_test = get_test_files(tests_dir);
+ tests_runner.run(to_test);
+};
+
+
+var get_test_files = function(tests_dir) {
+ if(!tests_dir.match(/\/$/)) tests_dir += '/';
+ var to_search_in = [];
+ var to_test = fs.readdirSync(tests_dir).map(function(fname){
+ return tests_dir + fname;
+ }).filter(function(fpath) {
+ if (fs.statSync(fpath).isDirectory()) {
+ to_search_in.push(fpath);
+ return false;
+ }
+ return fpath.match(/\/test_[^\/]+\.js$/);
+ }).map(function(fpath) {
+ return fpath.replace(/\.js$/, '');
+ });
+ to_search_in.forEach(function(dirpath) {
+ to_test = to_test.concat(get_test_files(dirpath));
+ });
+ return to_test;
+};
+
+run_tests();
+
@@ -0,0 +1,67 @@
+/* Runs all the tests in a file.
+ * Tests are ran one by one, synchronously.
+ *
+ * Tests must be in module.tests.
+ * You can specify a setup function (using exports.setup),
+ * which will run before every test.
+ */
+
+var sys = require("sys");
+
+var custom_assert = require("nodetk/testing/custom_assert");
+var CLB = require('nodetk/orchestration/callbacks');
+
+var verbose;
+var start_time;
+
+exports.run = function(tests_files) {
+ var args = {};
+ process.argv.forEach(function(e){args[e]=true;});
+ verbose = args['-v'];
+
+ start_time = new Date().getTime();
+ CLB.sync_calls(run_test_file, tests_files, function() {
+ display_process_infos();
+ // TODO: maybe we should wait a bit here, if there is more callbacks than expected,
+ // then there is a problem...
+ process.exit(0);
+ });
+};
+
+var dummy = function(callback) {callback()};
+var setup;
+
+var run_test = function(name, expected_asserts, test, callback) {
+ /* Run given test fct, having given name.
+ * The test function must use expected_asserts number of asserts.
+ * callback is ran when the expected number of asserts has been called.
+ */
+ setup(function() {
+ var test_waiter = CLB.get_waiter(expected_asserts, function(){
+ verbose && sys.puts(name + ': ' + expected_asserts + " asserts done.");
+ callback && callback();
+ });
+ custom_assert._set_assert_callback(test_waiter);
+ test();
+ });
+}
+
+var run_test_file = function(test_file, callback) {
+ var module = require(test_file);
+ setup = module.setup || dummy;
+ CLB.sync_calls(run_test, module.tests || [], function() {
+ verbose && sys.puts('-----------------');
+ verbose && sys.puts(test_file + '.js: ' + module.tests.length + " test(s) succeed\n");
+ callback();
+ });
+};
+
+var display_process_infos = function() {
+ var end_time = new Date().getTime();
+ var mem_use = process.memoryUsage();
+ sys.puts("\n================");
+ sys.puts("Ellapsed time: " + (end_time - start_time) + "ms.");
+ sys.puts("Memory use: " + JSON.stringify(mem_use));
+};
+
+

0 comments on commit a9d340d

Please sign in to comment.