<commit_before>var readline = require('readline');
var spawn = require('child_process').spawn;
var os = require('os').platform();
var spawnSync = require('child_process').spawnSync;
var expect = require('chai').expect;

var startingPort = 8000;
var tcpBeaconsPath = __dirname + "/assets/tcp.only-beacon.js";
var jobPath = __dirname + "/assets/job.js";
var badJobPath = __dirname + "/assets/bad.job.js";
var machinesWithLocalPath = __dirname + "/assets/machines.with.local.json";
var machinesWithoutLocalPath = __dirname + "/assets/machines.without.local.json";
var machinesWithWrongPass = __dirname + "/assets/machines.with.wrong.pass.json";
var runnerPath = __dirname + "/../../bin/main.js";
var beaconPath = __dirname + "/../../lib/beacon.js";
var tcpBeacons = [];
var localBeacon;

before(function() {

    this.timeout(10000);

    process.stdout.write('  Running Remote Beacons ...');

    for(var i = 0; i < 2; ++i) {
        var semiRemoteBeacon = spawn('node', [tcpBeaconsPath, startingPort + i]);
        tcpBeacons.push(semiRemoteBeacon);
    }

    process.stdout.write(' Done!\n');
    process.stdout.write('  Restarting Local Beacon ...');

    spawnSync('node', [runnerPath, '-d']);
    localBeacon = spawn('node', [beaconPath]);

    process.stdout.write(' Done!\n\n');
});

after(function() {

    this.timeout(10000);

    process.stdout.write('  Stopping Remote Beacons ...');

    tcpBeacons.forEach((beacon) => beacon.kill());

    process.stdout.write(' Done!\n');
    process.stdout.write('  Stopping Local Beacon ...');

    //spawnSync('node', [runnerPath, '-d']);
    localBeacon.kill();

    process.stdout.write(' Done!\n\n');
});

describe("Klyng's Integartion tests", function() {

    this.timeout(15000);

    it('runs a job of size 6 on local and 2 remote hosts', function(done) {

        var parent = spawn('node', [runnerPath, '-n', 6, '-m', machinesWithLocalPath, jobPath]);
        var parentStdout = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        parent.stderr.on('data', (chunk) => {
            console.log(chunk.toString().trim());
        });

        parent.on('exit', () => {
            for(var i = 0; i < 6; ++i) {
                for(var j = 0; j < 6; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }
            done();
        });
    });

    it('runs a job of size 6 on 2 remote hosts', function(done) {

        var parent = spawn('node', [runnerPath, '-n', 6, '-m', machinesWithoutLocalPath, jobPath]);
        var parentStdout = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        parent.stderr.on('data', (chunk) => {
            console.log(chunk.toString().trim());
        });

        parent.on('exit', () => {
            for(var i = 0; i < 6; ++i) {
                for(var j = 0; j < 6; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }
            done();
        });
    });

    it('aborts when an error occurs during the job', function(done) {
        var parent = spawn('node', [runnerPath, '-n', 6, '-m', machinesWithWrongPass, jobPath]);
        var parentStderr = [];

        var stderrRlInterface = readline.createInterface({input: parent.stderr});
        stderrRlInterface.on('line', (line) => {
            parentStderr.push(line);
        });

        parent.on('exit', () => {
            expect(parentStderr).to.include('[Aborted]: 127.0.0.1:8000 incorrect password');

            // wait for a second for the beacons to clear there data structures
            setTimeout(done, 1500);
        });
    });

    it('ensures that the beacons aborted gracefully (by running a job)', function(done) {

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, jobPath]);
        var parentStdout = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        parent.stderr.on('data', (chunk) => {
            console.log(chunk.toString().trim());
        });

        parent.on('exit', () => {
            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }
            done();
        });
    });

    it('aborts on keyboard interrupt (SIGINT)', function(done) {

        var spawnOptions = (os === "win32") ? {stdio: [null, null, null, 'ipc']} : {};

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, badJobPath], spawnOptions);
        var parentStdout = [];
        var parentStderr = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});
        var stderrRlInterface = readline.createInterface({input: parent.stderr});

        stderrRlInterface.on('line', (line) => {
            parentStderr.push(line);
        });

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        setTimeout(() => os === "win32" ? parent.send('SIGINT') : parent.kill('SIGINT'), 5000);

        parent.on('exit', () => {
            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }

            expect(parentStderr).to.include('[Aborted]: Keyboard Interrupt');

            // wait for a second for the beacons to clear there data structures
            setTimeout(done, 1500);
        });
    });

    it('ensures that the beacons aborted gracefully (by running a job)', function(done) {

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, jobPath]);
        var parentStdout = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        parent.stderr.on('data', (chunk) => {
            console.log(chunk.toString().trim());
        });

        parent.on('exit', () => {
            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }
            done();
        });
    });

    it('aborts when one of the remote node is not up', function(done) {
        // kill node at :8001
        tcpBeacons[1].kill();

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, jobPath]);
        var parentStderr = [];

        var stderrRlInterface = readline.createInterface({input: parent.stderr});
        stderrRlInterface.on('line', (line) => {
            parentStderr.push(line);
        });

        parent.on('exit', () => {
            expect(parentStderr).to.include('[Aborted]: connect ECONNREFUSED 127.0.0.1:8001');

            // wait for a second for the beacons to clear there data structures
            setTimeout(done, 1500);
        });
    });

    it('ensures that the beacons aborted gracefully (by running a job)', function(done) {

        tcpBeacons[1] = spawn('node', [tcpBeaconsPath, 8001]);

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, jobPath]);
        var parentStdout = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        parent.stderr.on('data', (chunk) => {
            console.log(chunk.toString().trim());
        });

        parent.on('exit', () => {
            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }
            done();
        });
    });

    it('aborts when one of the remote node fails during the job', function(done) {

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, badJobPath]);
        var parentStdout = [];
        var parentStderr = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});
        var stderrRlInterface = readline.createInterface({input: parent.stderr});

        stderrRlInterface.on('line', (line) => {
            parentStderr.push(line);
        });

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        setTimeout(() => tcpBeacons[1].kill(), 5000);

        parent.on('exit', () => {

            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }

            expect(parentStderr).to.include('[Aborted]: connect ECONNREFUSED 127.0.0.1:8001');

            // wait for a second for the beacons to clear there data structures
            setTimeout(done, 1500);
        });
    });

    it('ensures that the beacons aborted gracefully (by running a job)', function(done) {

        tcpBeacons[1] = spawn('node', [tcpBeaconsPath, 8001]);

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, jobPath]);
        var parentStdout = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        parent.stderr.on('data', (chunk) => {
            console.log(chunk.toString().trim());
        });

        parent.on('exit', () => {
            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }
            done();
        });
    });

    it('aborts when the local beacon fails during the job', function(done) {

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, badJobPath]);
        var parentStdout = [];
        var parentStderr = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});
        var stderrRlInterface = readline.createInterface({input: parent.stderr});

        stderrRlInterface.on('line', (line) => {
            parentStderr.push(line);
        });

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        setTimeout(() => localBeacon.kill(), 5000);

        parent.on('exit', () => {

            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }

            expect(parentStderr).to.include('[Aborted]: Lost connection to local beacon');

            // wait for a second for the beacons to clear there data structures
            setTimeout(done, 3000);
        });
    });

    it('ensures that the beacons aborted gracefully (by running a job)', function(done) {

        localBeacon = spawn('node', [beaconPath]);

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, jobPath]);
        var parentStdout = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        parent.stderr.on('data', (chunk) => {
            console.log(chunk.toString().trim());
        });

        parent.on('exit', () => {
            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }
            done();
        });
    });
});
<commit_msg>added abortion tests for runner faliure<commit_after>var readline = require('readline');
var spawn = require('child_process').spawn;
var os = require('os').platform();
var spawnSync = require('child_process').spawnSync;
var expect = require('chai').expect;

var startingPort = 8000;
var tcpBeaconsPath = __dirname + "/assets/tcp.only-beacon.js";
var jobPath = __dirname + "/assets/job.js";
var badJobPath = __dirname + "/assets/bad.job.js";
var machinesWithLocalPath = __dirname + "/assets/machines.with.local.json";
var machinesWithoutLocalPath = __dirname + "/assets/machines.without.local.json";
var machinesWithWrongPass = __dirname + "/assets/machines.with.wrong.pass.json";
var runnerPath = __dirname + "/../../bin/main.js";
var beaconPath = __dirname + "/../../lib/beacon.js";
var tcpBeacons = [];
var localBeacon;

before(function() {

    this.timeout(10000);

    process.stdout.write('  Running Remote Beacons ...');

    for(var i = 0; i < 2; ++i) {
        var semiRemoteBeacon = spawn('node', [tcpBeaconsPath, startingPort + i]);
        tcpBeacons.push(semiRemoteBeacon);
    }

    process.stdout.write(' Done!\n');
    process.stdout.write('  Restarting Local Beacon ...');

    spawnSync('node', [runnerPath, '-d']);
    localBeacon = spawn('node', [beaconPath]);

    process.stdout.write(' Done!\n\n');
});

after(function() {

    this.timeout(10000);

    process.stdout.write('  Stopping Remote Beacons ...');

    tcpBeacons.forEach((beacon) => beacon.kill());

    process.stdout.write(' Done!\n');
    process.stdout.write('  Stopping Local Beacon ...');

    //spawnSync('node', [runnerPath, '-d']);
    localBeacon.kill();

    process.stdout.write(' Done!\n\n');
});

