Collection generators

Collection-oriented Generators produce arrays conforming to different constraints depending on the mathematical definition the reproduce. All these Generators require as an input one or more Generators to be used to produce single elements.

Associative arrays

Associative arrays can be generated composing other generators for each of the keys of the desired array, which will contain the specified fixed set of keys and vary the values.

<?php
use Eris\Generator;

class AssociativeArrayTest extends PHPUnit_Framework_TestCase
{
    use Eris\TestTrait;

    public function testAssociativeArraysGeneratedOnStandardKeys()
    {
        $this->forAll(
            Generator\associative([
                'letter' => Generator\elements("A", "B", "C"),
                'cipher' => Generator\choose(0, 9),
            ])
        )
            ->then(function ($array) {
                $this->assertEquals(2, count($array));
                $letter = $array['letter'];
                $this->assertInternalType('string', $letter);
                $cipher = $array['cipher'];
                $this->assertInternalType('integer', $cipher);
            });
    }
}

Sequences

Sequences are defined as numeric arrays with a variable amount of elements of a single type. Both the length of the array and its values will be randomly generated.

<?php
use Eris\Generator;

class SequenceTest extends PHPUnit_Framework_TestCase
{
    use Eris\TestTrait;

    public function testArrayReversePreserveLength()
    {
        $this
            ->forAll(
                Generator\seq(Generator\nat())
            )
            ->then(function ($array) {
                $this->assertEquals(count($array), count(array_reverse($array)));
            });
    }

    public function testArrayReverse()
    {
        $this
            ->forAll(
                Generator\seq(Generator\nat())
            )
            ->then(function ($array) {
                $this->assertEquals($array, array_reverse(array_reverse($array)));
            });
    }

    public function testArraySortingIsIdempotent()
    {
        $this
            ->forAll(
                Generator\seq(Generator\nat())
            )
            ->then(function ($array) {
                sort($array);
                $expected = $array;
                sort($array);
                $this->assertEquals($expected, $array);
            });
    }
}

Vectors

Vectors are defined as numeric arrays with a fixed amount of elements of a single type. Only the values contained will be randomly generated.

As an example, consider vectors inside a fixed space such as the set of 2D or 3D points.

<?php
use Eris\Generator;

class VectorTest extends PHPUnit_Framework_TestCase
{
    use Eris\TestTrait;

    public function testConcatenationMaintainsLength()
    {
        $this->forAll(
            Generator\vector(10, Generator\nat(1000)),
            Generator\vector(10, Generator\nat(1000))
        )
            ->then(function ($first, $second) {
                $concatenated = array_merge($first, $second);
                $this->assertEquals(
                    count($concatenated),
                    count($first) + count($second),
                    var_export($first, true) . " and " . var_export($second, true) . " do not maintain their length when concatenated."
                );
            });
    }
}

Tuples

Tuples are defined as a small array of fixed size, consiting of a few heteregeneous types.

<?php
use Eris\Generator;

class TupleTest extends PHPUnit_Framework_TestCase
{
    use Eris\TestTrait;

    public function testConcatenationMaintainsLength()
    {
        $this->forAll(
            Generator\tuple(
                Generator\elements("A", "B", "C"),
                Generator\choose(0, 9)
            )
        )
            ->then(function ($tuple) {
                $letter = $tuple[0];
                $cipher = $tuple[1];
                $this->assertEquals(
                    2,
                    strlen($letter . $cipher),
                    "{$letter}{$cipher} is not a 2-char string"
                );
            });
    }
}

Sets

Sets are defined as array with a variable amount of elements of a single type, without any repeated element.

<?php
use Eris\Generator;
use Eris\TestTrait;

class SetTest extends PHPUnit_Framework_TestCase
{
    use TestTrait;

    public function testSetsOfAnotherGeneratorsDomain()
    {
        $this->forAll(
            Generator\set(Generator\nat())
        )
            ->then(function ($set) {
                $this->assertInternalType('array', $set);
                foreach ($set as $element) {
                    $this->assertGreaterThanOrEqual(0, $element);
                }
            });
    }
}

Subsets

Subsets are set whose elements are extracted from a fixed universe set, specified as an input.

<?php
use Eris\Generator;
use Eris\TestTrait;

class SubsetTest extends PHPUnit_Framework_TestCase
{
    use TestTrait;

    public function testSubsetsOfASet()
    {
        $this->forAll(
            Generator\subset([
                2, 4, 6, 8, 10
            ])
        )
            ->then(function ($set) {
                $this->assertInternalType('array', $set);
                foreach ($set as $element) {
                    $this->assertTrue($this->isEven($element), "Element $element is not even, where did it come from?");
                }
                var_dump($set);
            });
    }

    private function isEven($number)
    {
        return $number % 2 == 0;
    }
}