<commit_before>/*
  eval-apply-loop
 */
(function(s){

"use strict";

var ScmObject = s.ScmObject;
var EnvironmentFrame = s.EnvironmentFrame;

s.initEval = function() {
	s.addGlobalPrimProc("eval", scheme_eval_prim, 2);
}

s.eval = evaluate;
s.apply = apply;

s.evalString = function(str) {
	scheme.error = null;
	var exps = scheme.read(str);
	if(exps.constructor == String) {
		scheme.console.value += exps;
		return;
	}

	for(var i = 0; i < exps.length; i++) {
		try {
			var obj = scheme.eval(exps[i], scheme.globalEnvironment);
		} catch(e) {
			scheme.console.value += e + "\n";
			throw e;
		}
		if(!scheme.error)
			scheme.printValue(obj);
		else {
			scheme.printError();
			break;
		}
	}
}

function scheme_eval_prim(argv) {
	var exp = argv[0];
	var env = argv[1];
	if(!env.isNamespace())
		return s.wrongContract("meval", argv, "namespace?", env);
	return s.eval(exp, env.data);
}

function evaluate(exp, env) {
	if(s.error)
		return s.error;

	if(exp == s.voidValue)
		return exp;

	if(isSelfEvaluating(exp)) {
		return exp;
	}

	else if(exp.isSymbol()) {
		return lookupVariableValue(exp, env);
	}

	else if(s.isList(exp) && !exp.isEmptyList()) {
		var obj = s.car(exp);
		if(obj.isSymbol()) {
			if(obj == s.quoteSymbol) {
				return evalQuotation(exp);
			}
			else if(obj == s.assignmentSymbol) {
				return evalAssignment(exp, env);
			}
			else if(obj == s.defineSymbol) {
				return evalDefinition(exp, env);
			}
			else if(obj == s.ifSymbol) {
				return evalIf(exp, env);
			}
			else if(obj == s.lambdaSymbol) {
				return evalLambda(exp, env);
			}
			else if(obj == s.beginSymbol) {
				return evalSequence(beginActions(exp), env);
			}
			else if(obj == s.condSymbol) {
				return evaluate(condToIf(exp), env);
			}
			else if(obj == s.letSymbol) {
				return evaluate(letToCombination(exp), env);
			}
		}
		return apply(evaluate(operator(exp), env), listOfValues(operands(exp), env));
	}
	else
		s.makeError('eval', "不支持的表达式类型");
}

function apply(procedure, argv) {
	if(s.error)
		return s.error;

	if(procedure.isPrimProc()) {
		return applyPrimitiveProcedure(procedure, argv);
	}
	else if(procedure.isCompProc()) {
		var result = checkCompoundProcedureArguments(procedure, argv);
		if(result) {
			var env = extendEnvironment(s.compProcParamters(procedure), argv, s.compProcEnv(procedure));
			return evalSequence(s.compProcBody(procedure), env);
		}
	}
	else
		s.makeError('application', "expected a procedure that can be applied to arguments");
}

//------------------------
// syntactic abstractions
//------------------------
// if
function ifPredicate(exp) { return s.cadr(exp); }
function ifConsequent(exp) { return s.caddr(exp); }
function ifAlternative(exp) {
	exp = s.cdddr(exp);
	if(exp.isEmptyList())
		return exp;
	else // alternative
		return s.car(exp);
}
function makeIf(predicate, consequent, alternative) {
	return s.arrayToList([s.ifSymbol, predicate, consequent, alternative]);
}

// lambda
function lambdaParamters(exp) { return s.cadr(exp); }
function lambdaBody(exp) { return s.cddr(exp); }
function makeLambda(parameters, body) {
	return s.cons(s.lambdaSymbol, s.cons(parameters, body));
}

// application
function operator(exp) { return s.car(exp); }
function operands(exp) { return s.cdr(exp); }
function makeApplication(operator, operands) {
	return s.cons(operator, operands);
}

// assignment
function assignmentVar(exp) { return s.cadr(exp); }
function assignmentValue(exp) { return s.caddr(exp); }

// cond
function condClauses(exp) { return s.cdr(exp); }
function clauesPredicate(clause) { return s.car(clause); }
function clauseActions(clause) { return s.cdr(clause); }
function isElseClause(clause) { return clauesPredicate(clause) == s.elseSymbol; }

// begin
function beginActions(exp) {
	return s.cdr(exp);
}
function makeBegin(seq) {
	return s.cons(s.beginSymbol, seq);
}

// let
function letBindings(exp) { return s.cadr(exp); }
function letBody(exp) { return s.cddr(exp); }
function letBindingVars(bindings) {
	return s.mapList(function(bind){
		return s.car(bind);
	}, bindings);
}
function letBindingVals(bindings) {
	return s.mapList(function(bind){
		return s.cadr(bind);
	}, bindings);
}
function letToCombination(exp) {
	var bindings = letBindings(exp);
	return makeApplication(makeLambda(letBindingVars(bindings), letBody(exp)), letBindingVals(bindings));
}

// define variable/function
function definitionVar(exp) {
	if(s.cadr(exp).isSymbol())
		return s.cadr(exp);
	else
		return s.caadr(exp);
}
function definitionVal(exp) {
    if(s.cadr(exp).isSymbol())
        return s.caddr(exp);
    else {
        var formals = s.cdadr(exp);
        var body = s.cddr(exp);
		// to lambda
        return makeLambda(formals, body);
    }
}

function isSelfEvaluating(exp) {
	if(exp.isNumber()) return true;
	else if(exp.isChar()) return true;
	else if(exp.isString()) return true;
	else if(exp.isBoolean()) return true;
	else false;
}

function listOfValues(operands, env) {
	var values = [];
	while(!operands.isEmptyList()) {
		values.push(evaluate(s.car(operands), env));
		operands = s.cdr(operands);
	}
	return values;
}

function evalQuotation(exp) {
	return s.cadr(exp);
}

function evalAssignment(exp, env) {
	setVariableValue(assignmentVar(exp), evaluate(assignmentValue(exp), env), env);
	return s.ok;
}

function evalDefinition(exp, env) {
	var variable = definitionVar(exp);
	var valueExp = definitionVal(exp);
	var value = evaluate(valueExp, env);
	if(value.isCompProc())
		s.setCompProcName(value, variable.data);
	defineVariable(variable, value, env);
	return s.ok;
}

function evalIf(exp, env) {
	if(s.isTrue(evaluate(ifPredicate(exp), env)))
		return evaluate(ifConsequent(exp), env);
	else {
		var alt = ifAlternative(exp);
		if(alt.isEmptyList()) {
			return s.voidValue;
		} else {
			return evaluate(alt, env);
		}
	}
}

function evalLambda(exp, env) {
	var formals = lambdaParamters(exp);
	var minArgs, maxArgs;
	if(s.isList(formals)) {
		minArgs = s.listLength(formals);
	}
	else if(formals.isPair()) {
		minArgs = s.pairsLength(formals);
		maxArgs = -1;
	}
	else if(formals.isSymbol()) {
		minArgs = 0;
		maxArgs = -1;
	}
	else {
		s.makeError('','not an identifier');
	}
	return ScmObject.makeCompProc("", formals, lambdaBody(exp), env, minArgs, maxArgs);
}

function evalSequence(exps, env) {
	var values = [];
	while(!exps.isEmptyList()) {
		values.push( evaluate(s.car(exps), env) );
		exps = s.cdr(exps);
	}
	return values[values.length - 1];
}

function condToIf(exp) {
	return expandClauses(condClauses(exp));

	function expandClauses(clauses) {
		if(clauses.isEmptyList())
			return ScmObject.getBoolean(false);
		var first = s.car(clauses);
		var rest = s.cdr(clauses);
		if(isElseClause(first))
			if(rest.isEmptyList())
				return sequenceExp(clauseActions(first));
			else
				s.makeError('badSyntax', "'else' clause must be last");
		else {
			var predicate = clauesPredicate(first);
			var actionSequence= sequenceExp(clauseActions(first));
			if(actionSequence.isEmptyList())
				return makeIf(s.True, predicate, expandClauses(rest));
			else
				return makeIf(predicate, actionSequence, expandClauses(rest));
		}
	}
	function sequenceExp(seq) {
		if(seq.isEmptyList()) return seq;
		else if(s.cdr(seq).isEmptyList()) return s.car(seq);
		return makeBegin(seq);
	}
}

function applyPrimitiveProcedure(proc, argv) {
	var result = checkPimitiveProcedureArguments(proc, argv);
	if(result) {
		return s.primProcFunc(proc)(argv);
	}
	else
		return result;
}

function lookupVariableValue(variable, env) {
	var value;
	while(env && ((value = env.map[variable.data]) == undefined))
		env = env.baseEnv;
	if(value == undefined)
		return s.makeError('undefined', variable.data);
	return value;
}

function extendEnvironment(variables, values, baseEnv) {
	var map = {};
	if(s.isList(variables)) {
		variables = s.listToArray(variables);
		for(var i = 0; i < variables.length; i++)
			map[variables[i].data] = values[i];
	}
	else if(variables.isPair()) {
		variables = s.pairToArray(variables);
		var i;
		for(i = 0; i < variables.length - 1; i++)
			map[variables[i].data] = values[i];
		var restParameterIndex = i;
		var restValues = s.arrayToList(values.slice(restParameterIndex));
		map[variables[restParameterIndex].data] = restValues;
	}
	else if(variables.isSymbol()) {
		var variable = variables;
		map[variable.data] = s.arrayToList(values);
	}

	return new EnvironmentFrame(map, baseEnv);
}

function defineVariable(variable, value, env) {
	var name = variable.data;
	env.map[name] = value;
}

function setVariableValue(variable, value, env) {
	var name = variable.data;
	while(env && !env.map.hasOwnProperty(name))
		env = env.baseEnv;
	if(env == null)
		return s.makeError('undefined', name);
	env.map[name] = value;
}

function checkPimitiveProcedureArguments(procedure, argv) {
	var procedureName = s.primProcName(procedure);
	var arity = s.primProcArity(procedure);
	return matchArity(procedureName, argv, arity);
}

function checkCompoundProcedureArguments(procedure, argv) {
	var procedureName = s.compProcName(procedure);
	var arity = s.compProcArity(procedure);
	return matchArity(procedureName, argv, arity);
}

function matchArity(procedureName, argv, arity) {
	var min = arity[0];
	var mismatch = false;
	var isAtleast = true;
	var expected = "";
	if(arity.length == 1) {
		if(argv.length != min)
			mismatch = true;
		expected = min;
	}
	else if(arity.length == 2) {
		var max;
		if(arity[1] != -1) {
			max = arity[1];
			isAtleast = false;
			expected = min + " to " + max;
		} else {
			max = 0x3FFFFFFE;
			expected = min;
		}
		if(!(min <= argv.length && argv.length <= max))
			mismatch = true;
	}
	if(mismatch)
		s.makeArityMismatchError(procedureName, argv, isAtleast, expected, argv.length);
	return !mismatch;
}

})(scheme);<commit_msg>update: evalString return last value<commit_after>/*
  eval-apply-loop
 */
(function(s){

"use strict";

var ScmObject = s.ScmObject;
var EnvironmentFrame = s.EnvironmentFrame;

s.initEval = function() {
	s.addGlobalPrimProc("eval", scheme_eval_prim, 2);
}

s.eval = evaluate;
s.apply = apply;

s.evalString = function(str) {
	scheme.error = null;
	var exps = scheme.read(str);
	if(exps.constructor == String) {
		scheme.console.value += exps;
		return;
	}

	var obj;
	for(var i = 0; i < exps.length; i++) {
		try {
			obj = scheme.eval(exps[i], scheme.globalEnvironment);
		} catch(e) {
			scheme.console.value += e + "\n";
			throw e;
		}
		if(!scheme.error)
			scheme.printValue(obj);
		else {
			scheme.printError();
			break;
		}
	}
	return obj;//last value
}

function scheme_eval_prim(argv) {
	var exp = argv[0];
	var env = argv[1];
	if(!env.isNamespace())
		return s.wrongContract("meval", argv, "namespace?", env);
	return s.eval(exp, env.data);
}

function evaluate(exp, env) {
	if(s.error)
		return s.error;

	if(exp == s.voidValue)
		return exp;

	if(isSelfEvaluating(exp)) {
		return exp;
	}

	else if(exp.isSymbol()) {
		return lookupVariableValue(exp, env);
	}

	else if(s.isList(exp) && !exp.isEmptyList()) {
		var obj = s.car(exp);
		if(obj.isSymbol()) {
			if(obj == s.quoteSymbol) {
				return evalQuotation(exp);
			}
			else if(obj == s.assignmentSymbol) {
				return evalAssignment(exp, env);
			}
			else if(obj == s.defineSymbol) {
				return evalDefinition(exp, env);
			}
			else if(obj == s.ifSymbol) {
				return evalIf(exp, env);
			}
			else if(obj == s.lambdaSymbol) {
				return evalLambda(exp, env);
			}
			else if(obj == s.beginSymbol) {
				return evalSequence(beginActions(exp), env);
			}
			else if(obj == s.condSymbol) {
				return evaluate(condToIf(exp), env);
			}
			else if(obj == s.letSymbol) {
				return evaluate(letToCombination(exp), env);
			}
		}
		return apply(evaluate(operator(exp), env), listOfValues(operands(exp), env));
	}
	else
		s.makeError('eval', "不支持的表达式类型");
}

function apply(procedure, argv) {
	if(s.error)
		return s.error;

	if(procedure.isPrimProc()) {
		return applyPrimitiveProcedure(procedure, argv);
	}
	else if(procedure.isCompProc()) {
		var result = checkCompoundProcedureArguments(procedure, argv);
		if(result) {
			var env = extendEnvironment(s.compProcParamters(procedure), argv, s.compProcEnv(procedure));
			return evalSequence(s.compProcBody(procedure), env);
		}
	}
	else
		s.makeError('application', "expected a procedure that can be applied to arguments");
}

//------------------------
// syntactic abstractions
//------------------------
// if
function ifPredicate(exp) { return s.cadr(exp); }
function ifConsequent(exp) { return s.caddr(exp); }
function ifAlternative(exp) {
	exp = s.cdddr(exp);
	if(exp.isEmptyList())
		return exp;
	else // alternative
		return s.car(exp);
}
function makeIf(predicate, consequent, alternative) {
	return s.arrayToList([s.ifSymbol, predicate, consequent, alternative]);
}

// lambda
function lambdaParamters(exp) { return s.cadr(exp); }
function lambdaBody(exp) { return s.cddr(exp); }
function makeLambda(parameters, body) {
	return s.cons(s.lambdaSymbol, s.cons(parameters, body));
}

// application
function operator(exp) { return s.car(exp); }
function operands(exp) { return s.cdr(exp); }
function makeApplication(operator, operands) {
	return s.cons(operator, operands);
}

// assignment
function assignmentVar(exp) { return s.cadr(exp); }
function assignmentValue(exp) { return s.caddr(exp); }

// cond
function condClauses(exp) { return s.cdr(exp); }
function clauesPredicate(clause) { return s.car(clause); }
function clauseActions(clause) { return s.cdr(clause); }
function isElseClause(clause) { return clauesPredicate(clause) == s.elseSymbol; }

// begin
function beginActions(exp) {
	return s.cdr(exp);
}
function makeBegin(seq) {
	return s.cons(s.beginSymbol, seq);
}

// let
function letBindings(exp) { return s.cadr(exp); }
function letBody(exp) { return s.cddr(exp); }
function letBindingVars(bindings) {
	return s.mapList(function(bind){
		return s.car(bind);
	}, bindings);
}
function letBindingVals(bindings) {
	return s.mapList(function(bind){
		return s.cadr(bind);
	}, bindings);
}
function letToCombination(exp) {
	var bindings = letBindings(exp);
	return makeApplication(makeLambda(letBindingVars(bindings), letBody(exp)), letBindingVals(bindings));
}

// define variable/function
function definitionVar(exp) {
	if(s.cadr(exp).isSymbol())
		return s.cadr(exp);
	else
		return s.caadr(exp);
}
function definitionVal(exp) {
    if(s.cadr(exp).isSymbol())
        return s.caddr(exp);
    else {
        var formals = s.cdadr(exp);
        var body = s.cddr(exp);
		// to lambda
        return makeLambda(formals, body);
    }
}

function isSelfEvaluating(exp) {
	if(exp.isNumber()) return true;
	else if(exp.isChar()) return true;
	else if(exp.isString()) return true;
	else if(exp.isBoolean()) return true;
	else false;
}

function listOfValues(operands, env) {
	var values = [];
	while(!operands.isEmptyList()) {
		values.push(evaluate(s.car(operands), env));
		operands = s.cdr(operands);
	}
	return values;
}

function evalQuotation(exp) {
	return s.cadr(exp);
}

function evalAssignment(exp, env) {
	setVariableValue(assignmentVar(exp), evaluate(assignmentValue(exp), env), env);
	return s.ok;
}

function evalDefinition(exp, env) {
	var variable = definitionVar(exp);
	var valueExp = definitionVal(exp);
	var value = evaluate(valueExp, env);
	if(value.isCompProc())
		s.setCompProcName(value, variable.data);
	defineVariable(variable, value, env);
	return s.ok;
}

function evalIf(exp, env) {
	if(s.isTrue(evaluate(ifPredicate(exp), env)))
		return evaluate(ifConsequent(exp), env);
	else {
		var alt = ifAlternative(exp);
		if(alt.isEmptyList()) {
			return s.voidValue;
		} else {
			return evaluate(alt, env);
		}
	}
}

function evalLambda(exp, env) {
	var formals = lambdaParamters(exp);
	var minArgs, maxArgs;
	if(s.isList(formals)) {
		minArgs = s.listLength(formals);
	}
	else if(formals.isPair()) {
		minArgs = s.pairsLength(formals);
		maxArgs = -1;
	}
	else if(formals.isSymbol()) {
		minArgs = 0;
		maxArgs = -1;
	}
	else {
		s.makeError('','not an identifier');
	}
	return ScmObject.makeCompProc("", formals, lambdaBody(exp), env, minArgs, maxArgs);
}

function evalSequence(exps, env) {
	var values = [];
	while(!exps.isEmptyList()) {
		values.push( evaluate(s.car(exps), env) );
		exps = s.cdr(exps);
	}
	return values[values.length - 1];
}

function condToIf(exp) {
	return expandClauses(condClauses(exp));

	function expandClauses(clauses) {
		if(clauses.isEmptyList())
			return ScmObject.getBoolean(false);
		var first = s.car(clauses);
		var rest = s.cdr(clauses);
		if(isElseClause(first))
			if(rest.isEmptyList())
				return sequenceExp(clauseActions(first));
			else
				s.makeError('badSyntax', "'else' clause must be last");
		else {
			var predicate = clauesPredicate(first);
			var actionSequence= sequenceExp(clauseActions(first));
			if(actionSequence.isEmptyList())
				return makeIf(s.True, predicate, expandClauses(rest));
			else
				return makeIf(predicate, actionSequence, expandClauses(rest));
		}
	}
	function sequenceExp(seq) {
		if(seq.isEmptyList()) return seq;
		else if(s.cdr(seq).isEmptyList()) return s.car(seq);
		return makeBegin(seq);
	}
}

function applyPrimitiveProcedure(proc, argv) {
	var result = checkPimitiveProcedureArguments(proc, argv);
	if(result) {
		return s.primProcFunc(proc)(argv);
	}
	else
		return result;
}

function lookupVariableValue(variable, env) {
	var value;
	while(env && ((value = env.map[variable.data]) == undefined))
		env = env.baseEnv;
	if(value == undefined)
		return s.makeError('undefined', variable.data);
	return value;
}

function extendEnvironment(variables, values, baseEnv) {
	var map = {};
	if(s.isList(variables)) {
		variables = s.listToArray(variables);
		for(var i = 0; i < variables.length; i++)
			map[variables[i].data] = values[i];
	}
	else if(variables.isPair()) {
		variables = s.pairToArray(variables);
		var i;
		for(i = 0; i < variables.length - 1; i++)
			map[variables[i].data] = values[i];
		var restParameterIndex = i;
		var restValues = s.arrayToList(values.slice(restParameterIndex));
		map[variables[restParameterIndex].data] = restValues;
	}
	else if(variables.isSymbol()) {
		var variable = variables;
		map[variable.data] = s.arrayToList(values);
	}

	return new EnvironmentFrame(map, baseEnv);
}

function defineVariable(variable, value, env) {
	var name = variable.data;
	env.map[name] = value;
}

function setVariableValue(variable, value, env) {
	var name = variable.data;
	while(env && !env.map.hasOwnProperty(name))
		env = env.baseEnv;
	if(env == null)
		return s.makeError('undefined', name);
	env.map[name] = value;
}

function checkPimitiveProcedureArguments(procedure, argv) {
	var procedureName = s.primProcName(procedure);
	var arity = s.primProcArity(procedure);
	return matchArity(procedureName, argv, arity);
}

function checkCompoundProcedureArguments(procedure, argv) {
	var procedureName = s.compProcName(procedure);
	var arity = s.compProcArity(procedure);
	return matchArity(procedureName, argv, arity);
}

function matchArity(procedureName, argv, arity) {
	var min = arity[0];
	var mismatch = false;
	var isAtleast = true;
	var expected = "";
	if(arity.length == 1) {
		if(argv.length != min)
			mismatch = true;
		expected = min;
	}
	else if(arity.length == 2) {
		var max;
		if(arity[1] != -1) {
			max = arity[1];
			isAtleast = false;
			expected = min + " to " + max;
		} else {
			max = 0x3FFFFFFE;
			expected = min;
		}
		if(!(min <= argv.length && argv.length <= max))
			mismatch = true;
	}
	if(mismatch)
		s.makeArityMismatchError(procedureName, argv, isAtleast, expected, argv.length);
	return !mismatch;
}

})(scheme);<|endoftext|>


<commit_before>var superagent = require("superagent"),
    chai = require("chai"),
    expect = chai.expect,
    should = require("should");

describe("Index", function () {
  it("renders HTML", function (done) {
    superagent.get("http://localhost:3000/")
      .end(function (e, res) {
        (e === null).should.equal(true);
        res.text.should.equal("hey_buddy_20!");
        done();
      });
  });
});
<commit_msg>hey_buddy_21<commit_after>var superagent = require("superagent"),
    chai = require("chai"),
    expect = chai.expect,
    should = require("should");

describe("Index", function () {
  it("renders HTML", function (done) {
    superagent.get("http://localhost:3000/")
      .end(function (e, res) {
        (e === null).should.equal(true);
        res.text.should.equal("hey_buddy_21!");
        done();
      });
  });
});
<|endoftext|>


