Skip to content

Instantly share code, notes, and snippets.

@thepsion5
Last active August 31, 2017 16:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thepsion5/0659dadc1b4bed197dbec096b49cbccb to your computer and use it in GitHub Desktop.
Save thepsion5/0659dadc1b4bed197dbec096b49cbccb to your computer and use it in GitHub Desktop.
Example Permutation Generation
<?php
trait GeneratesPermutationsTrait
{
/**
* Generates an array with N unique combinations of inputs and a unique output, where N is equal to 2^count($params)
* For example, generatePermutations([], 'Param 1', 'Param 2') would return something similar to:
* [
* [
* 'inputs' => ['Param 1v1', 'Param 2v1'],
* 'output' => 'Param 1v1 Param 2v1'
* ],
* [
* 'inputs' => ['Param 1v1', 'Param 2v2'],
* 'output' => 'Param 1v1 Param 2v2'
* ],
* [
* 'inputs' => ['Param 1v2', 'Param 2v1'],
* 'output' => 'Param 1v2 Param 2v1'
* ],
* [
* 'inputs' => ['Param 1v2', 'Param 2v2'],
* 'output' => 'Param 1v2 Param 2v2'
* ]
* ]
*
* @param array $permutationTypes Associative array of permutation variable types. Supports "string", "bool", and "array"
* @param array ...$params One or more parameters used to generate permutations
* @return array[] Nested array of permutations, each with an 'inputs' key and an 'output' key
*/
protected function generatePermutations(array $permutationTypes, ...$params)
{
$permutations = [];
$parsedTypes = [];
foreach($params as $param) {
$parsedTypes[$param] = isset($permutationTypes[$param]) ? $permutationTypes[$param] : 'string';
}
$totalPermutations = 2**count($params);
for($permutationIndex = 1; $permutationIndex <= $totalPermutations; $permutationIndex++) {
$thisPermutation = [
'inputs' => [],
'output' => ''
];
foreach($params as $paramIndex => $param) {
$iteration = ( ( (int) ($permutationIndex / (2**$paramIndex) ) ) % 2) + 1;
$thisPermutation['inputs'][] = $this->generatePermutationInputForType($param, $parsedTypes[$param], $iteration);
}
$thisPermutation['output'] = array_reduce($thisPermutation['inputs'], function($carry, $item) {
return $carry . var_export($item, true);
}, '');
$permutations[] = $thisPermutation;
}
return $permutations;
}
/**
* Returns an input based on the supplied parameter name, parameter type, and iteration #
*
* @param string $param The parameter name
* @param string $type The parameter type - supports "array", "bool", and "string"
* @param int $iteration
* @return array|bool|string
*/
private function generatePermutationInputForType($param, $type, $iteration)
{
switch($type) {
case 'array':
return ["$param v$iteration"];
case 'bool':
return ($iteration % 2) === 0;
case 'string':
default:
return "$param v$iteration";
}
}
}
<?php
class SomeCacheDecoratorTest extends \PHPUnit\Framework\TestCase
{
use GeneratesPermutationsTrait;
/* snip - omitted non-relevant code */
/** @test */
public function caches_get_results_get_something_calls()
{
//returns 2^(# of params) arrays with an 'inputs' column and an 'output' column
$permutations = $this->generatePermutations([], 'Param 1', 'Param 2', 'Param 3');
$mockResults = array_column($permutations, 'output');
//setup expected method calls on the mock
foreach($permutations as $permutation) {
$this->mockRepo->shouldReceive('getSomething')
->with(...$permutation['inputs'])
->once()
->andReturn($permutation['output']);
}
$actualResults = [];
$cachedResults = [];
foreach($permutations as $permutation) {
//should call the underlying repository class (in this case, the mock)
$actualResults[] = $this->cacheDecorator()->getSomething(...$permutation['inputs']);
//should return the cached response without calling the underlying class
$cachedResults[] = $this->cacheDecorator()->getSomething(...$permutation['inputs']);
}
//assert the decorator properly returns the results of the underlying call the first time
$this->assertEquals($mockResults, $actualResults);
//assert the decorator properly returns the cached results the second time
$this->assertEquals($mockResults, $cachedResults);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment