<commit_before>module('Basics');

test('Namespace', 4, function () {
  equal(typeof genData, 'function', 'genData is a function.');
  equal(typeof genData.spawn, 'function', 'genData.spawn is a method.');
  equal(genData.length, 1, 'genData expects one or more parameters.');
  equal(genData.spawn.length, 0, 'genData.spawn() expects zero parameters.');
});

test('Dataset', 3, function () {
  var stuff = [1,'pipe',['echo',9]],
    dataset = genData(stuff);
  ok(dataset instanceof Array, "The dataset returned by genData is an array.");
  ok(dataset.every(function (data) {return data.hasOwnProperty('name') && typeof data.name === 'string';}), 'Each data object has the string member "name".');
  ok(dataset.every(function (data) {return data.hasOwnProperty('value');}), 'Each data object has the member "value".');
});

test('Parser', 10, function () {
  var
    stuff = 'anything',
    val1 = 0,
    val2 = val1 + 1,
    data,
    datasetParam,
    dataset = genData(
      stuff,
      function (name, value, parent, dataset, flags, shared) {
        data = this;
        equal(typeof this, 'object', 'The parser function scope is a data object.');
        ok(this instanceof genData, 'The data object is a genData instance.');
        equal(arguments.length, 6, 'The parser signature is six arguments.');
        equal(typeof name, 'string', 'The first parameter, "name", is a string.');
        ok(dataset instanceof Array, 'The fourth parameter, "dataset", is an array.');
        equal(typeof flags, 'object', 'The fifth parameter, "flags", is an object.');
        equal(typeof shared, 'object', 'The six parameter, "shared", is an object.');
        val1++;
        datasetParam = dataset;
      },
      function () {
        equal(val1, val2, 'genData executes parsers in the order they are passed.');
        ok(this === data, 'Parsers operate on the same data object.');
      }
    );
  ok(datasetParam === dataset, 'The "dataset" parameter, given to parsers, is the array returned by genData.');
});

test('Generator', 6, function () {
  var
    stuff = 'anything',
    trail = [],
    p1 = function () {trail.push(1);},
    p2 = function () {trail.push(0);},
    genA = genData.spawn(p1, p2),
    genB = genA.spawn();
  equal(typeof genA, 'function', 'genData.spawn() returns a generator.');
  equal(typeof genB, 'function', 'The .spawn() method of a generator, returns a new generator.');
  genA(stuff);
  genData(stuff, p1, p2);
  deepEqual(trail, [1,0,1,0], 'Generators curry parser configurations.');
  genB(stuff);
  deepEqual(trail, [1,0,1,0,1,0], 'Generators spawned from generators, preserve curried parser configurations.');
  ok(
    genData.prototype.isPrototypeOf(genA.prototype) &&
    genData.prototype.isPrototypeOf(genB.prototype) &&
    genA.prototype.isPrototypeOf(genB.prototype) &&
    !genB.prototype.isPrototypeOf(genA.prototype),
    'Generators extend the prototype-chain of the generator that spawned them.'
  );
  ok((genB())[0] instanceof genB, 'Data objects share the prototype of their generator.');
});

module('Normalize');

test('defaults', 2, function () {
  var
    stuff = [[0],'foo'],
    dataset = genData(stuff);
  strictEqual(dataset[0].name, '', 'The "name" member of the first data object is an empty string.');
  ok(dataset[0].value === stuff, 'The "value" member of the first data object is the argument passed to genData.');
});

test("nothing", 5, function () {
  var emptySet = genData(),
    nullSet = genData(null),
    undefinedSet = genData(undefined);
  equal(emptySet.length, 1, 'genData returns a dataset with one item, when called with no arguments.');
  equal(nullSet.length, 1, 'genData returns a dataset with one item, when passed "null".');
  equal(undefinedSet.length, 1, 'genData returns a dataset with one item, when passed "undefined".');
  equal(JSON.stringify(emptySet), JSON.stringify(undefinedSet), 'Passing "undefined" returns the same dataset resulting from no arguments.');
  notEqual(JSON.stringify(emptySet), JSON.stringify(nullSet), 'Passing "null" returns a different dataset than that from no arguments.');
});

test('scalar values', 3, function () {
  var
    string = 'hello world!',
    number = Math.random(),
    boolean = true,
    stringSet = genData(string),
    numberSet = genData(number),
    booleanSet = genData(boolean);
  equal(stringSet.length, 1, 'The dataset from a string has one item.');
  equal(numberSet.length, 1, 'The dataset from a number has one item.');
  equal(booleanSet.length, 1, 'The dataset from a boolean has one item.');
});