<commit_before>var ThingAPI = require('./thing-client')
  ;

/*
   get a copy of server.crt from your steward, it's the file

       steward/steward/sandbox/server.crt

   also known as

       http://steward.local/server.crt
 */

var deviceType = '/device/sensor/macguffin/sound';

var protothing = {};
    protothing[deviceType] =
{ device                         :
  { name                         : 'All-Ears Noise Detector'
  , maker                        : 'Macguffin Industries, Ltd.'
  }
, observe                        : [ 'motion' ]
, perform                        : [ 'speak'  ]
, name                           : true
, status                         : [ 'quiet', 'noisy' ]
, properties                     :
  {
    noise                        : 'db'
  , threshold                    : 'db'
  }
, validate                       :
  { observe                      : true
  , perform                      : true
  }
};

// the udn must be both globally-unique and specific to the thing being registered.
//   cf., https://github.com/TheThingSystem/steward/wiki/Simple-Thing-Protocol#define-instances
// since this is a test file, we are going to use a static value, when you write your code, you MUST use something meaningfully
// related to the thing in question...

var udn = '5eb160e4-e770-4e97-b8ef-dd89aa0a80ed';

var instathing = {};
    instathing.t1 =
{ devicetype                     : deviceType
, name                           : 'Living Room noise sensor'
, status                         : 'quiet'
, device                         :
  { name                         : protothing[deviceType].device.name
  , maker                        : protothing[deviceType].device.maker
/*
  , model                        :
    { name                       : '...'
    , descr                      : '...'
    , number                     : '...'
    }
 */
  , unit                         :
    { serial                     : '...'
    , udn                        : udn
    }
  }
, updated                        : new Date().getTime()
, info                           :
  { noise                        : 20
  , threshold                    : 35
  }
};

new ThingAPI.ThingAPI(
{ steward : { crtPath   : 'server.crt' }
, pairing : { thingUUID : 'testing1'
            }
, state   : null
}).on('paired', function(state) {
  console.log('paired state='+ JSON.stringify(state));

// when you get the value of state, then put it above and comment out 'pairing'
}).on('ready', function() {
  var self = this;

  self.prototype(protothing, function(message) {
    if ((!message.things) || (!message.things[deviceType])) {
      console.log('definition: invalid response');
      process.exit(1);
    }
    if (!message.things[deviceType].success) {
      console.log('definition: ' + JSON.stringify(message.things[deviceType]));
      process.exit(1);
    }

    self.register(instathing, function(message) {
      console.log(require('util').inspect(message, { depth: null }));

      if ((!message.things) || (!message.things.t1)) {
        console.log('registration: invalid response');
        process.exit(1);
      }
      if (!message.things.t1.success) {
        console.log('registration: ' + JSON.stringify(message.things.t1));
        process.exit(1);
      }

      getToWork(self, message.things.t1.thingID);
    });
  });
}).on('message', function(message) {
  console.log(require('util').inspect(message, { depth: null }));
}).on('close', function() {
  console.log('close');

// lost connection, should re-establish it...
  process.exit(0);
}).on('error', function(err) {
  console.log('error: ' + err.message);

// something is seriously wrong, not sure how to recover...
  process.exit(0);
});

var noise     = instathing.t1.info.noise;
var threshold = instathing.t1.info.threshold;
var observe   = {};

var getToWork = function(thing, thingID) {
  var state;

  console.log('>>> getToWork: thingID='+ thingID);

// heartbeat
  setInterval(function() {
    var status = {};

    status[thingID] = { updated: new Date().getTime() };
    thing.update(status);
  }, 50 * 1000);

// determine noise level (randomly)
  state = 'quiet';
  setInterval(function() {
    var didP
      , eventID
      , events
      , status = {};

         if (noise < 30) noise = 30 + Math.round(Math.random() * 10);
    else if (noise > 70) noise = 70 - Math.round(Math.random() * 10);
    else                 noise += Math.round(Math.random() * 20) - 10;

    if (state === 'quiet') {
      if (noise <= threshold) return;
      state = 'noisy';
    } else {
      if (noise >= threshold) return;
      state = 'quiet';
    }

    status[thingID] = { status: state, updated: new Date().getTime(), info: { noise: noise, threshold: threshold } };
    thing.update(status);

    didP = false;
    events = {};
    for (eventID in observe) if (observe.hasOwnProperty(eventID)) {
      didP = true;
      events[eventID] = { reason: 'observe' };
    }
    if (!didP) return;

    thing.report(events, function(message) {
      var eventID;

      if (!message.events) return;
      for (eventID in message.events) if (message.events.hasOwnProperty(eventID)) {
        if (message.events[eventID].status === 'success') delete(observe[eventID]);
      }
    });
  }, 30 * 1000);

  thing.on('message', function(message) {
    var f = { '/api/v1/thing/observe':
                function() {
                  var event, eventID, response;

                  response = { path: '/api/v1/thing/report', requestID: message.requestID, events: {} };

                  for (eventID in message.events) if (message.events.hasOwnProperty(eventID)) {
                    event = message.events[eventID];

                    if (event.observe !== 'motion') {
                      response.events[eventID] = { error: { permanent: true, diagnostic: 'invalid observe value' }
                                                 , reason: 'observe'
                                                 };
                      continue;
                    }
                    if (!event.testOnly) observe[eventID] = event;
                    response.events[eventID] = { success: true };
                  }

                  thing.reply(response);
                }

            , '/api/v1/thing/report':
                function() {
                  var event, eventID, response;

                  response = { path: '/api/v1/thing/report', requestID: message.requestID, events: {} };

                  for (eventID in message.events) if (message.events.hasOwnProperty(eventID)) {
                    event = message.events[eventID];

                    if (event.reason !== 'cancel') {
                      response.events[eventID] = { error: { permanent: true, diagnostic: 'invalid reason' }
                                                 , reason: 'observe'
                                                 };
                      continue;
                    }
                    if (!!observe[eventID]) {
                      response.events[eventID] = { error: { permanent: true, diagnostic: 'invalid eventID' }
                                                 , reason: 'observe'
                                                 };
                      continue;
                    }
                    delete(observe[eventID]);
                    response.events[eventID] = { status: 'success' };
                  }

                  thing.reply(response);
                }

            , '/api/v1/thing/perform':
                function() {
                  var task, taskID, response;

                  response = { path: '/api/v1/thing/report', requestID: message.requestID, tasks: {} };

                  for (taskID in message.tasks) if (message.tasks.hasOwnProperty(taskID)) {
                    task = message.tasks[taskID];

                    if (task.perform !== 'speak') {
                      response.tasks[taskID] = { error: { permanent: true, diagnostic: 'invalid perform value' }
                                               , reason: 'failure'
                                               };
                      continue;
                    }
                    if ((!task.parameter) || (typeof task.parameter !== 'string') || (task.parameter.length === 0)) {
                      response.tasks[taskID] = { error: { permanent: true, diagnostic: 'invalid parameter value' }
                                               , reason: 'failure'
                                               };
                      continue;
                    }
                    if (task.testOnly) {
                      response.tasks[taskID] = { status: 'success' };
                      continue;
                    }

                    console.log('>>> speaking: ' + task.parameter);
                  }

                  thing.reply(response);
                }
            }[message.path];
    if (!!f) return f();

    console.log('invalid message: ' + JSON.stringify(message));
  });
};
<commit_msg>add proceed message<commit_after>var ThingAPI = require('./thing-client')
  ;

/*
   get a copy of server.crt from your steward, it's the file

       steward/steward/sandbox/server.crt

   also known as

       http://steward.local/server.crt
 */

var deviceType = '/device/sensor/macguffin/sound';

var protothing = {};
    protothing[deviceType] =
{ device                         :
  { name                         : 'All-Ears Noise Detector'
  , maker                        : 'Macguffin Industries, Ltd.'
  }
, observe                        : [ 'motion' ]
, perform                        : [ 'speak'  ]
, name                           : true
, status                         : [ 'quiet', 'noisy' ]
, properties                     :
  {
    noise                        : 'db'
  , threshold                    : 'db'
  }
, validate                       :
  { observe                      : true
  , perform                      : true
  }
};

// the udn must be both globally-unique and specific to the thing being registered.
//   cf., https://github.com/TheThingSystem/steward/wiki/Simple-Thing-Protocol#define-instances
// since this is a test file, we are going to use a static value, when you write your code, you MUST use something meaningfully
// related to the thing in question...

var udn = '5eb160e4-e770-4e97-b8ef-dd89aa0a80ed';

var instathing = {};
    instathing.t1 =
{ devicetype                     : deviceType
, name                           : 'Living Room noise sensor'
, status                         : 'quiet'
, device                         :
  { name                         : protothing[deviceType].device.name
  , maker                        : protothing[deviceType].device.maker
/*
  , model                        :
    { name                       : '...'
    , descr                      : '...'
    , number                     : '...'
    }
 */
  , unit                         :
    { serial                     : '...'
    , udn                        : udn
    }
  }
, updated                        : new Date().getTime()
, info                           :
  { noise                        : 20
  , threshold                    : 35
  }
};

new ThingAPI.ThingAPI(
{ steward : { crtPath   : 'server.crt' }
, pairing : { thingUUID : 'testing1'
            }
, state   : null
}).on('paired', function(state) {
  console.log('paired state='+ JSON.stringify(state));

// when you get the value of state, then put it above and comment out 'pairing'
}).on('ready', function() {
  var self = this;

  self.prototype(protothing, function(message) {
    if ((!message.things) || (!message.things[deviceType])) {
      console.log('definition: invalid response');
      process.exit(1);
    }
    if (!message.things[deviceType].success) {
      console.log('definition: ' + JSON.stringify(message.things[deviceType]));
      process.exit(1);
    }

    self.register(instathing, function(message) {
      console.log(require('util').inspect(message, { depth: null }));

      if ((!message.things) || (!message.things.t1)) {
        console.log('registration: invalid response');
        process.exit(1);
      }
      if (!message.things.t1.success) {
        console.log('registration: ' + JSON.stringify(message.things.t1));
        process.exit(1);
      }

      getToWork(self, message.things.t1.thingID);
    });
  });
}).on('message', function(message) {
  console.log(require('util').inspect(message, { depth: null }));
}).on('close', function() {
  console.log('close');

// lost connection, should re-establish it...
  process.exit(0);
}).on('error', function(err) {
  console.log('error: ' + err.message);

// something is seriously wrong, not sure how to recover...
  process.exit(0);
});

var noise     = instathing.t1.info.noise;
var threshold = instathing.t1.info.threshold;
var observe   = {};

