Skip to content

Commit

Permalink
Merge pull request #14 from swagger-mock/unique-array-improvements
Browse files Browse the repository at this point in the history
Unique array improvements
  • Loading branch information
strider2038 authored Jul 24, 2019
2 parents d5aba39 + 5a93b4e commit a184a24
Show file tree
Hide file tree
Showing 31 changed files with 686 additions and 223 deletions.
2 changes: 1 addition & 1 deletion .dev/files/usr/local/etc/php/conf.d/xdebug.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ xdebug.var_display_max_depth = 6
xdebug.remote_enable = 1
xdebug.remote_autostart = 1
xdebug.remote_host = 172.17.0.1
xdebug.remote_connect_back = 1
xdebug.remote_connect_back = 0
xdebug.remote_port = 9000
xdebug.remote_handler = dbgp
xdebug.remote_mode = req
Expand Down
2 changes: 2 additions & 0 deletions .scrutinizer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ build:
- php-scrutinizer-run
tests:
environment:
php:
version: 7.3
variables:
APP_ENV: 'test'
tests:
Expand Down
4 changes: 4 additions & 0 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,7 @@ services:
class: Negotiation\Negotiator

App\OpenAPI\ErrorHandling\ErrorHandlerInterface: '@App\OpenAPI\ErrorHandling\LoggingErrorHandler'

App\Utility\EncoderDecorator:
decorates: Symfony\Component\Serializer\Encoder\EncoderInterface
arguments: ['@App\Utility\EncoderDecorator.inner']
4 changes: 2 additions & 2 deletions src/Mock/Generation/Value/Combined/AllOfValueGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public function generateValue(TypeInterface $type)
if (0 === \count($values)) {
$value = new \stdClass();
} else {
$value = \array_merge(...$values);
$value = (object) \array_merge(...$values);
}

return $value;
Expand All @@ -47,7 +47,7 @@ private function generateValues(AllOfType $type): array

foreach ($type->types as $internalType) {
$generator = $this->generatorLocator->getValueGenerator($internalType);
$values[] = $generator->generateValue($internalType);
$values[] = (array) $generator->generateValue($internalType);
}

return $values;
Expand Down
12 changes: 6 additions & 6 deletions src/Mock/Generation/Value/Combined/AnyOfValueGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ public function __construct(ValueGeneratorLocator $generatorLocator)
$this->generatorLocator = $generatorLocator;
}

public function generateValue(TypeInterface $type)
public function generateValue(TypeInterface $type): object
{
$values = $this->generateValues($type);

if (0 === \count($values)) {
$value = new \stdClass();
} else {
$value = \array_merge(...$values);
$value = (object) \array_merge(...$values);
}

return $value;
Expand All @@ -47,25 +47,25 @@ private function generateValues(AnyOfType $type): array

foreach ($type->types as $internalType) {
if (0 === random_int(0, 1)) {
$values[] = $this->generateValueOfType($internalType);
$values[] = (array) $this->generateValueOfType($internalType);
}
}

if (0 === \count($values) && $type->types->count() > 0) {
$values[] = $this->generateOneOfValues($type);
$values[] = (array) $this->generateOneOfValues($type);
}

return $values;
}

private function generateValueOfType(TypeInterface $type): array
private function generateValueOfType(TypeInterface $type)
{
$generator = $this->generatorLocator->getValueGenerator($type);

return $generator->generateValue($type);
}

private function generateOneOfValues(AnyOfType $type): array
private function generateOneOfValues(AnyOfType $type)
{
$randomInternalTypeIndex = random_int(0, $type->types->count() - 1);
$randomInternalType = $type->types->get($randomInternalTypeIndex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

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

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

Expand All @@ -18,17 +19,17 @@
*/
class ArrayRegularValueGenerator
{
/** @var ArrayLengthGenerator */
/** @var LengthGenerator */
private $lengthGenerator;

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

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

$values = [];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,39 @@

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

use App\Mock\Generation\Value\Length\LengthGenerator;
use App\Mock\Generation\Value\Unique\UniqueValueGeneratorFactory;
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 */
/** @var LengthGenerator */
private $lengthGenerator;

public function __construct(ArrayLengthGenerator $lengthGenerator)
/** @var UniqueValueGeneratorFactory */
private $uniqueValueGeneratorFactory;

public function __construct(LengthGenerator $lengthGenerator, UniqueValueGeneratorFactory $uniqueValueGeneratorFactory)
{
$this->lengthGenerator = $lengthGenerator;
$this->uniqueValueGeneratorFactory = $uniqueValueGeneratorFactory;
}

public function generateArray(ValueGeneratorInterface $generator, ArrayType $type): array
{
$length = $this->lengthGenerator->generateArrayLength($type);
$uniqueGenerator = $this->uniqueValueGeneratorFactory->createGenerator($generator, $type->items);
$length = $this->lengthGenerator->generateLength($type->minItems, $type->maxItems);

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

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

if ($attemptsExceeded) {
if ($uniqueGenerator->isAttemptsExceedingLimit()) {
if ($i > $length->minValue) {
break;
}
Expand All @@ -52,25 +55,4 @@ public function generateArray(ValueGeneratorInterface $generator, ArrayType $typ

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
Expand Up @@ -10,6 +10,7 @@

namespace App\Mock\Generation\Value\Composite;

use App\Mock\Generation\Value\Length\LengthGenerator;
use App\Mock\Generation\Value\ValueGeneratorInterface;
use App\Mock\Parameters\Schema\Type\Composite\FreeFormObjectType;
use App\Mock\Parameters\Schema\Type\TypeInterface;
Expand All @@ -20,18 +21,19 @@
*/
class FreeFormObjectValueGenerator implements ValueGeneratorInterface
{
private const DEFAULT_MIN_PROPERTIES = 1;
private const DEFAULT_MAX_PROPERTIES = 20;

/** @var Generator */
private $faker;

public function __construct(Generator $faker)
/** @var LengthGenerator */
private $lengthGenerator;

public function __construct(Generator $faker, LengthGenerator $lengthGenerator)
{
$this->faker = $faker;
$this->lengthGenerator = $lengthGenerator;
}

public function generateValue(TypeInterface $type): ?array
public function generateValue(TypeInterface $type): ?object
{
if ($type->isNullable() && 0 === random_int(0, 1)) {
$value = null;
Expand All @@ -42,25 +44,17 @@ public function generateValue(TypeInterface $type): ?array
return $value;
}

private function generateObject(FreeFormObjectType $type): array
private function generateObject(FreeFormObjectType $type): object
{
$properties = [];
$properties = new \stdClass();

$length = $this->generateRandomArrayLength($type);
$length = $this->lengthGenerator->generateLength($type->minProperties, $type->maxProperties);

for ($i = 0; $i < $length; $i++) {
for ($i = 0; $i < $length->value; $i++) {
$key = $this->faker->unique()->word();
$properties[$key] = $this->faker->word();
$properties->{$key} = $this->faker->word();
}

return $properties;
}

private function generateRandomArrayLength(FreeFormObjectType $type): int
{
$minItems = $type->minProperties > 0 ? $type->minProperties : self::DEFAULT_MIN_PROPERTIES;
$maxItems = $type->maxProperties > 0 ? $type->maxProperties : self::DEFAULT_MAX_PROPERTIES;

return random_int($minItems, $maxItems);
}
}
37 changes: 16 additions & 21 deletions src/Mock/Generation/Value/Composite/HashMapValueGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

namespace App\Mock\Generation\Value\Composite;

use App\Mock\Generation\Value\Length\LengthGenerator;
use App\Mock\Generation\Value\ValueGeneratorInterface;
use App\Mock\Generation\ValueGeneratorLocator;
use App\Mock\Parameters\Schema\Type\Composite\HashMapType;
Expand All @@ -21,22 +22,23 @@
*/
class HashMapValueGenerator implements ValueGeneratorInterface
{
private const DEFAULT_MIN_PROPERTIES = 1;
private const DEFAULT_MAX_PROPERTIES = 20;

/** @var Generator */
private $faker;

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

/** @var ValueGeneratorLocator */
private $generatorLocator;

public function __construct(Generator $faker, ValueGeneratorLocator $generatorLocator)
public function __construct(Generator $faker, LengthGenerator $lengthGenerator, ValueGeneratorLocator $generatorLocator)
{
$this->faker = $faker;
$this->lengthGenerator = $lengthGenerator;
$this->generatorLocator = $generatorLocator;
}

public function generateValue(TypeInterface $type): ?array
public function generateValue(TypeInterface $type): ?object
{
if ($type->isNullable() && 0 === random_int(0, 1)) {
$value = null;
Expand All @@ -47,44 +49,37 @@ public function generateValue(TypeInterface $type): ?array
return $value;
}

private function generateHashMap(HashMapType $type): array
private function generateHashMap(HashMapType $type): object
{
$defaultProperties = $this->generateDefaultProperties($type);

return $this->generateAndAppendRandomProperties($type, $defaultProperties);
}

private function generateDefaultProperties(HashMapType $type): array
private function generateDefaultProperties(HashMapType $type): object
{
$properties = [];
$properties = new \stdClass();

foreach ($type->required as $defaultPropertyName) {
$defaultPropertyType = $type->properties[$defaultPropertyName];
$valueGenerator = $this->generatorLocator->getValueGenerator($defaultPropertyType);
$properties[$defaultPropertyName] = $valueGenerator->generateValue($defaultPropertyType);
$properties->{$defaultPropertyName} = $valueGenerator->generateValue($defaultPropertyType);
}

return $properties;
}

private function generateAndAppendRandomProperties(HashMapType $type, array $properties): array
private function generateAndAppendRandomProperties(HashMapType $type, object $properties): object
{
$valueGenerator = $this->generatorLocator->getValueGenerator($type->value);
$length = $this->generateRandomArrayLength($type);
$length = $this->lengthGenerator->generateLength($type->minProperties, $type->maxProperties);
$count = \count(get_object_vars($properties));

for ($i = \count($properties); $i < $length; $i++) {
for ($i = $count; $i < $length->value; $i++) {
$key = $this->faker->unique()->word();
$properties[$key] = $valueGenerator->generateValue($type->value);
$properties->{$key} = $valueGenerator->generateValue($type->value);
}

return $properties;
}

private function generateRandomArrayLength(HashMapType $type): int
{
$minItems = $type->minProperties > 0 ? $type->minProperties : self::DEFAULT_MIN_PROPERTIES;
$maxItems = $type->maxProperties > 0 ? $type->maxProperties : self::DEFAULT_MAX_PROPERTIES;

return random_int($minItems, $maxItems);
}
}
22 changes: 11 additions & 11 deletions src/Mock/Generation/Value/Composite/ObjectValueGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function __construct(ValueGeneratorLocator $generatorLocator)
$this->generatorLocator = $generatorLocator;
}

public function generateValue(TypeInterface $type): ?array
public function generateValue(TypeInterface $type): ?object
{
if ($type->isNullable() && 0 === random_int(0, 1)) {
$value = null;
Expand All @@ -39,27 +39,27 @@ public function generateValue(TypeInterface $type): ?array
return $value;
}

private function generateValueByType(TypeInterface $type)
{
$propertyValueGenerator = $this->generatorLocator->getValueGenerator($type);

return $propertyValueGenerator->generateValue($type);
}

private function generateObject(ObjectType $type): array
private function generateObject(ObjectType $type): object
{
$object = [];
$object = new \stdClass();

/**
* @var string
* @var TypeInterface $propertyType
*/
foreach ($type->properties as $propertyName => $propertyType) {
if (!$propertyType->isWriteOnly()) {
$object[$propertyName] = $this->generateValueByType($propertyType);
$object->{$propertyName} = $this->generateValueByType($propertyType);
}
}

return $object;
}

private function generateValueByType(TypeInterface $type)
{
$propertyValueGenerator = $this->generatorLocator->getValueGenerator($type);

return $propertyValueGenerator->generateValue($type);
}
}
Loading

0 comments on commit a184a24

Please sign in to comment.