test('scalar objects', 3, function () {
  var
    string = new String('hello world'),
    number = new Number(Math.random()),
    boolean = new Boolean(true),
    stringSet = genData(string),
    numberSet = genData(number),
    booleanSet = genData(boolean);
  equal(stringSet.length, string.length + 1, 'The dataset from a string object has one data object (for the initial value), plus an item for each character.');
  equal(numberSet.length, 1, 'The dataset from a number object has one item.');
  equal(booleanSet.length, 1, 'The dataset from a boolean object has one item.');
});

test("objects", 2, function () {
  var
    firstChildName = 'hello',
    firstChildValue = Math.random(),
    secondChildName = 'world',
    secondChildValue = Math.random(),
    stuff = {
      foo: 'bar',
      baz: {
        foo: 'bar',
        baz: {
          foo: 'bar'
        }
      }
    },
    dataset = genData(stuff);
  equal(
    dataset.length,
    JSON.stringify(stuff).match(/\":/g).length + 1,
    'The dataset for an object has an entry for each descendent members plus the initial object.'
  );
  stuff = {};
  stuff[firstChildName] = firstChildValue;
  stuff[secondChildName] = secondChildValue;
  dataset = genData(stuff);
  ok(dataset[1].name === firstChildName && dataset[2].name === secondChildName, 'Child members are indexed in the order they are added to an object.');
});

test('arrays', 2, function () {
  var stuff = ['alpha', 'beta', 'theta'],
    dataset = genData(stuff),
    nbrNames = 0,
    i = 0, datasetCnt = dataset.length;
  equal(
    dataset.length,
    stuff.length + 1,
    'The dataset for an array has an entry for each descendent members plus the initial array.'
  );
  equal(dataset[1].name, parseInt(dataset[1].name), 'The "name" member of array data objects is the element index.');
});

test('associative-arrays', 3, function () {
  var stuff = [],
    assocKeyName = 'ping',
    val = Math.random(),
    val2 = val + 1,
    indexKeyName = '0',
    dataset;
  stuff[assocKeyName] = val;
  stuff.push(val2);
  dataset = genData(stuff);
  equal(dataset.length, stuff.length + 2, 'The dataset for an associative-array has an entry for each array element and associate key/value pair.');
  equal(dataset[1].value, val2, 'Non-numeric array members are processed after indexed element.');
  stuff = [];
  stuff[indexKeyName] = val;
  stuff.push(val2);
  dataset = genData(stuff);<commit_msg>Removed array members test. Result depends on the JavaScript engine.<commit_after>module('Basics');

test('Namespace', 4, function () {
  equal(typeof genData, 'function', 'genData is a function.');
  equal(typeof genData.spawn, 'function', 'genData.spawn is a method.');
  equal(genData.length, 1, 'genData expects one or more parameters.');
  equal(genData.spawn.length, 0, 'genData.spawn() expects zero parameters.');
});

test('Dataset', 3, function () {
  var stuff = [1,'pipe',['echo',9]],
    dataset = genData(stuff);
  ok(dataset instanceof Array, "The dataset returned by genData is an array.");
  ok(dataset.every(function (data) {return data.hasOwnProperty('name') && typeof data.name === 'string';}), 'Each data object has the string member "name".');
  ok(dataset.every(function (data) {return data.hasOwnProperty('value');}), 'Each data object has the member "value".');
});

test('Parser', 10, function () {
  var
    stuff = 'anything',
    val1 = 0,
    val2 = val1 + 1,
    data,
    datasetParam,
    dataset = genData(
      stuff,
      function (name, value, parent, dataset, flags, shared) {
        data = this;
        equal(typeof this, 'object', 'The parser function scope is a data object.');
        ok(this instanceof genData, 'The data object is a genData instance.');
        equal(arguments.length, 6, 'The parser signature is six arguments.');
        equal(typeof name, 'string', 'The first parameter, "name", is a string.');
        ok(dataset instanceof Array, 'The fourth parameter, "dataset", is an array.');
        equal(typeof flags, 'object', 'The fifth parameter, "flags", is an object.');
        equal(typeof shared, 'object', 'The six parameter, "shared", is an object.');
        val1++;
        datasetParam = dataset;
      },
      function () {
        equal(val1, val2, 'genData executes parsers in the order they are passed.');
        ok(this === data, 'Parsers operate on the same data object.');
      }
    );
  ok(datasetParam === dataset, 'The "dataset" parameter, given to parsers, is the array returned by genData.');
});

test('Generator', 6, function () {
  var
    stuff = 'anything',
    trail = [],
    p1 = function () {trail.push(1);},
    p2 = function () {trail.push(0);},
    genA = genData.spawn(p1, p2),
    genB = genA.spawn();
  equal(typeof genA, 'function', 'genData.spawn() returns a generator.');
  equal(typeof genB, 'function', 'The .spawn() method of a generator, returns a new generator.');
  genA(stuff);
  genData(stuff, p1, p2);
  deepEqual(trail, [1,0,1,0], 'Generators curry parser configurations.');
  genB(stuff);
  deepEqual(trail, [1,0,1,0,1,0], 'Generators spawned from generators, preserve curried parser configurations.');
  ok(
    genData.prototype.isPrototypeOf(genA.prototype) &&
    genData.prototype.isPrototypeOf(genB.prototype) &&
    genA.prototype.isPrototypeOf(genB.prototype) &&
    !genB.prototype.isPrototypeOf(genA.prototype),
    'Generators extend the prototype-chain of the generator that spawned them.'
  );
  ok((genB())[0] instanceof genB, 'Data objects share the prototype of their generator.');
});

module('Normalize');

test('defaults', 2, function () {
  var
    stuff = [[0],'foo'],
    dataset = genData(stuff);
  strictEqual(dataset[0].name, '', 'The "name" member of the first data object is an empty string.');
  ok(dataset[0].value === stuff, 'The "value" member of the first data object is the argument passed to genData.');
});

test("nothing", 5, function () {
  var emptySet = genData(),
    nullSet = genData(null),
    undefinedSet = genData(undefined);
  equal(emptySet.length, 1, 'genData returns a dataset with one item, when called with no arguments.');
  equal(nullSet.length, 1, 'genData returns a dataset with one item, when passed "null".');
  equal(undefinedSet.length, 1, 'genData returns a dataset with one item, when passed "undefined".');
  equal(JSON.stringify(emptySet), JSON.stringify(undefinedSet), 'Passing "undefined" returns the same dataset resulting from no arguments.');
  notEqual(JSON.stringify(emptySet), JSON.stringify(nullSet), 'Passing "null" returns a different dataset than that from no arguments.');
});

test('scalar values', 3, function () {
  var
    string = 'hello world!',
    number = Math.random(),
    boolean = true,
    stringSet = genData(string),
    numberSet = genData(number),
    booleanSet = genData(boolean);
  equal(stringSet.length, 1, 'The dataset from a string has one item.');
  equal(numberSet.length, 1, 'The dataset from a number has one item.');
  equal(booleanSet.length, 1, 'The dataset from a boolean has one item.');
});

test('scalar objects', 3, function () {
  var
    string = new String('hello world'),
    number = new Number(Math.random()),
    boolean = new Boolean(true),
    stringSet = genData(string),
    numberSet = genData(number),
    booleanSet = genData(boolean);
  equal(stringSet.length, string.length + 1, 'The dataset from a string object has one data object (for the initial value), plus an item for each character.');
  equal(numberSet.length, 1, 'The dataset from a number object has one item.');
  equal(booleanSet.length, 1, 'The dataset from a boolean object has one item.');
});

test("objects", 2, function () {
  var
    firstChildName = 'hello',
    firstChildValue = Math.random(),
    secondChildName = 'world',
    secondChildValue = Math.random(),
    stuff = {
      foo: 'bar',
      baz: {
        foo: 'bar',
        baz: {
          foo: 'bar'
        }
      }
    },
    dataset = genData(stuff);
  equal(
    dataset.length,
    JSON.stringify(stuff).match(/\":/g).length + 1,
    'The dataset for an object has an entry for each descendent members plus the initial object.'
  );
  stuff = {};
  stuff[firstChildName] = firstChildValue;
  stuff[secondChildName] = secondChildValue;
  dataset = genData(stuff);
  ok(dataset[1].name === firstChildName && dataset[2].name === secondChildName, 'Child members are indexed in the order they are added to an object.');
});

test('arrays', 2, function () {
  var stuff = ['alpha', 'beta', 'theta'],
    dataset = genData(stuff),
    nbrNames = 0,
    i = 0, datasetCnt = dataset.length;
  equal(
    dataset.length,
    stuff.length + 1,
    'The dataset for an array has an entry for each descendent members plus the initial array.'
  );
  equal(dataset[1].name, parseInt(dataset[1].name), 'The "name" member of array data objects is the element index.');
});

test('associative-arrays', 3, function () {
  var stuff = [],
    assocKeyName = 'ping',
    val = Math.random(),
    val2 = val + 1,
    indexKeyName = '0',
    dataset;
  stuff[assocKeyName] = val;
  stuff.push(val2);
  dataset = genData(stuff);
  equal(dataset.length, stuff.length + 2, 'The dataset for an associative-array has an entry for each array element and associate key/value pair.');
  // this test passes on WebKit and fails on Gecko
  // equal(dataset[1].value, val2, 'Non-numeric array members are processed after indexed element.');
  stuff = [];
  stuff[indexKeyName] = val;
  stuff.push(val2);
  dataset = genData(stuff);
{'fraction_non_alphanumeric': 0.1447564877355137, 'fraction_numerical': 0.010238179879132598, 'mean_word_length': 3.7472156598042523, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3476010', 'n_tokens_mistral': 4244, 'n_tokens_neox': 4220, 'n_words': 1397}