Skip to content

Commit

Permalink
Merge pull request #467: Fix EncodedValues to return null if possible…
Browse files Browse the repository at this point in the history
… when there is no value in Payloads
  • Loading branch information
roxblnfk authored Jul 2, 2024
2 parents cc87986 + 026140f commit b290246
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 3 deletions.
8 changes: 6 additions & 2 deletions src/DataConverter/EncodedValues.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use React\Promise\PromiseInterface;
use Temporal\Api\Common\V1\Payload;
use Temporal\Api\Common\V1\Payloads;
use Temporal\Workflow\ReturnType;
use Traversable;

/**
Expand Down Expand Up @@ -213,8 +214,11 @@ private function isVoidType(mixed $type = null): bool
{
return match (true) {
$type === null => true,
$type instanceof Type => \in_array($type->getName(), [Type::TYPE_VOID, Type::TYPE_NULL], true),
$type instanceof \ReflectionNamedType => $type->getName() === Type::TYPE_VOID,
\is_string($type) => \in_array($type, [Type::TYPE_VOID, Type::TYPE_NULL, Type::TYPE_ANY], true),
$type instanceof Type => $type->allowsNull(),
$type instanceof ReturnType => $type->nullable,
$type instanceof \ReflectionNamedType => $type->getName() === Type::TYPE_VOID || $type->allowsNull(),
$type instanceof \ReflectionUnionType => $type->allowsNull(),
default => false,
};
}
Expand Down
2 changes: 1 addition & 1 deletion src/Workflow/ReturnType.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,6 @@ public function __construct(
bool $nullable = false
) {
$this->name = $name;
$this->nullable = $nullable;
$this->nullable = $nullable || (new Type($name))->allowsNull();
}
}
76 changes: 76 additions & 0 deletions tests/Unit/Protocol/EncodingTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@

namespace Temporal\Tests\Unit\Protocol;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Temporal\DataConverter\DataConverter;
use Temporal\DataConverter\EncodedValues;
use Temporal\DataConverter\Type;
use Temporal\Workflow\ReturnType;

/**
* @group unit
Expand All @@ -27,4 +30,77 @@ public function nullValuesAreReturned(): void
$encodedValues = EncodedValues::fromValues([null, 'something'], new DataConverter());
$this->assertNull($encodedValues->getValue(0));
}

public static function getNotNullableTypes(): iterable
{
yield [Type::create(Type::TYPE_ARRAY)];
yield [Type::create(Type::TYPE_OBJECT)];
yield [Type::create(Type::TYPE_STRING)];
yield [Type::create(Type::TYPE_BOOL)];
yield [Type::create(Type::TYPE_INT)];
yield [Type::create(Type::TYPE_FLOAT)];
yield [Type::create(Type::TYPE_TRUE)];
yield [Type::create(Type::TYPE_FALSE)];
yield [Type::create(self::class)];
yield [Type::TYPE_ARRAY];
yield [Type::TYPE_OBJECT];
yield [Type::TYPE_STRING];
yield [Type::TYPE_BOOL];
yield [Type::TYPE_INT];
yield [Type::TYPE_FLOAT];
yield [Type::TYPE_TRUE];
yield [Type::TYPE_FALSE];
yield [self::class];
yield [new ReturnType(self::class)];
yield [self::getReturnType(static fn(): string => '')];
yield [self::getReturnType(static fn(): int => 0)];
yield [self::getReturnType(static fn(): float => 0.0)];
yield [self::getReturnType(static fn(): bool => false)];
yield [self::getReturnType(static fn(): array => [])];
yield [self::getReturnType(static fn(): object => new \stdClass())];
yield 'union' => [[self::getReturnType(static fn(): int|string => 0)]];
}

public static function getNullableTypes(): iterable
{
yield [null];
yield [Type::create(Type::TYPE_ANY)];
yield [Type::create(Type::TYPE_VOID)];
yield [Type::create(Type::TYPE_NULL)];
yield [new Type(self::class, true)];
yield [new ReturnType(self::class, true)];
yield [Type::TYPE_ANY];
yield [Type::TYPE_VOID];
yield [Type::TYPE_NULL];
yield 'nullable' => [self::getReturnType(static fn(): ?string => null)];
yield 'mixed' => [self::getReturnType(static fn(): mixed => null)];
yield 'void' => [self::getReturnType(static function (): void {})];
yield 'union' => [self::getReturnType(static fn(): int|string|null => null)];
}

#[Test]
#[DataProvider('getNullableTypes')]
public function payloadWithoutValueDecoding(mixed $type): void
{
$encodedValues = EncodedValues::fromPayloadCollection(new \ArrayIterator([]));

self::assertNull($encodedValues->getValue(0, $type));
}

#[Test]
#[DataProvider('getNotNullableTypes')]
public function payloadWithoutValueDecodingNotNullable(mixed $type): void
{
$encodedValues = EncodedValues::fromPayloadCollection(new \ArrayIterator([]));

self::expectException(\LogicException::class);
self::expectExceptionMessage('DataConverter is not set');

$encodedValues->getValue(0, $type);
}

private static function getReturnType(\Closure $closure): \ReflectionType
{
return (new \ReflectionFunction($closure))->getReturnType();
}
}

0 comments on commit b290246

Please sign in to comment.