describe("Klyng's Integartion tests", function() {

    this.timeout(15000);

    it('runs a job of size 6 on local and 2 remote hosts', function(done) {

        var parent = spawn('node', [runnerPath, '-n', 6, '-m', machinesWithLocalPath, jobPath]);
        var parentStdout = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        parent.stderr.on('data', (chunk) => {
            console.log(chunk.toString().trim());
        });

        parent.on('exit', () => {
            for(var i = 0; i < 6; ++i) {
                for(var j = 0; j < 6; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }
            done();
        });
    });

    it('runs a job of size 6 on 2 remote hosts', function(done) {

        var parent = spawn('node', [runnerPath, '-n', 6, '-m', machinesWithoutLocalPath, jobPath]);
        var parentStdout = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        parent.stderr.on('data', (chunk) => {
            console.log(chunk.toString().trim());
        });

        parent.on('exit', () => {
            for(var i = 0; i < 6; ++i) {
                for(var j = 0; j < 6; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }
            done();
        });
    });

    it('aborts when an error occurs during the job', function(done) {
        var parent = spawn('node', [runnerPath, '-n', 6, '-m', machinesWithWrongPass, jobPath]);
        var parentStderr = [];

        var stderrRlInterface = readline.createInterface({input: parent.stderr});
        stderrRlInterface.on('line', (line) => {
            parentStderr.push(line);
        });

        parent.on('exit', () => {
            expect(parentStderr).to.include('[Aborted]: 127.0.0.1:8000 incorrect password');

            // wait for a second for the beacons to clear there data structures
            setTimeout(done, 1500);
        });
    });

    it('ensures that the beacons aborted gracefully (by running a job)', function(done) {

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, jobPath]);
        var parentStdout = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        parent.stderr.on('data', (chunk) => {
            console.log(chunk.toString().trim());
        });

        parent.on('exit', () => {
            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }
            done();
        });
    });

    it('aborts on keyboard interrupt (SIGINT)', function(done) {

        var spawnOptions = (os === "win32") ? {stdio: [null, null, null, 'ipc']} : {};

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, badJobPath], spawnOptions);
        var parentStdout = [];
        var parentStderr = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});
        var stderrRlInterface = readline.createInterface({input: parent.stderr});

        stderrRlInterface.on('line', (line) => {
            parentStderr.push(line);
        });

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        setTimeout(() => os === "win32" ? parent.send('SIGINT') : parent.kill('SIGINT'), 5000);

        parent.on('exit', () => {
            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }

            expect(parentStderr).to.include('[Aborted]: Keyboard Interrupt');

            // wait for a second for the beacons to clear there data structures
            setTimeout(done, 1500);
        });
    });

    it('ensures that the beacons aborted gracefully (by running a job)', function(done) {

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, jobPath]);
        var parentStdout = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        parent.stderr.on('data', (chunk) => {
            console.log(chunk.toString().trim());
        });

        parent.on('exit', () => {
            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }
            done();
        });
    });

    it('aborts when one of the remote node is not up', function(done) {
        // kill node at :8001
        tcpBeacons[1].kill();

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, jobPath]);
        var parentStderr = [];

        var stderrRlInterface = readline.createInterface({input: parent.stderr});
        stderrRlInterface.on('line', (line) => {
            parentStderr.push(line);
        });

        parent.on('exit', () => {
            expect(parentStderr).to.include('[Aborted]: connect ECONNREFUSED 127.0.0.1:8001');

            // wait for a second for the beacons to clear there data structures
            setTimeout(done, 1500);
        });
    });

    it('ensures that the beacons aborted gracefully (by running a job)', function(done) {

        tcpBeacons[1] = spawn('node', [tcpBeaconsPath, 8001]);

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, jobPath]);
        var parentStdout = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        parent.stderr.on('data', (chunk) => {
            console.log(chunk.toString().trim());
        });

        parent.on('exit', () => {
            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }
            done();
        });
    });

    it('aborts when one of the remote node fails during the job', function(done) {

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, badJobPath]);
        var parentStdout = [];
        var parentStderr = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});
        var stderrRlInterface = readline.createInterface({input: parent.stderr});

        stderrRlInterface.on('line', (line) => {
            parentStderr.push(line);
        });

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        setTimeout(() => tcpBeacons[1].kill(), 5000);

        parent.on('exit', () => {

            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }

            expect(parentStderr).to.include('[Aborted]: connect ECONNREFUSED 127.0.0.1:8001');

            // wait for a second for the beacons to clear there data structures
            setTimeout(done, 1500);
        });
    });

    it('ensures that the beacons aborted gracefully (by running a job)', function(done) {

        tcpBeacons[1] = spawn('node', [tcpBeaconsPath, 8001]);

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, jobPath]);
        var parentStdout = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        parent.stderr.on('data', (chunk) => {
            console.log(chunk.toString().trim());
        });

        parent.on('exit', () => {
            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }
            done();
        });
    });

    it('aborts when the local beacon fails during the job', function(done) {

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, badJobPath]);
        var parentStdout = [];
        var parentStderr = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});
        var stderrRlInterface = readline.createInterface({input: parent.stderr});

        stderrRlInterface.on('line', (line) => {
            parentStderr.push(line);
        });

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        setTimeout(() => localBeacon.kill(), 5000);

        parent.on('exit', () => {

            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }

            expect(parentStderr).to.include('[Aborted]: Lost connection to local beacon');

            // wait for a second for the beacons to clear there data structures
            setTimeout(done, 3000);
        });
    });

    it('ensures that the beacons aborted gracefully (by running a job)', function(done) {

        localBeacon = spawn('node', [beaconPath]);

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, jobPath]);
        var parentStdout = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        parent.stderr.on('data', (chunk) => {
            console.log(chunk.toString().trim());
        });

        parent.on('exit', () => {
            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }
            done();
        });
    });

    it('aborts when the runner closes abruptly during a job', function(done) {
        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, badJobPath]);
        var parentStdout = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        parent.stderr.on('data', (chunk) => {
            console.log(chunk.toString().trim());
        });

        setTimeout(() => parent.kill(), 5000);

        parent.on('exit', () => {
            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }
            setTimeout(done, 3000);
        });
    });

    it('ensures that the beacons aborted gracefully (by running a job)', function(done) {

        var parent = spawn('node', [runnerPath, '-n', 3, '-m', machinesWithLocalPath, jobPath]);
        var parentStdout = [];

        var stdoutRlInterface = readline.createInterface({input: parent.stdout});

        stdoutRlInterface.on('line', (line) => {
            parentStdout.push(line);
        });

        parent.stderr.on('data', (chunk) => {
            console.log(chunk.toString().trim());
        });

        parent.on('exit', () => {
            for(var i = 0; i < 3; ++i) {
                for(var j = 0; j < 3; j++) {
                    if(i !== j) {
                        var msg = "Greetings P" + i + " from P" + j;
                        expect(parentStdout).to.include(msg);
                    }
                }
            }
            done();
        });
    });
});
<|endoftext|>


<commit_before>'use strict';

var servicesModuleQuote =
    angular.module('jobq.quote.services', ['ngResource']);
angular.module('jobq.quote.services').factory('QuoteService',
        function ($rootScope, $routeParams, $http, $log,
                  Quote, $location,Quotes,Plants) {

            var QuoteService = {};
            $rootScope.quote = {};
            $rootScope.loadForEdit = true;
            $rootScope.editingChanged = false;
            //$rootScope.editing = {};

            var margins = [{"value":0, "label":'Margin 0%'},
                {"value":0.1, "label":'Margin 10%'},
                {"value":0.15, "label":'Margin 15%'},
                {"value":0.2, "label":'Margin 20%'},
                {"value":0.25, "label":'Margin 25%'},
                {"value":0.3, "label":'Margin 30%'},
                {"value":0.35, "label":'Margin 35%'},
                {"value":0.4, "label":'Margin 40%'}];

            QuoteService.find = function(quoteId) {
                $log.info('find quoteId is ' + quoteId);
                var url = createUrl('/quotes/' + quoteId);
                return $http.get(url);
            }

            QuoteService.findOrCreate = function($scope) {
                QuoteService.load($scope);
            }

            QuoteService.findOrCreateForWorks = function($scope) {
                QuoteService.load($scope);
            }

            QuoteService.hasContents = function(contract) {
                if(!contract.sections) {
                    return false;
                }
                if(contract.sections.length == 1 &&
                    !contract.sections[0].content) {
                    return false;
                }
                return true;

//            return (!contract.sections ||
//                   (contract.sections.length == 1 && !contract.sections[0]));
            }

            function loadContractTemplate(quote) {
                var c = quote.contract;
                var tempalte = $rootScope.userProfile.template;
                var changed = false;

                if(!c.dear) {
                    c.dear = quote.client;
                    changed = true;
                }

                if(!c.paymentIntro) {
                    c.paymentIntro = tempalte.paymentIntro;
                    changed = true;
                }

                if(!c.payments) {
                    c.payments = tempalte.payments;
                    changed = true;
                }

                if(!c.intro) {
                    c.intro = tempalte.intro;
                    changed = true;
                }

                if(!QuoteService.hasContents(c)) {
                    c.sections = tempalte.sections;
                    changed = true;
                }
                return changed;
            }

            QuoteService.updateStatus = function(quote, job) {
                quote.status = job.status;
                quote.updated = job.updated;
                quote.version = job.version;

                return quote;
            }

            QuoteService.updateQuoteStatus = function(job) {
                $log.info('updateQuoteStatus: ' + job.status);
                QuoteService.updateStatus($rootScope.quote, job);

                //QuoteService.updateStatus($rootScope.editing, job);

                $rootScope.loadForEdit = true;
            }

            QuoteService.loadForEdit = function($scope, toLoad, quote) {
                $log.info('loadForEdit start: ' + toLoad);

                $rootScope.editing = quote;
                $rootScope.quote = $rootScope.editing;
                var quoteId = $rootScope.quoteId = $rootScope.editing._id;
                var jobId = $rootScope.editing._jobId;

                if($scope.workIdx == undefined) {
                    $scope.workIdx = 0;
                }

                if(!$rootScope.editing.status) {
                    $rootScope.editing.status = 'Preparing';
                    $rootScope.quoteFinalised = false;
                }

                if($rootScope.editing.status == 'Submitted') {
                    $rootScope.quoteFinalised = true;
                }

                Quote.updateSummary($rootScope);

                switch(toLoad) {
                    case 'contract':
                        loadContractTemplate(quote);
                        break;
                    default:
                        $scope.qot.loadWork($scope, toLoad);
                }

                $scope.updateQuoteActions($scope, jobId, quoteId);

                if(!$rootScope.editingChanged) {
                    $rootScope.editingChanged = false;
                }

                $rootScope.loadForEdit = true;

            }

            $rootScope.$watch('editing', function() {
                editingChanged($rootScope);
            }, true);

            function editingChanged($rootScope) {
                $log.info('editingChanged loadForEdit?: ' + $rootScope.loadForEdit
                + ' editingChanged?: ' + $rootScope.editingChanged);

                if($rootScope.loadForEdit) {
                    $log.info('editingChanged resetting loadForEdit, editingChanged dont change. ');
                    $rootScope.loadForEdit = false;
                    $rootScope.editingChanged = false;
                    return;
                }

                $log.info('editingChanged editingChanged is on.');
                $rootScope.editingChanged = true;

            }

            QuoteService.loadCachedIfCurrent = function($scope, toLoad) {
                $scope.quoteId = $routeParams.quoteId;
                $scope.workIdx = $routeParams.workIdx;

                if($rootScope.currentQuoteId == $scope.quoteId) {
                    $scope.$log.info("loading from cache: " + $rootScope.editing._id +
                    ' widx:' +$scope.workIdx +
                    ' changed?: ' + $rootScope.editingChanged);

                    QuoteService.loadForEdit($scope, toLoad, $rootScope.editing);

                    return true;
                }

                return false;
            }

            var saveCurrent = function (editing, afterSave) {
                $log.info("saveCurrent:" + editing._id);
                var quote = {};
                quote = editing,
                quote.updated = new Date(),
                quote.version++;

                quote = angular.copy(quote),
                quote.works.forEach(function(i) {
                    delete i.$$hashKey;
                })

                Quotes.save(quote).then(function(result) {
                    //var quote = result.data.quote;

                    $log.info("QuoteService save finished updating:" + quote._id + ' u: ' + quote.updated);

                    $rootScope.loadForEdit = true;
                    $rootScope.editingChanged = false;
                    var quoteId = $rootScope.currentQuoteId = quote._id;
                    var jobId = quote._jobId;

                    $rootScope.updateQuoteActions($rootScope, jobId, quoteId);

                    if(afterSave !== undefined) {
                        afterSave(quote);
                    }

                });
            }

            QuoteService.saveCurrent = function(open) {
                saveCurrent($rootScope.editing, open);
            }

            QuoteService.openPrint = function(quote) {
                $location.path('print-contract/' + quote._id);
                //window.open(
                //    '#/print-contract/' + quote._id,
                //    '_blank'
                //);
//            window.open(
//              'contract.html#/contract/' + quote.id,
//              '_blank'
//            );
            }

            QuoteService.load = function($scope, toLoad) {
                $scope.$log.info("QuoteService.load : quoteId: " + $scope.quoteId +
                ' cur:' + $rootScope.currentQuoteId);

                $scope.printQuote = function() {
                    $log.info("QuoteService print save first if changed: " + $rootScope.editing._id);

                    if($rootScope.editingChanged) {
                        $log.info("editingChanged: " + $rootScope.editingChanged);
                        saveCurrent($rootScope.editing, QuoteService.openPrint);
                        return;
                    }

                    QuoteService.openPrint($rootScope.editing);
                }

                $scope.submit = function() {
                    $rootScope.editing.status = 'Submitted';
                    saveCurrent($rootScope.editing);
                };

                $scope.save = function() {
                    saveCurrent($rootScope.editing);
                };

                //load from cache and save if changed.
                if(QuoteService.loadCachedIfCurrent($scope, toLoad)) {
                    return;
                }

                $rootScope.currentQuoteId = $scope.quoteId;

                QuoteService.find($scope.quoteId).then(function(result) {
                    var quote = result.data;
                    $scope.$log.info("loading from repository... " + quote._id);
                    QuoteService.loadForEdit($scope, toLoad, quote);
                });

            }

            QuoteService.findOrCreateForItems = function($scope) {
                $scope.itemTypes = [];

                $scope.$watch('userProfile.business.itemTypes', function() {
                    $scope.userProfile.business.itemTypes.forEach(function(i) {
                        if(i != undefined) {
                            $scope.itemTypes.push(i.type)
                        }
                    });
                });

                $scope.margins = margins;

                $scope.qot.createItemGrid($scope);

                QuoteService.load($scope, 'items');

                $scope.loadWork = function(idx) {
                    $scope.$log.info("load Work items " + idx);
                    $scope.workIdx = idx;
                    $scope.work = $scope.editing.works[idx];

                    $scope.qot.initItemNumbers($scope.work, 'items');

                    $scope.newEntry = Quote.newItem($scope.work.items.length,
                        $scope.userProfile.business);
                    QuoteService.focusItem();
                }
            }

            QuoteService.focusItem = function() {
                window.setTimeout(function() {
                    $('#newItem').focus();
                },100);
            }

            QuoteService.findOrCreateForLabours = function($scope) {

                $scope.$watch('userProfile.business.chargeRates', function() {
                    $scope.labourTypes = [];
                    angular.forEach($scope.userProfile.business.chargeRates,function(i) {
                        $scope.labourTypes.push(i.labour)
                    });
                });

                $scope.qot.createLabourGrid($scope);

                QuoteService.load($scope, 'labours');

                $scope.loadWork = function(idx) {
                    $scope.$log.info("load Work labours " + idx);
                    $scope.workIdx = idx;
                    $scope.work = $scope.editing.works[idx];

                    $scope.qot.initItemNumbers($scope.work,'labours');
                    $scope.newLabourEntry =
                        Quote.newLabour($scope.work.labours.length,
                            $scope.userProfile.business);
                    QuoteService.focusItem();
                }

            }

            QuoteService.findOrCreateForPlants = function($scope) {
                $scope.margins = margins;
                $scope.qot.createPlantsGrid($scope);
                QuoteService.load($scope, 'plants');

                $scope.loadWork = function(idx) {
                    $scope.$log.info("load Work plants " + idx);
                    $scope.workIdx = idx;
                    $scope.work = $scope.editing.works[idx];
                    $scope.work.plants = Plants.sort($scope.work.plants);
                    $scope.qot.initItemNumbers($scope.work, 'plants');
                    $scope.newPlantEntry = Quote.newPlant($scope.work.plants.length,
                        $scope.userProfile.business);
                    QuoteService.focusItem();

                }

            }

            QuoteService.findOrCreateForView = function($scope) {
                QuoteService.load($scope);
            }

            QuoteService.save = function(quote) {
                var json = JSON.stringify(quote);
                $log.info('save json is ' + json);
                return $http.put(createUrl('/quotes/'+ quote._id), json);
            }

            return QuoteService;
        });

<commit_msg>format<commit_after>'use strict';

var servicesModuleQuote =
  angular.module('jobq.quote.services', ['ngResource']);
angular.module('jobq.quote.services').factory('QuoteService',
  function ($rootScope, $routeParams, $http, $log,
            Quote, $location, Quotes, Plants) {

    var QuoteService = {};
    $rootScope.quote = {};
    $rootScope.loadForEdit = true;
    $rootScope.editingChanged = false;
    //$rootScope.editing = {};

    var margins = [{"value": 0, "label": 'Margin 0%'},
      {"value": 0.1, "label": 'Margin 10%'},
      {"value": 0.15, "label": 'Margin 15%'},
      {"value": 0.2, "label": 'Margin 20%'},
      {"value": 0.25, "label": 'Margin 25%'},
      {"value": 0.3, "label": 'Margin 30%'},
      {"value": 0.35, "label": 'Margin 35%'},
      {"value": 0.4, "label": 'Margin 40%'}];

    QuoteService.find = function (quoteId) {
      $log.info('find quoteId is ' + quoteId);
      var url = createUrl('/quotes/' + quoteId);
      return $http.get(url);
    }

    QuoteService.findOrCreate = function ($scope) {
      QuoteService.load($scope);
    }

    QuoteService.findOrCreateForWorks = function ($scope) {
      QuoteService.load($scope);
    }

    QuoteService.hasContents = function (contract) {
      if (!contract.sections) {
        return false;
      }
      if (contract.sections.length == 1 && !contract.sections[0].content) {
        return false;
      }
      return true;

//            return (!contract.sections ||
//                   (contract.sections.length == 1 && !contract.sections[0]));
    }

    function loadContractTemplate(quote) {
      var c = quote.contract;
      var tempalte = $rootScope.userProfile.template;
      var changed = false;

      if (!c.dear) {
        c.dear = quote.client;
        changed = true;
      }

      if (!c.paymentIntro) {
        c.paymentIntro = tempalte.paymentIntro;
        changed = true;
      }

      if (!c.payments) {
        c.payments = tempalte.payments;
        changed = true;
      }

      if (!c.intro) {
        c.intro = tempalte.intro;
        changed = true;
      }

      if (!QuoteService.hasContents(c)) {
        c.sections = tempalte.sections;
        changed = true;
      }
      return changed;
    }

    QuoteService.updateStatus = function (quote, job) {
      quote.status = job.status;
      quote.updated = job.updated;
      quote.version = job.version;

      return quote;
    }

    QuoteService.updateQuoteStatus = function (job) {
      $log.info('updateQuoteStatus: ' + job.status);
      QuoteService.updateStatus($rootScope.quote, job);

      //QuoteService.updateStatus($rootScope.editing, job);

      $rootScope.loadForEdit = true;
    }

    QuoteService.loadForEdit = function ($scope, toLoad, quote) {
      $log.info('loadForEdit start: ' + toLoad);

      $rootScope.editing = quote;
      $rootScope.quote = $rootScope.editing;
      var quoteId = $rootScope.quoteId = $rootScope.editing._id;
      var jobId = $rootScope.editing._jobId;

      if ($scope.workIdx == undefined) {
        $scope.workIdx = 0;
      }

      if (!$rootScope.editing.status) {
        $rootScope.editing.status = 'Preparing';
        $rootScope.quoteFinalised = false;
      }

      if ($rootScope.editing.status == 'Submitted') {
        $rootScope.quoteFinalised = true;
      }

      Quote.updateSummary($rootScope);

      switch (toLoad) {
        case 'contract':
          loadContractTemplate(quote);
          break;
        default:
          $scope.qot.loadWork($scope, toLoad);
      }

      $scope.updateQuoteActions($scope, jobId, quoteId);

      if (!$rootScope.editingChanged) {
        $rootScope.editingChanged = false;
      }

      $rootScope.loadForEdit = true;

    }

    $rootScope.$watch('editing', function () {
      editingChanged($rootScope);
    }, true);

    function editingChanged($rootScope) {
      $log.info('editingChanged loadForEdit?: ' + $rootScope.loadForEdit
      + ' editingChanged?: ' + $rootScope.editingChanged);

      if ($rootScope.loadForEdit) {
        $log.info('editingChanged resetting loadForEdit, editingChanged dont change. ');
        $rootScope.loadForEdit = false;
        $rootScope.editingChanged = false;
        return;
      }

      $log.info('editingChanged editingChanged is on.');
      $rootScope.editingChanged = true;

    }

    QuoteService.loadCachedIfCurrent = function ($scope, toLoad) {
      $scope.quoteId = $routeParams.quoteId;
      $scope.workIdx = $routeParams.workIdx;

      if ($rootScope.currentQuoteId == $scope.quoteId) {
        $scope.$log.info("loading from cache: " + $rootScope.editing._id +
        ' widx:' + $scope.workIdx +
        ' changed?: ' + $rootScope.editingChanged);

        QuoteService.loadForEdit($scope, toLoad, $rootScope.editing);

        return true;
      }

      return false;
    }

    var saveCurrent = function (editing, afterSave) {
      $log.info("saveCurrent:" + editing._id);
      var quote = {};
      quote = editing,
        quote.updated = new Date(),
        quote.version++;

      quote = angular.copy(quote),
        quote.works.forEach(function (i) {
          delete i.$$hashKey;
        })

      Quotes.save(quote).then(function (result) {
        //var quote = result.data.quote;

        $log.info("QuoteService save finished updating:" + quote._id + ' u: ' + quote.updated);

        $rootScope.loadForEdit = true;
        $rootScope.editingChanged = false;
        var quoteId = $rootScope.currentQuoteId = quote._id;
        var jobId = quote._jobId;

        $rootScope.updateQuoteActions($rootScope, jobId, quoteId);

        if (afterSave !== undefined) {
          afterSave(quote);
        }

      });
    }

    QuoteService.saveCurrent = function (open) {
      saveCurrent($rootScope.editing, open);
    }

    QuoteService.openPrint = function (quote) {
      $location.path('print-contract/' + quote._id);
      //window.open(
      //    '#/print-contract/' + quote._id,
      //    '_blank'
      //);
//            window.open(
//              'contract.html#/contract/' + quote.id,
//              '_blank'
//            );
    }

    QuoteService.load = function ($scope, toLoad) {
      $scope.$log.info("QuoteService.load : quoteId: " + $scope.quoteId +
      ' cur:' + $rootScope.currentQuoteId);

      $scope.printQuote = function () {
        $log.info("QuoteService print save first if changed: " + $rootScope.editing._id);

        if ($rootScope.editingChanged) {
          $log.info("editingChanged: " + $rootScope.editingChanged);
          saveCurrent($rootScope.editing, QuoteService.openPrint);
          return;
        }

        QuoteService.openPrint($rootScope.editing);
      }

      $scope.submit = function () {
        $rootScope.editing.status = 'Submitted';
        saveCurrent($rootScope.editing);
      };

      $scope.save = function () {
        saveCurrent($rootScope.editing);
      };

      //load from cache and save if changed.
      if (QuoteService.loadCachedIfCurrent($scope, toLoad)) {
        return;
      }

      $rootScope.currentQuoteId = $scope.quoteId;

      QuoteService.find($scope.quoteId).then(function (result) {
        var quote = result.data;
        $scope.$log.info("loading from repository... " + quote._id);
        QuoteService.loadForEdit($scope, toLoad, quote);
      });

    }

    QuoteService.findOrCreateForItems = function ($scope) {
      $scope.itemTypes = [];

      $scope.$watch('userProfile.business.itemTypes', function () {
        $scope.userProfile.business.itemTypes.forEach(function (i) {
          if (i != undefined) {
            $scope.itemTypes.push(i.type)
          }
        });
      });

      $scope.margins = margins;

      $scope.qot.createItemGrid($scope);

      QuoteService.load($scope, 'items');

      $scope.loadWork = function (idx) {
        $scope.$log.info("load Work items " + idx);
        $scope.workIdx = idx;
        $scope.work = $scope.editing.works[idx];

        $scope.qot.initItemNumbers($scope.work, 'items');

        $scope.newEntry = Quote.newItem($scope.work.items.length,
          $scope.userProfile.business);
        QuoteService.focusItem();
      }
    }

    QuoteService.focusItem = function () {
      window.setTimeout(function () {
        $('#newItem').focus();
      }, 100);
    }

    QuoteService.findOrCreateForLabours = function ($scope) {

      $scope.$watch('userProfile.business.chargeRates', function () {
        $scope.labourTypes = [];
        angular.forEach($scope.userProfile.business.chargeRates, function (i) {
          $scope.labourTypes.push(i.labour)
        });
      });

      $scope.qot.createLabourGrid($scope);

      QuoteService.load($scope, 'labours');

      $scope.loadWork = function (idx) {
        $scope.$log.info("load Work labours " + idx);
        $scope.workIdx = idx;
        $scope.work = $scope.editing.works[idx];

        $scope.qot.initItemNumbers($scope.work, 'labours');
        $scope.newLabourEntry =
          Quote.newLabour($scope.work.labours.length,
            $scope.userProfile.business);
        QuoteService.focusItem();
      }

    }

    QuoteService.findOrCreateForPlants = function ($scope) {
      $scope.margins = margins;
      $scope.qot.createPlantsGrid($scope);
      QuoteService.load($scope, 'plants');

      $scope.loadWork = function (idx) {
        $scope.$log.info("load Work plants " + idx);
        $scope.workIdx = idx;
        $scope.work = $scope.editing.works[idx];
        $scope.work.plants = Plants.sort($scope.work.plants);
        $scope.qot.initItemNumbers($scope.work, 'plants');
        $scope.newPlantEntry = Quote.newPlant($scope.work.plants.length,
          $scope.userProfile.business);
        QuoteService.focusItem();

      }

    }

    QuoteService.findOrCreateForView = function ($scope) {
      QuoteService.load($scope);
    }

    QuoteService.save = function (quote) {
      var json = JSON.stringify(quote);
      $log.info('save json is ' + json);
      return $http.put(createUrl('/quotes/' + quote._id), json);
    }

    return QuoteService;
  });

<|endoftext|>


<commit_before>import bip39 from 'bip39'
import { decrypt } from './encryption-utils'
import { HDNode } from 'bitcoinjs-lib'
import crypto from 'crypto'
import log4js from 'log4js'

const logger = log4js.getLogger('utils/account-utils.js')

function hashCode(string) {
  let hash = 0
  if (string.length === 0) return hash
  for (let i = 0; i < string.length; i++) {
    const character = string.charCodeAt(i)
    hash = ((hash << 5) - hash) + character
    hash = hash & hash
  }
  return hash & 0x7fffffff
}

const APPS_NODE_INDEX = 0
const SIGNING_NODE_INDEX = 1
const ENCRYPTION_NODE_INDEX = 2
export const MAX_TRUST_LEVEL = 99

export class AppNode {
  constructor(hdNode, appDomain) {
    this.hdNode = hdNode
    this.appDomain = appDomain
  }

  getAppPrivateKey() {
    return this.hdNode.keyPair.d.toBuffer(32).toString('hex')
  }

  getAddress() {
    return this.hdNode.getAddress()
  }
}

export class AppsNode {
  constructor(appsHdNode, salt) {
    this.hdNode = appsHdNode
    this.salt = salt
  }

  getNode() {
    return this.hdNode
  }

  getAppNode(appDomain) {
    const hash = crypto.createHash('sha256').update(`${appDomain}${this.salt}`).digest('hex')
    const appIndex = hashCode(hash)
    const appNode = this.hdNode.deriveHardened(appIndex)
    return new AppNode(appNode, appDomain)
  }

  toBase58() {
    return this.hdNode.toBase58()
  }

  getSalt() {
    return this.salt
  }
}

class IdentityAddressOwnerNode {
  constructor(ownerHdNode, salt) {
    this.hdNode = ownerHdNode
    this.salt = salt
  }

  getNode() {
    return this.hdNode
  }

  getSalt() {
    return this.salt
  }

  getIdentityKey() {
    return this.hdNode.keyPair.d.toBuffer(32).toString('hex')
  }

  getIdentityKeyID() {
    return this.hdNode.keyPair.getPublicKeyBuffer().toString('hex')
  }

  getAppsNode() {
    return new AppsNode(this.hdNode.deriveHardened(APPS_NODE_INDEX), this.salt)
  }

  getAddress() {
    return this.hdNode.getAddress()
  }

  getEncryptionNode() {
    return this.hdNode.deriveHardened(ENCRYPTION_NODE_INDEX)
  }

  getSigningNode() {
    return this.hdNode.deriveHardened(SIGNING_NODE_INDEX)
  }
}

export function isPasswordValid(password) {
  let isValid = false
  let error = null

  if (password.length >= 8) {
    isValid = true
    error = 'Password must be at least 8 characters'
  }

  return { isValid, error }
}

export function isBackupPhraseValid(backupPhrase) {
  let isValid = true
  let error = null

  if (!bip39.validateMnemonic(backupPhrase)) {
    isValid = false
    error = 'Backup phrase is not a valid set of words'
  }

  return { isValid, error }
}

export function decryptMasterKeychain(password, encryptedBackupPhrase) {
  return new Promise((resolve, reject) => {
    const dataBuffer = new Buffer(encryptedBackupPhrase, 'hex')
    decrypt(dataBuffer, password)
    .then((plaintextBuffer) => {
      const backupPhrase = plaintextBuffer.toString()
      const seed = bip39.mnemonicToSeed(backupPhrase)
      const masterKeychain = HDNode.fromSeedBuffer(seed)
      logger.trace('decryptMasterKeychain: decrypted!')
      resolve(masterKeychain)
    }, (error) => {
      logger.error('decryptMasterKeychain: error', error)
      reject('Incorrect password')
    })
  })
}

const EXTERNAL_ADDRESS = 'EXTERNAL_ADDRESS'
const CHANGE_ADDRESS = 'CHANGE_ADDRESS'

export function getBitcoinPrivateKeychain(masterKeychain) {
  const BIP_44_PURPOSE = 44
  const BITCOIN_COIN_TYPE = 0
  const ACCOUNT_INDEX = 0

  return masterKeychain.deriveHardened(BIP_44_PURPOSE)
  .deriveHardened(BITCOIN_COIN_TYPE)
  .deriveHardened(ACCOUNT_INDEX)
}

export function getBitcoinPublicKeychain(masterKeychain) {
  return getBitcoinPrivateKeychain(masterKeychain).neutered()
}

export function getBitcoinAddressNode(bitcoinKeychain,
  addressIndex = 0, chainType = EXTERNAL_ADDRESS) {
  let chain = null

  if (chainType === EXTERNAL_ADDRESS) {
    chain = 0
  } else if (chainType === CHANGE_ADDRESS) {
    chain = 1
  } else {
    throw new Error('Invalid chain type')
  }

  return bitcoinKeychain.derive(chain).derive(addressIndex)
}

export function decryptBitcoinPrivateKey(password, encryptedBackupPhrase) {
  return new Promise((resolve, reject) =>
     decryptMasterKeychain(password, encryptedBackupPhrase)
    .then((masterKeychain) => {
      const bitcoinPrivateKeychain = getBitcoinPrivateKeychain(masterKeychain)
      const bitcoinAddressHDNode = getBitcoinAddressNode(bitcoinPrivateKeychain, 0)
      const privateKey = bitcoinAddressHDNode.keyPair.d.toBuffer(32).toString('hex')
      resolve(privateKey)
    })
    .catch((error) => {
      reject(error)
    }))
}

