<commit_before>'use strict';

const path = require('path');
const vm = require('vm');
const assert = require('assert');
const spawn = require('child_process').spawn;

module.exports = {testSolution, runSolution, initTests, runTests};

/**
 * Run tests in a sandbox.
 *
 * usage:
 *
 *   testSolution('var foo = 1;', 'test('foo should be set', function(){ assert.equal(1, foo)})')
 *   // would return `{solved: true, results:[{test: 'foo should be set', correct: true}]}`
 *
 *
 * @param  {String} solution User provided JS solution
 * @param  {String} tests    User (admin) provided JS tests
 * @return {Object}          holding `solved` (bool), `results` and `errors`
 *
 */
function testSolution(solution, tests, opts) {
  opts = opts || {};

  return new Promise(function(resolve) {
    let out = '';
    let err = '';
    let resolved = false;
    const tester = spawn(process.execPath, [
      path.join(__dirname, '_runner.js'),
      '--solution', solution,
      '--tests', tests
    ]);

    let timeout = setTimeout(() => {
      tester.kill('SIGTERM');
      timeout = null;

      if (resolved) {
        return;
      }

      resolved = true;
      resolve({solved: false, errors: 'timeout'});
    }, opts.timeout || 5000);

    tester.stdout.on('data', data => {
      out += data;
    });

    tester.stderr.on('data', data => {
      process.stderr.write(data);
    });

    tester.on('close', code => {
      if (timeout) {
        clearTimeout(timeout);
      }

      if (resolved) {
        return;
      }

      resolved = true;
      if (code) {
        resolve({solved: false, errors: err});
      } else {
        resolve(JSON.parse(out));
      }
    });

    tester.on('error', e => {
      if (timeout) {
        clearTimeout(timeout);
      }

      if (resolved) {
        return;
      }

      resolved = true;
      resolve({solved: false, errors: e.toString()});
    });
  });
}

/**
 * Run the user provided solution inside a sandbox.
 *<commit_msg>Kill solution runner child process on SIGTERM<commit_after>'use strict';

const path = require('path');
const vm = require('vm');
const assert = require('assert');
const spawn = require('child_process').spawn;

module.exports = {testSolution, runSolution, initTests, runTests};

/**
 * Run tests in a sandbox.
 *
 * usage:
 *
 *   testSolution('var foo = 1;', 'test('foo should be set', function(){ assert.equal(1, foo)})')
 *   // would return `{solved: true, results:[{test: 'foo should be set', correct: true}]}`
 *
 *
 * @param  {String} solution User provided JS solution
 * @param  {String} tests    User (admin) provided JS tests
 * @return {Object}          holding `solved` (bool), `results` and `errors`
 *
 */
function testSolution(solution, tests, opts) {
  opts = opts || {};

  return new Promise(function(resolve) {
    let out = '';
    let err = '';
    let resolved = false;

    const tester = spawn(process.execPath, [
      path.join(__dirname, '_runner.js'),
      '--solution', solution,
      '--tests', tests
    ]);
    const stop = () => tester.kill('SIGKILL');

    let timeout = setTimeout(() => {
      stop();
      timeout = null;

      if (resolved) {
        return;
      }

      resolved = true;
      resolve({solved: false, errors: 'timeout'});
    }, opts.timeout || 5000);
    const cancelTimeout = () => {
      if (timeout) {
        clearTimeout(timeout);
      }
    };

    tester.stdout.on('data', data => {
      out += data;
    });

    tester.stderr.on('data', data => {
      process.stderr.write(data);
    });

    tester.on('close', code => {
      cancelTimeout();

      if (resolved) {
        return;
      }

      resolved = true;
      if (code) {
        resolve({solved: false, errors: err});
      } else {
        resolve(JSON.parse(out));
      }
    });

    tester.on('error', e => {
      cancelTimeout();

      if (resolved) {
        return;
      }

      resolved = true;
      resolve({solved: false, errors: e.toString()});
    });

    process.on('SIGTERM', stop);
  });
}

/**
 * Run the user provided solution inside a sandbox.
 *
{'fraction_non_alphanumeric': 0.16743958994386135, 'fraction_numerical': 0.002928972418843056, 'mean_word_length': 2.4321608040201004, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 15, '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': '5266428', 'n_tokens_mistral': 1296, 'n_tokens_neox': 1241, 'n_words': 328}