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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial