Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
timacdonald committed May 29, 2024
1 parent d76c0e8 commit 2c5d269
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/Drivers/DatabaseDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ public function get($feature, $scope): mixed
$this->insert($feature, $scope, $value);
} catch (UniqueConstraintViolationException $e) {
if ($this->retryDepth === 1) {
throw new RuntimeException('Unable to insert feature value from the database.', previous: $e);
throw new RuntimeException('Unable to insert feature value into the database.', previous: $e);
}

$this->retryDepth++;
Expand Down
90 changes: 90 additions & 0 deletions tests/Feature/DatabaseDriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

namespace Tests\Feature;

use Exception;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Database\UniqueConstraintViolationException;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Str;
use InvalidArgumentException;
use Laravel\Pennant\Contracts\FeatureScopeable;
use Laravel\Pennant\Events\AllFeaturesPurged;
Expand All @@ -19,6 +23,7 @@
use Laravel\Pennant\Events\FeatureUpdatedForAllScopes;
use Laravel\Pennant\Events\UnknownFeatureResolved;
use Laravel\Pennant\Feature;
use RuntimeException;
use Tests\TestCase;
use Workbench\App\Models\User;
use Workbench\Database\Factories\UserFactory;
Expand Down Expand Up @@ -1293,6 +1298,91 @@ public function test_it_can_list_stored_features()

$this->assertSame(Feature::stored(), ['bar', 'baz']);
}

public function test_it_retries_3_times_and_then_fails()
{
Feature::define('foo', fn () => true);
Feature::define('bar', fn () => true);
$insertAttempts = 0;
DB::listen(function (QueryExecuted $event) use (&$insertAttempts) {
if (Str::startsWith($event->sql, 'insert into "features"')) {
$insertAttempts++;
DB::table('features')->delete();
throw new UniqueConstraintViolationException($event->connectionName, $event->sql, $event->bindings, new RuntimeException());
}
});


try {
Feature::for('tim')->loadMissing(['foo', 'bar']);
$this->fail('Should have failed.');
} catch (Exception $e) {
$this->assertInstanceOf(RuntimeException::class, $e);
$this->assertSame('Unable to insert feature values into the database.', $e->getMessage());
$this->assertInstanceOf(UniqueConstraintViolationException::class, $e->getPrevious());
}

$this->assertSame(3, $insertAttempts);
}

public function test_it_only_retries_on_conflicts()
{
Feature::define('foo', fn () => true);
Feature::define('bar', fn () => true);
$insertAttempts = 0;
DB::listen(function (QueryExecuted $event) use (&$insertAttempts) {
if (Str::startsWith($event->sql, 'insert into "features"')) {
$insertAttempts++;
throw new UniqueConstraintViolationException($event->connectionName, $event->sql, $event->bindings, new RuntimeException());
}
});

Feature::for('tim')->loadMissing(['foo', 'bar']);

$this->assertSame(1, $insertAttempts);
}

public function test_it_retries_2_times_and_then_fails_for_individual_queries()
{
Feature::define('foo', fn () => true);
Feature::define('bar', fn () => true);
$insertAttempts = 0;
DB::listen(function (QueryExecuted $event) use (&$insertAttempts) {
if (Str::startsWith($event->sql, 'insert into "features"')) {
$insertAttempts++;
DB::table('features')->delete();
throw new UniqueConstraintViolationException($event->connectionName, $event->sql, $event->bindings, new RuntimeException());
}
});

try {
Feature::driver('database')->get('foo', 'tim');
$this->fail('Should have failed.');
} catch (Exception $e) {
$this->assertInstanceOf(RuntimeException::class, $e);
$this->assertSame('Unable to insert feature value into the database.', $e->getMessage());
$this->assertInstanceOf(UniqueConstraintViolationException::class, $e->getPrevious());
}

$this->assertSame(2, $insertAttempts);
}

public function test_it_only_retries_on_conflicts_for_individual_queries()
{
Feature::define('foo', fn () => true);
Feature::define('bar', fn () => true);
$insertAttempts = 0;
DB::listen(function (QueryExecuted $event) use (&$insertAttempts) {
if (Str::startsWith($event->sql, 'insert into "features"')) {
$insertAttempts++;
throw new UniqueConstraintViolationException($event->connectionName, $event->sql, $event->bindings, new RuntimeException());
}
});

Feature::driver('database')->get('foo', 'tim');

$this->assertSame(1, $insertAttempts);
}
}

class UnregisteredFeature
Expand Down

0 comments on commit 2c5d269

Please sign in to comment.