var getToWork = function(thing, thingID) {
  var state;

  console.log('>>> getToWork: thingID='+ thingID);

// heartbeat
  setInterval(function() {
    var status = {};

    status[thingID] = { updated: new Date().getTime() };
    thing.update(status);
  }, 50 * 1000);

// determine noise level (randomly)
  state = 'quiet';
  setInterval(function() {
    var didP
      , eventID
      , events
      , status = {};

         if (noise < 30) noise = 30 + Math.round(Math.random() * 10);
    else if (noise > 70) noise = 70 - Math.round(Math.random() * 10);
    else                 noise += Math.round(Math.random() * 20) - 10;

    if (state === 'quiet') {
      if (noise <= threshold) return;
      state = 'noisy';
    } else {
      if (noise >= threshold) return;
      state = 'quiet';
    }

    status[thingID] = { status: state, updated: new Date().getTime(), info: { noise: noise, threshold: threshold } };
    thing.update(status);

    didP = false;
    events = {};
    for (eventID in observe) if (observe.hasOwnProperty(eventID)) {
      didP = true;
      events[eventID] = { reason: 'observe' };
    }
    if (!didP) return;

    thing.report(events, function(message) {
      var eventID;

      if (!message.events) return;
      for (eventID in message.events) if (message.events.hasOwnProperty(eventID)) {
        if (message.events[eventID].status !== 'success') delete(observe[eventID]);
      }
    });
  }, 30 * 1000);

  thing.on('message', function(message) {
    var f = { '/api/v1/thing/observe':
                function() {
                  var event, eventID, response;

                  response = { path: '/api/v1/thing/report', requestID: message.requestID, events: {} };

                  for (eventID in message.events) if (message.events.hasOwnProperty(eventID)) {
                    event = message.events[eventID];

                    if (event.observe !== 'motion') {
                      response.events[eventID] = { error: { permanent: true, diagnostic: 'invalid observe value' }
                                                 , reason: 'observe'
                                                 };
                      continue;
                    }
                    if (!event.testOnly) observe[eventID] = event;
                    response.events[eventID] = { status: 'proceed' };
                  }

                  thing.reply(response);
                }

            , '/api/v1/thing/report':
                function() {
                  var event, eventID, response;

                  response = { path: '/api/v1/thing/report', requestID: message.requestID, events: {} };

                  for (eventID in message.events) if (message.events.hasOwnProperty(eventID)) {
                    event = message.events[eventID];

                    if (event.reason !== 'cancel') {
                      response.events[eventID] = { error: { permanent: true, diagnostic: 'invalid reason' }
                                                 , reason: 'observe'
                                                 };
                      continue;
                    }
                    if (!!observe[eventID]) {
                      response.events[eventID] = { error: { permanent: true, diagnostic: 'invalid eventID' }
                                                 , reason: 'observe'
                                                 };
                      continue;
                    }
                    delete(observe[eventID]);
                    response.events[eventID] = { status: 'success' };
                  }

                  thing.reply(response);
                }

            , '/api/v1/thing/perform':
                function() {
                  var task, taskID, response;

                  response = { path: '/api/v1/thing/report', requestID: message.requestID, tasks: {} };

                  for (taskID in message.tasks) if (message.tasks.hasOwnProperty(taskID)) {
                    task = message.tasks[taskID];

                    if (task.perform !== 'speak') {
                      response.tasks[taskID] = { error: { permanent: true, diagnostic: 'invalid perform value' }
                                               , reason: 'failure'
                                               };
                      continue;
                    }
                    if ((!task.parameter) || (typeof task.parameter !== 'string') || (task.parameter.length === 0)) {
                      response.tasks[taskID] = { error: { permanent: true, diagnostic: 'invalid parameter value' }
                                               , reason: 'failure'
                                               };
                      continue;
                    }
                    if (task.testOnly) {
                      response.tasks[taskID] = { status: 'success' };
                      continue;
                    }

                    console.log('>>> speaking: ' + task.parameter);
                  }

                  thing.reply(response);
                }
            }[message.path];
    if (!!f) return f();

    console.log('invalid message: ' + JSON.stringify(message));
  });
};
<|endoftext|>


<commit_before>queuelight = require('./queue-light.js');
var queue = queuelight.init(
  {
    filename: './data/queue.json',
    finishedFilename: './data/queue.finished.json',
    defaultReadyState: false
  }
);

var data = {name: 'first'}
queue.push(data, function(err,data2){
  queue.setReady(data2,function(err,data3){
    queue.pull(function(err,item){
      console.log(item);
      if(item){
        queue.finish(item, function(err, i){

        });
      }
    });
  })

});

// queue.return();
// queue.pull();
// queue.finish();
<commit_msg>Update method - fixes #8<commit_after>queuelight = require('./queue-light.js');
var queue = queuelight.init(
  {
    filename: './data/queue.json',
    finishedFilename: './data/queue.finished.json',
    defaultReadyState: false
  }
);

var data = {name: 'first'}
queue.push(data, function(err,data2){
  data2.data.name = "david";
  queue.update(data2,function(err, data22){
    queue.setReady(data22,function(err,data3){
      queue.pull(function(err,item){
        console.log(item);
        if(item){
          queue.finish(item, function(err, i){

          });
        }
      });
    })
  })

});

// queue.return();
// queue.pull();
// queue.finish();
<|endoftext|>


<commit_before>'use strict'

var test = require('tap').test
var pino = require('./')
var writeStream = require('flush-write-stream')
var os = require('os')
var split = require('split2')
var http = require('http')
var pid = process.pid
var hostname = os.hostname()

function sink (func) {
  var result = split(JSON.parse)
  result.pipe(writeStream.obj(func))
  return result
}

function check (t, chunk, level, msg) {
  t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
  delete chunk.time
  t.deepEqual(chunk, {
    pid: pid,
    hostname: hostname,
    level: level,
    msg: msg,
    v: 1
  })
}

function levelTest (name, level) {
  test(name + ' logs as ' + level, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      check(t, chunk, level, 'hello world')
    }))

    instance.level = name
    instance[name]('hello world')
  })

  test('passing objects at level ' + name, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        hello: 'world',
        v: 1
      })
    }))

    instance.level = name
    instance[name]({ hello: 'world' })
  })

  test('passing an object and a string at level ' + name, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        msg: 'a string',
        hello: 'world',
        v: 1
      })
    }))

    instance.level = name
    instance[name]({ hello: 'world' }, 'a string')
  })

  test('formatting logs as ' + name, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      check(t, chunk, level, 'hello 42')
    }))

    instance.level = name
    instance[name]('hello %d', 42)
  })

  test('passing error at level ' + name, function (t) {
    t.plan(2)
    var err = new Error('myerror')
    var instance = pino(sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        type: 'Error',
        msg: err.message,
        stack: err.stack,
        v: 1
      })
      cb()
    }))

    instance.level = name
    instance[name](err)
  })

  test('passing error with a serializer at level ' + name, function (t) {
    t.plan(2)
    var err = new Error('myerror')
    var instance = pino({
      serializers: {
        err: pino.stdSerializers.err
      }
    }, sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        err: {
          type: 'Error',
          message: err.message,
          stack: err.stack
        },
        v: 1
      })
      cb()
    }))

    instance.level = name
    instance[name]({ err: err })
  })

  test('child logger for level ' + name, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        msg: 'hello world',
        hello: 'world',
        v: 1
      })
    }))

    instance.level = name
    var child = instance.child({
      hello: 'world'
    })
    child[name]('hello world')
  })
}

levelTest('fatal', 60)
levelTest('error', 50)
levelTest('warn', 40)
levelTest('info', 30)
levelTest('debug', 20)
levelTest('trace', 10)

test('set the level', function (t) {
  t.plan(4)
  var expected = [{
    level: 50,
    msg: 'this is an error'
  }, {
    level: 60,
    msg: 'this is fatal'
  }]
  var instance = pino(sink(function (chunk, enc, cb) {
    var current = expected.shift()
    check(t, chunk, current.level, current.msg)
    cb()
  }))

  instance.level = 'error'
  instance.info('hello world')
  instance.error('this is an error')
  instance.fatal('this is fatal')
})

test('does not explode with a circular ref', function (t) {
  var instance = pino(sink(function (chunk, enc, cb) {
    // nothing to check
    cb()
  }))
  var b = {}
  var a = {
    hello: b
  }
  b.a = a // circular ref
  instance.info(a)
  t.end()
})

test('explode with a circular ref with safe = false', function (t) {
  var instance = pino({ safe: false }, sink(function (chunk, enc, cb) {
    // nothing to check
    cb()
  }))
  var b = {}
  var a = {
    hello: b
  }
  b.a = a // circular ref
  t.throws(function () {
    instance.info(a)
  })
  t.end()
})

test('set the name', function (t) {
  t.plan(2)

  var instance = pino({
    name: 'hello'
  }, sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 60,
      name: 'hello',
      msg: 'this is fatal',
      v: 1
    })
    cb()
  }))

  instance.fatal('this is fatal')
})

test('set the level via constructor', function (t) {
  t.plan(4)
  var expected = [{
    level: 50,
    msg: 'this is an error'
  }, {
    level: 60,
    msg: 'this is fatal'
  }]
  var instance = pino({ level: 'error' }, sink(function (chunk, enc, cb) {
    var current = expected.shift()
    check(t, chunk, current.level, current.msg)
    cb()
  }))

  instance.info('hello world')
  instance.error('this is an error')
  instance.fatal('this is fatal')
})

test('set undefined properties', function (t) {
  t.plan(2)

  var instance = pino(sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      hello: 'world',
      v: 1
    })
    cb()
  }))

  instance.info({ hello: 'world', property: undefined })
})

test('set properties defined in the prototype chain', function (t) {
  t.plan(2)

  var instance = pino(sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      hello: 'world',
      v: 1
    })
    cb()
  }))

  function MyObject () {
    this.hello = 'world'
  }

  MyObject.prototype.some = function () {}

  instance.info(new MyObject())
})

test('http request support', function (t) {
  t.plan(3)

  var originalReq
  var instance = pino(sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: 'my request',
      v: 1,
      req: {
        method: originalReq.method,
        url: originalReq.url,
        headers: originalReq.headers,
        remoteAddress: originalReq.connection.remoteAddress,
        remotePort: originalReq.connection.remotePort
      }
    })
    cb()
  }))

  var server = http.createServer(function (req, res) {
    originalReq = req
    instance.info(req, 'my request')
    res.end('hello')
  }).listen(function (err) {
    t.error(err)
    t.teardown(server.close.bind(server))

    http.get('http://localhost:' + server.address().port, function (res) {
      res.resume()
    })
  })
})

test('http request support via serializer', function (t) {
  t.plan(3)

  var originalReq
  var instance = pino({
    serializers: {
      req: pino.stdSerializers.req
    }
  }, sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: 'my request',
      v: 1,
      req: {
        method: originalReq.method,
        url: originalReq.url,
        headers: originalReq.headers,
        remoteAddress: originalReq.connection.remoteAddress,
        remotePort: originalReq.connection.remotePort
      }
    })
    cb()
  }))

  var server = http.createServer(function (req, res) {
    originalReq = req
    instance.info({ req: req }, 'my request')
    res.end('hello')
  }).listen(function (err) {
    t.error(err)
    t.teardown(server.close.bind(server))

    http.get('http://localhost:' + server.address().port, function (res) {
      res.resume()
    })
  })
})

test('http response support', function (t) {
  t.plan(3)

  var originalRes
  var instance = pino(sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: 'my response',
      v: 1,
      res: {
        statusCode: originalRes.statusCode,
        header: originalRes._header
      }
    })
    cb()
  }))

  var server = http.createServer(function (req, res) {
    originalRes = res
    res.end('hello')
    instance.info(res, 'my response')
  }).listen(function (err) {
    t.error(err)
    t.teardown(server.close.bind(server))

    http.get('http://localhost:' + server.address().port, function (res) {
      res.resume()
    })
  })
})

test('http response support via a serializer', function (t) {
  t.plan(3)

  var originalRes
  var instance = pino({
    serializers: {
      res: pino.stdSerializers.res
    }
  }, sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: 'my response',
      v: 1,
      res: {
        statusCode: originalRes.statusCode,
        header: originalRes._header
      }
    })
    cb()
  }))

  var server = http.createServer(function (req, res) {
    originalRes = res
    res.end('hello')
    instance.info({ res: res }, 'my response')
  }).listen(function (err) {
    t.error(err)
    t.teardown(server.close.bind(server))

    http.get('http://localhost:' + server.address().port, function (res) {
      res.resume()
    })
  })
})

