<commit_before>var fs = require("fs"),
    child_process = require("child_process"),
    path = require("path"),
    chain = require("slide").chain,
    asyncMap = require("slide").asyncMap,
    TapProducer = require("./tap-producer"),
    TapConsumer = require("./tap-consumer"),
    assert = require("./tap-assert"),
    inherits = require("inherits"),
    util = require('util'),
    CovHtml = require('./tap-cov-html');



var Runner = module.exports = function(dir, diag, cb) {
  Runner.super.call(this, diag);

  // An array of full paths to files to obtain coverage
  this.coverage_files = [];
  // The source of these files
  this.coverage_files_source = {};
  // Where to write coverage information
  this.coverage_out_dir = './coverage';
  // Temporary test files bunkerified we'll remove later
  this.f2delete = [];
  // Raw coverage stats, as read from JSON files
  this.raw_cov_stats = [];
  // Processed coverage information, per file to cover:
  this.cov_stats = {};

  if (dir) {
    var files_to_cover = './lib',
        coverage_out_dir = './coverage';
    if (process.env.TAP_COV) {
      dir = dir.filter(function(arg) {
        if (arg.match(/^--cover=/)) {
          files_to_cover = arg.split('--cover=')[1];
          return false;
        } else if (arg.match(/^--cover-dir=/)) {
          coverage_out_dir = arg.split('--cover-dir=')[1];
          return false;
        }
        return true;
      });
      coverage_out_dir = path.resolve(coverage_out_dir);
      path.exists(coverage_out_dir, function(exists) {
        if (!exists) {
          fs.mkdir(coverage_out_dir, 0755, function(er) {
            if (er) {
              throw er;
            }
          });
        }
      });
      this.coverage_out_dir = coverage_out_dir;
      this.getFilesToCover(files_to_cover);
    }
    this.run(dir, cb);
  }
}

inherits(Runner, TapProducer);


Runner.prototype.run = function() {
  var self = this,
      args = Array.prototype.slice.call(arguments),
      cb = args.pop() || function (er) {
        if (er) {
          self.emit("error", er);
        }

        if (process.env.TAP_COV) {
          // Cleanup temporary test files with coverage:
          self.f2delete.forEach(function(f) {
            fs.unlinkSync(f);
          });
          self.getFilesToCoverSource(function(err, data) {
            if (err) {
              self.emit('error', err);
            }
            self.getPerFileCovInfo(function(err, data) {
              if (err) {
                self.emit('error', err);
              }
              self.mergeCovStats(function(err, data) {
                if (err) {
                  self.emit('error', err);
                }
                CovHtml(self.cov_stats, self.coverage_out_dir, function() {
                  setTimeout(function() {
                    self.end();
                  }, 500);
                })
              });
            });
          });
        } else {
          self.end();
        }
      };
  if (Array.isArray(args[0])) {
    args = args[0];
  }
  self.runFiles(args, "", cb);
}

Runner.prototype.runDir = function (dir, cb) {
  var self = this;
  fs.readdir(dir, function (er, files) {
    if (er) {
      self.write(assert.fail("failed to readdir " + dir,
                           { error: er }));
      self.end();
      return;
    }
    files = files.sort(function(a, b) {
      return a > b ? 1 : -1;
    });
    files = files.filter(function(f) {
      return !f.match(/^\./);
    });
    files = files.map(path.resolve.bind(path, dir));

    self.runFiles(files, path.resolve(dir), cb);
  })
}