const IDENTITY_KEYCHAIN = 888
const BLOCKSTACK_ON_BITCOIN = 0
export function getIdentityPrivateKeychain(masterKeychain) {
  return masterKeychain.deriveHardened(IDENTITY_KEYCHAIN)
  .deriveHardened(BLOCKSTACK_ON_BITCOIN)
}

export function getIdentityPublicKeychain(masterKeychain) {
  return getIdentityPrivateKeychain(masterKeychain).neutered()
}

export function getIdentityOwnerAddressNode(identityPrivateKeychain, identityIndex = 0) {
  if (identityPrivateKeychain.isNeutered()) {
    throw new Error('You need the private key to generate identity addresses')
  }

  const publicKeyHex = identityPrivateKeychain.keyPair.getPublicKeyBuffer().toString('hex')
  const salt = crypto.createHash('sha256').update(publicKeyHex).digest('hex')

  return new IdentityAddressOwnerNode(identityPrivateKeychain.deriveHardened(identityIndex), salt)
}

export function deriveIdentityKeyPair(identityOwnerAddressNode) {
  const address = identityOwnerAddressNode.getAddress()
  const identityKey = identityOwnerAddressNode.getIdentityKey()
  const identityKeyID = identityOwnerAddressNode.getIdentityKeyID()
  const appsNode = identityOwnerAddressNode.getAppsNode()
  const keyPair = {
    key: identityKey,
    keyID: identityKeyID,
    address,
    appsNodeKey: appsNode.toBase58(),
    salt: appsNode.getSalt()
  }
  return keyPair
}

export function getWebAccountTypes(api) {
  const webAccountTypes = {
    twitter: {
      label: 'Twitter', iconClass: 'fa-twitter', social: true,
      urlTemplate: 'https://twitter.com/{identifier}'
    },
    facebook: {
      label: 'Facebook', iconClass: 'fa-facebook', social: true,
      urlTemplate: 'https://facebook.com/{identifier}'
    },
    github: {
      label: 'GitHub', iconClass: 'fa-github-alt', social: true,
      urlTemplate: 'https://github.com/{identifier}'
    },
    instagram: {
      label: 'Instagram', iconClass: 'fa-instagram', social: true,
      urlTemplate: 'https://instagram.com/{identifier}'
    },
    linkedIn: {
      label: 'LinkedIn', iconClass: 'fa-linkedin', social: true,
      urlTemplate: 'https://www.linkedin.com/in/{identifier}'
    },
    tumblr: {
      label: 'Tumblr', iconClass: 'fa-tumblr', social: true,
      urlTemplate: 'http://{identifier}.tumblr.com'
    },
    reddit: {
      label: 'Reddit', iconClass: 'fa-reddit-alien', social: true,
      urlTemplate: 'https://www.reddit.com/user/{identifier}'
    },
    pinterest: {
      label: 'Pinterest', iconClass: 'fa-pinterest', social: true,
      urlTemplate: 'https://pinterest.com/{identifier}'
    },
    youtube: {
      label: 'YouTube', iconClass: 'fa-youtube', social: true,
      urlTemplate: 'https://www.youtube.com/channel/{identifier}'
    },
    'google-plus': {
      label: 'Google+', iconClass: 'fa-google-plus', social: true,
      urlTemplate: 'https://plus.google.com/u/{identifier}'
    },
    angellist: {
      label: 'AngelList', iconClass: 'fa-angellist', social: true,
      urlTemplate: 'https://angel.co/{identifier}'
    },
    'stack-overflow': {
      label: 'StackOverflow', iconClass: 'fa-stack-overflow', social: true,
      urlTemplate: 'http://stackoverflow.com/users/{identifier}'
    },
    hackerNews: {
      label: 'Hacker News', iconClass: 'fa-hacker-news', social: true,
      urlTemplate: 'https://news.ycombinator.com/user?id={identifier}'
    },
    openbazaar: {
      label: 'OpenBazaar', iconClass: 'fa-shopping-cart', social: true,
      urlTemplate: 'ob://{identifier}'
    },
    snapchat: {
      label: 'Snapchat', iconClass: 'fa-snapchat-ghost', social: true,
      urlTemplate: 'https://snapchat.com/add/{identifier}'
    },
    website: {
      label: 'Website', iconClass: 'fa-link', social: false,
      urlTemplate: '{identifier}'
    },
    ssh: {
      label: 'SSH', iconClass: 'fa-key', social: false
    },
    pgp: {
      label: 'PGP', iconClass: 'fa-key', social: false
    },
    bitcoin: {
      label: 'Bitcoin', iconClass: 'fa-bitcoin', social: false,
      urlTemplate: api.bitcoinAddressUrl
    },
    ethereum: {
      label: 'Ethereum', iconClass: 'fa-key', social: false,
      urlTemplate: api.ethereumAddressUrl
    }
  }
  return webAccountTypes
}

export function calculateTrustLevel(verifications) {
  if (!verifications || verifications.length < 1) {
    return 0
  }

  let trustLevel = 0
  verifications.forEach(verification => {
    if (verification.valid && trustLevel < MAX_TRUST_LEVEL) {
      trustLevel++
    }
  })

  return trustLevel
}

export function calculateProfileCompleteness(profile, verifications) {
  let complete = 0
  const totalItems = 2
  const maxVerificationItems = 1

  if (profile.name && profile.name.length > 0) {
    complete++
  }

  if (profile.description && profile.description.length > 0) {
    complete++
  }

  if (profile.image && profile.image.length > 0) {
    complete++
  }

  complete += Math.min(calculateTrustLevel(verifications), maxVerificationItems)

  return complete / totalItems
}

export function findAddressIndex(address, identityAddresses) {
  for (let i = 0; i < identityAddresses.length; i++) {
    if (identityAddresses[i] === address) {
      return i
    }
  }
  return null
}
<commit_msg>Fix profile complete percentage calculation.<commit_after>import bip39 from 'bip39'
import { decrypt } from './encryption-utils'
import { HDNode } from 'bitcoinjs-lib'
import crypto from 'crypto'
import log4js from 'log4js'

const logger = log4js.getLogger('utils/account-utils.js')

function hashCode(string) {
  let hash = 0
  if (string.length === 0) return hash
  for (let i = 0; i < string.length; i++) {
    const character = string.charCodeAt(i)
    hash = ((hash << 5) - hash) + character
    hash = hash & hash
  }
  return hash & 0x7fffffff
}

const APPS_NODE_INDEX = 0
const SIGNING_NODE_INDEX = 1
const ENCRYPTION_NODE_INDEX = 2
export const MAX_TRUST_LEVEL = 99

export class AppNode {
  constructor(hdNode, appDomain) {
    this.hdNode = hdNode
    this.appDomain = appDomain
  }

  getAppPrivateKey() {
    return this.hdNode.keyPair.d.toBuffer(32).toString('hex')
  }

  getAddress() {
    return this.hdNode.getAddress()
  }
}

export class AppsNode {
  constructor(appsHdNode, salt) {
    this.hdNode = appsHdNode
    this.salt = salt
  }

  getNode() {
    return this.hdNode
  }

  getAppNode(appDomain) {
    const hash = crypto.createHash('sha256').update(`${appDomain}${this.salt}`).digest('hex')
    const appIndex = hashCode(hash)
    const appNode = this.hdNode.deriveHardened(appIndex)
    return new AppNode(appNode, appDomain)
  }

  toBase58() {
    return this.hdNode.toBase58()
  }

  getSalt() {
    return this.salt
  }
}

class IdentityAddressOwnerNode {
  constructor(ownerHdNode, salt) {
    this.hdNode = ownerHdNode
    this.salt = salt
  }

  getNode() {
    return this.hdNode
  }

  getSalt() {
    return this.salt
  }

  getIdentityKey() {
    return this.hdNode.keyPair.d.toBuffer(32).toString('hex')
  }

  getIdentityKeyID() {
    return this.hdNode.keyPair.getPublicKeyBuffer().toString('hex')
  }

  getAppsNode() {
    return new AppsNode(this.hdNode.deriveHardened(APPS_NODE_INDEX), this.salt)
  }

  getAddress() {
    return this.hdNode.getAddress()
  }

  getEncryptionNode() {
    return this.hdNode.deriveHardened(ENCRYPTION_NODE_INDEX)
  }

  getSigningNode() {
    return this.hdNode.deriveHardened(SIGNING_NODE_INDEX)
  }
}

export function isPasswordValid(password) {
  let isValid = false
  let error = null

  if (password.length >= 8) {
    isValid = true
    error = 'Password must be at least 8 characters'
  }

  return { isValid, error }
}

export function isBackupPhraseValid(backupPhrase) {
  let isValid = true
  let error = null

  if (!bip39.validateMnemonic(backupPhrase)) {
    isValid = false
    error = 'Backup phrase is not a valid set of words'
  }

  return { isValid, error }
}

export function decryptMasterKeychain(password, encryptedBackupPhrase) {
  return new Promise((resolve, reject) => {
    const dataBuffer = new Buffer(encryptedBackupPhrase, 'hex')
    decrypt(dataBuffer, password)
    .then((plaintextBuffer) => {
      const backupPhrase = plaintextBuffer.toString()
      const seed = bip39.mnemonicToSeed(backupPhrase)
      const masterKeychain = HDNode.fromSeedBuffer(seed)
      logger.trace('decryptMasterKeychain: decrypted!')
      resolve(masterKeychain)
    }, (error) => {
      logger.error('decryptMasterKeychain: error', error)
      reject('Incorrect password')
    })
  })
}

const EXTERNAL_ADDRESS = 'EXTERNAL_ADDRESS'
const CHANGE_ADDRESS = 'CHANGE_ADDRESS'

export function getBitcoinPrivateKeychain(masterKeychain) {
  const BIP_44_PURPOSE = 44
  const BITCOIN_COIN_TYPE = 0
  const ACCOUNT_INDEX = 0

  return masterKeychain.deriveHardened(BIP_44_PURPOSE)
  .deriveHardened(BITCOIN_COIN_TYPE)
  .deriveHardened(ACCOUNT_INDEX)
}

export function getBitcoinPublicKeychain(masterKeychain) {
  return getBitcoinPrivateKeychain(masterKeychain).neutered()
}

export function getBitcoinAddressNode(bitcoinKeychain,
  addressIndex = 0, chainType = EXTERNAL_ADDRESS) {
  let chain = null

  if (chainType === EXTERNAL_ADDRESS) {
    chain = 0
  } else if (chainType === CHANGE_ADDRESS) {
    chain = 1
  } else {
    throw new Error('Invalid chain type')
  }

  return bitcoinKeychain.derive(chain).derive(addressIndex)
}