test('slowtime', function (t) {
  var instance = pino({slowtime: true},
    sink(function (chunk, enc, cb) {
      t.ok(Date.parse(chunk.time) <= new Date(), 'time is greater than Date.now()')
      t.end()
    }))

  instance.info('hello world')
})

test('http request support via serializer in a child', function (t) {
  t.plan(3)

  var originalReq
  var instance = pino({
    serializers: {
      req: pino.stdSerializers.req
    }
  }, sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: 'my request',
      v: 1,
      req: {
        method: originalReq.method,
        url: originalReq.url,
        headers: originalReq.headers,
        remoteAddress: originalReq.connection.remoteAddress,
        remotePort: originalReq.connection.remotePort
      }
    })
    cb()
  }))

  var server = http.createServer(function (req, res) {
    originalReq = req
    var child = instance.child({ req: req })
    child.info('my request')
    res.end('hello')
  }).listen(function (err) {
    t.error(err)
    t.teardown(server.close.bind(server))

    http.get('http://localhost:' + server.address().port, function (res) {
      res.resume()
    })
  })
})

test('throw if creating child without bindings', function (t) {
  t.plan(1)

  var instance = pino(
    sink(function (chunk, enc, cb) {
      t.ok(Date.parse(chunk.time) <= new Date(), 'time is greater than Date.now()')
      t.end()
    }))

  t.throws(function () {
    instance.child()
  })
})

test('extreme mode', function (t) {
  var now = Date.now
  Date.now = function () {
    return 1459875739796
  }

  var expected = ''
  var actual = ''
  var normal = pino(writeStream(function (s, enc, cb) {
    expected += s
    cb()
  }))

  var extreme = pino({extreme: true}, writeStream(function (s, enc, cb) {
    actual += s
    cb()
  }))

  var i = 44
  while (i--) {
    normal.info('h')
    extreme.info('h')
  }

  t.is(actual, expected)

  Date.now = now
  t.end()
})
<commit_msg>make extreme mode test reliable<commit_after>'use strict'

var test = require('tap').test
var pino = require('./')
var writeStream = require('flush-write-stream')
var os = require('os')
var split = require('split2')
var http = require('http')
var pid = process.pid
var hostname = os.hostname()

function sink (func) {
  var result = split(JSON.parse)
  result.pipe(writeStream.obj(func))
  return result
}

function check (t, chunk, level, msg) {
  t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
  delete chunk.time
  t.deepEqual(chunk, {
    pid: pid,
    hostname: hostname,
    level: level,
    msg: msg,
    v: 1
  })
}

function levelTest (name, level) {
  test(name + ' logs as ' + level, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      check(t, chunk, level, 'hello world')
    }))

    instance.level = name
    instance[name]('hello world')
  })

  test('passing objects at level ' + name, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        hello: 'world',
        v: 1
      })
    }))

    instance.level = name
    instance[name]({ hello: 'world' })
  })

  test('passing an object and a string at level ' + name, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        msg: 'a string',
        hello: 'world',
        v: 1
      })
    }))

    instance.level = name
    instance[name]({ hello: 'world' }, 'a string')
  })

  test('formatting logs as ' + name, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      check(t, chunk, level, 'hello 42')
    }))

    instance.level = name
    instance[name]('hello %d', 42)
  })

  test('passing error at level ' + name, function (t) {
    t.plan(2)
    var err = new Error('myerror')
    var instance = pino(sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        type: 'Error',
        msg: err.message,
        stack: err.stack,
        v: 1
      })
      cb()
    }))

    instance.level = name
    instance[name](err)
  })

  test('passing error with a serializer at level ' + name, function (t) {
    t.plan(2)
    var err = new Error('myerror')
    var instance = pino({
      serializers: {
        err: pino.stdSerializers.err
      }
    }, sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        err: {
          type: 'Error',
          message: err.message,
          stack: err.stack
        },
        v: 1
      })
      cb()
    }))

    instance.level = name
    instance[name]({ err: err })
  })

  test('child logger for level ' + name, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        msg: 'hello world',
        hello: 'world',
        v: 1
      })
    }))

    instance.level = name
    var child = instance.child({
      hello: 'world'
    })
    child[name]('hello world')
  })
}

levelTest('fatal', 60)
levelTest('error', 50)
levelTest('warn', 40)
levelTest('info', 30)
levelTest('debug', 20)
levelTest('trace', 10)

test('set the level', function (t) {
  t.plan(4)
  var expected = [{
    level: 50,
    msg: 'this is an error'
  }, {
    level: 60,
    msg: 'this is fatal'
  }]
  var instance = pino(sink(function (chunk, enc, cb) {
    var current = expected.shift()
    check(t, chunk, current.level, current.msg)
    cb()
  }))

  instance.level = 'error'
  instance.info('hello world')
  instance.error('this is an error')
  instance.fatal('this is fatal')
})

test('does not explode with a circular ref', function (t) {
  var instance = pino(sink(function (chunk, enc, cb) {
    // nothing to check
    cb()
  }))
  var b = {}
  var a = {
    hello: b
  }
  b.a = a // circular ref
  instance.info(a)
  t.end()
})

test('explode with a circular ref with safe = false', function (t) {
  var instance = pino({ safe: false }, sink(function (chunk, enc, cb) {
    // nothing to check
    cb()
  }))
  var b = {}
  var a = {
    hello: b
  }
  b.a = a // circular ref
  t.throws(function () {
    instance.info(a)
  })
  t.end()
})

test('set the name', function (t) {
  t.plan(2)

  var instance = pino({
    name: 'hello'
  }, sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 60,
      name: 'hello',
      msg: 'this is fatal',
      v: 1
    })
    cb()
  }))

  instance.fatal('this is fatal')
})

test('set the level via constructor', function (t) {
  t.plan(4)
  var expected = [{
    level: 50,
    msg: 'this is an error'
  }, {
    level: 60,
    msg: 'this is fatal'
  }]
  var instance = pino({ level: 'error' }, sink(function (chunk, enc, cb) {
    var current = expected.shift()
    check(t, chunk, current.level, current.msg)
    cb()
  }))

  instance.info('hello world')
  instance.error('this is an error')
  instance.fatal('this is fatal')
})

test('set undefined properties', function (t) {
  t.plan(2)

  var instance = pino(sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      hello: 'world',
      v: 1
    })
    cb()
  }))

  instance.info({ hello: 'world', property: undefined })
})

test('set properties defined in the prototype chain', function (t) {
  t.plan(2)

  var instance = pino(sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      hello: 'world',
      v: 1
    })
    cb()
  }))

  function MyObject () {
    this.hello = 'world'
  }

  MyObject.prototype.some = function () {}

  instance.info(new MyObject())
})

test('http request support', function (t) {
  t.plan(3)

  var originalReq
  var instance = pino(sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: 'my request',
      v: 1,
      req: {
        method: originalReq.method,
        url: originalReq.url,
        headers: originalReq.headers,
        remoteAddress: originalReq.connection.remoteAddress,
        remotePort: originalReq.connection.remotePort
      }
    })
    cb()
  }))

  var server = http.createServer(function (req, res) {
    originalReq = req
    instance.info(req, 'my request')
    res.end('hello')
  }).listen(function (err) {
    t.error(err)
    t.teardown(server.close.bind(server))

    http.get('http://localhost:' + server.address().port, function (res) {
      res.resume()
    })
  })
})

test('http request support via serializer', function (t) {
  t.plan(3)

  var originalReq
  var instance = pino({
    serializers: {
      req: pino.stdSerializers.req
    }
  }, sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: 'my request',
      v: 1,
      req: {
        method: originalReq.method,
        url: originalReq.url,
        headers: originalReq.headers,
        remoteAddress: originalReq.connection.remoteAddress,
        remotePort: originalReq.connection.remotePort
      }
    })
    cb()
  }))

  var server = http.createServer(function (req, res) {
    originalReq = req
    instance.info({ req: req }, 'my request')
    res.end('hello')
  }).listen(function (err) {
    t.error(err)
    t.teardown(server.close.bind(server))

    http.get('http://localhost:' + server.address().port, function (res) {
      res.resume()
    })
  })
})

test('http response support', function (t) {
  t.plan(3)

  var originalRes
  var instance = pino(sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: 'my response',
      v: 1,
      res: {
        statusCode: originalRes.statusCode,
        header: originalRes._header
      }
    })
    cb()
  }))

  var server = http.createServer(function (req, res) {
    originalRes = res
    res.end('hello')
    instance.info(res, 'my response')
  }).listen(function (err) {
    t.error(err)
    t.teardown(server.close.bind(server))

    http.get('http://localhost:' + server.address().port, function (res) {
      res.resume()
    })
  })
})

test('http response support via a serializer', function (t) {
  t.plan(3)

  var originalRes
  var instance = pino({
    serializers: {
      res: pino.stdSerializers.res
    }
  }, sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: 'my response',
      v: 1,
      res: {
        statusCode: originalRes.statusCode,
        header: originalRes._header
      }
    })
    cb()
  }))

  var server = http.createServer(function (req, res) {
    originalRes = res
    res.end('hello')
    instance.info({ res: res }, 'my response')
  }).listen(function (err) {
    t.error(err)
    t.teardown(server.close.bind(server))

    http.get('http://localhost:' + server.address().port, function (res) {
      res.resume()
    })
  })
})

test('slowtime', function (t) {
  var instance = pino({slowtime: true},
    sink(function (chunk, enc, cb) {
      t.ok(Date.parse(chunk.time) <= new Date(), 'time is greater than Date.now()')
      t.end()
    }))

  instance.info('hello world')
})

test('http request support via serializer in a child', function (t) {
  t.plan(3)

  var originalReq
  var instance = pino({
    serializers: {
      req: pino.stdSerializers.req
    }
  }, sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: 'my request',
      v: 1,
      req: {
        method: originalReq.method,
        url: originalReq.url,
        headers: originalReq.headers,
        remoteAddress: originalReq.connection.remoteAddress,
        remotePort: originalReq.connection.remotePort
      }
    })
    cb()
  }))

  var server = http.createServer(function (req, res) {
    originalReq = req
    var child = instance.child({ req: req })
    child.info('my request')
    res.end('hello')
  }).listen(function (err) {
    t.error(err)
    t.teardown(server.close.bind(server))

    http.get('http://localhost:' + server.address().port, function (res) {
      res.resume()
    })
  })
})

test('throw if creating child without bindings', function (t) {
  t.plan(1)

  var instance = pino(
    sink(function (chunk, enc, cb) {
      t.ok(Date.parse(chunk.time) <= new Date(), 'time is greater than Date.now()')
      t.end()
    }))

  t.throws(function () {
    instance.child()
  })
})

test('extreme mode', function (t) {
  var now = Date.now
  var hostname = os.hostname
  var proc = process
  global.process = {
    __proto__: process,
    pid: 123456
  }
  Date.now = function () {
    return 1459875739796
  }
  os.hostname = function () {
    return 'abcdefghijklmnopqr'
  }
  delete require.cache[require.resolve('./')]
  var pino = require('./')
  var expected = ''
  var actual = ''
  var normal = pino(writeStream(function (s, enc, cb) {
    expected += s
    cb()
  }))

  var extreme = pino({extreme: true}, writeStream(function (s, enc, cb) {
    actual += s
    cb()
  }))

  var i = 44
  while (i--) {
    normal.info('h')
    extreme.info('h')
  }

  t.is(actual, expected)
  os.hostname = hostname
  Date.now = now
  global.process = proc
  t.end()
})
<|endoftext|>


