UNPKG

6.34 kBJavaScriptView Raw
1/* @flow weak */
2"use strict";
3
4var arbitraryBless = require("./arbitraryBless");
5var assert = require("assert");
6var generator = require("./generator.js");
7var random = require("./random.js");
8var show = require("./show.js");
9var shrink = require("./shrink.js");
10var utils = require("./utils.js");
11
12/**
13 ### Primitive arbitraries
14*/
15
16function extendWithDefault(arb) {
17 var def = arb();
18 arb.generator = def.generator;
19 arb.shrink = def.shrink;
20 arb.show = def.show;
21 arb.smap = def.smap;
22}
23
24function numeric(impl) {
25 return function (minsize, maxsize) {
26 if (arguments.length === 2) {
27 var arb = arbitraryBless(impl(maxsize - minsize));
28 var to = function to(x) {
29 return Math.abs(x) + minsize;
30 };
31 var from = function from(x) {
32 return x - minsize;
33 };
34
35 return arb.smap(to, from);
36 } else if (arguments.length === 1) {
37 return arbitraryBless(impl(minsize /* as maxsize */));
38 } else {
39 return arbitraryBless(impl());
40 }
41 };
42}
43
44/**
45 - `integer: arbitrary integer`
46 - `integer(maxsize: nat): arbitrary integer`
47 - `integer(minsize: integer, maxsize: integer): arbitrary integer`
48
49 Integers, ℤ
50*/
51var integer = numeric(function integer(maxsize) {
52 return {
53 generator: generator.bless(function (size) {
54 size = maxsize === undefined ? size : maxsize;
55 return random(-size, size);
56 }),
57 shrink: shrink.bless(function (i) {
58 assert(typeof i === "number", "integer.shrink have to be a number");
59
60 i = Math.abs(i);
61 if (i === 0) {
62 return [];
63 } else {
64 var arr = [0];
65 var j = utils.div2(i);
66 var k = Math.max(j, 1);
67 while (j < i) {
68 arr.push(j);
69 arr.push(-j);
70 k = Math.max(utils.div2(k), 1);
71 j += k;
72 }
73 return arr;
74 }
75 }),
76
77 show: show.def,
78 };
79});
80
81extendWithDefault(integer);
82
83/**
84 - `nat: arbitrary nat`
85 - `nat(maxsize: nat): arbitrary nat`
86
87 Natural numbers, ℕ (0, 1, 2...)
88*/
89function nat(maxsize) {
90 return arbitraryBless({
91 generator: generator.bless(function (size) {
92 size = maxsize === undefined ? size : maxsize;
93 return random(0, size);
94 }),
95 shrink: shrink.bless(function (i) {
96 assert(typeof i === "number", "nat.shrink have to be a number");
97
98 var arr = [];
99 var j = utils.div2(i);
100 var k = Math.max(j, 1);
101 while (j < i) {
102 arr.push(j);
103 k = Math.max(utils.div2(k), 1);
104 j += k;
105 }
106 return arr;
107 }),
108 show: show.def,
109 });
110}
111
112extendWithDefault(nat);
113
114/**
115 - `number: arbitrary number`
116 - `number(maxsize: number): arbitrary number`
117 - `number(min: number, max: number): arbitrary number`
118
119 JavaScript numbers, "doubles", ℝ. `NaN` and `Infinity` are not included.
120*/
121var number = numeric(function number(maxsize) {
122 return {
123 generator: generator.bless(function (size) {
124 size = maxsize === undefined ? size : maxsize;
125 return random.number(-size, size);
126 }),
127 shrink: shrink.bless(function (x) {
128 assert(typeof x === "number", "number.shrink have to be a number");
129
130 if (Math.abs(x) > 1e-6) {
131 return [0, x / 2, -x / 2];
132 } else {
133 return [];
134 }
135 }),
136 show: show.def,
137 };
138});
139
140extendWithDefault(number);
141
142/**
143 - `uint8: arbitrary nat`
144 - `uint16: arbitrary nat`
145 - `uint32: arbitrary nat`
146*/
147var uint8 = nat(0xff);
148var uint16 = nat(0xffff);
149var uint32 = nat(0xffffffff);
150
151/**
152 - `int8: arbitrary integer`
153 - `int16: arbitrary integer`
154 - `int32: arbitrary integer`
155*/
156var int8 = integer(-0x80, 0x7f);
157var int16 = integer(-0x8000, 0x7fff);
158var int32 = integer(-0x80000000, 0x7fffffff);
159
160/**
161 - `bool: arbitrary bool`
162
163 Booleans, `true` or `false`.
164*/
165var bool = arbitraryBless({
166 generator: generator.bless(function (/* size */) {
167 var i = random(0, 1);
168 return i === 1;
169 }),
170
171 shrink: shrink.bless(function (b) {
172 assert(b === true || b === false, "bool.shrink excepts true or false");
173 return b === true ? [false] : [];
174 }),
175 show: show.def,
176});
177
178/**
179 - `datetime: arbitrary datetime`
180
181 Random datetime
182*/
183var datetimeConst = 1416499879495; // arbitrary datetime
184
185function datetime(from, to) {
186 var toDate;
187 var fromDate;
188 var arb;
189
190 if (arguments.length === 2) {
191 toDate = function toDateFn(x) {
192 return new Date(x);
193 };
194 fromDate = function fromDateFn(x) {
195 return x.getTime();
196 };
197 from = fromDate(from);
198 to = fromDate(to);
199 arb = number(from, to);
200
201 return arb.smap(toDate, fromDate);
202 } else {
203 toDate = function toDateFn(x) {
204 return new Date(x * 768000000 + datetimeConst);
205 };
206 arb = number;
207
208 return arbitraryBless({
209 generator: arb.generator.map(toDate),
210 shrink: shrink.noop,
211 show: show.def,
212 });
213 }
214}
215
216extendWithDefault(datetime);
217
218/**
219 - `elements(args: array a): arbitrary a`
220
221 Random element of `args` array.
222*/
223function elements(args) {
224 assert(args.length !== 0, "elements: at least one parameter expected");
225
226 return arbitraryBless({
227 generator: generator.bless(function (/* size */) {
228 var i = random(0, args.length - 1);
229 return args[i];
230 }),
231
232 shrink: shrink.bless(function (x) {
233 var idx = args.indexOf(x);
234 if (idx <= 0) {
235 return [];
236 } else {
237 return args.slice(0, idx);
238 }
239 }),
240 show: show.def,
241 });
242}
243
244/**
245 - `falsy: arbitrary *`
246
247 Generates falsy values: `false`, `null`, `undefined`, `""`, `0`, and `NaN`.
248*/
249var falsy = elements([false, null, undefined, "", 0, NaN]);
250falsy.show = function (v) {
251 if (v !== v) {
252 return "falsy: NaN";
253 } else if (v === "") {
254 return "falsy: empty string";
255 } else if (v === undefined) {
256 return "falsy: undefined";
257 } else {
258 return "falsy: " + v;
259 }
260};
261
262/**
263 - `constant(x: a): arbitrary a`
264
265 Returns an unshrinkable arbitrary that yields the given object.
266*/
267function constant(x) {
268 return arbitraryBless({
269 generator: generator.constant(x),
270 shrink: shrink.noop,
271 show: show.def,
272 });
273}
274
275module.exports = {
276 integer: integer,
277 nat: nat,
278 int8: int8,
279 int16: int16,
280 int32: int32,
281 uint8: uint8,
282 uint16: uint16,
283 uint32: uint32,
284 number: number,
285 elements: elements,
286 bool: bool,
287 falsy: falsy,
288 constant: constant,
289 datetime: datetime,
290};