export function decryptBitcoinPrivateKey(password, encryptedBackupPhrase) {
  return new Promise((resolve, reject) =>
     decryptMasterKeychain(password, encryptedBackupPhrase)
    .then((masterKeychain) => {
      const bitcoinPrivateKeychain = getBitcoinPrivateKeychain(masterKeychain)
      const bitcoinAddressHDNode = getBitcoinAddressNode(bitcoinPrivateKeychain, 0)
      const privateKey = bitcoinAddressHDNode.keyPair.d.toBuffer(32).toString('hex')
      resolve(privateKey)
    })
    .catch((error) => {
      reject(error)
    }))
}

const IDENTITY_KEYCHAIN = 888
const BLOCKSTACK_ON_BITCOIN = 0
export function getIdentityPrivateKeychain(masterKeychain) {
  return masterKeychain.deriveHardened(IDENTITY_KEYCHAIN)
  .deriveHardened(BLOCKSTACK_ON_BITCOIN)
}

export function getIdentityPublicKeychain(masterKeychain) {
  return getIdentityPrivateKeychain(masterKeychain).neutered()
}

export function getIdentityOwnerAddressNode(identityPrivateKeychain, identityIndex = 0) {
  if (identityPrivateKeychain.isNeutered()) {
    throw new Error('You need the private key to generate identity addresses')
  }

  const publicKeyHex = identityPrivateKeychain.keyPair.getPublicKeyBuffer().toString('hex')
  const salt = crypto.createHash('sha256').update(publicKeyHex).digest('hex')

  return new IdentityAddressOwnerNode(identityPrivateKeychain.deriveHardened(identityIndex), salt)
}

export function deriveIdentityKeyPair(identityOwnerAddressNode) {
  const address = identityOwnerAddressNode.getAddress()
  const identityKey = identityOwnerAddressNode.getIdentityKey()
  const identityKeyID = identityOwnerAddressNode.getIdentityKeyID()
  const appsNode = identityOwnerAddressNode.getAppsNode()
  const keyPair = {
    key: identityKey,
    keyID: identityKeyID,
    address,
    appsNodeKey: appsNode.toBase58(),
    salt: appsNode.getSalt()
  }
  return keyPair
}

export function getWebAccountTypes(api) {
  const webAccountTypes = {
    twitter: {
      label: 'Twitter', iconClass: 'fa-twitter', social: true,
      urlTemplate: 'https://twitter.com/{identifier}'
    },
    facebook: {
      label: 'Facebook', iconClass: 'fa-facebook', social: true,
      urlTemplate: 'https://facebook.com/{identifier}'
    },
    github: {
      label: 'GitHub', iconClass: 'fa-github-alt', social: true,
      urlTemplate: 'https://github.com/{identifier}'
    },
    instagram: {
      label: 'Instagram', iconClass: 'fa-instagram', social: true,
      urlTemplate: 'https://instagram.com/{identifier}'
    },
    linkedIn: {
      label: 'LinkedIn', iconClass: 'fa-linkedin', social: true,
      urlTemplate: 'https://www.linkedin.com/in/{identifier}'
    },
    tumblr: {
      label: 'Tumblr', iconClass: 'fa-tumblr', social: true,
      urlTemplate: 'http://{identifier}.tumblr.com'
    },
    reddit: {
      label: 'Reddit', iconClass: 'fa-reddit-alien', social: true,
      urlTemplate: 'https://www.reddit.com/user/{identifier}'
    },
    pinterest: {
      label: 'Pinterest', iconClass: 'fa-pinterest', social: true,
      urlTemplate: 'https://pinterest.com/{identifier}'
    },
    youtube: {
      label: 'YouTube', iconClass: 'fa-youtube', social: true,
      urlTemplate: 'https://www.youtube.com/channel/{identifier}'
    },
    'google-plus': {
      label: 'Google+', iconClass: 'fa-google-plus', social: true,
      urlTemplate: 'https://plus.google.com/u/{identifier}'
    },
    angellist: {
      label: 'AngelList', iconClass: 'fa-angellist', social: true,
      urlTemplate: 'https://angel.co/{identifier}'
    },
    'stack-overflow': {
      label: 'StackOverflow', iconClass: 'fa-stack-overflow', social: true,
      urlTemplate: 'http://stackoverflow.com/users/{identifier}'
    },
    hackerNews: {
      label: 'Hacker News', iconClass: 'fa-hacker-news', social: true,
      urlTemplate: 'https://news.ycombinator.com/user?id={identifier}'
    },
    openbazaar: {
      label: 'OpenBazaar', iconClass: 'fa-shopping-cart', social: true,
      urlTemplate: 'ob://{identifier}'
    },
    snapchat: {
      label: 'Snapchat', iconClass: 'fa-snapchat-ghost', social: true,
      urlTemplate: 'https://snapchat.com/add/{identifier}'
    },
    website: {
      label: 'Website', iconClass: 'fa-link', social: false,
      urlTemplate: '{identifier}'
    },
    ssh: {
      label: 'SSH', iconClass: 'fa-key', social: false
    },
    pgp: {
      label: 'PGP', iconClass: 'fa-key', social: false
    },
    bitcoin: {
      label: 'Bitcoin', iconClass: 'fa-bitcoin', social: false,
      urlTemplate: api.bitcoinAddressUrl
    },
    ethereum: {
      label: 'Ethereum', iconClass: 'fa-key', social: false,
      urlTemplate: api.ethereumAddressUrl
    }
  }
  return webAccountTypes
}

export function calculateTrustLevel(verifications) {
  if (!verifications || verifications.length < 1) {
    return 0
  }

  let trustLevel = 0
  verifications.forEach(verification => {
    if (verification.valid && trustLevel < MAX_TRUST_LEVEL) {
      trustLevel++
    }
  })

  return trustLevel
}

export function calculateProfileCompleteness(profile, verifications) {
  let complete = 0
  const totalItems = 2
  const maxVerificationItems = 1

  if (profile.name && profile.name.length > 0) {
    complete++
  }

  // if (profile.description && profile.description.length > 0) {
  //   complete++
  // }

  // if (profile.image && profile.image.length > 0) {
  //   complete++
  // }

  complete += Math.min(calculateTrustLevel(verifications), maxVerificationItems)

  return complete / totalItems
}

export function findAddressIndex(address, identityAddresses) {
  for (let i = 0; i < identityAddresses.length; i++) {
    if (identityAddresses[i] === address) {
      return i
    }
  }
  return null
}
<|endoftext|>


<commit_before>function aasubmit(){
  var sEmail = document.getElementById("email");
  var sPass = document.getElementById("pass");
  firebase.auth().createUserWithEmailAndPassword(sEmail.value, sPass.value).catch(function(error) {
    // Handle Errors here.
    var errorCode = error.code;
    var errorMessage = error.message;
    alert("Error " + errorCode + ": " + errorMessage)
  });
}

firebase.auth().onAuthStateChanged(function(user){
  if (user) {
    var users = firebase.database().ref().child("users").push()
    users.child(firebase.auth().currentUser.uid).push()
    firebase.auth().signOut();
    window.location.href = "index.html"
    window.location.reload()
  }
})
<commit_msg>fixed<commit_after>function aasubmit(){
  var sEmail = document.getElementById("email");
  var sPass = document.getElementById("pass");
  firebase.auth().createUserWithEmailAndPassword(sEmail.value, sPass.value).catch(function(error) {
    // Handle Errors here.
    var errorCode = error.code;
    var errorMessage = error.message;
    alert("Error " + errorCode + ": " + errorMessage)
  });
}

firebase.auth().onAuthStateChanged(function(user){
  if (user) {
    window.location.href = "index.html"
  }
})
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'

import { InputGroup } from '../../components/index'

class ExportPage extends Component {
  constructor() {
    super()
  }

  render() {
    return (

Export Identity

Export your identity to another address.

          <InputGroup label="Recipient address" placeholder="Recipient address" />

            <button className="btn btn-primary">Send</button>

    )
  }
}

export default ExportPage<commit_msg>update to export page<commit_after>import React, { Component, PropTypes } from 'react'

import { PageHeader } from '../../components/index'
import { InputGroup } from '../../components/index'

class ExportPage extends Component {
  constructor() {
    super()
  }

  render() {
    return (

        <PageHeader title="Export" />

Export Identity

Export your identity to another address.

            <InputGroup label="Recipient address" placeholder="Recipient address" />

              <button className="btn btn-primary">Send</button>

    )
  }
}

export default ExportPage<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2014 Jonas Finnemann Jensen
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

var uuid = require('uuid');