<commit_before>/* istanbul ignore next */
describe('recovery', function () {
  'use strict';

  var assume = require('assume')
    , Recovery = require('./')
    , recovery;

  beforeEach(function () {
    recovery = new Recovery();
  });

  afterEach(function () {
    recovery.reset();
  });

  this.timeout(60000);

  it('is exported as a function', function () {
    assume(Recovery).is.a('function');
  });

  it('returns a new instance if constructed without new', function () {
    assume(Recovery()).is.instanceOf(Recovery);
  });

  describe('#reconnect', function () {
    it('emits `reconnect scheduled` when starting', function (next) {
      recovery.once('reconnect scheduled', function (opts) {
        assume(opts).is.a('object');
        assume(opts.attempt).to.equal(1);
        assume(opts.retries).to.equal(recovery.retries);
        assume(opts.max).to.equal(recovery.max);
        assume(opts.mix).to.equal(recovery.mix);
        assume(opts.scheduled).is.least(opts.min);
        assume(opts.scheduled).is.most(opts.max);
        assume(opts.duration).is.equal(0);

        next();
      });

      recovery.reconnect();
    });

    it('emits `reconnect` when you need to start the reconnect', function (next) {
      recovery.once('reconnect', function (opts) {
        assume(opts).is.a('object');
        assume(opts.attempt).to.equal(1);
        assume(opts.retries).to.equal(recovery.retries);
        assume(opts.max).to.equal(recovery.max);
        assume(opts.mix).to.equal(recovery.mix);
        assume(opts.scheduled).is.least(opts.min);
        assume(opts.scheduled).is.most(opts.max);

        next();
      });

      recovery.reconnect();
    });

    it('emits `reconnect timeout` when the reconnect attempt timed out', function (next) {
      recovery.once('reconnect timeout', function (err, opts) {
        assume(err).is.a('error');
        assume(err.message).contains('time');

        assume(opts).is.a('object');
        assume(opts.attempt).to.equal(1);
        assume(opts.retries).to.equal(recovery.retries);
        assume(opts.max).to.equal(recovery.max);
        assume(opts.mix).to.equal(recovery.mix);
        assume(opts.scheduled).is.least(opts.min);
        assume(opts.scheduled).is.most(opts.max);

        next();
      });

      recovery['reconnect timeout'] = 100;
      recovery.reconnect();
    });

    it('emits `reconnect failed` when all attempts failed', function (next) {
      var attempts = 0
        , start = Date.now();

      recovery.on('reconnect scheduled', function (opts) {
        attempts++;

        assume(opts.attempt).to.equal(attempts);
        assume(opts.retries).to.equal(recovery.retries);
        assume(opts.max).to.equal(recovery.max);
        assume(opts.mix).to.equal(recovery.mix);
        assume(opts.scheduled).is.least(opts.min);
        assume(opts.scheduled).is.most(opts.max);

        if (attempts === 1) return;

        assume(opts.duration).to.most(Date.now() - start);
        assume(opts.duration).to.least((Date.now() - start) - 10);
      });

      recovery.on('reconnect timeout', function (err, opts) {
        assume(opts.attempt).to.equal(attempts);
      });

      recovery.on('reconnect failed', function (err, opts) {
        assume(err).is.a('error');
        assume(err.message).contains('recover');

        assume(opts.attempt).to.equal(recovery.retries);
        assume(opts.attempt).to.equal(opts.retries);
        assume(opts.duration).to.most(Date.now() - start);
        assume(opts.duration).to.least((Date.now() - start) - 10);

        assume(recovery._fn).to.equal(null);

        next();
      });

      recovery['reconnect timeout'] = 100;
      recovery.max = 2000;
      recovery.reconnect();
    });

    it('emits a `reconnected` event for a successful connection', function (next) {
      var start = Date.now();

      recovery.on('reconnected', function (opts) {
        assume(opts.attempt).equals(2);
        assume(opts.duration).to.most(Date.now() - start);
        assume(opts.duration).to.least((Date.now() - start) - 10);

        assume(recovery._fn).to.equal(null);

        next();
      });

      recovery.on('reconnect', function (opts) {
        if (opts.attempt === 1) return setTimeout(function () {
          recovery.reconnected(new Error('Nope, we failed'));
        }, 50);

        setTimeout(function () {
          recovery.reconnected();
        }, 50);
      });

      recovery['reconnect timeout'] = 100;
      recovery.reconnect();
    });

    it('can use the .reconnected API', function (next) {
      var start = Date.now();

      recovery.on('reconnected', function (opts) {
        assume(opts.attempt).equals(2);
        assume(opts.duration).to.most(Date.now() - start);
        assume(opts.duration).to.least((Date.now() - start) - 10);

        assume(recovery._fn).to.equal(null);

        next();
      });

      recovery.on('reconnect', function (opts) {
        if (opts.attempt === 1) return setTimeout(function () {
          recovery.reconnected(new Error('Shit broke'));
        }, 50);

        setTimeout(function () {
          recovery.reconnected();
        }, 50);
      });

      recovery['reconnect timeout'] = 100;
      recovery.reconnect();
    });

    it('can call the reconnected API when no attempt is running', function () {
      recovery.on('reconnected', function () {
        throw new Error('I should not be triggered');
      });

      recovery.reconnected();
    });

    it('doesnt allow another reconnection attempt while busy', function (next) {
      var attempts = 0;

      recovery.on('reconnect', function () {
        recovery.reconnected();
      });

      recovery.on('reconnected', function () {
        next();
      });

      recovery.on('reconnect scheduled', function (fn, opts) {
        attempts++;

        if (attempts > 1) throw new Error('I should only reconnect once');
      });

      recovery['reconnect timeout'] = 100;
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
    });
  });

  describe('#reconnecting', function () {
    it('returns a boolean', function (next) {
      assume(recovery.reconnecting()).is.false();

      recovery.on('reconnected', function (opts) {
        assume(recovery.reconnecting()).is.false();
        next();
      });

      recovery.on('reconnect scheduled', function () {
        assume(recovery.reconnecting()).is.true();
      });

      recovery.on('reconnect', function (opts) {
        assume(recovery.reconnecting()).is.true();

        setTimeout(function () {
         recovery.reconnected();
        }, 50);
      });

      recovery['reconnect timeout'] = 100;
      recovery.reconnect();
      assume(recovery.reconnecting()).is.true();
    });
  });

  describe('#reset', function () {
    it('only removes our assigned listeners', function (next) {
      recovery.timers.setTimeout('next', next, 25);
      recovery.reconnect();

      setTimeout(function () {
        recovery.reset();
        assume(recovery._fn).equals(null);
        assume(recovery.attempt).equals(null);

        assume(recovery.timers.active('reconnect')).is.false();
        assume(recovery.timers.active('timeout')).is.false();
        assume(recovery.timers.active('next')).is.true();
      }, 0);
    });
  });
});
<commit_msg>[test] Fix tests for older browsers<commit_after>/* istanbul ignore next */
describe('recovery', function () {
  'use strict';

  var assume = require('assume')
    , Recovery = require('./')
    , recovery;

  beforeEach(function () {
    recovery = new Recovery();
  });

  afterEach(function () {
    recovery.reset();
  });

  this.timeout(60000);

  it('is exported as a function', function () {
    assume(Recovery).is.a('function');
  });

  it('returns a new instance if constructed without new', function () {
    assume(Recovery()).is.instanceOf(Recovery);
  });

  describe('#reconnect', function () {
    it('emits `reconnect scheduled` when starting', function (next) {
      recovery.once('reconnect scheduled', function (opts) {
        assume(opts).is.a('object');
        assume(opts.attempt).to.equal(1);
        assume(opts.retries).to.equal(recovery.retries);
        assume(opts.max).to.equal(recovery.max);
        assume(opts.mix).to.equal(recovery.mix);
        assume(opts.scheduled).is.least(opts.min);
        assume(opts.scheduled).is.most(opts.max);
        assume(opts.duration).is.equal(0);

        next();
      });

      recovery.reconnect();
    });

    it('emits `reconnect` when you need to start the reconnect', function (next) {
      recovery.once('reconnect', function (opts) {
        assume(opts).is.a('object');
        assume(opts.attempt).to.equal(1);
        assume(opts.retries).to.equal(recovery.retries);
        assume(opts.max).to.equal(recovery.max);
        assume(opts.mix).to.equal(recovery.mix);
        assume(opts.scheduled).is.least(opts.min);
        assume(opts.scheduled).is.most(opts.max);

        next();
      });

      recovery.reconnect();
    });

    it('emits `reconnect timeout` when the reconnect attempt timed out', function (next) {
      recovery.once('reconnect timeout', function (err, opts) {
        assume(err).is.a('error');
        assume(err.message).contains('time');

        assume(opts).is.a('object');
        assume(opts.attempt).to.equal(1);
        assume(opts.retries).to.equal(recovery.retries);
        assume(opts.max).to.equal(recovery.max);
        assume(opts.mix).to.equal(recovery.mix);
        assume(opts.scheduled).is.least(opts.min);
        assume(opts.scheduled).is.most(opts.max);

        next();
      });

      recovery['reconnect timeout'] = 100;
      recovery.reconnect();
    });

    it('emits `reconnect failed` when all attempts failed', function (next) {
      var start = +new Date()
        , attempts = 0;

      recovery.on('reconnect scheduled', function (opts) {
        var elapsed = +new Date() - start;

        attempts++;

        assume(opts.attempt).to.equal(attempts);
        assume(opts.retries).to.equal(recovery.retries);
        assume(opts.max).to.equal(recovery.max);
        assume(opts.mix).to.equal(recovery.mix);
        assume(opts.scheduled).is.least(opts.min);
        assume(opts.scheduled).is.most(opts.max);

        if (attempts === 1) return;

        assume(opts.duration).is.lte(elapsed);
        assume(opts.duration).is.gte(elapsed - 20);
      });

      recovery.on('reconnect timeout', function (err, opts) {
        assume(opts.attempt).to.equal(attempts);
      });

      recovery.on('reconnect failed', function (err, opts) {
        var elapsed = +new Date() - start;

        assume(err).is.a('error');
        assume(err.message).contains('recover');

        assume(opts.attempt).to.equal(recovery.retries);
        assume(opts.attempt).to.equal(opts.retries);
        assume(opts.duration).is.lte(elapsed);
        assume(opts.duration).is.gte(elapsed - 20);

        assume(recovery._fn).to.equal(null);

        next();
      });

      recovery['reconnect timeout'] = 100;
      recovery.max = 2000;
      recovery.reconnect();
    });

    it('emits a `reconnected` event for a successful connection', function (next) {
      var start = +new Date();

      recovery.on('reconnected', function (opts) {
        var elapsed = +new Date() - start;

        assume(opts.attempt).equals(2);
        assume(opts.duration).is.lte(elapsed);
        assume(opts.duration).is.gte(elapsed - 20);

        assume(recovery._fn).to.equal(null);

        next();
      });

      recovery.on('reconnect', function (opts) {
        if (opts.attempt === 1) return setTimeout(function () {
          recovery.reconnected(new Error('Nope, we failed'));
        }, 50);

        setTimeout(function () {
          recovery.reconnected();
        }, 50);
      });

      recovery['reconnect timeout'] = 100;
      recovery.reconnect();
    });

    it('can use the .reconnected API', function (next) {
      var start = +new Date();

      recovery.on('reconnected', function (opts) {
        var elapsed = +new Date() - start;

        assume(opts.attempt).equals(2);
        assume(opts.duration).is.lte(elapsed);
        assume(opts.duration).is.gte(elapsed - 20);

        assume(recovery._fn).to.equal(null);

        next();
      });

      recovery.on('reconnect', function (opts) {
        if (opts.attempt === 1) return setTimeout(function () {
          recovery.reconnected(new Error('Shit broke'));
        }, 50);

        setTimeout(function () {
          recovery.reconnected();
        }, 50);
      });

      recovery['reconnect timeout'] = 100;
      recovery.reconnect();
    });

    it('can call the reconnected API when no attempt is running', function () {
      recovery.on('reconnected', function () {
        throw new Error('I should not be triggered');
      });

      recovery.reconnected();
    });

    it('doesnt allow another reconnection attempt while busy', function (next) {
      var attempts = 0;

      recovery.on('reconnect', function () {
        recovery.reconnected();
      });

      recovery.on('reconnected', function () {
        next();
      });

      recovery.on('reconnect scheduled', function () {
        attempts++;

        if (attempts > 1) throw new Error('I should only reconnect once');
      });

      recovery['reconnect timeout'] = 100;
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
      recovery.reconnect();
    });
  });

  describe('#reconnecting', function () {
    it('returns a boolean', function (next) {
      assume(recovery.reconnecting()).equals(false);

      recovery.on('reconnected', function () {
        assume(recovery.reconnecting()).equals(false);
        next();
      });

      recovery.on('reconnect scheduled', function () {
        assume(recovery.reconnecting()).equals(true);
      });

      recovery.on('reconnect', function () {
        assume(recovery.reconnecting()).equals(true);

        setTimeout(function () {
          recovery.reconnected();
        }, 50);
      });

      recovery['reconnect timeout'] = 100;
      recovery.reconnect();
      assume(recovery.reconnecting()).equals(true);
    });
  });

  describe('#reset', function () {
    it('only removes our assigned listeners', function (next) {
      recovery.timers.setTimeout('next', next, 25);
      recovery.reconnect();

      setTimeout(function () {
        recovery.reset();
        assume(recovery._fn).equals(null);
        assume(recovery.attempt).equals(null);

        assume(recovery.timers.active('reconnect')).equals(false);
        assume(recovery.timers.active('timeout')).equals(false);
        assume(recovery.timers.active('next')).equals(true);
      }, 0);
    });
  });
});
<|endoftext|>


