contractis
Advanced tools
Comparing version 0.0.12 to 0.0.13
@@ -64,3 +64,3 @@ const gen = require("./generators"); | ||
const isPromise = contr => | ||
const isPromise = (contr) => | ||
get_arguments_returns(contr).returns && | ||
@@ -67,0 +67,0 @@ get_arguments_returns(contr).returns.contract_name === "promise"; |
@@ -6,3 +6,3 @@ var stackTrace = require("stack-trace"); | ||
get_arguments_returns, | ||
ContractViolation | ||
ContractViolation, | ||
} = require("./util.js"); | ||
@@ -79,3 +79,3 @@ | ||
var pr_rv = rv; | ||
rv = pr_rv.then(v => { | ||
rv = pr_rv.then((v) => { | ||
check_contract( | ||
@@ -102,3 +102,3 @@ opts.returns.options, | ||
const contract_class = that => { | ||
const contract_class = (that) => { | ||
if (!enabled) return; | ||
@@ -194,3 +194,3 @@ const proto = Object.getPrototypeOf(that); | ||
var callert = trace.find( | ||
t => !t.getFileName().includes("contractis/contract.js") | ||
(t) => !t.getFileName().includes("contractis/contract.js") | ||
); | ||
@@ -197,0 +197,0 @@ var caller = `${callert.getFunctionName()} (${callert.getFileName()}:${callert.getLineNumber()})`; |
@@ -9,6 +9,6 @@ const bool = () => Math.random() > 0.5; | ||
const generate_from = contr => | ||
const generate_from = (contr) => | ||
contr.generate ? contr.generate() : rejection_sample(contr); | ||
const oneOf = vs => vs[Math.floor(Math.random() * vs.length)]; | ||
const oneOf = (vs) => vs[Math.floor(Math.random() * vs.length)]; | ||
@@ -43,3 +43,3 @@ const ntimes = (n, f) => { | ||
const array = g => () => { | ||
const array = (g) => () => { | ||
const n = Math.round(num_between(0, 20)); | ||
@@ -49,3 +49,3 @@ return ntimes(n, g); | ||
const konst = x => () => x; | ||
const konst = (x) => () => x; | ||
@@ -61,3 +61,3 @@ const anyObj = () => { | ||
const obj = o => () => { | ||
const obj = (o) => () => { | ||
var res = {}; | ||
@@ -79,12 +79,12 @@ Object.entries(o).forEach(([k, v]) => { | ||
anyObj, | ||
date | ||
date, | ||
])(); | ||
const gen_arguments = args => { | ||
const gen_arguments = (args) => { | ||
if (!args) return []; | ||
const argumentcs = Array.isArray(args) ? args : [args]; | ||
return argumentcs.map(c => generate_from(c)); | ||
return argumentcs.map((c) => generate_from(c)); | ||
}; | ||
const generate_class = cls => () => { | ||
const generate_class = (cls) => () => { | ||
const contr = cls.contract; | ||
@@ -123,3 +123,3 @@ const cargs = contr.constructs ? gen_arguments(contr.constructs) : []; | ||
accept_if, | ||
date | ||
date, | ||
}; |
160
is.js
const gen = require("./generators"); | ||
const check_contract = require("./check"); | ||
const isnum = x => typeof x === "number"; | ||
const isnum = (x) => typeof x === "number"; | ||
const mkContract = c => { | ||
const mkContract = (c) => { | ||
function checker(x) { | ||
@@ -19,7 +19,7 @@ check_contract(checker, x, "value check", undefined, checker); | ||
const number = opts => | ||
const number = (opts) => | ||
mkContract({ | ||
name: "number", | ||
options: opts, | ||
check: x => | ||
check: (x) => | ||
typeof x === "number" && | ||
@@ -35,11 +35,11 @@ (isnum((opts || {}).lte) ? x <= opts.lte : true) && | ||
? opts.gte + gen.num_positive | ||
: gen.any_num() | ||
: gen.any_num(), | ||
}); | ||
const integer = opts => | ||
const integer = (opts) => | ||
mkContract({ | ||
name: "integer", | ||
options: opts, | ||
check: x => number(opts).check(x) && x === Math.round(x), | ||
generate: () => Math.round(number(opts).generate()) | ||
check: (x) => number(opts).check(x) && x === Math.round(x), | ||
generate: () => Math.round(number(opts).generate()), | ||
}); | ||
@@ -49,4 +49,4 @@ | ||
name: "positive", | ||
check: x => typeof x === "number" && x >= 0, | ||
generate: gen.num_positive | ||
check: (x) => typeof x === "number" && x >= 0, | ||
generate: gen.num_positive, | ||
}); | ||
@@ -58,11 +58,11 @@ | ||
options: [args, ret], | ||
check: x => typeof x === "function" | ||
check: (x) => typeof x === "function", | ||
}); | ||
const getter = ret => fun(null, ret); | ||
const getter = (ret) => fun(null, ret); | ||
const bool = mkContract({ | ||
name: "fun", | ||
check: x => typeof x === "boolean", | ||
generate: gen.bool | ||
check: (x) => typeof x === "boolean", | ||
generate: gen.bool, | ||
}); | ||
@@ -72,23 +72,23 @@ | ||
name: "defined", | ||
check: x => typeof x !== "undefined", | ||
generate: gen.reject_if(gen.any, x => typeof x === "undefined") | ||
check: (x) => typeof x !== "undefined", | ||
generate: gen.reject_if(gen.any, (x) => typeof x === "undefined"), | ||
}); | ||
const klass = cls => | ||
const klass = (cls) => | ||
mkContract({ | ||
name: "class", | ||
options: cls, | ||
check: x => | ||
check: (x) => | ||
x && | ||
x.constructor && | ||
x.constructor.name === (typeof cls === "string" ? cls : cls.name), | ||
generate: cls.contract && gen.generate_class(cls) | ||
generate: cls.contract && gen.generate_class(cls), | ||
}); | ||
const promise = t => | ||
const promise = (t) => | ||
mkContract({ | ||
name: "promise", | ||
options: typeof t === "undefined" ? any : t, | ||
check: x => x.constructor.name === Promise.name, | ||
generate: t && t.generate ? () => Promise.resolve(t.generate()) : undefined | ||
check: (x) => x.constructor.name === Promise.name, | ||
generate: t && t.generate ? () => Promise.resolve(t.generate()) : undefined, | ||
}); | ||
@@ -98,4 +98,4 @@ | ||
name: "contract", | ||
check: x => | ||
x && typeof x.contract_name === "string" && typeof x.check === "function" | ||
check: (x) => | ||
x && typeof x.contract_name === "string" && typeof x.check === "function", | ||
}); | ||
@@ -107,3 +107,3 @@ | ||
options: o, | ||
get_error_message: x => { | ||
get_error_message: (x) => { | ||
if (typeof x !== "object") | ||
@@ -124,3 +124,3 @@ return `Expected object with fields ${JSON.stringify( | ||
}, | ||
check: x => | ||
check: (x) => | ||
typeof x === "object" && | ||
@@ -134,10 +134,10 @@ x !== null && | ||
? gen.obj(o) | ||
: gen.accept_if(gen.obj(o), alsoCheckThat) | ||
: gen.accept_if(gen.obj(o), alsoCheckThat), | ||
}); | ||
const objVals = c => | ||
const objVals = (c) => | ||
mkContract({ | ||
name: "objVals", | ||
options: c, | ||
get_error_message: x => { | ||
get_error_message: (x) => { | ||
if (typeof x !== "object") return `Expected object, got type ${typeof x}`; | ||
@@ -151,4 +151,4 @@ const failing = Object.entries(x).find(([k, v]) => !c.check(c)); | ||
}, | ||
check: x => | ||
typeof x === "object" && Object.entries(x).every(([k, v]) => c.check(v)) | ||
check: (x) => | ||
typeof x === "object" && Object.entries(x).every(([k, v]) => c.check(v)), | ||
}); | ||
@@ -158,4 +158,4 @@ | ||
name: "num", | ||
check: x => typeof x === "number", | ||
generate: gen.any_num | ||
check: (x) => typeof x === "number", | ||
generate: gen.any_num, | ||
}); | ||
@@ -165,4 +165,4 @@ | ||
name: "int", | ||
check: x => typeof x === "number" && Math.round(x) === x, | ||
generate: () => Math.round(gen.any_num()) | ||
check: (x) => typeof x === "number" && Math.round(x) === x, | ||
generate: () => Math.round(gen.any_num()), | ||
}); | ||
@@ -172,4 +172,4 @@ | ||
name: "posint", | ||
check: x => typeof x === "number" && Math.round(x) === x && x >= 0, | ||
generate: () => Math.round(gen.num_positive()) | ||
check: (x) => typeof x === "number" && Math.round(x) === x && x >= 0, | ||
generate: () => Math.round(gen.num_positive()), | ||
}); | ||
@@ -179,4 +179,4 @@ | ||
name: "date", | ||
check: v => v instanceof Date && !isNaN(v), | ||
generate: gen.date | ||
check: (v) => v instanceof Date && !isNaN(v), | ||
generate: gen.date, | ||
}); | ||
@@ -186,41 +186,41 @@ | ||
name: "str", | ||
check: x => typeof x === "string", | ||
generate: gen.string | ||
check: (x) => typeof x === "string", | ||
generate: gen.string, | ||
}); | ||
const eq = v => | ||
const eq = (v) => | ||
mkContract({ | ||
name: "eq", | ||
options: v, | ||
check: x => x === v, | ||
generate: () => v | ||
check: (x) => x === v, | ||
generate: () => v, | ||
}); | ||
const one_of = vs => | ||
const one_of = (vs) => | ||
mkContract({ | ||
name: "one_of", | ||
options: vs, | ||
check: x => vs.includes(x), | ||
generate: () => gen.oneOf(vs) | ||
check: (x) => vs.includes(x), | ||
generate: () => gen.oneOf(vs), | ||
}); | ||
const lte = v => | ||
const lte = (v) => | ||
mkContract({ | ||
name: "lte", | ||
options: v, | ||
check: x => x <= v | ||
check: (x) => x <= v, | ||
}); | ||
const gte = v => | ||
const gte = (v) => | ||
mkContract({ | ||
name: "gte", | ||
options: v, | ||
check: x => x >= v | ||
check: (x) => x >= v, | ||
}); | ||
const sat = f => | ||
const sat = (f) => | ||
mkContract({ | ||
name: "sat", | ||
options: f.toString(), | ||
check: x => f(x) | ||
check: (x) => f(x), | ||
}); | ||
@@ -230,7 +230,7 @@ | ||
name: "any", | ||
check: x => true, | ||
generate: gen.any | ||
check: (x) => true, | ||
generate: gen.any, | ||
}); | ||
const maybe = c => | ||
const maybe = (c) => | ||
mkContract({ | ||
@@ -240,6 +240,6 @@ name: `maybe(${c.contract_name})`, | ||
get_error_message: c.get_error_message | ||
? x => c.get_error_message(x) | ||
? (x) => c.get_error_message(x) | ||
: undefined, | ||
check: x => typeof x === "undefined" || x === null || c.check(x), | ||
generate: () => (gen.bool() ? undefined : gen.generate_from(c)) | ||
check: (x) => typeof x === "undefined" || x === null || c.check(x), | ||
generate: () => (gen.bool() ? undefined : gen.generate_from(c)), | ||
}); | ||
@@ -249,5 +249,5 @@ | ||
mkContract({ | ||
name: `and(${contrs.map(c => c.contract_name).join()})`, | ||
get_error_message: x => { | ||
const failing = contrs.find(c => !c.check(x)); | ||
name: `and(${contrs.map((c) => c.contract_name).join()})`, | ||
get_error_message: (x) => { | ||
const failing = contrs.find((c) => !c.check(x)); | ||
return failing.options | ||
@@ -262,10 +262,10 @@ ? `${x} violates (in and) ${failing.contract_name}(${JSON.stringify( | ||
options: contrs, | ||
check: x => contrs.every(c => c.check(x)), | ||
check: (x) => contrs.every((c) => c.check(x)), | ||
generate: | ||
contrs.filter(c => c.generate).length > 0 && (() => and_gen(contrs)) | ||
contrs.filter((c) => c.generate).length > 0 && (() => and_gen(contrs)), | ||
}); | ||
function and_gen(contrs) { | ||
const val = gen.oneOf(contrs.filter(c => c.generate)).generate(); | ||
if (contrs.every(c => c.check(val))) return val; | ||
const val = gen.oneOf(contrs.filter((c) => c.generate)).generate(); | ||
if (contrs.every((c) => c.check(val))) return val; | ||
else return and_gen(contrs); | ||
@@ -276,8 +276,8 @@ } | ||
mkContract({ | ||
name: `or(${contrs.map(c => c.contract_name).join()})`, | ||
name: `or(${contrs.map((c) => c.contract_name).join()})`, | ||
options: contrs, | ||
check: x => contrs.some(c => c.check(x)), | ||
check: (x) => contrs.some((c) => c.check(x)), | ||
generate: | ||
contrs.filter(c => c.generate).length > 0 && | ||
(() => gen.oneOf(contrs.filter(c => c.generate)).generate()) | ||
contrs.filter((c) => c.generate).length > 0 && | ||
(() => gen.oneOf(contrs.filter((c) => c.generate)).generate()), | ||
}); | ||
@@ -287,18 +287,18 @@ | ||
mkContract({ | ||
name: `xor(${contrs.map(c => c.contract_name).join()})`, | ||
name: `xor(${contrs.map((c) => c.contract_name).join()})`, | ||
options: contrs, | ||
check: x => contrs.filter(c => c.check(x)).length === 1, | ||
check: (x) => contrs.filter((c) => c.check(x)).length === 1, | ||
//todo check only one is right in generate | ||
generate: | ||
contrs.filter(c => c.generate).length > 0 && | ||
(() => gen.oneOf(contrs.filter(c => c.generate)).generate()) | ||
contrs.filter((c) => c.generate).length > 0 && | ||
(() => gen.oneOf(contrs.filter((c) => c.generate)).generate()), | ||
}); | ||
const array = c => | ||
const array = (c) => | ||
mkContract({ | ||
name: "array", | ||
options: c, | ||
get_error_message: vs => { | ||
get_error_message: (vs) => { | ||
if (!Array.isArray(vs)) return `Expected Array, got type ${typeof x}`; | ||
const failingIx = vs.findIndex(v => !c.check(v)); | ||
const failingIx = vs.findIndex((v) => !c.check(v)); | ||
@@ -309,4 +309,4 @@ if (c.get_error_message) | ||
}, | ||
check: vs => Array.isArray(vs) && vs.every(v => c.check(v)), | ||
generate: c.generate && gen.array(c.generate) | ||
check: (vs) => Array.isArray(vs) && vs.every((v) => c.check(v)), | ||
generate: c.generate && gen.array(c.generate), | ||
}); | ||
@@ -343,3 +343,3 @@ | ||
contract, | ||
undefined: eq(undefined) | ||
undefined: eq(undefined), | ||
}; |
{ | ||
"name": "contractis", | ||
"version": "0.0.12", | ||
"version": "0.0.13", | ||
"description": "Design by Contract for JavaScript", | ||
@@ -21,3 +21,3 @@ "repository": "github:saltcorn/saltcorn", | ||
}, | ||
"gitHead": "88ae255c919879e321b718d9cd433781e588efd8" | ||
"gitHead": "ee69772ae35736292ea2d00933fa08f95b3b8e01" | ||
} |
70
test.js
@@ -10,3 +10,3 @@ const { contract, is, auto_test } = require("."); | ||
const add1 = x => x + 1; | ||
const add1 = (x) => x + 1; | ||
@@ -46,11 +46,11 @@ class Counter { | ||
arguments: [], | ||
returns: is.positive | ||
returns: is.positive, | ||
}, | ||
get_with_added: { | ||
arguments: [is.positive], | ||
returns: is.positive | ||
returns: is.positive, | ||
}, | ||
get_with_added1: is.fun(is.positive, is.positive), | ||
get_with_added2: is.fun(is.positive, is.promise(is.positive)), | ||
mygetter: is.getter(is.positive) | ||
mygetter: is.getter(is.positive), | ||
}, | ||
@@ -61,4 +61,4 @@ static_methods: { | ||
is.class("Counter") | ||
) | ||
} | ||
), | ||
}, | ||
}; | ||
@@ -80,4 +80,4 @@ | ||
methods: { | ||
get_in_wrong: is.fun(is.positive, is.promise(is.str)) | ||
} | ||
get_in_wrong: is.fun(is.positive, is.promise(is.str)), | ||
}, | ||
}; | ||
@@ -115,3 +115,3 @@ | ||
arguments: [is.num], | ||
returns: is.num | ||
returns: is.num, | ||
}, | ||
@@ -132,5 +132,5 @@ add1 | ||
arguments: [is.num], | ||
returns: is.promise(is.num) | ||
returns: is.promise(is.num), | ||
}, | ||
async x => x + 1 | ||
async (x) => x + 1 | ||
); | ||
@@ -145,5 +145,5 @@ await add1C(3); | ||
arguments: [is.num], | ||
returns: is.promise(is.str) | ||
returns: is.promise(is.str), | ||
}, | ||
async x => x + 1 | ||
async (x) => x + 1 | ||
); | ||
@@ -155,3 +155,3 @@ | ||
}) | ||
.catch(err => { | ||
.catch((err) => { | ||
expect(err).toBeInstanceOf(ContractViolation); | ||
@@ -168,3 +168,3 @@ }); | ||
argcheck: (lo, hi) => hi > lo, | ||
returns: is.positive | ||
returns: is.positive, | ||
}, | ||
@@ -184,3 +184,3 @@ (lo, hi) => hi - lo | ||
returns: is.num, | ||
retcheck: x => r => r > x | ||
retcheck: (x) => (r) => r > x, | ||
}, | ||
@@ -193,3 +193,3 @@ add1 | ||
returns: is.num, | ||
retcheck: x => r => r < x | ||
retcheck: (x) => (r) => r < x, | ||
}, | ||
@@ -252,3 +252,3 @@ add1 | ||
arguments: [is.maybe(is.num)], | ||
returns: is.or(is.str, is.num) | ||
returns: is.or(is.str, is.num), | ||
}); | ||
@@ -266,3 +266,3 @@ expect(add1C(3)).toBe(4); | ||
arguments: [is.num], | ||
returns: is.num | ||
returns: is.num, | ||
}, | ||
@@ -281,7 +281,7 @@ add1 | ||
arguments: [is.num], | ||
returns: x => is.number({ gte: x }) | ||
returns: (x) => is.number({ gte: x }), | ||
}); | ||
const add1CWrong = contract.with(add1, { | ||
arguments: [is.num], | ||
returns: x => is.number({ lte: x }) | ||
returns: (x) => is.number({ lte: x }), | ||
}); | ||
@@ -295,3 +295,3 @@ expect(add1C(3)).toBe(4); | ||
arguments: [is.num], | ||
returns: x => is.and(is.num, is.gte(x)) | ||
returns: (x) => is.and(is.num, is.gte(x)), | ||
}); | ||
@@ -304,3 +304,3 @@ | ||
arguments: [is.num], | ||
returns: x => is.and(is.num, is.lte(x)) | ||
returns: (x) => is.and(is.num, is.lte(x)), | ||
}); | ||
@@ -316,3 +316,3 @@ expect(() => add1CWrong(3)).toThrow(Error); | ||
arguments: [is.num], | ||
returns: is.num | ||
returns: is.num, | ||
}, | ||
@@ -327,3 +327,3 @@ add1 | ||
arguments: [is.num], | ||
returns: is.str | ||
returns: is.str, | ||
}, | ||
@@ -340,3 +340,3 @@ add1 | ||
is.fun(is.num, is.promise(is.num)), | ||
async x => x + 1 | ||
async (x) => x + 1 | ||
); | ||
@@ -348,3 +348,3 @@ await auto_test(add1C); | ||
is.fun(is.num, is.promise(is.str)), | ||
async x => x + 1 | ||
async (x) => x + 1 | ||
); | ||
@@ -355,3 +355,3 @@ await auto_test(add1C) | ||
}) | ||
.catch(err => { | ||
.catch((err) => { | ||
expect(err).toBeInstanceOf(ContractViolation); | ||
@@ -371,3 +371,3 @@ }); | ||
it("run", () => { | ||
const f1 = contract(is.fun(is.str, is.posint), v => v.length); | ||
const f1 = contract(is.fun(is.str, is.posint), (v) => v.length); | ||
auto_test(f1); | ||
@@ -381,3 +381,3 @@ }); | ||
is.fun(is.or(is.str, is.array(is.int)), is.posint), | ||
v => v.length | ||
(v) => v.length | ||
); | ||
@@ -392,3 +392,3 @@ auto_test(f1); | ||
is.fun(is.or(is.str, is.array(is.any)), is.posint), | ||
v => v.length | ||
(v) => v.length | ||
); | ||
@@ -403,3 +403,3 @@ auto_test(f1); | ||
is.fun(is.and(is.str, is.str), is.posint), | ||
v => v.length | ||
(v) => v.length | ||
); | ||
@@ -419,3 +419,3 @@ auto_test(f1); | ||
}) | ||
.catch(err => { | ||
.catch((err) => { | ||
expect(err).toBeInstanceOf(ContractViolation); | ||
@@ -428,3 +428,3 @@ }); | ||
it("run when correct", () => { | ||
const f1 = contract(is.fun(is.class(Counter), is.positive), c => c.count); | ||
const f1 = contract(is.fun(is.class(Counter), is.positive), (c) => c.count); | ||
auto_test(f1); | ||
@@ -434,3 +434,3 @@ }); | ||
it("fail when incorrect", () => { | ||
const f1 = contract(is.fun(is.class(Counter), is.str), c => c.count); | ||
const f1 = contract(is.fun(is.class(Counter), is.str), (c) => c.count); | ||
expect(() => auto_test(f1)).toThrow(Error); | ||
@@ -437,0 +437,0 @@ }); |
@@ -6,3 +6,3 @@ const get_return_contract = (returns, args) => | ||
const get_arguments_returns = contract => { | ||
const get_arguments_returns = (contract) => { | ||
if (contract.contract_name === "fun") | ||
@@ -48,3 +48,3 @@ return { arguments: contract.options[0], returns: contract.options[1] }; | ||
ContractViolation, | ||
log_it | ||
log_it, | ||
}; |
32163