/** Encode uuid as a short 22 byte slug */
exports.encode = function(uuid_) {
  var bytes   = uuid.parse(uuid_);
  var base64  = (new Buffer(bytes)).toString('base64');
  var slug = base64
              .replace(/\+/g, '-')  // Replace + with - (see RFC 4648, sec. 5)
              .replace(/\//g, '_')  // Replace / with _ (see RFC 4648, sec. 5)
              .substring(0, 22);    // Drop '==' padding
  return slug;
};

/** Decode 22 byte slug to uuid */
exports.decode = function(slug) {
  var base64 = slug
                  .replace(/-/g, '+')
                  .replace(/_/g, '/')
                  + '==';
  return uuid.unparse(new Buffer(base64, 'base64'));
};

/** Generate a v4 (random) uuid and encode it to a slug */
exports.v4 = function() {
  do {
    var bytes   = uuid.v4(null, new Buffer(16));
    var base64  = bytes.toString('base64');
  } while (base64.substring(0, 1) == "+");
  var slug = base64
              .replace(/\+/g, '-')  // Replace + with - (see RFC 4648, sec. 5)
              .replace(/\//g, '_')  // Replace / with _ (see RFC 4648, sec. 5)
              .substring(0, 22);    // Drop '==' padding
  return slug;
};
<commit_msg>improved function comments<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2014 Jonas Finnemann Jensen
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

var uuid = require('uuid');

/** Returns the given uuid as a 22 character slug, potentially with leading `-`
 * character. It is recommended to generate slugs using v4() function which
 * guarantees that the returned slug will not lead with the `-` character,
 * which can be dangerous if used as a command line argument. */
exports.encode = function(uuid_) {
  var bytes   = uuid.parse(uuid_);
  var base64  = (new Buffer(bytes)).toString('base64');
  var slug = base64
              .replace(/\+/g, '-')  // Replace + with - (see RFC 4648, sec. 5)
              .replace(/\//g, '_')  // Replace / with _ (see RFC 4648, sec. 5)
              .substring(0, 22);    // Drop '==' padding
  return slug;
};

/** Returns the uuid represented by the given slug. Slugs with leading `-` are
 * allowed but not recommended, in order to be backwardly compatible. */
exports.decode = function(slug) {
  var base64 = slug
                  .replace(/-/g, '+')
                  .replace(/_/g, '/')
                  + '==';
  return uuid.unparse(new Buffer(base64, 'base64'));
};

/** Returns a randomly generated uuid v4 complaint slug guaranteed not to have
 * a leading `-` character */
exports.v4 = function() {
  do {
    var bytes   = uuid.v4(null, new Buffer(16));
    var base64  = bytes.toString('base64');
  } while (/^\+/.test(base64));  // disallow leading '-' ('+' => '-' below)
  var slug = base64
              .replace(/\+/g, '-')  // Replace + with - (see RFC 4648, sec. 5)
              .replace(/\//g, '_')  // Replace / with _ (see RFC 4648, sec. 5)
              .substring(0, 22);    // Drop '==' padding
  return slug;
};
<|endoftext|>


<commit_before>var Queue = require('bull');
var Promise = require('bluebird');

/**
  Adds a job to the queue.
  @method add
  @param data: {} Custom data to store for this job. Should be JSON serializable.
  @param opts: JobOptions Options for this job.
*/
Queue.prototype.add = function (data, opts) {
    var _this = this;
    opts = opts || {};

    // If we fail after incrementing the job id we may end having an unused
    // id, but this should not be so harmful
    return _this.client.incrAsync(this.toKey('id')).then(function (jobId) {
        return Job.create(_this, jobId, data, opts).then(function (job) {
            var key = _this.toKey('wait');
            var channel = _this.toKey("jobs");
            var multi = _this.client.multi();
            multi[(opts.lifo ? 'r' : 'l') + 'push'](key, jobId);
            multi.publish(channel, jobId);
            // if queue is LIFO use rpushAsync
            return multi.execAsync().then(function () {
                return job;
            });
        });
    });
}

var q = new Queue(process.argv[2], 6379, "localhost");
var times = parseInt(process.argv[3]);
console.log("adding " + times + " job to queue " + process.argv[2]);
var promisses = [];
for (var i = 0; i < times; i++) {
    promisses.push(q.add({ value: "test" }));
}
Promise.all(promisses).then(function (item) {
	q.count().then(function(c) {
		console.log("done: " + item);
		console.log("q length: " + c);
		process.exit(0);
	});
});<commit_msg>require Job<commit_after>var Queue = require('bull');
var Job = require('./node_modules/bull/lib/job');
var Promise = require('bluebird');

/**
  Adds a job to the queue.
  @method add
  @param data: {} Custom data to store for this job. Should be JSON serializable.
  @param opts: JobOptions Options for this job.
*/
Queue.prototype.add = function (data, opts) {
    var _this = this;
    opts = opts || {};

    // If we fail after incrementing the job id we may end having an unused
    // id, but this should not be so harmful
    return _this.client.incrAsync(this.toKey('id')).then(function (jobId) {
        return Job.create(_this, jobId, data, opts).then(function (job) {
            var key = _this.toKey('wait');
            var channel = _this.toKey("jobs");
            var multi = _this.client.multi();
            multi[(opts.lifo ? 'r' : 'l') + 'push'](key, jobId);
            multi.publish(channel, jobId);
            // if queue is LIFO use rpushAsync
            return multi.execAsync().then(function () {
                return job;
            });
        });
    });
}

var q = new Queue(process.argv[2], 6379, "localhost");
var times = parseInt(process.argv[3]);
console.log("adding " + times + " job to queue " + process.argv[2]);
var promisses = [];
for (var i = 0; i < times; i++) {
    promisses.push(q.add({ value: "test" }));
}
Promise.all(promisses).then(function (item) {
	q.count().then(function(c) {
		console.log("done: " + item);
		console.log("q length: " + c);
		process.exit(0);
	});
});<|endoftext|>


<commit_before>enyo.kind({
	name: "moon.sample.DatePickerSample",
	kind: "FittableRows",
	classes: "moon enyo-unselectable enyo-fit",
	components: [
		{kind: 'moon.Scroller', fit: true, components: [
			{classes: "moon-7h", components: [
				{kind: "moon.DatePicker", name:"picker", noneText: "Pick a Date", content: "Date", onChange: "changed"},
				{kind: "moon.DatePicker", name:"disabledPicker", disabled: true, noneText: "Disabled Date Picker", content: "Disabled Date"},
				{name: "localePicker", kind: "moon.ExpandablePicker", noneText: "No Locale Selected", content: "Choose Locale", onChange:"pickerHandler", components: [
					{content: 'Use Default Locale', active: true},
					{content: 'en-US'},
					{content: "th-TH"},	//Thailand
					{content: 'ko-KR'},
					{content: 'en-CA'},
					{content: 'en-IE'},
					{content: 'en-GB'},
					{content: 'en-MX'},
					{content: 'de-DE'},
					{content: 'fr-FR'},
					{content: 'fr-CA'},
					{content: 'it-IT'},
					{content: 'es-ES'},
					{content: 'es-MX'},
					{content: 'es-US'}
				]}
			]}
		]},
		{kind: "moon.Divider", content:"Result"},
		{kind: "moon.BodyText", name: "result", content: "No change yet"}
	],
	create: function(){
		this.inherited(arguments);
		if (!window.ilib) {
			this.$.localePicker.hide();
			this.log("iLib not present -- hiding locale picker");
		}
	},
	pickerHandler: function(inSender, inEvent){
		var opt = inEvent.selected.content,
			val = (opt == "Use Default Locale") ? null : opt;
		this.$.picker.setLocale(val);
		this.$.disabledPicker.setLocale(val);
		return true;
	},
	changed: function(inSender, inEvent) {
		if (this.$.result && inEvent.value){
			this.$.result.setContent(inEvent.name + " changed to " + inEvent.value.toDateString());
		}
	}
});<commit_msg>ANG-6413 Add specific date setting test to sample.<commit_after>enyo.kind({
	name: "moon.sample.DatePickerSample",
	kind: "FittableRows",
	classes: "moon enyo-unselectable enyo-fit",
	components: [
		{kind: 'moon.Scroller', fit: true, components: [
			{classes: "moon-7h", components: [
				{kind: "moon.DatePicker", name:"picker", noneText: "Pick a Date", content: "Date", onChange: "changed"},
				{kind: "moon.DatePicker", name:"disabledPicker", disabled: true, noneText: "Disabled Date Picker", content: "Disabled Date"},
				{classes:"moon-hspacing", components: [
					{kind: "moon.InputDecorator", classes: "moon-2h", components: [
						{kind: "moon.Input", name:"yearInput", placeholder: "Year"}
					]},
					{kind: "moon.InputDecorator", classes: "moon-2h", components: [
						{kind: "moon.Input", name:"monthInput", placeholder: "Month"}
					]},
					{kind: "moon.InputDecorator", classes: "moon-2h", components: [
						{kind: "moon.Input", name:"dayInput", placeholder: "Day"}
					]}
				]},
				{classes:"moon-hspacing", components: [
					{kind: "moon.Button", small:true, content:"Set Date", ontap:"setDate"},
					{kind: "moon.Button", small:true, content:"Reset to Current", ontap:"resetDate"}
				]},
				{name: "localePicker", kind: "moon.ExpandablePicker", noneText: "No Locale Selected", content: "Choose Locale", onChange:"pickerHandler", components: [
					{content: 'Use Default Locale', active: true},
					{content: 'en-US'},
					{content: "th-TH"},	//Thailand
					{content: 'ko-KR'},
					{content: 'en-CA'},
					{content: 'en-IE'},
					{content: 'en-GB'},
					{content: 'en-MX'},
					{content: 'de-DE'},
					{content: 'fr-FR'},
					{content: 'fr-CA'},
					{content: 'it-IT'},
					{content: 'es-ES'},
					{content: 'es-MX'},
					{content: 'es-US'}
				]}
			]}
		]},
		{kind: "moon.Divider", content:"Result"},
		{kind: "moon.BodyText", name: "result", content: "No change yet"}
	],
	create: function(){
		this.inherited(arguments);
		if (!window.ilib) {
			this.$.localePicker.hide();
			this.log("iLib not present -- hiding locale picker");
		}
	},
	pickerHandler: function(inSender, inEvent){
		var opt = inEvent.selected.content,
			val = (opt == "Use Default Locale") ? null : opt;
		this.$.picker.setLocale(val);
		this.$.disabledPicker.setLocale(val);
		return true;
	},
	setDate: function() {
		var year = isNaN(parseInt(this.$.yearInput.getValue())) ? this.$.picker.value.getFullYear() : parseInt(this.$.yearInput.getValue());
		var month = isNaN(parseInt(this.$.monthInput.getValue())) ? this.$.picker.value.getMonth() : parseInt(this.$.monthInput.getValue()) - 1;
		var day = isNaN(parseInt(this.$.dayInput.getValue())) ? this.$.picker.value.getDate() : parseInt(this.$.dayInput.getValue());
		this.$.picker.setValue(new Date(year, month, day));
	},
	resetDate: function() {
		this.$.picker.setValue(new Date());
	},
	changed: function(inSender, inEvent) {
		if (this.$.result && inEvent.value){
			this.$.result.setContent(inEvent.name + " changed to " + inEvent.value.toDateString());
		}
	}
});<|endoftext|>


<commit_before>enyo.kind({
	name: "moon.sample.TimePickerSample",
	kind: "FittableRows",
	classes: "moon enyo-unselectable enyo-fit",
	components: [
		{kind: 'moon.Scroller', fit: true, components: [
			{classes: "moon-7h moon-vspacing-s", components: [
				{kind: "moon.DatePicker", name:"datepicker", noneText: "Pick a Date", content: "Linked Date", onChange: "datechanged"},
				{kind: "moon.TimePicker", name:"timepicker", noneText: "Pick a Time", content: "Linked Time", meridiemEnable: true, onChange: "timechanged"},
				{kind: "moon.TimePicker", name: "pickerTime", noneText: "Pick a Time", content: "Time", meridiemEnable: true, onChange: "timechanged"},
				{kind: "moon.Button", name: "buttonReset", content: "Reset Time", small: true, ontap: "resetTapped"},
				{kind: "moon.TimePicker", name:"disabledPicker", meridiemEnable: true, disabled: true, noneText: "Disabled Time Picker", content: "Disabled Time"},
				{name: "localePicker", kind: "moon.ExpandablePicker", noneText: "No Locale Selected", content: "Choose Locale", onChange:"pickerHandler", components: [
					{content: "Use Default Locale", active: true},
					{content: 'jp-JP'},
					{content: 'en-US'},
					{content: 'ko-KR'},
					{content: "th-TH"},	//Thailand
					{content: 'en-CA'},
					{content: 'en-IE'},
					{content: 'en-GB'},
					{content: 'en-MX'},
					{content: 'de-DE'},
					{content: 'fr-FR'},
					{content: 'fr-CA'},
					{content: 'it-IT'},
					{content: 'es-ES'},
					{content: 'es-MX'},
					{content: 'es-US'}
				]}
			]}
		]},
		{kind: "moon.Divider", content:"Result"},
		{kind: "moon.BodyText", name: "result", content: "No change yet"}
	],
	bindings: [
		{from:".value", to:".$.datepicker.value", oneWay:false},
		{from:".value", to:".$.timepicker.value", oneWay:false}
	],
	create: function(){
		this.inherited(arguments);
		if (!window.ilib) {
			this.$.localePicker.hide();
			this.log("iLib not present -- hiding locale picker");
		}
		this.set("value", new Date("Mar 09 2014 01:59"));
	},
	pickerHandler: function(inSender, inEvent){
		var opt = inEvent.selected.content,
			val = (opt == "Use Default Locale") ? null : opt;
		this.$.datepicker.setLocale(val);
		this.$.timepicker.setLocale(val);
		this.$.disabledPicker.setLocale(val);
		this.$.result.setContent("locale changed to " + opt);
		return true;
	},
	timechanged: function(inSender, inEvent) {
		if (this.$.result && inEvent.value){
			var timeArray = inEvent.value.toTimeString().split(":");
			this.$.result.setContent(inEvent.name + " changed to " + timeArray[0] + ":" + timeArray[1]);
		}
	},
	datechanged: function(inSender, inEvent) {
		if (this.$.result && inEvent.value){
			this.$.result.setContent(inEvent.name + " changed to " + inEvent.value.toDateString());
		}
	},
	resetTapped: function(inSender, inEvent) {
		this.$.pickerTime.set("value", null);
		return true;
	}
});<commit_msg>BHV-9408: Update picker locale when locale changed, make control names consistent.<commit_after>enyo.kind({
	name: "moon.sample.TimePickerSample",
	kind: "FittableRows",
	classes: "moon enyo-unselectable enyo-fit",
	components: [
		{kind: 'moon.Scroller', fit: true, components: [
			{classes: "moon-7h moon-vspacing-s", components: [
				{kind: "moon.DatePicker", name:"pickerDateLinked", noneText: "Pick a Date", content: "Linked Date", onChange: "dateChanged"},
				{kind: "moon.TimePicker", name:"pickerTimeLinked", noneText: "Pick a Time", content: "Linked Time", meridiemEnable: true, onChange: "timeChanged"},
				{kind: "moon.TimePicker", name: "pickerTime", noneText: "Pick a Time", content: "Time", meridiemEnable: true, onChange: "timeChanged"},
				{kind: "moon.Button", name: "buttonReset", content: "Reset Time", small: true, ontap: "resetTapped"},
				{kind: "moon.TimePicker", name:"pickerDisabled", meridiemEnable: true, disabled: true, noneText: "Disabled Time Picker", content: "Disabled Time"},
				{kind: "moon.ExpandablePicker", name: "pickerLocale", noneText: "No Locale Selected", content: "Choose Locale", onChange:"pickerHandler", components: [
					{content: "Use Default Locale", active: true},
					{content: 'jp-JP'},
					{content: 'en-US'},
					{content: 'ko-KR'},
					{content: "th-TH"},	//Thailand
					{content: 'en-CA'},
					{content: 'en-IE'},
					{content: 'en-GB'},
					{content: 'en-MX'},
					{content: 'de-DE'},
					{content: 'fr-FR'},
					{content: 'fr-CA'},
					{content: 'it-IT'},
					{content: 'es-ES'},
					{content: 'es-MX'},
					{content: 'es-US'}
				]}
			]}
		]},
		{kind: "moon.Divider", content:"Result"},
		{kind: "moon.BodyText", name: "result", content: "No change yet"}
	],
	bindings: [
		{from:".value", to:".$.pickerDateLinked.value", oneWay:false},
		{from:".value", to:".$.pickerTimeLinked.value", oneWay:false}
	],
	create: function(){
		this.inherited(arguments);
		if (!window.ilib) {
			this.$.pickerLocale.hide();
			this.log("iLib not present -- hiding locale picker");
		}
		this.set("value", new Date("Mar 09 2014 01:59"));
	},
	pickerHandler: function(inSender, inEvent){
		var opt = inEvent.selected.content,
			val = (opt == "Use Default Locale") ? null : opt;
		this.$.pickerDateLinked.setLocale(val);
		this.$.pickerTimeLinked.setLocale(val);
		this.$.pickerTime.setLocale(val);
		this.$.pickerDisabled.setLocale(val);
		this.$.result.setContent("locale changed to " + opt);
		return true;
	},
	timeChanged: function(inSender, inEvent) {
		if (this.$.result && inEvent.value){
			var timeArray = inEvent.value.toTimeString().split(":");
			this.$.result.setContent(inEvent.name + " changed to " + timeArray[0] + ":" + timeArray[1]);
		}
	},
	dateChanged: function(inSender, inEvent) {
		if (this.$.result && inEvent.value){
			this.$.result.setContent(inEvent.name + " changed to " + inEvent.value.toDateString());
		}
	},
	resetTapped: function(inSender, inEvent) {
		this.$.pickerTime.set("value", null);
		return true;
	}
});<|endoftext|>


<commit_before>var path = require('path');
var fs = require('fs');
var gulp = require('gulp');
var util = require('gulp-util');
var notify = require('gulp-notify');
var size = require('gulp-size');
var swig = require('gulp-swig');
var data = require('gulp-data');
var glob = require('glob');
var prettify = require('gulp-prettify');

var getJsonData = function(dataDir) {
    return function(file) {
        var jsonData;
        try {
            var basename = path.basename(file.path, path.extname(file.path));
            var dataStr = fs.readFileSync(dataDir + '/' + basename + '.json', { encoding: 'utf-8' });
            jsonData = JSON.parse(dataStr);
        } catch(e) {
            jsonData = null;
        }
        return jsonData;
    };
};

var getJsonGlobals = function (dataDir) {

    var globals = {};

    glob.sync(dataDir + '/**/_*.json').forEach(function(fileGlob) {
        var prop = path.basename(fileGlob).replace('.json', '');
        globals[prop] = getJsonData(dataDir)({ path: fileGlob });
    });

    return globals;
};

gulp.task('templates', function() {

    var buildDir = util.env.buildDir;
    var baseDir = util.env.baseDir;
    var pagesDir = util.env.templatePagesDir;
    var dataDir = util.env.templateDataDir;

    var globals = getJsonGlobals(dataDir);

    globals.package = util.env.PACKAGE;
    globals.params = util.env.PARAMS;
    globals['__DEV__'] = util.env.watching;

    var opts = {
        setup: function(swigInstance) {
            swigInstance.setDefaults({
                loader: swigInstance.loaders.fs(baseDir)
            });
        },
        defaults: {
            cache: false,
            locals: globals
        }
    };

    return gulp.src(pagesDir + '/**/*.html')
        .pipe(data(getJsonData(dataDir)))
        .on('error', notify.onError())
        .pipe(swig(opts))
        .on('error', notify.onError())
        .pipe(prettify({ 'indent_size': 2 }))
        .pipe(size( { title: 'templates' }))
        .pipe(gulp.dest(buildDir));
});
<commit_msg>fix prettify mangling issue<commit_after>var path = require('path');
var fs = require('fs');
var gulp = require('gulp');
var util = require('gulp-util');
var notify = require('gulp-notify');
var size = require('gulp-size');
var swig = require('gulp-swig');
var data = require('gulp-data');
var glob = require('glob');
var prettify = require('gulp-prettify');

var getJsonData = function(dataDir) {
    return function(file) {
        var jsonData;
        try {
            var basename = path.basename(file.path, path.extname(file.path));
            var dataStr = fs.readFileSync(dataDir + '/' + basename + '.json', { encoding: 'utf-8' });
            jsonData = JSON.parse(dataStr);
        } catch(e) {
            jsonData = null;
        }
        return jsonData;
    };
};

var getJsonGlobals = function (dataDir) {

    var globals = {};

    glob.sync(dataDir + '/**/_*.json').forEach(function(fileGlob) {
        var prop = path.basename(fileGlob).replace('.json', '');
        globals[prop] = getJsonData(dataDir)({ path: fileGlob });
    });

    return globals;
};

gulp.task('templates', function() {

    var buildDir = util.env.buildDir;
    var baseDir = util.env.baseDir;
    var pagesDir = util.env.templatePagesDir;
    var dataDir = util.env.templateDataDir;

    var globals = getJsonGlobals(dataDir);

    globals.package = util.env.PACKAGE;
    globals.params = util.env.PARAMS;
    globals['__DEV__'] = util.env.watching;

    var opts = {
        setup: function(swigInstance) {
            swigInstance.setDefaults({
                loader: swigInstance.loaders.fs(baseDir)
            });
        },
        defaults: {
            cache: false,
            locals: globals
        }
    };

    return gulp.src(pagesDir + '/**/*.html')
        .pipe(data(getJsonData(dataDir)))
        .on('error', notify.onError())
        .pipe(swig(opts))
        .on('error', notify.onError())
        .pipe(prettify({ 'indent_size': 2, 'unformatted': ['script'] }))
        .pipe(size( { title: 'templates' }))
        .pipe(gulp.dest(buildDir));
});
<|endoftext|>


<commit_before>/**
 * Created by suakbas on 25.11.2015.
 */
'use strict';

/*
 * Constants
 */

var Constants = {
    'LatestAcceptedVersionCode':'413',
    'ServerMessage':'Your application is out of date. Please download the new version from Google Play Store.'
};

module.exports = Constants;<commit_msg>Constants name changed<commit_after>/**
 * Created by suakbas on 25.11.2015.
 */
'use strict';

/*
 * Constants
 */

var Constants = {
    'MinimumAcceptedVersionCode':'413',
    'ServerMessage':'Your application is out of date. Please download the new version from Google Play Store.'
};

module.exports = Constants;<|endoftext|>