<commit_before>'use strict';
require('co-mocha');
var sinon = require('sinon');
var assertSpy = sinon.assert;
var assert = require('assert');
var proxyquire = require('proxyquire');

var promiseResolver = require('./');
var noPromiseResolver = proxyquire('./', {'native-or-bluebird/promise': false});

var resolve;
var reject;
var cb;
var resolver;
var PromiseStub;

function timeout(delay) {
	return new Promise(resolve => setTimeout(resolve, delay || 0));
}

beforeEach(() => {
	resolve = sinon.spy();
	reject = sinon.spy();
	cb = sinon.spy();

	PromiseStub = sinon.spy(function (fn) {
		fn(resolve, reject);
		return {
			then: sinon.spy(),
			catch: sinon.spy()
		};
	});
});

it('rejects with first argument', function () {
	resolver = promiseResolver(resolve, reject);
	var err = new Error('err');
	resolver(err, 'hello!');
	assertSpy.notCalled(resolve);
	assertSpy.calledOnce(reject);
	assertSpy.calledWith(reject, err);
});

it('resolves with second argument', function () {
	resolver = promiseResolver(resolve, reject);
	resolver(null, 'howdy!');
	assertSpy.notCalled(reject);
	assertSpy.calledOnce(resolve);
	assertSpy.calledWith(resolve, 'howdy!');
});

it('calls callback with error', function *() {
	resolver = promiseResolver(null, null, cb);
	var err = new Error('err');
	resolver(err, 'hello!');
	yield timeout();
	assertSpy.calledOnce(cb);
	assertSpy.calledWith(cb, err, 'hello!');
});

it('calls callback with result', function *() {
	resolver = promiseResolver(null, null, cb);
	resolver(null, 'hello!');
	yield timeout();
	assertSpy.calledOnce(cb);
	assertSpy.calledWith(cb, null, 'hello!');
});

it('calls reject and callback with error', function *() {
	resolver = promiseResolver(resolve, reject, cb);
	var err = new Error('err');
	resolver(err, 'hello!');
	yield timeout();
	assertSpy.notCalled(resolve);
	assertSpy.calledOnce(reject);
	assertSpy.calledWith(reject, err);
	assertSpy.calledOnce(cb);
	assertSpy.calledWith(cb, err, 'hello!');
});

it('calls resolve and callback with result', function *() {
	resolver = promiseResolver(resolve, reject, cb);
	resolver(null, 'goodbye!');
	yield timeout();
	assertSpy.notCalled(reject);
	assertSpy.calledOnce(resolve);
	assertSpy.calledWith(resolve, 'goodbye!');
	assertSpy.calledOnce(cb);
	assertSpy.calledWith(cb, null, 'goodbye!');
});

it('will only call cb once', function *() {
	resolver = promiseResolver(resolve, reject, cb);
	resolver(null, 'goodbye!');
	yield timeout();
	assertSpy.calledOnce(cb);
	resolver(null, 'hello!');
	yield timeout();
	assertSpy.calledOnce(cb);
	assertSpy.calledWith(cb, null, 'goodbye!');
});

it('defer() creates a defer object', function *() {
	var defer = promiseResolver.defer(cb, PromiseStub);
	resolver = defer.cb;
	assert.strictEqual(typeof defer.resolve, 'function');
	assert.strictEqual(typeof defer.reject, 'function');
	assert.strictEqual(typeof defer.promise.then, 'function');
	assert.strictEqual(typeof defer.promise.catch, 'function');

	resolver(null, 'goodbye!');
	yield timeout();

	assertSpy.notCalled(reject);
	assertSpy.calledOnce(resolve);
	assertSpy.calledWith(resolve, 'goodbye!');
	assertSpy.calledOnce(cb);
	assertSpy.calledWith(cb, null, 'goodbye!');
});

it('defer() suppresses unhandledRejection if cb is provided', function *() {
	var spy = sinon.spy();
	process.once('unhandledRejection', spy);
	promiseResolver.defer(cb).cb(new Error('hello'));
	yield timeout();
	assertSpy.notCalled(spy);
});

it('defer() does NOT suppress unhandledRejection if cb is NOT provided', function *() {
	var spy = sinon.spy();
	process.once('unhandledRejection', spy);
	promiseResolver.defer().cb(new Error('hello'));
	yield timeout();
	assertSpy.called(spy);
});

it('defer().reject will call callback with error as first arg', function *() {
	promiseResolver.defer(cb).reject(new Error('defer.reject'));
	yield timeout();
	assertSpy.calledWith(cb, sinon.match.has('message', 'defer.reject'));
});

it('defer().resolve will result to callback as second arg', function *() {
	promiseResolver.defer(cb).resolve('hello');
	yield timeout();
	assertSpy.calledWith(cb, null, 'hello');
});

it('defer().resolve works using a callback even if there is no installed promise implementation', function *() {
	noPromiseResolver.defer(cb).resolve('hello');
	yield timeout();
	assertSpy.calledWith(cb, null, 'hello');
});

it('defer().reject works using a callback even if there is no installed promise implementation', function *() {
	noPromiseResolver.defer(cb).reject(new Error('uh oh'));
	yield timeout();
	assertSpy.calledWith(cb, sinon.match.has('message', 'uh oh'));
});

it('defer().reject(null) rejects a promise, even though error is falsie', function *() {
	promiseResolver.defer(cb, PromiseStub).reject(null);
	yield timeout();
	assertSpy.calledWith(cb, sinon.match.has('message', 'reject called with falsie reason'));
	assertSpy.calledWith(reject, sinon.match.has('message', 'reject called with falsie reason'));
});

it('defer() will throw without an installed promise implementation or supplied callback', function () {
	assert.throws(function () {
		noPromiseResolver.defer();
	}, /No Promise Implementation/);
});
<commit_msg>increase setTimeout delay in tests (increase stability).<commit_after>'use strict';
require('co-mocha');
var sinon = require('sinon');
var assertSpy = sinon.assert;
var assert = require('assert');
var proxyquire = require('proxyquire');

var promiseResolver = require('./');
var noPromiseResolver = proxyquire('./', {'native-or-bluebird/promise': false});

var resolve;
var reject;
var cb;
var resolver;
var PromiseStub;

function timeout(delay) {
	return new Promise(resolve => setTimeout(resolve, typeof delay === 'number' ? delay : 30));
}

beforeEach(() => {
	resolve = sinon.spy();
	reject = sinon.spy();
	cb = sinon.spy();

	PromiseStub = sinon.spy(function (fn) {
		fn(resolve, reject);
		return {
			then: sinon.spy(),
			catch: sinon.spy()
		};
	});
});

it('rejects with first argument', function () {
	resolver = promiseResolver(resolve, reject);
	var err = new Error('err');
	resolver(err, 'hello!');
	assertSpy.notCalled(resolve);
	assertSpy.calledOnce(reject);
	assertSpy.calledWith(reject, err);
});

it('resolves with second argument', function () {
	resolver = promiseResolver(resolve, reject);
	resolver(null, 'howdy!');
	assertSpy.notCalled(reject);
	assertSpy.calledOnce(resolve);
	assertSpy.calledWith(resolve, 'howdy!');
});

it('calls callback with error', function *() {
	resolver = promiseResolver(null, null, cb);
	var err = new Error('err');
	resolver(err, 'hello!');
	yield timeout();
	assertSpy.calledOnce(cb);
	assertSpy.calledWith(cb, err, 'hello!');
});

it('calls callback with result', function *() {
	resolver = promiseResolver(null, null, cb);
	resolver(null, 'hello!');
	yield timeout();
	assertSpy.calledOnce(cb);
	assertSpy.calledWith(cb, null, 'hello!');
});

it('calls reject and callback with error', function *() {
	resolver = promiseResolver(resolve, reject, cb);
	var err = new Error('err');
	resolver(err, 'hello!');
	yield timeout();
	assertSpy.notCalled(resolve);
	assertSpy.calledOnce(reject);
	assertSpy.calledWith(reject, err);
	assertSpy.calledOnce(cb);
	assertSpy.calledWith(cb, err, 'hello!');
});

it('calls resolve and callback with result', function *() {
	resolver = promiseResolver(resolve, reject, cb);
	resolver(null, 'goodbye!');
	yield timeout();
	assertSpy.notCalled(reject);
	assertSpy.calledOnce(resolve);
	assertSpy.calledWith(resolve, 'goodbye!');
	assertSpy.calledOnce(cb);
	assertSpy.calledWith(cb, null, 'goodbye!');
});

it('will only call cb once', function *() {
	resolver = promiseResolver(resolve, reject, cb);
	resolver(null, 'goodbye!');
	yield timeout();
	assertSpy.calledOnce(cb);
	resolver(null, 'hello!');
	yield timeout();
	assertSpy.calledOnce(cb);
	assertSpy.calledWith(cb, null, 'goodbye!');
});

it('defer() creates a defer object', function *() {
	var defer = promiseResolver.defer(cb, PromiseStub);
	resolver = defer.cb;
	assert.strictEqual(typeof defer.resolve, 'function');
	assert.strictEqual(typeof defer.reject, 'function');
	assert.strictEqual(typeof defer.promise.then, 'function');
	assert.strictEqual(typeof defer.promise.catch, 'function');

	resolver(null, 'goodbye!');
	yield timeout();

	assertSpy.notCalled(reject);
	assertSpy.calledOnce(resolve);
	assertSpy.calledWith(resolve, 'goodbye!');
	assertSpy.calledOnce(cb);
	assertSpy.calledWith(cb, null, 'goodbye!');
});

it('defer() suppresses unhandledRejection if cb is provided', function *() {
	var spy = sinon.spy();
	process.once('unhandledRejection', spy);
	promiseResolver.defer(cb).cb(new Error('hello'));
	yield timeout();
	assertSpy.notCalled(spy);
});

it('defer() does NOT suppress unhandledRejection if cb is NOT provided', function *() {
	var spy = sinon.spy();
	process.once('unhandledRejection', spy);
	promiseResolver.defer().cb(new Error('hello'));
	yield timeout();
	assertSpy.called(spy);
});

it('defer().reject will call callback with error as first arg', function *() {
	promiseResolver.defer(cb).reject(new Error('defer.reject'));
	yield timeout();
	assertSpy.calledWith(cb, sinon.match.has('message', 'defer.reject'));
});

it('defer().resolve will result to callback as second arg', function *() {
	promiseResolver.defer(cb).resolve('hello');
	yield timeout();
	assertSpy.calledWith(cb, null, 'hello');
});

it('defer().resolve works using a callback even if there is no installed promise implementation', function *() {
	noPromiseResolver.defer(cb).resolve('hello');
	yield timeout();
	assertSpy.calledWith(cb, null, 'hello');
});

it('defer().reject works using a callback even if there is no installed promise implementation', function *() {
	noPromiseResolver.defer(cb).reject(new Error('uh oh'));
	yield timeout();
	assertSpy.calledWith(cb, sinon.match.has('message', 'uh oh'));
});

it('defer().reject(null) rejects a promise, even though error is falsie', function *() {
	promiseResolver.defer(cb, PromiseStub).reject(null);
	yield timeout();
	assertSpy.calledWith(cb, sinon.match.has('message', 'reject called with falsie reason'));
	assertSpy.calledWith(reject, sinon.match.has('message', 'reject called with falsie reason'));
});

it('defer() will throw without an installed promise implementation or supplied callback', function () {
	assert.throws(function () {
		noPromiseResolver.defer();
	}, /No Promise Implementation/);
});
<|endoftext|>


<commit_before>const test = require('ava');
const random = require('./helpers/random');
const all = require('./products');

test('all()', t => {
  t.true(all.length > 0);
});

test('random()', t => {
  t.truthy(random(all));
  t.not(random(all), random(all));
});
<commit_msg>🤖(break): 2017-12-4 01:46:59<commit_after>const test = require('ava');
const random = require('./helpers/random');
const all = require('./products');

test('all()', t => {
  t.true(all.length < 0);
});

test('random()', t => {
  t.truthy(random(all));
  t.not(random(all), random(all));
});
<|endoftext|>


<commit_before>var cproc = require('child_process');
var util = require('util');
var _ = require('underscore')._;
_.mixin(require('underscore.string'));

var Timer = (function() {
  var Timer = require('./proto').proto();
  function time() { return (new Date()).getTime(); }
  Timer.init = function() {
    this._t = time();
  };
  Timer.elapsed = function() {
    return time() - this._t;
  };
  return Timer;
})();

exports.Timer = Timer;

function rtrim(s) {
	return s.replace(/\s+$/, '');
}

var color = require("./ansi-color").set;

var shutdownCallback;
exports.onShutdown = function(cb) { shutdownCallback = cb; };

function shutdown(signal) {
  if (signal !== 'exit') { info('Received ' + signal +'.'); }
  killLaunchedProcesses();
  if (shutdownCallback) { shutdownCallback(signal); }
  if (signal !== 'exit') { process.exit(); }
}

process.on('SIGTERM', function() { shutdown('SIGTERM'); });
process.on('SIGHUP', function() { shutdown('SIGHUP'); });
process.on('exit', function () { shutdown('exit'); });

var launchedProcesses = [];

function addLaunchedProcess(proc) {
  launchedProcesses.push(proc);
}

function removeLaunchedProcess(proc) {
  launchedProcesses = _.without(launchedProcesses, proc);
}

function killLaunchedProcesses() {
  _.each(launchedProcesses, function(child) {
    verbose('Killing host process ' + child.pid);
    child.kill();
  });
  launchedProcesses = [];
}

function exec2(cmd, args, opts, cb) {
  var simple = _.prune(cmd + ' ' + args.join(' '), 80);
  var printFn = (opts.verbose ? info : verbose);
  printFn('exec2: ' + simple + ' ' + util.inspect(opts));
  if (!opts || !opts.cwd) {
    error('cwd not specified in ' + simple);
  }
  var proc = cproc.spawn.call(this, cmd, args, opts),
      out = [],
      err = [],
      t = Timer.make();
  function log(x) {
    process.stdout.write(x + '');
  }
  var lineBuffer = '';
  proc.stdout.on('data', function (data) {
    if (opts.pipe || opts.pipeStdout) { log(data); }
    var lineBuffer = lineBuffer + data;
    while (true) {
      var lineMatch = lineBuffer.match(/.+/);
      if (lineMatch) {
        proc.stdout.emit(lineMatch[0]);
        lineBuffer = lineBuffer.replace(/.*/, '');
      } else {
        break;
      }
    }
    proc.emit('stdout', data);
    out.push(data);
  });
  proc.stderr.on('data', function (data) {
    if (!opts.quietError) {
      //process.stderr.write(color('    error in ' + simple + ':\n', 'black', true) + color(data + '', 'red'));
      log(data);
    }
    proc.emit('stderr', data);
    err.push(data);
  });
  proc.on('exit', function (code) {
    printFn(t.elapsed() + '  completed2: ' + simple + (code ? ' (' + code + ')' : ''));
    if (cb) {
      cb(code, out.join(''), err.join(''));
    }
    removeLaunchedProcess(proc);
  });
  addLaunchedProcess(proc);
  return proc;
}

function exec(cmd, opts, cb) {
  if (opts && opts.length !== undefined) {
    return exec2.apply(this, arguments);
  } else {
    info('exec: ' + cmd);
    var t = Timer.make();
    var proc = cproc.exec(cmd, opts, function(error, stdout, stderr) {
      info(t.elapsed() + '  completed ' + cmd);
      if (error) { error('error: ' + error); }
      info(stderr);
      if (cb) { cb.apply(this, arguments); }
      removeLaunchedProcess(proc);
    });
    addLaunchedProcess(proc);
  }
}

exports.exec = exec;
<commit_msg>Making awesome, duh.<commit_after>var cproc = require('child_process');
var util = require('util');
var _ = require('underscore')._;
_.mixin(require('underscore.string'));

var Timer = (function() {
  var Timer = require('./proto').proto();
  function time() { return (new Date()).getTime(); }
  Timer.init = function() {
    this._t = time();
  };
  Timer.elapsed = function() {
    return time() - this._t;
  };
  return Timer;
})();

exports.Timer = Timer;

function rtrim(s) {
	return s.replace(/\s+$/, '');
}

var color = require("./ansi-color").set;

var shutdownCallback;
exports.onShutdown = function(cb) { shutdownCallback = cb; };

function shutdown(signal) {
  if (signal !== 'exit') { info('Received ' + signal +'.'); }
  killLaunchedProcesses();
  if (shutdownCallback) { shutdownCallback(signal); }
  if (signal !== 'exit') { process.exit(); }
}

process.on('SIGTERM', function() { shutdown('SIGTERM'); });
process.on('SIGHUP', function() { shutdown('SIGHUP'); });
process.on('exit', function () { shutdown('exit'); });

var launchedProcesses = [];

function addLaunchedProcess(proc) {
  launchedProcesses.push(proc);
}

function removeLaunchedProcess(proc) {
  launchedProcesses = _.without(launchedProcesses, proc);
}

function killLaunchedProcesses() {
  _.each(launchedProcesses, function(child) {
    verbose('Killing host process ' + child.pid);
    child.kill();
  });
  launchedProcesses = [];
}

function exec2(cmd, args, opts, cb) {
  var simple = _.prune(cmd + ' ' + args.join(' '), 80);
  var printFn = (opts.verbose ? info : verbose);
  printFn('exec2: ' + simple + ' ' + util.inspect(opts));
  if (!opts || !opts.cwd) {
    error('cwd not specified in ' + simple);
  }
  var proc = cproc.spawn.call(this, cmd, args, opts),
      out = [],
      err = [],
      t = Timer.make();
  function log(x) {
    process.stdout.write(x + '');
  }
  var lineBuffer = '';
  proc.stdout.on('data', function (data) {
    if (opts.pipe || opts.pipeStdout) { log(data); }
    var lineBuffer = lineBuffer + data;
    while (true) {
      var lineMatch = lineBuffer.match(/.+/);
      if (lineMatch) {
        proc.stdout.emit(lineMatch[0]);
        lineBuffer = lineBuffer.replace(/.+/, '');
      } else {
        break;
      }
    }
    proc.emit('stdout', data);
    out.push(data);
  });
  proc.stderr.on('data', function (data) {
    if (!opts.quietError) {
      //process.stderr.write(color('    error in ' + simple + ':\n', 'black', true) + color(data + '', 'red'));
      log(data);
    }
    proc.emit('stderr', data);
    err.push(data);
  });
  proc.on('exit', function (code) {
    printFn(t.elapsed() + '  completed2: ' + simple + (code ? ' (' + code + ')' : ''));
    if (cb) {
      cb(code, out.join(''), err.join(''));
    }
    removeLaunchedProcess(proc);
  });
  addLaunchedProcess(proc);
  return proc;
}

function exec(cmd, opts, cb) {
  if (opts && opts.length !== undefined) {
    return exec2.apply(this, arguments);
  } else {
    info('exec: ' + cmd);
    var t = Timer.make();
    var proc = cproc.exec(cmd, opts, function(error, stdout, stderr) {
      info(t.elapsed() + '  completed ' + cmd);
      if (error) { error('error: ' + error); }
      info(stderr);
      if (cb) { cb.apply(this, arguments); }
      removeLaunchedProcess(proc);
    });
    addLaunchedProcess(proc);
  }
}

exports.exec = exec;
<|endoftext|>


<commit_before>
<commit_msg>Delete test.js<commit_after><|endoftext|>


<commit_before>'use strict';
var test = require('tape');
var childProcess = require('child_process');

test('User name validation check', function (t) {
	t.plan(1);
	childProcess.execFile('./cli.js', [''], {cwd: __dirname}, function (err, stdout) {
		t.equal('User name required', stdout, 'Both strings are equal');
	});
});<commit_msg>xo resolved<commit_after>'use strict';
var test = require('tape');
var childProcess = require('child_process');

test('User name validation check', function (t) {
	t.plan(1);
	childProcess.execFile('./cli.js', [''], {cwd: __dirname}, function (err, stdout) {
		t.equal('User name required', stdout, 'Both strings are equal');
	});
});
<|endoftext|>