<commit_before>// genericMock when called with a spyFactory and a nodeunit test object
// can simulate something like the exec function
function genericMock(spyFactory, test) {
    var spies = [], spyIndex = 0;

    function run() {
        var spy = spies[spyIndex];
        spyIndex++;
        if (!spy) {
            throw new Error('unepectedly trying to call: ' + arguments[0]);
        }
        spy.apply(null, arguments);
    }

    run.expect = function(/*args*/) {
        for (var i = 0; i < arguments.length; i++) {
            spies.push(spyFactory(test, arguments[i]));
        }
        return run;
    }

    run.assertAllCalled = function() {
        spies.forEach(function(spy) {
            test.equal(spy.called, 1, 'spy called not called: ' + spy);
        });
    }

    run.toString = function() {
        return 'Mock< spies:' + spies.join('\n') + '>';
    }

    return run;
}

//
// exec
//

function execEquals(test, actualCommand, expectedCmd, actualCwd, expectedCwd) {
    test.equal(actualCommand, expectedCmd);
    test.equal(actualCwd, expectedCwd);
}

function createExecSpy(test, spec) {
    var spy = function(cmd, options, callback) {
        spy.called++;
        execEquals(test, cmd, spec.cmd, options.cwd, spec.cwd);
        if (!callback) {
            throw new Error('No callback for ' + spy);
        }
        callback(spec.code || null, spec.out || "");
    }
    spy.called = 0;
    spy.toString = function() { return 'execSpy<' + spec.cmd + '>' };
    return spy;
}

exports.execForTest = genericMock.bind(null, createExecSpy);

//
// fs
//

function fsWriteEquals(test, actualFile, expectedFile, actualWriteContent, expectedWriteContent) {
    test.equal(actualFile, expectedFile);
    test.equal(actualWriteContent, expectedWriteContent);
}

function createFsWriteSpy(test, spec) {
    var spy = function(fn, data, callback) {
        spy.called++;
        fsWriteEquals(test, fn, spec.file, data, spec.data);
        callback(spec.code || null);
    }
    spy.called = 0;
    spy.toString = function() { return 'fsWriteSpy<' + spec.file + '>' };
    return spy;
}

function fsReadEquals(test, actualFile, expectedFile) {
    test.equal(actualFile, expectedFile);
}

function createFsReadSpy(test, spec) {
    var spy = function(fn, callback) {
        spy.called++;
        fsWriteEquals(test, fn, spec.file);
        callback(spec.code || null, spec.data || '');
    }
    spy.called = 0;
    spy.toString = function() { return 'fsReadSpy<' + spec.file + '>' };
    return spy;
}

exports.fsForTest = function(test) {
    return {
        writeFile: genericMock(createFsWriteSpy, test),
        readFile: genericMock(createFsReadSpy, test)
    }
}<commit_msg>cleaning up spy code and adding spy for shelljs<commit_after>var util = require("util");

// genericMock when called with a spyFactory and a nodeunit test object
// can simulate something like the exec function
function genericSpy(bodyFunc) {
    var invovationsToRun = [],
        ignoreUnexpected = false,
        callCount = 0;

    function createInvocation(spec) {
        function invocation() {
            var actualArgs = [];
            for (var i = 0; i < arguments.length; i++) { actualArgs.push(arguments[i]); }
            callCount++;
            return bodyFunc.apply(invocation, [spec].concat(actualArgs));
        }
        invocation.toString = function() { return bodyFunc.name + '<' + util.inspect(spec) + '>' };
        return invocation;
    }

    function run() {
        var spy = invovationsToRun.shift();
        if (!spy) {
            if (ignoreUnexpected) return;
            throw new Error('unepectedly trying to call: ' + arguments[0]);
        }
        spy.apply(null, arguments);
    }

    run.ignoreUnexpected = function() { ignoreUnexpected = true }

    run.expect = function(/*specs*/) {
        for (var i = 0; i < arguments.length; i++) {
            invovationsToRun.push(createInvocation(arguments[i]));
        }
        return run;
    }

    run.assertAllCalled = function() {
        if (invovationsToRun.length === 0) return;
        throw new Error('spies not called: ' + invovationsToRun);
    }

    run.toString = function() {
        return 'Mock< invovationsToRun:' + invovationsToRun.join('\n') + '>';
    }

    return run;
}

//
// exec
//
exports.execForTest = function(test) {
    return genericSpy(function execSpy(spec, cmd, options, callback) {
        test.equal(cmd, spec.cmd);
        test.equal(options.cwd, spec.cwd);
        if (!callback) {
            throw new Error('No callback for ' + this);
        }
        callback(spec.code || null, spec.out || "");
    });
}

//
// fs
//
exports.fsForTest = function(test) {
    return {
        writeFile: genericSpy(function writeSpy(spec, fn, data, callback) {
            test.equal(fn, spec.file);
            test.equal(data, spec.data);
            callback(spec.code || null);
        }),
        readFile: genericSpy(function readSpy(spec, fn, callback) {
            test.equal(fn, spec.file);
            callback(spec.code || null, spec.data || '');
        })
    }
}

exports.shelljs = function(test) {
    var spies = {
        echo: genericSpy(function echoSpy(expectedString, actualString) {
            test.equal(actualString, expectedString, "echo not OK"); })
    };
    spies.beGlobal = function() {
        Object.keys(spies).forEach(function(name) {
            global[name] = spies[name];
        });
    }
    return spies;
}
{'fraction_non_alphanumeric': 0.13871144369410476, 'fraction_numerical': 0.0021901806899069175, 'mean_word_length': 2.4530560806553243, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 9, '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': '7563043', 'n_tokens_mistral': 1681, 'n_tokens_neox': 1663, 'n_words': 383}