Runner.prototype.runFiles = function (files, dir, cb) {

  var self = this;
  chain(files.map(function(f) {
    return function (cb) {
      var relDir = dir || path.dirname(f),
          fileName = relDir === "." ? f : f.substr(relDir.length + 1);

      self.write(fileName);
      fs.lstat(f, function(er, st) {
        if (er) {
          self.write(assert.fail("failed to stat " + f,
                               {error: er}));
          return cb();
        }

        var cmd = f, args = [], env = {};

        if (path.extname(f) === ".js") {
          cmd = "node";
          args = [fileName];
        } else if (path.extname(f) === ".coffee") {
          cmd = "coffee";
          args = [fileName];
        }

        if (st.isDirectory()) {
          return self.runDir(f, cb);
        }

        if (process.env.TAP_COV && path.extname(f) === ".js") {
          var foriginal = fs.readFileSync(f, 'utf8'),
              fcontents = self.coverHeader() + foriginal + self.coverFooter(),
              tmp_fname = path.dirname(f) + '/' +
                          path.basename(f, path.extname(f)) +
                          '.with-coverage.' + process.pid + path.extname(f),
              i;

          fs.writeFileSync(tmp_fname, fcontents, 'utf8');
          args = [tmp_fname];
        }

        for (i in process.env) {
          env[i] = process.env[i];
        }
        env.TAP = 1;

        var cp = child_process.spawn(cmd, args, { env: env, cwd: relDir }),
          out = "",
          err = "",
          tc = new TapConsumer(),
          childTests = [f];

        tc.on("data", function(c) {
          self.emit("result", c);
          self.write(c);
        });

        cp.stdout.pipe(tc);
        cp.stdout.on("data", function(c) { out += c });
        cp.stderr.on("data", function(c) { err += c });

        cp.on("exit", function(code) {
          //childTests.forEach(function (c) { self.write(c) })
          var res = {
            name: path.dirname(f).replace(process.cwd() + '/', '') +
                  '/' + fileName,
            ok: !code
          };

          if (err) {
            res.stderr = err;
            if (tc.results.ok && tc.results.tests === 0) {
              // perhaps a compilation error or something else failed...
              console.error(err);
            }
          }
          res.command = [cmd].concat(args).map(JSON.stringify).join(" ");
          self.emit("result", res);
          self.emit("file", f, res, tc.results);
          self.write(res);
          self.write("\n");
          if (process.env.TAP_COV) {
            self.f2delete.push(tmp_fname);
          }
          cb();<commit_msg>Fix #2 Added TAP_TIMEOUT=<seconds> option<commit_after>var fs = require("fs"),
    child_process = require("child_process"),
    path = require("path"),
    chain = require("slide").chain,
    asyncMap = require("slide").asyncMap,
    TapProducer = require("./tap-producer"),
    TapConsumer = require("./tap-consumer"),
    assert = require("./tap-assert"),
    inherits = require("inherits"),
    util = require('util'),
    CovHtml = require('./tap-cov-html');



var Runner = module.exports = function(dir, diag, cb) {
  Runner.super.call(this, diag);

  // An array of full paths to files to obtain coverage
  this.coverage_files = [];
  // The source of these files
  this.coverage_files_source = {};
  // Where to write coverage information
  this.coverage_out_dir = './coverage';
  // Temporary test files bunkerified we'll remove later
  this.f2delete = [];
  // Raw coverage stats, as read from JSON files
  this.raw_cov_stats = [];
  // Processed coverage information, per file to cover:
  this.cov_stats = {};

  if (dir) {
    var files_to_cover = './lib',
        coverage_out_dir = './coverage';
    if (process.env.TAP_COV) {
      dir = dir.filter(function(arg) {
        if (arg.match(/^--cover=/)) {
          files_to_cover = arg.split('--cover=')[1];
          return false;
        } else if (arg.match(/^--cover-dir=/)) {
          coverage_out_dir = arg.split('--cover-dir=')[1];
          return false;
        }
        return true;
      });
      coverage_out_dir = path.resolve(coverage_out_dir);
      path.exists(coverage_out_dir, function(exists) {
        if (!exists) {
          fs.mkdir(coverage_out_dir, 0755, function(er) {
            if (er) {
              throw er;
            }
          });
        }
      });
      this.coverage_out_dir = coverage_out_dir;
      this.getFilesToCover(files_to_cover);
    }
    this.run(dir, cb);
  }
}

inherits(Runner, TapProducer);


Runner.prototype.run = function() {
  var self = this,
      args = Array.prototype.slice.call(arguments),
      cb = args.pop() || function (er) {
        if (er) {
          self.emit("error", er);
        }

        if (process.env.TAP_COV) {
          // Cleanup temporary test files with coverage:
          self.f2delete.forEach(function(f) {
            fs.unlinkSync(f);
          });
          self.getFilesToCoverSource(function(err, data) {
            if (err) {
              self.emit('error', err);
            }
            self.getPerFileCovInfo(function(err, data) {
              if (err) {
                self.emit('error', err);
              }
              self.mergeCovStats(function(err, data) {
                if (err) {
                  self.emit('error', err);
                }
                CovHtml(self.cov_stats, self.coverage_out_dir, function() {
                  setTimeout(function() {
                    self.end();
                  }, 500);
                })
              });
            });
          });
        } else {
          self.end();
        }
      };
  if (Array.isArray(args[0])) {
    args = args[0];
  }
  self.runFiles(args, "", cb);
}

Runner.prototype.runDir = function (dir, cb) {
  var self = this;
  fs.readdir(dir, function (er, files) {
    if (er) {
      self.write(assert.fail("failed to readdir " + dir,
                           { error: er }));
      self.end();
      return;
    }
    files = files.sort(function(a, b) {
      return a > b ? 1 : -1;
    });
    files = files.filter(function(f) {
      return !f.match(/^\./);
    });
    files = files.map(path.resolve.bind(path, dir));

    self.runFiles(files, path.resolve(dir), cb);
  })
}


Runner.prototype.runFiles = function (files, dir, cb) {

  var self = this;
  chain(files.map(function(f) {
    return function (cb) {
      var relDir = dir || path.dirname(f),
          fileName = relDir === "." ? f : f.substr(relDir.length + 1);

      self.write(fileName);
      fs.lstat(f, function(er, st) {
        if (er) {
          self.write(assert.fail("failed to stat " + f,
                               {error: er}));
          return cb();
        }

        var cmd = f, args = [], env = {};

        if (path.extname(f) === ".js") {
          cmd = "node";
          args = [fileName];
        } else if (path.extname(f) === ".coffee") {
          cmd = "coffee";
          args = [fileName];
        }

        if (st.isDirectory()) {
          return self.runDir(f, cb);
        }

        if (process.env.TAP_COV && path.extname(f) === ".js") {
          var foriginal = fs.readFileSync(f, 'utf8'),
              fcontents = self.coverHeader() + foriginal + self.coverFooter(),
              tmp_fname = path.dirname(f) + '/' +
                          path.basename(f, path.extname(f)) +
                          '.with-coverage.' + process.pid + path.extname(f),
              i;

          fs.writeFileSync(tmp_fname, fcontents, 'utf8');
          args = [tmp_fname];
        }

        for (i in process.env) {
          env[i] = process.env[i];
        }
        env.TAP = 1;

        var cp = child_process.spawn(cmd, args, { env: env, cwd: relDir }),
          out = "",
          err = "",
          tc = new TapConsumer(),
          childTests = [f];

        setTimeout(function () {
          if (!cp._ended) {
            cp.kill();
            console.error('killing: ' + f + ' (timed out)');
          }
        }, ((process.env.TAP_TIMEOUT || 30) * 1000));

        tc.on("data", function(c) {
          self.emit("result", c);
          self.write(c);
        });

        cp.stdout.pipe(tc);
        cp.stdout.on("data", function(c) { out += c });
        cp.stderr.on("data", function(c) { err += c });

        cp.on("exit", function(code) {
          cp._ended = true;
          //childTests.forEach(function (c) { self.write(c) })
          var res = {
            name: path.dirname(f).replace(process.cwd() + '/', '') +
                  '/' + fileName,
            ok: !code
          };

          if (err) {
            res.stderr = err;
            if (tc.results.ok && tc.results.tests === 0) {
              // perhaps a compilation error or something else failed...
              console.error(err);
            }
          }
          res.command = [cmd].concat(args).map(JSON.stringify).join(" ");
          self.emit("result", res);
          self.emit("file", f, res, tc.results);
          self.write(res);
          self.write("\n");
          if (process.env.TAP_COV) {
            self.f2delete.push(tmp_fname);
          }
          cb();
{'fraction_non_alphanumeric': 0.15897395914548573, 'fraction_numerical': 0.003820364883829721, 'mean_word_length': 1.6551438625543367, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6371233', 'n_tokens_mistral': 4080, 'n_tokens_neox': 3980, 'n_words': 790}