1 |
|
2 | "use strict";
|
3 |
|
4 | var arbitraryBless = require("./arbitraryBless");
|
5 | var assert = require("assert");
|
6 | var generator = require("./generator.js");
|
7 | var random = require("./random.js");
|
8 | var show = require("./show.js");
|
9 | var shrink = require("./shrink.js");
|
10 | var utils = require("./utils.js");
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | function 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 |
|
24 | function 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 ));
|
38 | } else {
|
39 | return arbitraryBless(impl());
|
40 | }
|
41 | };
|
42 | }
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 | var integer = numeric(function integer(maxsize) {
|
52 | return {
|
53 | generator: generator.bless(function (size) {
|
54 | size = maxsize || size;
|
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 |
|
81 | extendWithDefault(integer);
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 | function nat(maxsize) {
|
90 | return arbitraryBless({
|
91 | generator: generator.bless(function (size) {
|
92 | size = maxsize || size;
|
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 |
|
112 | extendWithDefault(nat);
|
113 |
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 | var number = numeric(function number(maxsize) {
|
122 | return {
|
123 | generator: generator.bless(function (size) {
|
124 | size = maxsize || size;
|
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 |
|
140 | extendWithDefault(number);
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 | var uint8 = nat(0xff);
|
148 | var uint16 = nat(0xffff);
|
149 | var uint32 = nat(0xffffffff);
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 | var int8 = integer(-0x80, 0x7f);
|
157 | var int16 = integer(-0x8000, 0x7fff);
|
158 | var int32 = integer(-0x80000000, 0x7fffffff);
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 | var bool = arbitraryBless({
|
166 | generator: generator.bless(function (/* size */) {
|
167 | var i = random(0, 1);
|
168 | return i === 0 ? false : true;
|
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 |
|
180 |
|
181 |
|
182 |
|
183 | var datetimeConst = 1416499879495;
|
184 |
|
185 | function 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 |
|
216 | extendWithDefault(datetime);
|
217 |
|
218 |
|
219 |
|
220 |
|
221 |
|
222 |
|
223 | function 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 |
|
246 |
|
247 |
|
248 |
|
249 | var falsy = elements([false, null, undefined, "", 0, NaN]);
|
250 | falsy.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 |
|
264 |
|
265 |
|
266 |
|
267 | function constant(x) {
|
268 | return arbitraryBless({
|
269 | generator: generator.constant(x),
|
270 | shrink: shrink.noop,
|
271 | show: show.def
|
272 | });
|
273 | }
|
274 |
|
275 | module.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 | };
|