Commits

kai zhu committed a28f268

add code coverage and reporting via --cover flag. remove middlewareCover. migrate from requireOptimist to requireNopt.

Comments (0)

Files changed (5)

       //// require
       EXPORTS.requireFs = EXPORTS.requireFs || require('fs');
       EXPORTS.requirePath = EXPORTS.requirePath || require('path');
-      EXPORTS.requireOptimist = EXPORTS.requireOptimist || require('optimist');
-      EXPORTS.ARGV = EXPORTS.ARGV || EXPORTS.requireOptimist.argv;
+      EXPORTS.requireNopt = EXPORTS.requireNopt || require('nopt');
+      EXPORTS.ARGV = EXPORTS.ARGV || EXPORTS.requireNopt();
       EXPORTS.FS_CWD = EXPORTS.FS_CWD || process.cwd();
 
       //// command line 1
-      EXPORTS.requireOptimist
-        .options('debug', {
-          describe: 'enable debug mode'
-        })
-        .options('help', {
-          describe: 'display help'
-        })
-        .options('port', {
-          describe: 'set server port'
-        })
-        .usage(
-          'usage: $0 [file ...] [options ...]'
-        );
       Object.keys(EXPORTS.ARGV).forEach(function (key) {
         var val = EXPORTS.ARGV[key];
         if (!val) { return; }
+        try { val = JSON.parse(val); } catch (errParse) {}
+        EXPORTS['IS_' + key.replace((/\W/g), '_').toUpperCase()] = val;
         switch (key) {
-        case 'build':
-          EXPORTS.IS_BUILD = val;
-          break;
         case 'debug':
           //// display environment
-          console.log(['process.EXPORTS.ARGV', process.EXPORTS.ARGV]);
+          console.log(['process.argv', process.EXPORTS.ARGV]);
           console.log(['cwd', EXPORTS.FS_CWD]);
           console.log(['nodejs', process.version]);
           console.log(['module', module.filename, module.id]);
           EXPORTS.IS_DEBUG = val;
           break;
-        case 'help':
-          EXPORTS.EXIT = val;
-          console.log(EXPORTS.requireOptimist.help());
-          return;
         case 'port':
           EXPORTS.HTTP_PORT = val;
           break;
-        case 'test':
-          EXPORTS.IS_TEST = val;
-          break;
         }
       });
       if (EXPORTS.EXIT) { return; }
 
       //// bootstrap
