Skip to content

Commit

Permalink
Merge pull request #12 from swagger-mock/unique-array-generator-impro…
Browse files Browse the repository at this point in the history
…vement

fix: issue with exceeding limits of unique array value generator
  • Loading branch information
strider2038 authored Jul 17, 2019
2 parents 170c888 + ced00c1 commit 9522bbb
Show file tree
Hide file tree
Showing 16 changed files with 620 additions and 251 deletions.
2 changes: 1 addition & 1 deletion config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ parameters:
App\Mock\Parameters\Schema\Type\Composite\ObjectType: 'App\Mock\Generation\Value\Composite\ObjectValueGenerator'
App\Mock\Parameters\Schema\Type\Composite\FreeFormObjectType: 'App\Mock\Generation\Value\Composite\FreeFormObjectValueGenerator'
App\Mock\Parameters\Schema\Type\Composite\HashMapType: 'App\Mock\Generation\Value\Composite\HashMapValueGenerator'
App\Mock\Parameters\Schema\Type\Composite\ArrayType: 'App\Mock\Generation\Value\Composite\ArrayValueGenerator'
App\Mock\Parameters\Schema\Type\Composite\ArrayType: 'App\Mock\Generation\Value\Composite\ArrayGenerator\DelegatingArrayValueGenerator'
App\Mock\Parameters\Schema\Type\Combined\OneOfType: 'App\Mock\Generation\Value\Combined\OneOfValueGenerator'
App\Mock\Parameters\Schema\Type\Combined\AllOfType: 'App\Mock\Generation\Value\Combined\AllOfValueGenerator'
App\Mock\Parameters\Schema\Type\Combined\AnyOfType: 'App\Mock\Generation\Value\Combined\AnyOfValueGenerator'
Expand Down
8 changes: 6 additions & 2 deletions examples/persons.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,15 @@ components:
format: date
tags:
type: array
minItems: 0
minItems: 1
maxItems: 3
uniqueItems: true
items:
type: string
maxLength: 10
enum:
- manager
- admin
- programmer
Persons:
type: array
items:
Expand Down
1 change: 1 addition & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
cacheResult="false"
>
<php>
<ini name="error_reporting" value="-1" />
Expand Down
23 changes: 23 additions & 0 deletions src/Mock/Generation/Value/Composite/ArrayGenerator/ArrayLength.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
/*
* This file is part of Swagger Mock.
*
* (c) Igor Lazarev <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace App\Mock\Generation\Value\Composite\ArrayGenerator;

/**
* @author Igor Lazarev <[email protected]>
*/
class ArrayLength
{
/** @var int */
public $value;

/** @var int */
public $minValue;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
/*
* This file is part of Swagger Mock.
*
* (c) Igor Lazarev <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace App\Mock\Generation\Value\Composite\ArrayGenerator;

use App\Mock\Parameters\Schema\Type\Composite\ArrayType;

/**
* @author Igor Lazarev <[email protected]>
*/
class ArrayLengthGenerator
{
private const DEFAULT_MIN_ITEMS = 1;
private const DEFAULT_MAX_ITEMS = 20;

public function generateArrayLength(ArrayType $type): ArrayLength
{
$minItems = $type->minItems > 0 ? $type->minItems : self::DEFAULT_MIN_ITEMS;
$maxItems = $type->maxItems > 0 ? $type->maxItems : self::DEFAULT_MAX_ITEMS;

$length = new ArrayLength();
$length->value = random_int($minItems, $maxItems);
$length->minValue = $minItems;

return $length;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php
/*
* This file is part of Swagger Mock.
*
* (c) Igor Lazarev <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace App\Mock\Generation\Value\Composite\ArrayGenerator;

use App\Mock\Generation\Value\ValueGeneratorInterface;
use App\Mock\Parameters\Schema\Type\Composite\ArrayType;

/**
* @author Igor Lazarev <[email protected]>
*/
class ArrayRegularValueGenerator
{
/** @var ArrayLengthGenerator */
private $lengthGenerator;

public function __construct(ArrayLengthGenerator $lengthGenerator)
{
$this->lengthGenerator = $lengthGenerator;
}

public function generateArray(ValueGeneratorInterface $generator, ArrayType $type): array
{
$length = $this->lengthGenerator->generateArrayLength($type);

$values = [];

for ($i = 1; $i <= $length->value; $i++) {
$values[] = $generator->generateValue($type->items);
}

return $values;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php
/*
* This file is part of Swagger Mock.
*
* (c) Igor Lazarev <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace App\Mock\Generation\Value\Composite\ArrayGenerator;

use App\Mock\Generation\Value\ValueGeneratorInterface;
use App\Mock\Parameters\Schema\Type\Composite\ArrayType;
use App\Mock\Parameters\Schema\Type\TypeInterface;

/**
* @author Igor Lazarev <[email protected]>
*/
class ArrayUniqueValueGenerator
{
private const MAX_ATTEMPTS = 100;

/** @var ArrayLengthGenerator */
private $lengthGenerator;

public function __construct(ArrayLengthGenerator $lengthGenerator)
{
$this->lengthGenerator = $lengthGenerator;
}

public function generateArray(ValueGeneratorInterface $generator, ArrayType $type): array
{
$length = $this->lengthGenerator->generateArrayLength($type);

$values = [];
$uniqueValues = [];

for ($i = 1; $i <= $length->value; $i++) {
[$value, $attemptsExceeded] = $this->generateUniqueValue($generator, $type->items, $uniqueValues);

if ($attemptsExceeded) {
if ($i > $length->minValue) {
break;
}

throw new \RuntimeException('Cannot generate array with unique values, attempts limit exceeded');
}

$values[] = $value;
}

return $values;
}

private function generateUniqueValue(ValueGeneratorInterface $generator, TypeInterface $itemsType, array &$uniqueValues): array
{
$attempts = 0;
$attemptsExceeded = false;

do {
$value = $generator->generateValue($itemsType);
$attempts++;

if ($attempts > self::MAX_ATTEMPTS) {
$attemptsExceeded = true;

break;
}
} while (\in_array($value, $uniqueValues, true));

$uniqueValues[] = $value;

return [$value, $attemptsExceeded];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php
/*
* This file is part of Swagger Mock.
*
* (c) Igor Lazarev <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace App\Mock\Generation\Value\Composite\ArrayGenerator;

use App\Mock\Generation\Value\ValueGeneratorInterface;
use App\Mock\Generation\ValueGeneratorLocator;
use App\Mock\Parameters\Schema\Type\Composite\ArrayType;
use App\Mock\Parameters\Schema\Type\TypeInterface;

/**
* @author Igor Lazarev <[email protected]>
*/
class DelegatingArrayValueGenerator implements ValueGeneratorInterface
{
/** @var ValueGeneratorLocator */
private $generatorLocator;

/** @var ArrayRegularValueGenerator */
private $regularValueGenerator;

/** @var ArrayUniqueValueGenerator */
private $uniqueValueGenerator;

public function __construct(
ValueGeneratorLocator $generatorLocator,
ArrayRegularValueGenerator $regularValueGenerator,
ArrayUniqueValueGenerator $uniqueValueGenerator
) {
$this->generatorLocator = $generatorLocator;
$this->regularValueGenerator = $regularValueGenerator;
$this->uniqueValueGenerator = $uniqueValueGenerator;
}

public function generateValue(TypeInterface $type): ?array
{
if ($type->isNullable() && 0 === random_int(0, 1)) {
$value = null;
} else {
$value = $this->generateArray($type);
}

return $value;
}

private function generateArray(ArrayType $type): array
{
$valueGenerator = $this->generatorLocator->getValueGenerator($type->items);

if ($type->uniqueItems) {
$value = $this->uniqueValueGenerator->generateArray($valueGenerator, $type);
} else {
$value = $this->regularValueGenerator->generateArray($valueGenerator, $type);
}

return $value;
}
}
97 changes: 0 additions & 97 deletions src/Mock/Generation/Value/Composite/ArrayValueGenerator.php

This file was deleted.

2 changes: 1 addition & 1 deletion tests/Http/request.http
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
GET http://localhost:8080/pets
GET http://localhost:8080/persons

###
Loading

0 comments on commit 9522bbb

Please sign in to comment.