addon-sdk/source/test/test-sequence.js

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4 "use strict";
michael@0 5
michael@0 6 let { seq, iterate, filter, map, reductions, reduce, count,
michael@0 7 isEmpty, every, isEvery, some, take, takeWhile, drop,
michael@0 8 dropWhile, concat, first, rest, nth, last, dropLast,
michael@0 9 distinct, remove, mapcat, fromEnumerator, string,
michael@0 10 object, pairs, keys, values, each
michael@0 11 } = require("sdk/util/sequence");
michael@0 12
michael@0 13 const boom = () => { throw new Error("Boom!"); };
michael@0 14 const broken = seq(function*() {
michael@0 15 yield 1;
michael@0 16 throw new Error("Boom!");
michael@0 17 });
michael@0 18
michael@0 19 exports["test seq"] = assert => {
michael@0 20 let xs = seq(function*() {
michael@0 21 yield 1;
michael@0 22 yield 2;
michael@0 23 yield 3;
michael@0 24 });
michael@0 25
michael@0 26 assert.deepEqual([...seq(null)], [], "seq of null is empty");
michael@0 27 assert.deepEqual([...seq(void(0))], [], "seq of void is empty");
michael@0 28 assert.deepEqual([...xs], [1, 2, 3], "seq of 1 2 3");
michael@0 29 assert.deepEqual([...seq(xs)], [1, 2, 3], "seq of seq is seq");
michael@0 30
michael@0 31 assert.deepEqual([...seq([])], [], "seq of emtpy array is empty");
michael@0 32 assert.deepEqual([...seq([1])], [1], "seq of lonly array is single element");
michael@0 33 assert.deepEqual([...seq([1, 2, 3])], [1, 2, 3], "seq of array is it's elements");
michael@0 34
michael@0 35 assert.deepEqual([...seq("")], [], "seq of emtpy string is empty");
michael@0 36 assert.deepEqual([...seq("o")], ["o"], "seq of char is single char seq");
michael@0 37 assert.deepEqual([...seq("hello")], ["h", "e", "l", "l", "o"],
michael@0 38 "seq of string are chars");
michael@0 39
michael@0 40 assert.deepEqual([...seq(new Set())], [], "seq of emtpy set is empty");
michael@0 41 assert.deepEqual([...seq(new Set([1]))], [1], "seq of lonely set is single");
michael@0 42 assert.deepEqual([...seq(new Set([1, 2, 3]))], [1, 2, 3], "seq of lonely set is single");
michael@0 43
michael@0 44 assert.deepEqual([...seq(new Map())], [], "seq of emtpy map is empty");
michael@0 45 assert.deepEqual([...seq(new Map([[1, 2]]))], [[1, 2]], "seq single mapping is that mapping");
michael@0 46 assert.deepEqual([...seq(new Map([[1, 2], [3, 4], [5, 6]]))],
michael@0 47 [[1, 2], [3, 4], [5, 6]],
michael@0 48 "seq of map is key value mappings");
michael@0 49
michael@0 50 [function(){}, 1, /foo/, true].forEach(x => {
michael@0 51 assert.throws(() => seq(x), "Type is not seq-able");
michael@0 52 });
michael@0 53
michael@0 54 assert.throws(() => [...broken],
michael@0 55 /Boom/,
michael@0 56 "broken sequence errors propagate");
michael@0 57 };
michael@0 58
michael@0 59 exports["test seq casting"] = assert => {
michael@0 60 const xs = seq(function*() { yield 1; yield 2; yield 3; });
michael@0 61 const ys = seq(function*() { yield 1; });
michael@0 62 const zs = seq(function*() {});
michael@0 63 const kvs = seq(function*() { yield ["a", 1]; yield ["b", 2]; });
michael@0 64 const kv = seq(function*() { yield ["a", 1]; });
michael@0 65
michael@0 66 assert.deepEqual([...xs], [1, 2, 3], "cast to array");
michael@0 67 assert.deepEqual([...ys], [1], "cast to of one element");
michael@0 68 assert.deepEqual([...zs], [], "cast empty array");
michael@0 69
michael@0 70 assert.deepEqual(string(...xs), "123", "cast to string");
michael@0 71 assert.deepEqual(string(...ys), "1", "cast to char");
michael@0 72 assert.deepEqual(string(...zs), "", "cast to empty string");
michael@0 73
michael@0 74 assert.deepEqual(new Set(xs), new Set([1, 2, 3]),
michael@0 75 "cast to set of items");
michael@0 76 assert.deepEqual(new Set(ys), new Set([1]),
michael@0 77 "cast to set of one item");
michael@0 78 assert.deepEqual(new Set(zs), new Set(),
michael@0 79 "cast to set of one item");
michael@0 80
michael@0 81 assert.deepEqual(new Map(kvs), new Map([["a", 1], ["b", 2]]),
michael@0 82 "cast to map");
michael@0 83 assert.deepEqual(new Map(kv), new Map([["a", 1]]),
michael@0 84 "cast to single mapping");
michael@0 85 assert.deepEqual(new Map(zs), new Map(),
michael@0 86 "cast to empty map");
michael@0 87
michael@0 88 assert.deepEqual(object(...kvs), {a: 1, b: 2},
michael@0 89 "cast to object");
michael@0 90 assert.deepEqual(object(...kv), {a: 1},
michael@0 91 "cast to single pair");
michael@0 92 assert.deepEqual(object(...zs), {},
michael@0 93 "cast to empty object");
michael@0 94 };
michael@0 95
michael@0 96 exports["test pairs"] = assert => {
michael@0 97 assert.deepEqual([...pairs(null)], [], "pairs on null is empty");
michael@0 98 assert.deepEqual([...pairs(void(0))], [], "pairs on void is empty");
michael@0 99 assert.deepEqual([...pairs({})], [], "empty sequence");
michael@0 100 assert.deepEqual([...pairs({a: 1})], [["a", 1]], "single pair");
michael@0 101 assert.deepEqual([...pairs({a: 1, b: 2, c: 3})].sort(),
michael@0 102 [["a", 1], ["b", 2], ["c", 3]],
michael@0 103 "creates pairs");
michael@0 104 let items = [];
michael@0 105 for (let [key, value] of pairs({a: 1, b: 2, c: 3}))
michael@0 106 items.push([key, value]);
michael@0 107
michael@0 108 assert.deepEqual(items.sort(),
michael@0 109 [["a", 1], ["b", 2], ["c", 3]],
michael@0 110 "for of works on pairs");
michael@0 111
michael@0 112
michael@0 113 assert.deepEqual([...pairs([])], [], "pairs on empty array is empty");
michael@0 114 assert.deepEqual([...pairs([1])], [[0, 1]], "pairs on array is [index, element]");
michael@0 115 assert.deepEqual([...pairs([1, 2, 3])],
michael@0 116 [[0, 1], [1, 2], [2, 3]],
michael@0 117 "for arrays it pair of [index, element]");
michael@0 118
michael@0 119 assert.deepEqual([...pairs("")], [], "pairs on empty string is empty");
michael@0 120 assert.deepEqual([...pairs("a")], [[0, "a"]], "pairs on char is [0, char]");
michael@0 121 assert.deepEqual([...pairs("hello")],
michael@0 122 [[0, "h"], [1, "e"], [2, "l"], [3, "l"], [4, "o"]],
michael@0 123 "for strings it's pair of [index, char]");
michael@0 124
michael@0 125 assert.deepEqual([...pairs(new Map())],
michael@0 126 [],
michael@0 127 "pairs on empty map is empty");
michael@0 128 assert.deepEqual([...pairs(new Map([[1, 3]]))],
michael@0 129 [[1, 3]],
michael@0 130 "pairs on single mapping single mapping");
michael@0 131 assert.deepEqual([...pairs(new Map([[1, 2], [3, 4]]))],
michael@0 132 [[1, 2], [3, 4]],
michael@0 133 "pairs on map returs key vaule pairs");
michael@0 134
michael@0 135 assert.throws(() => pairs(new Set()),
michael@0 136 "can't pair set");
michael@0 137
michael@0 138 assert.throws(() => pairs(4),
michael@0 139 "can't pair number");
michael@0 140
michael@0 141 assert.throws(() => pairs(true),
michael@0 142 "can't pair boolean");
michael@0 143 };
michael@0 144
michael@0 145 exports["test keys"] = assert => {
michael@0 146 assert.deepEqual([...keys(null)], [], "keys on null is empty");
michael@0 147 assert.deepEqual([...keys(void(0))], [], "keys on void is empty");
michael@0 148 assert.deepEqual([...keys({})], [], "empty sequence");
michael@0 149 assert.deepEqual([...keys({a: 1})], ["a"], "single key");
michael@0 150 assert.deepEqual([...keys({a: 1, b: 2, c: 3})].sort(),
michael@0 151 ["a", "b", "c"],
michael@0 152 "all keys");
michael@0 153
michael@0 154 let items = [];
michael@0 155 for (let key of keys({a: 1, b: 2, c: 3}))
michael@0 156 items.push(key);
michael@0 157
michael@0 158 assert.deepEqual(items.sort(),
michael@0 159 ["a", "b", "c"],
michael@0 160 "for of works on keys");
michael@0 161
michael@0 162
michael@0 163 assert.deepEqual([...keys([])], [], "keys on empty array is empty");
michael@0 164 assert.deepEqual([...keys([1])], [0], "keys on array is indexes");
michael@0 165 assert.deepEqual([...keys([1, 2, 3])],
michael@0 166 [0, 1, 2],
michael@0 167 "keys on arrays returns indexes");
michael@0 168
michael@0 169 assert.deepEqual([...keys("")], [], "keys on empty string is empty");
michael@0 170 assert.deepEqual([...keys("a")], [0], "keys on char is 0");
michael@0 171 assert.deepEqual([...keys("hello")],
michael@0 172 [0, 1, 2, 3, 4],
michael@0 173 "keys on strings is char indexes");
michael@0 174
michael@0 175 assert.deepEqual([...keys(new Map())],
michael@0 176 [],
michael@0 177 "keys on empty map is empty");
michael@0 178 assert.deepEqual([...keys(new Map([[1, 3]]))],
michael@0 179 [1],
michael@0 180 "keys on single mapping single mapping is single key");
michael@0 181 assert.deepEqual([...keys(new Map([[1, 2], [3, 4]]))],
michael@0 182 [1, 3],
michael@0 183 "keys on map is keys from map");
michael@0 184
michael@0 185 assert.throws(() => keys(new Set()),
michael@0 186 "can't keys set");
michael@0 187
michael@0 188 assert.throws(() => keys(4),
michael@0 189 "can't keys number");
michael@0 190
michael@0 191 assert.throws(() => keys(true),
michael@0 192 "can't keys boolean");
michael@0 193 };
michael@0 194
michael@0 195 exports["test values"] = assert => {
michael@0 196 assert.deepEqual([...values({})], [], "empty sequence");
michael@0 197 assert.deepEqual([...values({a: 1})], [1], "single value");
michael@0 198 assert.deepEqual([...values({a: 1, b: 2, c: 3})].sort(),
michael@0 199 [1, 2, 3],
michael@0 200 "all values");
michael@0 201
michael@0 202 let items = [];
michael@0 203 for (let value of values({a: 1, b: 2, c: 3}))
michael@0 204 items.push(value);
michael@0 205
michael@0 206 assert.deepEqual(items.sort(),
michael@0 207 [1, 2, 3],
michael@0 208 "for of works on values");
michael@0 209
michael@0 210 assert.deepEqual([...values([])], [], "values on empty array is empty");
michael@0 211 assert.deepEqual([...values([1])], [1], "values on array elements");
michael@0 212 assert.deepEqual([...values([1, 2, 3])],
michael@0 213 [1, 2, 3],
michael@0 214 "values on arrays returns elements");
michael@0 215
michael@0 216 assert.deepEqual([...values("")], [], "values on empty string is empty");
michael@0 217 assert.deepEqual([...values("a")], ["a"], "values on char is char");
michael@0 218 assert.deepEqual([...values("hello")],
michael@0 219 ["h", "e", "l", "l", "o"],
michael@0 220 "values on strings is chars");
michael@0 221
michael@0 222 assert.deepEqual([...values(new Map())],
michael@0 223 [],
michael@0 224 "values on empty map is empty");
michael@0 225 assert.deepEqual([...values(new Map([[1, 3]]))],
michael@0 226 [3],
michael@0 227 "keys on single mapping single mapping is single key");
michael@0 228 assert.deepEqual([...values(new Map([[1, 2], [3, 4]]))],
michael@0 229 [2, 4],
michael@0 230 "values on map is values from map");
michael@0 231
michael@0 232 assert.deepEqual([...values(new Set())], [], "values on empty set is empty");
michael@0 233 assert.deepEqual([...values(new Set([1]))], [1], "values on set is it's items");
michael@0 234 assert.deepEqual([...values(new Set([1, 2, 3]))],
michael@0 235 [1, 2, 3],
michael@0 236 "values on set is it's items");
michael@0 237
michael@0 238
michael@0 239 assert.throws(() => values(4),
michael@0 240 "can't values number");
michael@0 241
michael@0 242 assert.throws(() => values(true),
michael@0 243 "can't values boolean");
michael@0 244 };
michael@0 245
michael@0 246 exports["test fromEnumerator"] = assert => {
michael@0 247 const { Cc, Ci } = require("chrome");
michael@0 248 const { enumerateObservers,
michael@0 249 addObserver,
michael@0 250 removeObserver } = Cc["@mozilla.org/observer-service;1"].
michael@0 251 getService(Ci.nsIObserverService);
michael@0 252
michael@0 253
michael@0 254 const topic = "sec:" + Math.random().toString(32).substr(2);
michael@0 255 const [a, b, c] = [{wrappedJSObject: {}},
michael@0 256 {wrappedJSObject: {}},
michael@0 257 {wrappedJSObject: {}}];
michael@0 258 const unwrap = x => x.wrappedJSObject;
michael@0 259
michael@0 260 [a, b, c].forEach(x => addObserver(x, topic, false));
michael@0 261
michael@0 262 const xs = fromEnumerator(() => enumerateObservers(topic));
michael@0 263 const ys = map(unwrap, xs);
michael@0 264
michael@0 265 assert.deepEqual([...ys], [a, b, c].map(unwrap),
michael@0 266 "all observers are there");
michael@0 267
michael@0 268 removeObserver(b, topic);
michael@0 269
michael@0 270 assert.deepEqual([...ys], [a, c].map(unwrap),
michael@0 271 "b was removed");
michael@0 272
michael@0 273 removeObserver(a, topic);
michael@0 274
michael@0 275 assert.deepEqual([...ys], [c].map(unwrap),
michael@0 276 "a was removed");
michael@0 277
michael@0 278 removeObserver(c, topic);
michael@0 279
michael@0 280 assert.deepEqual([...ys], [],
michael@0 281 "c was removed, now empty");
michael@0 282
michael@0 283 addObserver(a, topic, false);
michael@0 284
michael@0 285 assert.deepEqual([...ys], [a].map(unwrap),
michael@0 286 "a was added");
michael@0 287
michael@0 288 removeObserver(a, topic);
michael@0 289
michael@0 290 assert.deepEqual([...ys], [].map(unwrap),
michael@0 291 "a was removed, now empty");
michael@0 292
michael@0 293 };
michael@0 294
michael@0 295 exports["test filter"] = assert => {
michael@0 296 const isOdd = x => x % 2;
michael@0 297 const odds = seq(function*() { yield 1; yield 3; yield 5; });
michael@0 298 const evens = seq(function*() { yield 2; yield 4; yield 6; });
michael@0 299 const mixed = seq(function*() {
michael@0 300 yield 1;
michael@0 301 yield 2;
michael@0 302 yield 3;
michael@0 303 yield 4;
michael@0 304 });
michael@0 305
michael@0 306 assert.deepEqual([...filter(isOdd, mixed)], [1, 3],
michael@0 307 "filtered odds");
michael@0 308 assert.deepEqual([...filter(isOdd, odds)], [1, 3, 5],
michael@0 309 "kept all");
michael@0 310 assert.deepEqual([...filter(isOdd, evens)], [],
michael@0 311 "kept none");
michael@0 312
michael@0 313
michael@0 314 let xs = filter(boom, mixed);
michael@0 315 assert.throws(() => [...xs], /Boom/, "errors propagate");
michael@0 316
michael@0 317 assert.throws(() => [...filter(isOdd, broken)], /Boom/,
michael@0 318 "sequence errors propagate");
michael@0 319 };
michael@0 320
michael@0 321 exports["test filter array"] = assert => {
michael@0 322 let isOdd = x => x % 2;
michael@0 323 let xs = filter(isOdd, [1, 2, 3, 4]);
michael@0 324 let ys = filter(isOdd, [1, 3, 5]);
michael@0 325 let zs = filter(isOdd, [2, 4, 6]);
michael@0 326
michael@0 327 assert.deepEqual([...xs], [1, 3], "filteres odds");
michael@0 328 assert.deepEqual([...ys], [1, 3, 5], "kept all");
michael@0 329 assert.deepEqual([...zs], [], "kept none");
michael@0 330 assert.ok(!Array.isArray(xs));
michael@0 331 };
michael@0 332
michael@0 333 exports["test filter set"] = assert => {
michael@0 334 let isOdd = x => x % 2;
michael@0 335 let xs = filter(isOdd, new Set([1, 2, 3, 4]));
michael@0 336 let ys = filter(isOdd, new Set([1, 3, 5]));
michael@0 337 let zs = filter(isOdd, new Set([2, 4, 6]));
michael@0 338
michael@0 339 assert.deepEqual([...xs], [1, 3], "filteres odds");
michael@0 340 assert.deepEqual([...ys], [1, 3, 5], "kept all");
michael@0 341 assert.deepEqual([...zs], [], "kept none");
michael@0 342 };
michael@0 343
michael@0 344 exports["test filter string"] = assert => {
michael@0 345 let isUpperCase = x => x.toUpperCase() === x;
michael@0 346 let xs = filter(isUpperCase, "aBcDe");
michael@0 347 let ys = filter(isUpperCase, "ABC");
michael@0 348 let zs = filter(isUpperCase, "abcd");
michael@0 349
michael@0 350 assert.deepEqual([...xs], ["B", "D"], "filteres odds");
michael@0 351 assert.deepEqual([...ys], ["A", "B", "C"], "kept all");
michael@0 352 assert.deepEqual([...zs], [], "kept none");
michael@0 353 };
michael@0 354
michael@0 355 exports["test filter lazy"] = assert => {
michael@0 356 const x = 1;
michael@0 357 let y = 2;
michael@0 358
michael@0 359 const xy = seq(function*() { yield x; yield y; });
michael@0 360 const isOdd = x => x % 2;
michael@0 361 const actual = filter(isOdd, xy);
michael@0 362
michael@0 363 assert.deepEqual([...actual], [1], "only one odd number");
michael@0 364 y = 3;
michael@0 365 assert.deepEqual([...actual], [1, 3], "filter is lazy");
michael@0 366 };
michael@0 367
michael@0 368 exports["test filter non sequences"] = assert => {
michael@0 369 const False = _ => false;
michael@0 370 assert.throws(() => [...filter(False, 1)],
michael@0 371 "can't iterate number");
michael@0 372 assert.throws(() => [...filter(False, {a: 1, b:2})],
michael@0 373 "can't iterate object");
michael@0 374 };
michael@0 375
michael@0 376 exports["test map"] = assert => {
michael@0 377 let inc = x => x + 1;
michael@0 378 let xs = seq(function*() { yield 1; yield 2; yield 3; });
michael@0 379 let ys = map(inc, xs);
michael@0 380
michael@0 381 assert.deepEqual([...ys], [2, 3, 4], "incremented each item");
michael@0 382
michael@0 383 assert.deepEqual([...map(inc, null)], [], "mapping null is empty");
michael@0 384 assert.deepEqual([...map(inc, void(0))], [], "mapping void is empty");
michael@0 385 assert.deepEqual([...map(inc, new Set([1, 2, 3]))], [2, 3, 4], "maps set items");
michael@0 386 };
michael@0 387
michael@0 388 exports["test map two inputs"] = assert => {
michael@0 389 let sum = (x, y) => x + y;
michael@0 390 let xs = seq(function*() { yield 1; yield 2; yield 3; });
michael@0 391 let ys = seq(function*() { yield 4; yield 5; yield 6; });
michael@0 392
michael@0 393 let zs = map(sum, xs, ys);
michael@0 394
michael@0 395 assert.deepEqual([...zs], [5, 7, 9], "summed numbers");
michael@0 396 };
michael@0 397
michael@0 398 exports["test map diff sized inputs"] = assert => {
michael@0 399 let sum = (x, y) => x + y;
michael@0 400 let xs = seq(function*() { yield 1; yield 2; yield 3; });
michael@0 401 let ys = seq(function*() { yield 4; yield 5; yield 6; yield 7; yield 8; });
michael@0 402
michael@0 403 let zs = map(sum, xs, ys);
michael@0 404
michael@0 405 assert.deepEqual([...zs], [5, 7, 9], "summed numbers");
michael@0 406 assert.deepEqual([...map(sum, ys, xs)], [5, 7, 9],
michael@0 407 "index of exhasting input is irrelevant");
michael@0 408 };
michael@0 409
michael@0 410 exports["test map multi"] = assert => {
michael@0 411 let sum = (x, y, z, w) => x + y + z + w;
michael@0 412 let xs = seq(function*() { yield 1; yield 2; yield 3; yield 4; });
michael@0 413 let ys = seq(function*() { yield 4; yield 5; yield 6; yield 7; yield 8; });
michael@0 414 let zs = seq(function*() { yield 10; yield 11; yield 12; });
michael@0 415 let ws = seq(function*() { yield 0; yield 20; yield 40; yield 60; });
michael@0 416
michael@0 417 let actual = map(sum, xs, ys, zs, ws);
michael@0 418
michael@0 419 assert.deepEqual([...actual], [15, 38, 61], "summed numbers");
michael@0 420 };
michael@0 421
michael@0 422 exports["test map errors"] = assert => {
michael@0 423 assert.deepEqual([...map(boom, [])], [],
michael@0 424 "won't throw if empty");
michael@0 425
michael@0 426 const xs = map(boom, [1, 2, 4]);
michael@0 427
michael@0 428 assert.throws(() => [...xs], /Boom/, "propagates errors");
michael@0 429
michael@0 430 assert.throws(() => [...map(x => x, broken)], /Boom/,
michael@0 431 "sequence errors propagate");
michael@0 432 };
michael@0 433
michael@0 434 exports["test reductions"] = assert => {
michael@0 435 let sum = (...xs) => xs.reduce((x, y) => x + y, 0);
michael@0 436
michael@0 437 assert.deepEqual([...reductions(sum, [1, 1, 1, 1])],
michael@0 438 [1, 2, 3, 4],
michael@0 439 "works with arrays");
michael@0 440 assert.deepEqual([...reductions(sum, 5, [1, 1, 1, 1])],
michael@0 441 [5, 6, 7, 8, 9],
michael@0 442 "array with initial");
michael@0 443
michael@0 444 assert.deepEqual([...reductions(sum, seq(function*() {
michael@0 445 yield 1;
michael@0 446 yield 2;
michael@0 447 yield 3;
michael@0 448 }))],
michael@0 449 [1, 3, 6],
michael@0 450 "works with sequences");
michael@0 451
michael@0 452 assert.deepEqual([...reductions(sum, 10, seq(function*() {
michael@0 453 yield 1;
michael@0 454 yield 2;
michael@0 455 yield 3;
michael@0 456 }))],
michael@0 457 [10, 11, 13, 16],
michael@0 458 "works with sequences");
michael@0 459
michael@0 460 assert.deepEqual([...reductions(sum, [])], [0],
michael@0 461 "invokes accumulator with no args");
michael@0 462
michael@0 463 assert.throws(() => [...reductions(boom, 1, [1])],
michael@0 464 /Boom/,
michael@0 465 "arg errors errors propagate");
michael@0 466 assert.throws(() => [...reductions(sum, 1, broken)],
michael@0 467 /Boom/,
michael@0 468 "sequence errors propagate");
michael@0 469 };
michael@0 470
michael@0 471 exports["test reduce"] = assert => {
michael@0 472 let sum = (...xs) => xs.reduce((x, y) => x + y, 0);
michael@0 473
michael@0 474 assert.deepEqual(reduce(sum, [1, 2, 3, 4, 5]),
michael@0 475 15,
michael@0 476 "works with arrays");
michael@0 477
michael@0 478 assert.deepEqual(reduce(sum, seq(function*() {
michael@0 479 yield 1;
michael@0 480 yield 2;
michael@0 481 yield 3;
michael@0 482 })),
michael@0 483 6,
michael@0 484 "works with sequences");
michael@0 485
michael@0 486 assert.deepEqual(reduce(sum, 10, [1, 2, 3, 4, 5]),
michael@0 487 25,
michael@0 488 "works with array & initial");
michael@0 489
michael@0 490 assert.deepEqual(reduce(sum, 5, seq(function*() {
michael@0 491 yield 1;
michael@0 492 yield 2;
michael@0 493 yield 3;
michael@0 494 })),
michael@0 495 11,
michael@0 496 "works with sequences & initial");
michael@0 497
michael@0 498 assert.deepEqual(reduce(sum, []), 0, "reduce with no args");
michael@0 499 assert.deepEqual(reduce(sum, "a", []), "a", "reduce with initial");
michael@0 500 assert.deepEqual(reduce(sum, 1, [1]), 2, "reduce with single & initial");
michael@0 501
michael@0 502 assert.throws(() => [...reduce(boom, 1, [1])],
michael@0 503 /Boom/,
michael@0 504 "arg errors errors propagate");
michael@0 505 assert.throws(() => [...reduce(sum, 1, broken)],
michael@0 506 /Boom/,
michael@0 507 "sequence errors propagate");
michael@0 508 };
michael@0 509
michael@0 510 exports["test each"] = assert => {
michael@0 511 const collect = xs => {
michael@0 512 let result = [];
michael@0 513 each((...etc) => result.push(...etc), xs);
michael@0 514 return result;
michael@0 515 };
michael@0 516
michael@0 517 assert.deepEqual(collect(null), [], "each ignores null");
michael@0 518 assert.deepEqual(collect(void(0)), [], "each ignores void");
michael@0 519
michael@0 520 assert.deepEqual(collect([]), [], "each ignores empty");
michael@0 521 assert.deepEqual(collect([1]), [1], "each works on single item arrays");
michael@0 522 assert.deepEqual(collect([1, 2, 3, 4, 5]),
michael@0 523 [1, 2, 3, 4, 5],
michael@0 524 "works with arrays");
michael@0 525
michael@0 526 assert.deepEqual(collect(seq(function*() {
michael@0 527 yield 1;
michael@0 528 yield 2;
michael@0 529 yield 3;
michael@0 530 })),
michael@0 531 [1, 2, 3],
michael@0 532 "works with sequences");
michael@0 533
michael@0 534 assert.deepEqual(collect(""), [], "ignores empty strings");
michael@0 535 assert.deepEqual(collect("a"), ["a"], "works on chars");
michael@0 536 assert.deepEqual(collect("hello"), ["h", "e", "l", "l", "o"],
michael@0 537 "works on strings");
michael@0 538
michael@0 539 assert.deepEqual(collect(new Set()), [], "ignores empty sets");
michael@0 540 assert.deepEqual(collect(new Set(["a"])), ["a"],
michael@0 541 "works on single item sets");
michael@0 542 assert.deepEqual(collect(new Set([1, 2, 3])), [1, 2, 3],
michael@0 543 "works on muti item tests");
michael@0 544
michael@0 545 assert.deepEqual(collect(new Map()), [], "ignores empty maps");
michael@0 546 assert.deepEqual(collect(new Map([["a", 1]])), [["a", 1]],
michael@0 547 "works on single mapping maps");
michael@0 548 assert.deepEqual(collect(new Map([[1, 2], [3, 4], [5, 6]])),
michael@0 549 [[1, 2], [3, 4], [5, 6]],
michael@0 550 "works on muti mapping maps");
michael@0 551
michael@0 552 assert.throws(() => collect({}), "objects arn't supported");
michael@0 553 assert.throws(() => collect(1), "numbers arn't supported");
michael@0 554 assert.throws(() => collect(true), "booleas arn't supported");
michael@0 555 };
michael@0 556
michael@0 557 exports["test count"] = assert => {
michael@0 558 assert.equal(count(null), 0, "null counts to 0");
michael@0 559 assert.equal(count(), 0, "undefined counts to 0");
michael@0 560 assert.equal(count([]), 0, "empty array");
michael@0 561 assert.equal(count([1, 2, 3]), 3, "non-empty array");
michael@0 562 assert.equal(count(""), 0, "empty string");
michael@0 563 assert.equal(count("hello"), 5, "non-empty string");
michael@0 564 assert.equal(count(new Map()), 0, "empty map");
michael@0 565 assert.equal(count(new Map([[1, 2], [2, 3]])), 2, "non-empty map");
michael@0 566 assert.equal(count(new Set()), 0, "empty set");
michael@0 567 assert.equal(count(new Set([1, 2, 3, 4])), 4, "non-empty set");
michael@0 568 assert.equal(count(seq(function*() {})), 0, "empty sequence");
michael@0 569 assert.equal(count(seq(function*() { yield 1; yield 2; })), 2,
michael@0 570 "non-empty sequence");
michael@0 571
michael@0 572 assert.throws(() => count(broken),
michael@0 573 /Boom/,
michael@0 574 "sequence errors propagate");
michael@0 575 };
michael@0 576
michael@0 577 exports["test isEmpty"] = assert => {
michael@0 578 assert.equal(isEmpty(null), true, "null is empty");
michael@0 579 assert.equal(isEmpty(), true, "undefined is empty");
michael@0 580 assert.equal(isEmpty([]), true, "array is array");
michael@0 581 assert.equal(isEmpty([1, 2, 3]), false, "array isn't empty");
michael@0 582 assert.equal(isEmpty(""), true, "string is empty");
michael@0 583 assert.equal(isEmpty("hello"), false, "non-empty string");
michael@0 584 assert.equal(isEmpty(new Map()), true, "empty map");
michael@0 585 assert.equal(isEmpty(new Map([[1, 2], [2, 3]])), false, "non-empty map");
michael@0 586 assert.equal(isEmpty(new Set()), true, "empty set");
michael@0 587 assert.equal(isEmpty(new Set([1, 2, 3, 4])), false , "non-empty set");
michael@0 588 assert.equal(isEmpty(seq(function*() {})), true, "empty sequence");
michael@0 589 assert.equal(isEmpty(seq(function*() { yield 1; yield 2; })), false,
michael@0 590 "non-empty sequence");
michael@0 591
michael@0 592 assert.equal(isEmpty(broken), false, "hasn't reached error");
michael@0 593 };
michael@0 594
michael@0 595 exports["test isEvery"] = assert => {
michael@0 596 let isOdd = x => x % 2;
michael@0 597 let isTrue = x => x === true;
michael@0 598 let isFalse = x => x === false;
michael@0 599
michael@0 600 assert.equal(isEvery(isOdd, seq(function*() {
michael@0 601 yield 1;
michael@0 602 yield 3;
michael@0 603 yield 5;
michael@0 604 })), true, "all are odds");
michael@0 605
michael@0 606 assert.equal(isEvery(isOdd, seq(function*() {
michael@0 607 yield 1;
michael@0 608 yield 2;
michael@0 609 yield 3;
michael@0 610 })), false, "contains even");
michael@0 611
michael@0 612 assert.equal(isEvery(isTrue, seq(function*() {})), true, "true if empty");
michael@0 613 assert.equal(isEvery(isFalse, seq(function*() {})), true, "true if empty");
michael@0 614
michael@0 615 assert.equal(isEvery(isTrue, null), true, "true for null");
michael@0 616 assert.equal(isEvery(isTrue, undefined), true, "true for undefined");
michael@0 617
michael@0 618 assert.throws(() => isEvery(boom, [1, 2]),
michael@0 619 /Boom/,
michael@0 620 "arg errors errors propagate");
michael@0 621 assert.throws(() => isEvery(x => true, broken),
michael@0 622 /Boom/,
michael@0 623 "sequence errors propagate");
michael@0 624
michael@0 625 assert.equal(isEvery(x => false, broken), false,
michael@0 626 "hasn't reached error");
michael@0 627 };
michael@0 628
michael@0 629 exports["test some"] = assert => {
michael@0 630 let isOdd = x => x % 2;
michael@0 631 let isTrue = x => x === true;
michael@0 632 let isFalse = x => x === false;
michael@0 633
michael@0 634 assert.equal(some(isOdd, seq(function*() {
michael@0 635 yield 2;
michael@0 636 yield 4;
michael@0 637 yield 6;
michael@0 638 })), null, "all are even");
michael@0 639
michael@0 640 assert.equal(some(isOdd, seq(function*() {
michael@0 641 yield 2;
michael@0 642 yield 3;
michael@0 643 yield 4;
michael@0 644 })), true, "contains odd");
michael@0 645
michael@0 646 assert.equal(some(isTrue, seq(function*() {})), null,
michael@0 647 "null if empty")
michael@0 648 assert.equal(some(isFalse, seq(function*() {})), null,
michael@0 649 "null if empty")
michael@0 650
michael@0 651 assert.equal(some(isTrue, null), null, "null for null");
michael@0 652 assert.equal(some(isTrue, undefined), null, "null for undefined");
michael@0 653
michael@0 654 assert.throws(() => some(boom, [1, 2]),
michael@0 655 /Boom/,
michael@0 656 "arg errors errors propagate");
michael@0 657 assert.throws(() => some(x => false, broken),
michael@0 658 /Boom/,
michael@0 659 "sequence errors propagate");
michael@0 660
michael@0 661 assert.equal(some(x => true, broken), true,
michael@0 662 "hasn't reached error");
michael@0 663 };
michael@0 664
michael@0 665 exports["test take"] = assert => {
michael@0 666 let xs = seq(function*() {
michael@0 667 yield 1;
michael@0 668 yield 2;
michael@0 669 yield 3;
michael@0 670 yield 4;
michael@0 671 yield 5;
michael@0 672 yield 6;
michael@0 673 });
michael@0 674
michael@0 675 assert.deepEqual([...take(3, xs)], [1, 2, 3], "took 3 items");
michael@0 676 assert.deepEqual([...take(3, [1, 2, 3, 4, 5])], [1, 2, 3],
michael@0 677 "took 3 from array");
michael@0 678
michael@0 679 let ys = seq(function*() { yield 1; yield 2; });
michael@0 680 assert.deepEqual([...take(3, ys)], [1, 2], "takes at max n");
michael@0 681 assert.deepEqual([...take(3, [1, 2])], [1, 2],
michael@0 682 "takes at max n from arary");
michael@0 683
michael@0 684 let empty = seq(function*() {});
michael@0 685 assert.deepEqual([...take(5, empty)], [], "nothing to take");
michael@0 686
michael@0 687 assert.throws(() => [...take(3, broken)],
michael@0 688 /Boom/,
michael@0 689 "sequence errors propagate");
michael@0 690
michael@0 691 assert.deepEqual([...take(1, broken)], [1],
michael@0 692 "hasn't reached error");
michael@0 693 };
michael@0 694
michael@0 695 exports["test iterate"] = assert => {
michael@0 696 let inc = x => x + 1;
michael@0 697 let nums = iterate(inc, 0);
michael@0 698
michael@0 699 assert.deepEqual([...take(5, nums)], [0, 1, 2, 3, 4], "took 5");
michael@0 700 assert.deepEqual([...take(10, nums)], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], "took 10");
michael@0 701
michael@0 702 let xs = iterate(x => x * 3, 2);
michael@0 703 assert.deepEqual([...take(4, xs)], [2, 6, 18, 54], "took 4");
michael@0 704
michael@0 705 assert.throws(() => [...iterate(boom, 0)],
michael@0 706 /Boom/,
michael@0 707 "function exceptions propagate");
michael@0 708 };
michael@0 709
michael@0 710 exports["test takeWhile"] = assert => {
michael@0 711 let isNegative = x => x < 0;
michael@0 712 let xs = seq(function*() {
michael@0 713 yield -2;
michael@0 714 yield -1;
michael@0 715 yield 0;
michael@0 716 yield 1;
michael@0 717 yield 2;
michael@0 718 yield 3;
michael@0 719 });
michael@0 720
michael@0 721 assert.deepEqual([...takeWhile(isNegative, xs)], [-2, -1],
michael@0 722 "took until 0");
michael@0 723
michael@0 724 let ys = seq(function*() {});
michael@0 725 assert.deepEqual([...takeWhile(isNegative, ys)], [],
michael@0 726 "took none");
michael@0 727
michael@0 728 let zs = seq(function*() {
michael@0 729 yield 0;
michael@0 730 yield 1;
michael@0 731 yield 2;
michael@0 732 yield 3;
michael@0 733 });
michael@0 734
michael@0 735 assert.deepEqual([...takeWhile(isNegative, zs)], [],
michael@0 736 "took none");
michael@0 737
michael@0 738 assert.throws(() => [...takeWhile(boom, zs)],
michael@0 739 /Boom/,
michael@0 740 "function errors errors propagate");
michael@0 741 assert.throws(() => [...takeWhile(x => true, broken)],
michael@0 742 /Boom/,
michael@0 743 "sequence errors propagate");
michael@0 744
michael@0 745 assert.deepEqual([...takeWhile(x => false, broken)],
michael@0 746 [],
michael@0 747 "hasn't reached error");
michael@0 748 };
michael@0 749
michael@0 750 exports["test drop"] = assert => {
michael@0 751 let testDrop = xs => {
michael@0 752 assert.deepEqual([...drop(2, xs)],
michael@0 753 [3, 4],
michael@0 754 "dropped two elements");
michael@0 755
michael@0 756 assert.deepEqual([...drop(1, xs)],
michael@0 757 [2, 3, 4],
michael@0 758 "dropped one");
michael@0 759
michael@0 760 assert.deepEqual([...drop(0, xs)],
michael@0 761 [1, 2, 3, 4],
michael@0 762 "dropped 0");
michael@0 763
michael@0 764 assert.deepEqual([...drop(-2, xs)],
michael@0 765 [1, 2, 3, 4],
michael@0 766 "dropped 0 on negative `n`");
michael@0 767
michael@0 768 assert.deepEqual([...drop(5, xs)],
michael@0 769 [],
michael@0 770 "dropped all items");
michael@0 771 };
michael@0 772
michael@0 773 testDrop([1, 2, 3, 4]);
michael@0 774 testDrop(seq(function*() {
michael@0 775 yield 1;
michael@0 776 yield 2;
michael@0 777 yield 3;
michael@0 778 yield 4;
michael@0 779 }));
michael@0 780
michael@0 781 assert.throws(() => [...drop(1, broken)],
michael@0 782 /Boom/,
michael@0 783 "sequence errors propagate");
michael@0 784 };
michael@0 785
michael@0 786
michael@0 787 exports["test dropWhile"] = assert => {
michael@0 788 let isNegative = x => x < 0;
michael@0 789 let True = _ => true;
michael@0 790 let False = _ => false;
michael@0 791
michael@0 792 let test = xs => {
michael@0 793 assert.deepEqual([...dropWhile(isNegative, xs)],
michael@0 794 [0, 1, 2],
michael@0 795 "dropped negative");
michael@0 796
michael@0 797 assert.deepEqual([...dropWhile(True, xs)],
michael@0 798 [],
michael@0 799 "drop all");
michael@0 800
michael@0 801 assert.deepEqual([...dropWhile(False, xs)],
michael@0 802 [-2, -1, 0, 1, 2],
michael@0 803 "keep all");
michael@0 804 };
michael@0 805
michael@0 806 test([-2, -1, 0, 1, 2]);
michael@0 807 test(seq(function*() {
michael@0 808 yield -2;
michael@0 809 yield -1;
michael@0 810 yield 0;
michael@0 811 yield 1;
michael@0 812 yield 2;
michael@0 813 }));
michael@0 814
michael@0 815 assert.throws(() => [...dropWhile(boom, [1, 2, 3])],
michael@0 816 /Boom/,
michael@0 817 "function errors errors propagate");
michael@0 818 assert.throws(() => [...dropWhile(x => true, broken)],
michael@0 819 /Boom/,
michael@0 820 "sequence errors propagate");
michael@0 821 };
michael@0 822
michael@0 823
michael@0 824 exports["test concat"] = assert => {
michael@0 825 let test = (a, b, c, d) => {
michael@0 826 assert.deepEqual([...concat()],
michael@0 827 [],
michael@0 828 "nothing to concat");
michael@0 829 assert.deepEqual([...concat(a)],
michael@0 830 [1, 2, 3],
michael@0 831 "concat with nothing returns same as first");
michael@0 832 assert.deepEqual([...concat(a, b)],
michael@0 833 [1, 2, 3, 4, 5],
michael@0 834 "concat items from both");
michael@0 835 assert.deepEqual([...concat(a, b, a)],
michael@0 836 [1, 2, 3, 4, 5, 1, 2, 3],
michael@0 837 "concat itself");
michael@0 838 assert.deepEqual([...concat(c)],
michael@0 839 [],
michael@0 840 "concat of empty is empty");
michael@0 841 assert.deepEqual([...concat(a, c)],
michael@0 842 [1, 2, 3],
michael@0 843 "concat with empty");
michael@0 844 assert.deepEqual([...concat(c, c, c)],
michael@0 845 [],
michael@0 846 "concat of empties is empty");
michael@0 847 assert.deepEqual([...concat(c, b)],
michael@0 848 [4, 5],
michael@0 849 "empty can be in front");
michael@0 850 assert.deepEqual([...concat(d)],
michael@0 851 [7],
michael@0 852 "concat singular");
michael@0 853 assert.deepEqual([...concat(d, d)],
michael@0 854 [7, 7],
michael@0 855 "concat singulars");
michael@0 856
michael@0 857 assert.deepEqual([...concat(a, a, b, c, d, c, d, d)],
michael@0 858 [1, 2, 3, 1, 2, 3, 4, 5, 7, 7, 7],
michael@0 859 "many concats");
michael@0 860
michael@0 861 let ab = concat(a, b);
michael@0 862 let abcd = concat(ab, concat(c, d));
michael@0 863 let cdabcd = concat(c, d, abcd);
michael@0 864
michael@0 865 assert.deepEqual([...cdabcd],
michael@0 866 [7, 1, 2, 3, 4, 5, 7],
michael@0 867 "nested concats");
michael@0 868 };
michael@0 869
michael@0 870 test([1, 2, 3],
michael@0 871 [4, 5],
michael@0 872 [],
michael@0 873 [7]);
michael@0 874
michael@0 875 test(seq(function*() { yield 1; yield 2; yield 3; }),
michael@0 876 seq(function*() { yield 4; yield 5; }),
michael@0 877 seq(function*() { }),
michael@0 878 seq(function*() { yield 7; }));
michael@0 879
michael@0 880 assert.throws(() => [...concat(broken, [1, 2, 3])],
michael@0 881 /Boom/,
michael@0 882 "function errors errors propagate");
michael@0 883 };
michael@0 884
michael@0 885
michael@0 886 exports["test first"] = assert => {
michael@0 887 let test = (xs, empty) => {
michael@0 888 assert.equal(first(xs), 1, "returns first");
michael@0 889 assert.equal(first(empty), null, "returns null empty");
michael@0 890 };
michael@0 891
michael@0 892 test("1234", "");
michael@0 893 test([1, 2, 3], []);
michael@0 894 test([1, 2, 3], null);
michael@0 895 test([1, 2, 3], undefined);
michael@0 896 test(seq(function*() { yield 1; yield 2; yield 3; }),
michael@0 897 seq(function*() { }));
michael@0 898 assert.equal(first(broken), 1, "did not reached error");
michael@0 899 };
michael@0 900
michael@0 901 exports["test rest"] = assert => {
michael@0 902 let test = (xs, x, nil) => {
michael@0 903 assert.deepEqual([...rest(xs)], ["b", "c"],
michael@0 904 "rest items");
michael@0 905 assert.deepEqual([...rest(x)], [],
michael@0 906 "empty when singular");
michael@0 907 assert.deepEqual([...rest(nil)], [],
michael@0 908 "empty when empty");
michael@0 909 };
michael@0 910
michael@0 911 test("abc", "a", "");
michael@0 912 test(["a", "b", "c"], ["d"], []);
michael@0 913 test(seq(function*() { yield "a"; yield "b"; yield "c"; }),
michael@0 914 seq(function*() { yield "d"; }),
michael@0 915 seq(function*() {}));
michael@0 916 test(["a", "b", "c"], ["d"], null);
michael@0 917 test(["a", "b", "c"], ["d"], undefined);
michael@0 918
michael@0 919 assert.throws(() => [...rest(broken)],
michael@0 920 /Boom/,
michael@0 921 "sequence errors propagate");
michael@0 922 };
michael@0 923
michael@0 924
michael@0 925 exports["test nth"] = assert => {
michael@0 926 let notFound = {};
michael@0 927 let test = xs => {
michael@0 928 assert.equal(nth(xs, 0), "h", "first");
michael@0 929 assert.equal(nth(xs, 1), "e", "second");
michael@0 930 assert.equal(nth(xs, 5), void(0), "out of bound");
michael@0 931 assert.equal(nth(xs, 5, notFound), notFound, "out of bound");
michael@0 932 assert.equal(nth(xs, -1), void(0), "out of bound");
michael@0 933 assert.equal(nth(xs, -1, notFound), notFound, "out of bound");
michael@0 934 assert.equal(nth(xs, 4), "o", "5th");
michael@0 935 };
michael@0 936
michael@0 937 let testEmpty = xs => {
michael@0 938 assert.equal(nth(xs, 0), void(0), "no first in empty");
michael@0 939 assert.equal(nth(xs, 5), void(0), "no 5th in empty");
michael@0 940 assert.equal(nth(xs, 0, notFound), notFound, "notFound on out of bound");
michael@0 941 };
michael@0 942
michael@0 943 test("hello");
michael@0 944 test(["h", "e", "l", "l", "o"]);
michael@0 945 test(seq(function*() {
michael@0 946 yield "h";
michael@0 947 yield "e";
michael@0 948 yield "l";
michael@0 949 yield "l";
michael@0 950 yield "o";
michael@0 951 }));
michael@0 952 testEmpty(null);
michael@0 953 testEmpty(undefined);
michael@0 954 testEmpty([]);
michael@0 955 testEmpty("");
michael@0 956 testEmpty(seq(function*() {}));
michael@0 957
michael@0 958
michael@0 959 assert.throws(() => nth(broken, 1),
michael@0 960 /Boom/,
michael@0 961 "sequence errors propagate");
michael@0 962 assert.equal(nth(broken, 0), 1, "have not reached error");
michael@0 963 };
michael@0 964
michael@0 965
michael@0 966 exports["test last"] = assert => {
michael@0 967 assert.equal(last(null), null, "no last in null");
michael@0 968 assert.equal(last(void(0)), null, "no last in undefined");
michael@0 969 assert.equal(last([]), null, "no last in []");
michael@0 970 assert.equal(last(""), null, "no last in ''");
michael@0 971 assert.equal(last(seq(function*() { })), null, "no last in empty");
michael@0 972
michael@0 973 assert.equal(last("hello"), "o", "last from string");
michael@0 974 assert.equal(last([1, 2, 3]), 3, "last from array");
michael@0 975 assert.equal(last([1]), 1, "last from singular");
michael@0 976 assert.equal(last(seq(function*() {
michael@0 977 yield 1;
michael@0 978 yield 2;
michael@0 979 yield 3;
michael@0 980 })), 3, "last from sequence");
michael@0 981
michael@0 982 assert.throws(() => last(broken),
michael@0 983 /Boom/,
michael@0 984 "sequence errors propagate");
michael@0 985 };
michael@0 986
michael@0 987
michael@0 988 exports["test dropLast"] = assert => {
michael@0 989 let test = xs => {
michael@0 990 assert.deepEqual([...dropLast(xs)],
michael@0 991 [1, 2, 3, 4],
michael@0 992 "dropped last");
michael@0 993 assert.deepEqual([...dropLast(0, xs)],
michael@0 994 [1, 2, 3, 4, 5],
michael@0 995 "dropped none on 0");
michael@0 996 assert.deepEqual([...dropLast(-3, xs)],
michael@0 997 [1, 2, 3, 4, 5],
michael@0 998 "drop none on negative");
michael@0 999 assert.deepEqual([...dropLast(3, xs)],
michael@0 1000 [1, 2],
michael@0 1001 "dropped given number");
michael@0 1002 assert.deepEqual([...dropLast(5, xs)],
michael@0 1003 [],
michael@0 1004 "dropped all");
michael@0 1005 };
michael@0 1006
michael@0 1007 let testEmpty = xs => {
michael@0 1008 assert.deepEqual([...dropLast(xs)],
michael@0 1009 [],
michael@0 1010 "nothing to drop");
michael@0 1011 assert.deepEqual([...dropLast(0, xs)],
michael@0 1012 [],
michael@0 1013 "dropped none on 0");
michael@0 1014 assert.deepEqual([...dropLast(-3, xs)],
michael@0 1015 [],
michael@0 1016 "drop none on negative");
michael@0 1017 assert.deepEqual([...dropLast(3, xs)],
michael@0 1018 [],
michael@0 1019 "nothing to drop");
michael@0 1020 };
michael@0 1021
michael@0 1022 test([1, 2, 3, 4, 5]);
michael@0 1023 test(seq(function*() {
michael@0 1024 yield 1;
michael@0 1025 yield 2;
michael@0 1026 yield 3;
michael@0 1027 yield 4;
michael@0 1028 yield 5;
michael@0 1029 }));
michael@0 1030 testEmpty([]);
michael@0 1031 testEmpty("");
michael@0 1032 testEmpty(seq(function*() {}));
michael@0 1033
michael@0 1034 assert.throws(() => [...dropLast(broken)],
michael@0 1035 /Boom/,
michael@0 1036 "sequence errors propagate");
michael@0 1037 };
michael@0 1038
michael@0 1039
michael@0 1040 exports["test distinct"] = assert => {
michael@0 1041 let test = (xs, message) => {
michael@0 1042 assert.deepEqual([...distinct(xs)],
michael@0 1043 [1, 2, 3, 4, 5],
michael@0 1044 message);
michael@0 1045 };
michael@0 1046
michael@0 1047 test([1, 2, 1, 3, 1, 4, 1, 5], "works with arrays");
michael@0 1048 test(seq(function*() {
michael@0 1049 yield 1;
michael@0 1050 yield 2;
michael@0 1051 yield 1;
michael@0 1052 yield 3;
michael@0 1053 yield 1;
michael@0 1054 yield 4;
michael@0 1055 yield 1;
michael@0 1056 yield 5;
michael@0 1057 }), "works with sequences");
michael@0 1058 test(new Set([1, 2, 1, 3, 1, 4, 1, 5]),
michael@0 1059 "works with sets");
michael@0 1060 test(seq(function*() {
michael@0 1061 yield 1;
michael@0 1062 yield 2;
michael@0 1063 yield 2;
michael@0 1064 yield 2;
michael@0 1065 yield 1;
michael@0 1066 yield 3;
michael@0 1067 yield 1;
michael@0 1068 yield 4;
michael@0 1069 yield 4;
michael@0 1070 yield 4;
michael@0 1071 yield 1;
michael@0 1072 yield 5;
michael@0 1073 }), "works with multiple repeatitions");
michael@0 1074 test([1, 2, 3, 4, 5], "work with distinct arrays");
michael@0 1075 test(seq(function*() {
michael@0 1076 yield 1;
michael@0 1077 yield 2;
michael@0 1078 yield 3;
michael@0 1079 yield 4;
michael@0 1080 yield 5;
michael@0 1081 }), "works with distinct seqs");
michael@0 1082 };
michael@0 1083
michael@0 1084
michael@0 1085 exports["test remove"] = assert => {
michael@0 1086 let isPositive = x => x > 0;
michael@0 1087 let test = xs => {
michael@0 1088 assert.deepEqual([...remove(isPositive, xs)],
michael@0 1089 [-2, -1, 0],
michael@0 1090 "removed positives");
michael@0 1091 };
michael@0 1092
michael@0 1093 test([1, -2, 2, -1, 3, 7, 0]);
michael@0 1094 test(seq(function*() {
michael@0 1095 yield 1;
michael@0 1096 yield -2;
michael@0 1097 yield 2;
michael@0 1098 yield -1;
michael@0 1099 yield 3;
michael@0 1100 yield 7;
michael@0 1101 yield 0;
michael@0 1102 }));
michael@0 1103
michael@0 1104 assert.throws(() => [...distinct(broken)],
michael@0 1105 /Boom/,
michael@0 1106 "sequence errors propagate");
michael@0 1107 };
michael@0 1108
michael@0 1109
michael@0 1110 exports["test mapcat"] = assert => {
michael@0 1111 let upto = n => seq(function* () {
michael@0 1112 let index = 0;
michael@0 1113 while (index < n) {
michael@0 1114 yield index;
michael@0 1115 index = index + 1;
michael@0 1116 }
michael@0 1117 });
michael@0 1118
michael@0 1119 assert.deepEqual([...mapcat(upto, [1, 2, 3, 4])],
michael@0 1120 [0, 0, 1, 0, 1, 2, 0, 1, 2, 3],
michael@0 1121 "expands given sequence");
michael@0 1122
michael@0 1123 assert.deepEqual([...mapcat(upto, [0, 1, 2, 0])],
michael@0 1124 [0, 0, 1],
michael@0 1125 "expands given sequence");
michael@0 1126
michael@0 1127 assert.deepEqual([...mapcat(upto, [0, 0, 0])],
michael@0 1128 [],
michael@0 1129 "expands given sequence");
michael@0 1130
michael@0 1131 assert.deepEqual([...mapcat(upto, [])],
michael@0 1132 [],
michael@0 1133 "nothing to expand");
michael@0 1134
michael@0 1135 assert.deepEqual([...mapcat(upto, null)],
michael@0 1136 [],
michael@0 1137 "nothing to expand");
michael@0 1138
michael@0 1139 assert.deepEqual([...mapcat(upto, void(0))],
michael@0 1140 [],
michael@0 1141 "nothing to expand");
michael@0 1142
michael@0 1143 let xs = seq(function*() {
michael@0 1144 yield 0;
michael@0 1145 yield 1;
michael@0 1146 yield 0;
michael@0 1147 yield 2;
michael@0 1148 yield 0;
michael@0 1149 });
michael@0 1150
michael@0 1151 assert.deepEqual([...mapcat(upto, xs)],
michael@0 1152 [0, 0, 1],
michael@0 1153 "expands given sequence");
michael@0 1154
michael@0 1155 assert.throws(() => [...mapcat(boom, xs)],
michael@0 1156 /Boom/,
michael@0 1157 "function errors errors propagate");
michael@0 1158 assert.throws(() => [...mapcat(upto, broken)],
michael@0 1159 /Boom/,
michael@0 1160 "sequence errors propagate");
michael@0 1161 };
michael@0 1162
michael@0 1163 require("sdk/test").run(exports);

mercurial