-      EXPORTS.ARGV._.forEach(function (filename) {
+      EXPORTS.ARGV.argv.remain.forEach(function (filename) {
         require(EXPORTS.requirePath.resolve(EXPORTS.FS_CWD, filename));
       });
       require('./libBootstrap');
 
       //// start application
-      if (EXPORTS.startApp) {
-        EXPORTS.startApp();
-      }
+      if (EXPORTS.startApp) { EXPORTS.startApp(); }
 
       //// command line 2
       Object.keys(EXPORTS.ARGV).forEach(function (key) {
       EXPORTS.requireUrl = EXPORTS.requireUrl || require('url');
       EXPORTS.requireUtil = EXPORTS.requireUtil || require('util');
       EXPORTS.requireVm = EXPORTS.requireVm || require('vm');
+      EXPORTS.COVER = EXPORTS.COVER || new EXPORTS.requireIstanbul.Instrumenter();
+      EXPORTS.COVER_FILE = EXPORTS.COVER_FILE || {};
       EXPORTS.FS_MODULE = EXPORTS.FS_MODULE || EXPORTS.requirePath.dirname(module.filename);
       EXPORTS.JSLINT_WATCH = EXPORTS.JSLINT_WATCH || {};
       EXPORTS.MODULE = EXPORTS.MODULE || module;
       EXPORTS.MODULES = EXPORTS.MODULES || {};
       EXPORTS.MODULE_ACTION = {
         base64Decode: local.moduleBase64Decode,
+        cover: local.moduleCover,
+        coverSelf: local.moduleCoverSelf,
         eval: local.moduleEval,
         jslint: local.moduleJslint,
         watch: local.moduleWatch,
       };
       EXPORTS.MODULE_FILE = EXPORTS.MODULE_FILE || {};
       EXPORTS.MODULE_WATCH = EXPORTS.MODULE_WATCH || {};
+      EXPORTS.requireIstanbul.Store.mix(EXPORTS.requireIstanbul.Report.create('html').opts.sourceStore.constructor, {
+        get: function (key) {
+          return EXPORTS.COVER_FILE[key];
+        }
+      });
       EXPORTS.STR_ASCII = EXPORTS.STR_ASCII || '\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~';
       EXPORTS.TEST = EXPORTS.TEST || {};
       EXPORTS.TEST_HTTP = EXPORTS.TEST_HTTP || {};
       local.jslintWatch('./libUnused.js2');
     },
 
+    coverInstrument: function (code, filename) {
+      var ii = 0;
+      EXPORTS.COVER_FILE[filename] = code;
+      switch ((/\w*$/).exec(filename)[0]) {
+      //// instrument js embedded in html
+      case 'html':
+        return code.replace((/<script>([\S\s]+)<\/script>/g), function (_, code) {
+          return '<script>' + EXPORTS.COVER.instrumentSync(code, filename + '.script.' + (ii += 1)) + '</script>';
+        });
+      //// instrument js
+      default:
+        return EXPORTS.COVER.instrumentSync(code, filename);
+      }
+    },
+
     exportLocal: function (local) {
       //// export local methods to EXPORTS
       var arr, ii, key;
       EXPORTS.MODULE_FILE[file.name] = new Buffer(code, 'base64');
     },
 
+    moduleCover: function (module, file, code) {
+      if (EXPORTS.IS_COVER) {
+        EXPORTS.MODULE_FILE[file.name] = EXPORTS.coverInstrument(code, module.id + '.' + file.name);
+      }
+    },
+
+    moduleCoverSelf: function (module, file, code) {
+      if (EXPORTS.IS_COVER === 'self') {
+        EXPORTS.MODULE_FILE[file.name] = EXPORTS.coverInstrument(code, module.id + '.' + file.name);
+      }
+    },
+
     moduleEval: function (module, file, code) {
       module._compile(code, module.filename);
     },
-/*FILE_BEG {"actions": ["jslint", "eval", "watch"], "name": "libCore.js"}*/
+/*FILE_BEG {"actions": ["jslint", "coverSelf", "eval", "watch"], "name": "libCore.js"}*/
 /*jslint bitwise: true, indent: 2, nomen: true, stupid: true*/
 (function () {
 
       reader.on('error', onEnd);
     },
 
-    testRun: function () {
-      //// run tests
-      Object.keys(EXPORTS.TEST).sort().forEach(function (key) { EXPORTS.TEST[key](); });
-      if (EXPORTS.HTTP_SERVER) {
-        Object.keys(EXPORTS.TEST_HTTP).sort().forEach(function (key) {
-          EXPORTS.TEST_HTTP[key]();
-        });
-      }
-    },
-
     uuid4: function () {
       //// return uuid4 string of form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
       var uuid = '', ii;
 
 
 
-/*FILE_BEG {"actions": ["jslint", "eval"], "name": "libRepl.js"}*/
+/*FILE_BEG {"actions": ["jslint", "coverSelf", "eval"], "name": "libRepl.js"}*/
 /*jslint indent: 2, nomen: true, regexp: true*/
 (function () {
 
 
 
 
-/*FILE_BEG {"actions": ["jslint", "eval", "watch"], "name": "libHttp.js"}*/
+/*FILE_BEG {"actions": ["jslint", "coverSelf", "eval", "watch"], "name": "libHttp.js"}*/
 /*jslint indent: 2, nomen: true, regexp: true, stupid: true*/
 (function () {
 
     init: function () {
       //// EXPORTS
       EXPORTS.exportLocal(local);
-      EXPORTS.COVERAGE = EXPORTS.COVERAGE || new EXPORTS.requireIstanbul.Instrumenter();
       EXPORTS.HTTP_HANDLER = EXPORTS.HTTP_HANDLER || {};
       EXPORTS.HTTP_HANDLER['/echo'] = EXPORTS.handlerEcho;
       EXPORTS.HTTP_HANDLER['/http:'] = EXPORTS.handlerHttpProxy;
         EXPORTS.HTTP_APP.use(EXPORTS.requireConnect.logger('dev'));
         //// middleware - security
         EXPORTS.HTTP_APP.use(EXPORTS.middlewareSecurity);
-        //// middleware - js coverage
-        EXPORTS.HTTP_APP.use(EXPORTS.middlewareCoverage);
         //// middleware - dynamic path handler
         EXPORTS.HTTP_APP.use(EXPORTS.middlewarePath);
       }
     },
 
-    coverageInstrument: function (code, filename) {
-      //// instrument js code
-      return EXPORTS.COVERAGE.instrumentSync(code, filename);
-    },
-
-    coverageInstrumentHtml: function (str, filename) {
-      //// instrument js scripts embedded in html
-      var ii = 0;
-      return str.replace((/<script>([\S\s]+)<\/script>/g), function (_, code) {
-        return '<script>' + EXPORTS.coverageInstrument(code, filename + '.script.' + (ii += 1)) + '</script>';
-      });
-    },
-
     handlerEcho: function (request, response) {
       //// echo's back request along with post data if any
       var headers, name;
       }
     },
 
-    middlewareCoverage: function (request, response, next) {
-      //// TODO - cache instrumented code
-      var chunks = '',
-        end = response.end,
-        write = response.write;
-      if (!(/\bcoverage=1\b/).test(request.url)) {
-        next();
-        return;
-      }
-      //// instrument file
-      response.end = function (chunk) {
-        var instrumented;
-        if (chunk) { chunks += chunk; }
-        //// restore response.end and response.write
-        response.end = end;
-        response.write = write;
-        try {
-          switch ((/\w+$/).exec(request.absolutePath)[0]) {
-          case 'html':
-            instrumented = EXPORTS.coverageInstrumentHtml(chunks, request.absolutePath);
-            break;
-          case 'js':
-            instrumented = EXPORTS.coverageInstrument(chunks, request.absolutePath);
-            break;
-          }
-          response.setHeader('content-length', Buffer.byteLength(instrumented));
-          response.end(instrumented);
-        } catch (err) {
-          next(err);
-        }
-      };
-      response.write = function (chunk) {
-        chunks += chunk;
-        return true;
-      };
-      next();
-    },
-
     middlewarePath: function (request, response, next) {
       var path;
       //// debug history of requests / responses
 
 
 
-/*FILE_BEG {"actions": ["jslint", "eval", "watch"], "name": "libExternal.js"}*/
+/*FILE_BEG {"actions": ["jslint", "coverSelf", "eval", "watch"], "name": "libExternal.js"}*/
 /*jslint indent: 2, nomen: true, regexp: true, stupid: true*/
 (function () {
 
 
 
 
-/*FILE_BEG {"actions": ["jslint", "eval", "watch"], "name": "libAdmin.js"}*/
+/*FILE_BEG {"actions": ["jslint", "coverSelf", "eval", "watch"], "name": "libAdmin.js"}*/
 /*jslint indent: 2, nomen: true, regexp: true, stupid: true*/
 (function () {
 
 
 
 
-/*FILE_BEG {"actions": ["jslint", "eval", "watch"], "name": "libDb.js"}*/
+/*FILE_BEG {"actions": ["jslint", "coverSelf", "eval", "watch"], "name": "libDb.js"}*/
 /*jslint bitwise: true, indent: 2, nomen: true, regexp: true, stupid: true*/
 (function () {
 
 
 
 
-/*FILE_BEG {"actions": ["jslint", "eval"], "name": "libTest.js"}*/
+/*FILE_BEG {"actions": ["jslint", "coverSelf", "eval"], "name": "libTest.js"}*/
 /*jslint bitwise: true, indent: 2, nomen: true, regexp: true, stupid: true*/
 (function () {
 
   var EXPORTS = process.EXPORTS || {}, local = {
 
     init: function () {
+      //// EXPORTS
+      EXPORTS.exportLocal(local);
       //// http tests
       if (!EXPORTS.HTTP_SERVER) { return; }
       EXPORTS.TEST_HTTP.proxy = function () {
           url: '/http://localhost:' + EXPORTS.HTTP_PORT + '/echo/foo',
         });
       };
-      EXPORTS.testRun();
+      EXPORTS.startTest();
+    },
+
+    coverClear: function () {
+      //// clear __coverage__
+      var arr, cov = global.__coverage__, key, obj;
+      for (key in cov) {
+        if (cov.hasOwnProperty(key)) {
+          obj = cov[key];
+          arr = obj.b;
+          for (key in arr) { if (arr.hasOwnProperty(key)) { arr[key] = [0, 0]; } }
+          arr = obj.f;
+          for (key in arr) { if (arr.hasOwnProperty(key)) { arr[key] = 0; } }
+          arr = obj.s;
+          for (key in arr) { if (arr.hasOwnProperty(key)) { arr[key] = 0; } }
+        }
+      }
+    },
+
+    startTest: function () {
+      EXPORTS.coverClear();
+      //// run tests
+      Object.keys(EXPORTS.TEST).sort().forEach(function (key) { EXPORTS.TEST[key](); });
+      if (EXPORTS.HTTP_SERVER) {
+        Object.keys(EXPORTS.TEST_HTTP).sort().forEach(function (key) {
+          EXPORTS.TEST_HTTP[key]();
+        });
+      }
     }
 
   };
     "jslint": "*",
     "mime": "*",
     "minify": "*",
-    "optimist": "*",
+    "nopt": "*",
     "tinyjs-external": "*",
     "uglify-js": "*"
   },
 /*
 CHANGELOG
-auto-version package.json
-add MODULE_ACTION['write']
+add code coverage and reporting via --cover flag.  remove middlewareCover.  migrate from requireOptimist to requireNopt.
 
 TODO
-add code coverage
-auto-generate online documentation
-add optional istanbul coverage in require
-add client-side interactive tests
-rewrite db
+auto-generate online documentation via yuidoc.
+add optional istanbul coverage in require.
+add client-side interactive tests.
+rewrite db.
  */
 
 
 
-/*FILE_BEG {"actions": ["jslint", "eval", "watch"], "name": "libUnstable.js"}*/
+/*FILE_BEG {"actions": ["jslint", "coverSelf", "eval", "watch"], "name": "libUnstable.js"}*/
 /*jslint bitwise: true, continue: true, indent: 2, nomen: true, regexp: true, stupid: true*/
 (function () {
 
     init: function () {
       //// EXPORTS
       EXPORTS.exportLocal(local);
-      // debug
-      // printd(
-        // EXPORTS.stringFormat2('{{console.log(aa)}}', {aa: 1, console: 34})
-      // );
     },
 
+    coverReport: function () {
+      var collector = new EXPORTS.requireIstanbul.Collector();
+      collector.add(global.__coverage__);
+      EXPORTS.requireIstanbul.Report.create('lcov', { dir: EXPORTS.FS_CWD + '/coverage' }).writeReport(collector);
+    }
+
   };
 
   local.init();
 
 
 
-/*FILE_BEG {"actions": ["jslint"], "name": "/admin/admin.html"}*/
+/*FILE_BEG {"actions": ["jslint", "coverSelf"], "name": "/admin/admin.html"}*/
 <html>
 <head>
 <link rel="stylesheet" href="/public/cacheVersion/{{EXPORTS.VERSION}}/externalRollup.css">
     "jslint": "*",
     "mime": "*",
     "minify": "*",
-    "optimist": "*",
+    "nopt": "*",
     "tinyjs-external": "*",
     "uglify-js": "*"
   },
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1"
   },
-  "version": "2013.03.16-11.05"
+  "version": "2013.03.16-16.47"
 }