diff --git a/.github/workflows/mutation.yml b/.github/workflows/mutation.yml index df1db8d..7f71d5f 100644 --- a/.github/workflows/mutation.yml +++ b/.github/workflows/mutation.yml @@ -28,6 +28,7 @@ jobs: ['ubuntu-latest'] php: >- ['8.3'] - min-covered-msi: 100 + min-msi: 100 + threads: 1 secrets: STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }} diff --git a/composer.json b/composer.json index 3c7c8b1..00df417 100644 --- a/composer.json +++ b/composer.json @@ -64,6 +64,7 @@ }, "scripts": { "cs-fix": "php-cs-fixer fix", + "mutation": "roave-infection-static-analysis-plugin --min-msi=100", "rector": "rector", "test": "phpunit", "test-watch": "phpunit-watcher watch" diff --git a/infection.json.dist b/infection.json.dist index 9419316..7aedcac 100644 --- a/infection.json.dist +++ b/infection.json.dist @@ -16,6 +16,16 @@ "ignoreSourceCodeByRegex": [ "\\$this->invalidateScriptCache.*" ] + }, + "DecrementInteger": { + "ignoreSourceCodeByRegex": [ + "mkdir\\(.*permissions: 0775.*" + ] + }, + "IncrementInteger": { + "ignoreSourceCodeByRegex": [ + "mkdir\\(.*permissions: 0775.*" + ] } } } diff --git a/tests/AssignmentsStorageTest.php b/tests/AssignmentsStorageTest.php index f2b2783..cd78b06 100644 --- a/tests/AssignmentsStorageTest.php +++ b/tests/AssignmentsStorageTest.php @@ -44,6 +44,21 @@ public function testGetFileUpdatedAtException(): void ); } + public function testRemoveNonExistingDoesNotSaveFile(): void + { + $filePath = $this->getAssignmentsStorageFilePath(); + $storage = new AssignmentsStorage($filePath); + + touch($filePath, time() - 100); + clearstatcache(); + $modifiedTimeBefore = filemtime($filePath); + + $storage->remove(itemName: 'Operator', userId: 'john'); + + clearstatcache(); + $this->assertSame($modifiedTimeBefore, filemtime($filePath)); + } + protected function createItemsStorage(): ItemsStorageInterface { return new ItemsStorage($this->getItemsStorageFilePath()); diff --git a/tests/AssignmentsStorageWithConcurrencyHandledTest.php b/tests/AssignmentsStorageWithConcurrencyHandledTest.php index a8d9668..e0c7def 100644 --- a/tests/AssignmentsStorageWithConcurrencyHandledTest.php +++ b/tests/AssignmentsStorageWithConcurrencyHandledTest.php @@ -150,6 +150,21 @@ public function testRemoveByItemName(): void $this->assertEmpty($innerTestStorage->getByItemNames(['Accountant'])); } + public function testNoReloadWhenTimestampIsUnchanged(): void + { + $filePath = $this->getAssignmentsStorageFilePath(); + $innerStorage = new AssignmentsStorage($filePath, getFileUpdatedAt: static fn(): int => 12345); + $decorator = new ConcurrentAssignmentsStorageDecorator($innerStorage); + + $decorator->add(new Assignment(userId: 'testUser', itemName: 'Researcher', createdAt: time())); + + (new AssignmentsStorage($filePath))->add( + new Assignment(userId: 'testUser', itemName: 'Accountant', createdAt: time()), + ); + + $this->assertArrayNotHasKey('Accountant', $decorator->getByUserId('testUser')); + } + protected function createItemsStorage(): ItemsStorageInterface { return new ConcurrentItemsStorageDecorator(new ItemsStorage($this->getItemsStorageFilePath())); diff --git a/tests/ItemsStorage/ItemsStorageTest.php b/tests/ItemsStorage/ItemsStorageTest.php index 2ce3011..03521ff 100644 --- a/tests/ItemsStorage/ItemsStorageTest.php +++ b/tests/ItemsStorage/ItemsStorageTest.php @@ -100,6 +100,36 @@ public function testLoadWithCustomGetFileUpdatedAt(): void $this->assertSame($time, $storage->get('test')->getCreatedAt()); } + public function testRemoveChildNonExistingDoesNotSaveFile(): void + { + $filePath = $this->getItemsStorageFilePath(); + $storage = new ItemsStorage($filePath); + + touch($filePath, time() - 100); + clearstatcache(); + $mtimeBefore = filemtime($filePath); + + $storage->removeChild('posts.viewer', 'non-existing'); + + clearstatcache(); + $this->assertSame($mtimeBefore, filemtime($filePath)); + } + + public function testRemoveChildrenNonExistingDoesNotSaveFile(): void + { + $filePath = $this->getItemsStorageFilePath(); + $storage = new ItemsStorage($filePath); + + touch($filePath, time() - 100); + clearstatcache(); + $mtimeBefore = filemtime($filePath); + + $storage->removeChildren('posts.view'); + + clearstatcache(); + $this->assertSame($mtimeBefore, filemtime($filePath)); + } + public function testGetFileUpdatedAtException(): void { $this->expectException(RuntimeException::class);