diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 50b1bb5..48a5639 100755 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,11 +11,11 @@ jobs: if: "!contains(github.event.head_commit.message, 'skip ci')" name: PHP ${{ matrix.php-versions }} on ${{ matrix.os }} runs-on: ${{ matrix.os }} - continue-on-error: ${{ matrix.php-versions == '8.2' }} + continue-on-error: ${{ matrix.php-versions >= '8.4' }} strategy: fail-fast: false matrix: - php-versions: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] + php-versions: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] os: [ubuntu-latest, windows-latest] steps: @@ -24,7 +24,7 @@ jobs: run: git config --system core.autocrlf false; git config --system core.eol lf - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up PHP ${{ matrix.php-versions }} uses: shivammathur/setup-php@v2 @@ -32,9 +32,6 @@ jobs: php-version: ${{ matrix.php-versions }} ini-values: date.timezone=Europe/Berlin - - name: Setup Problem Matchers for PHP - run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" - - name: Validate composer.json and composer.lock run: composer validate @@ -43,7 +40,7 @@ jobs: run: echo "::set-output name=dir::$(composer config cache-files-dir)" - name: Cache dependencies - uses: actions/cache@v2.1.3 + uses: actions/cache@v3 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} @@ -51,9 +48,9 @@ jobs: - name: Install dependencies run: > - curl -sSL https://baltocdn.com/xp-framework/xp-runners/distribution/downloads/e/entrypoint/xp-run-8.6.2.sh > xp-run && + curl -sSL https://baltocdn.com/xp-framework/xp-runners/distribution/downloads/e/entrypoint/xp-run-8.8.0.sh > xp-run && composer install --prefer-dist && echo "vendor/autoload.php" > composer.pth - name: Run test suite - run: sh xp-run xp.unittest.TestRunner src/test/php + run: sh xp-run xp.test.Runner -r Dots src/test/php diff --git a/ChangeLog.md b/ChangeLog.md index 48358ea..d9ca704 100755 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -3,6 +3,17 @@ Credentials change log ## ?.?.? / ????-??-?? +## 3.1.0 / 2024-03-24 + +* Made compatible with XP 12 - @thekid + +## 3.0.0 / 2024-02-04 + +* Made compatible with https://github.com/xp-forge/keepass version 2.0 + (@thekid) +* Implemented xp-framework/rfc#341: Drop XP <= 9 compatibility - @thekid +* Merged PR #11: Migrate to new testing library - @thekid + ## 2.1.0 / 2022-02-26 * Merged PR #10: Throw exceptions if vault is down - @thekid diff --git a/composer.json b/composer.json index 2777d64..08520c0 100755 --- a/composer.json +++ b/composer.json @@ -6,13 +6,13 @@ "description" : "Credentials", "keywords": ["module", "xp"], "require" : { - "xp-framework/core": "^11.0 | ^10.0 | ^9.0 | ^8.0 | ^7.0", + "xp-framework/core": "^12.0 | ^11.0 | ^10.0", "xp-forge/rest-client": "^5.0 | ^4.0 | ^3.0 | ^2.0 | ^1.0", - "xp-forge/keepass": "^1.0", + "xp-forge/keepass": "^2.0 | ^1.0", "php" : ">=7.0.0" }, "require-dev" : { - "xp-framework/unittest": "^11.0 | ^10.0 | ^9.0 | ^8.0 | ^7.0" + "xp-framework/test": "^2.0 | ^1.0" }, "autoload" : { "files" : ["src/main/php/autoload.php"] diff --git a/src/test/php/security/credentials/unittest/AbstractSecretsTest.class.php b/src/test/php/security/credentials/unittest/AbstractSecretsTest.class.php index d06e578..ae29bb4 100755 --- a/src/test/php/security/credentials/unittest/AbstractSecretsTest.class.php +++ b/src/test/php/security/credentials/unittest/AbstractSecretsTest.class.php @@ -1,11 +1,11 @@ open(); try { - $this->assertEquals($expected, $fixture->named($name)->reveal()); + Assert::equals($expected, $fixture->named($name)->reveal()); } finally { $fixture->close(); } @@ -37,7 +37,7 @@ protected function assertCredential($fixture, $expected, $name) { protected function assertCredentials($fixture, $expected, $pattern) { $fixture->open(); try { - $this->assertEquals($expected, array_map( + Assert::equals($expected, array_map( function($s) { return $s->reveal(); }, iterator_to_array($fixture->all($pattern)) )); @@ -48,7 +48,7 @@ function($s) { return $s->reveal(); }, #[Test] public function open_and_close_can_be_called_twice() { - $fixture= $this->newFixture(); + $fixture= $this->newFixture(__FUNCTION__); $fixture->open(); $fixture->open(); @@ -58,20 +58,20 @@ public function open_and_close_can_be_called_twice() { #[Test, Values([['test_db_password', 'db'], ['test_ldap_password', 'ldap'], ['prod_master_key', 'master']])] public function credential($name, $result) { - $this->assertCredential($this->newFixture(), $result, $name); + $this->assertCredential($this->newFixture(__FUNCTION__), $result, $name); } #[Test, Values([['test_*', ['test_db_password' => 'db', 'test_ldap_password' => 'ldap']], ['prod_*', ['prod_master_key' => 'master']], ['non_existant_*', []]])] public function credentials($filter, $result) { - $this->assertCredentials($this->newFixture(), $result, $filter); + $this->assertCredentials($this->newFixture(__FUNCTION__), $result, $filter); } #[Test] public function non_existant_credential() { - $fixture= $this->newFixture(); + $fixture= $this->newFixture(__FUNCTION__); $fixture->open(); try { - $this->assertNull($fixture->named('non_existant_value')); + Assert::null($fixture->named('non_existant_value')); } finally { $fixture->close(); } diff --git a/src/test/php/security/credentials/unittest/CredentialsTest.class.php b/src/test/php/security/credentials/unittest/CredentialsTest.class.php index 79203cb..4f88fc8 100755 --- a/src/test/php/security/credentials/unittest/CredentialsTest.class.php +++ b/src/test/php/security/credentials/unittest/CredentialsTest.class.php @@ -2,10 +2,11 @@ use lang\{ElementNotFoundException, IllegalArgumentException}; use security\credentials\{Credentials, Secrets}; -use unittest\{Expect, Test, Values}; +use test\Assert; +use test\{Expect, Test, Values}; use util\Secret; -class CredentialsTest extends \unittest\TestCase { +class CredentialsTest { #[Test] public function can_create() { @@ -32,7 +33,7 @@ public function credential() { 'close' => function() { } ])); - $this->assertEquals($secret, $credentials->named('test')); + Assert::equals($secret, $credentials->named('test')); } #[Test, Values(['test', '*'])] @@ -45,7 +46,7 @@ public function credentials($pattern) { 'close' => function() { } ])); - $this->assertEquals(['test' => $secret], iterator_to_array($credentials->all($pattern))); + Assert::equals(['test' => $secret], iterator_to_array($credentials->all($pattern))); } #[Test, Expect(ElementNotFoundException::class)] @@ -71,7 +72,7 @@ public function explicit_open() { ])); $credentials->open(); - $this->assertEquals(true, $opened); + Assert::equals(true, $opened); } #[Test] @@ -92,7 +93,7 @@ public function secrets_not_opened_until_actually_needed() { ]) ); - $this->assertEquals($secret, $credentials->named('test')); + Assert::equals($secret, $credentials->named('test')); } #[Test] @@ -114,6 +115,6 @@ public function secrets_opened_during_all() { $opened= []; iterator_count($credentials->all('*')); - $this->assertEquals(['a', 'b'], $opened); + Assert::equals(['a', 'b'], $opened); } } \ No newline at end of file diff --git a/src/test/php/security/credentials/unittest/FromDockerSecretsTest.class.php b/src/test/php/security/credentials/unittest/FromDockerSecretsTest.class.php index f74e195..242ac27 100755 --- a/src/test/php/security/credentials/unittest/FromDockerSecretsTest.class.php +++ b/src/test/php/security/credentials/unittest/FromDockerSecretsTest.class.php @@ -3,18 +3,18 @@ use io\{Folder, Path}; use lang\Environment; use security\credentials\FromDockerSecrets; -use unittest\Test; +use test\{Assert, After, Before, Test}; use util\Secret; class FromDockerSecretsTest extends AbstractSecretsTest { private $path; /** @return security.credentials.Secrets */ - protected function newFixture() { + protected function newFixture($name) { return new FromDockerSecrets($this->path); } - /** @return void */ + #[Before] public function setUp() { $this->path= new Folder(Environment::tempDir(), 'secrets'); $this->path->exists() && $this->path->unlink(); @@ -30,7 +30,7 @@ public function setUp() { file_put_contents(new Path($subfolder, 'mysql'), "test\n"); } - /** @return void */ + #[After] public function tearDown() { $this->path->exists() && $this->path->unlink(); } @@ -38,22 +38,22 @@ public function tearDown() { #[Test] public function path() { $path= new Path('.'); - $this->assertEquals($path, (new FromDockerSecrets($path))->path()); + Assert::equals($path, (new FromDockerSecrets($path))->path()); } #[Test] public function string_path() { - $this->assertEquals(new Path('.'), (new FromDockerSecrets('.'))->path()); + Assert::equals(new Path('.'), (new FromDockerSecrets('.'))->path()); } #[Test] public function folder_path() { $folder= new Folder('.'); - $this->assertEquals(new Path($folder->getURI()), (new FromDockerSecrets($folder))->path()); + Assert::equals(new Path($folder->getURI()), (new FromDockerSecrets($folder))->path()); } #[Test] public function default_path() { - $this->assertNotEquals(null, (new FromDockerSecrets())->path()); + Assert::notEquals(null, (new FromDockerSecrets())->path()); } } \ No newline at end of file diff --git a/src/test/php/security/credentials/unittest/FromEnvironmentTest.class.php b/src/test/php/security/credentials/unittest/FromEnvironmentTest.class.php index f54345a..0364ccc 100755 --- a/src/test/php/security/credentials/unittest/FromEnvironmentTest.class.php +++ b/src/test/php/security/credentials/unittest/FromEnvironmentTest.class.php @@ -2,21 +2,19 @@ use lang\Environment; use security\credentials\FromEnvironment; -use unittest\Test; +use test\{Assert, Test}; use util\Secret; class FromEnvironmentTest extends AbstractSecretsTest { /** @return security.vault.Secrets */ - protected function newFixture() { return new FromEnvironment(); } - - /** @return void */ - public function setUp() { + protected function newFixture($name) { Environment::export([ 'TEST_DB_PASSWORD' => 'db', 'TEST_LDAP_PASSWORD' => 'ldap', 'PROD_MASTER_KEY' => 'master', ]); + return new FromEnvironment(); } #[Test] @@ -26,6 +24,7 @@ public function can_create() { #[Test] public function removed_after_use() { + Environment::export(['TEST_DB_PASSWORD' => 'db']); $before= Environment::variable('TEST_DB_PASSWORD', null); with (new FromEnvironment(FromEnvironment::REMOVE), function($fixture) { @@ -35,6 +34,6 @@ public function removed_after_use() { }); $after= Environment::variable('TEST_DB_PASSWORD', null); - $this->assertEquals(['db', null], [$before, $after]); + Assert::equals(['db', null], [$before, $after]); } } \ No newline at end of file diff --git a/src/test/php/security/credentials/unittest/FromFileTest.class.php b/src/test/php/security/credentials/unittest/FromFileTest.class.php index 97614c2..c6a3c46 100755 --- a/src/test/php/security/credentials/unittest/FromFileTest.class.php +++ b/src/test/php/security/credentials/unittest/FromFileTest.class.php @@ -3,12 +3,12 @@ use io\streams\{MemoryInputStream, Streams}; use io\{File, TempFile}; use security\credentials\FromFile; -use unittest\{Test, Values}; +use test\{Assert, Test, Values}; class FromFileTest extends AbstractSecretsTest { /** @return security.vault.Secrets */ - protected function newFixture() { + protected function newFixture($name) { return new FromFile(Streams::readableFd(new MemoryInputStream( "TEST_DB_PASSWORD=db\n". "TEST_LDAP_PASSWORD=ldap\n". @@ -23,31 +23,31 @@ private function files() { yield ['filename', 'filenames']; } - #[Test, Values('files')] + #[Test, Values(from: 'files')] public function can_create($arg, $from) { new FromFile($arg); } #[Test] public function file_kept_by_default() { - $file= new TempFile($this->name); + $file= new TempFile('secrets'); $fixture= new FromFile($file); $fixture->open(); $fixture->close(); - $this->assertTrue($file->exists()); + Assert::true($file->exists()); } #[Test] public function can_optionally_be_removed_after_close() { - $file= new TempFile($this->name); + $file= new TempFile('secrets'); $fixture= new FromFile($file, FromFile::REMOVE); $fixture->open(); $fixture->close(); - $this->assertFalse($file->exists()); + Assert::false($file->exists()); } #[Test] public function byte_escape_sequence() { - $this->assertCredential($this->newFixture(), "S\xa7T", 'cloud_secret'); + $this->assertCredential($this->newFixture(__FUNCTION__), "S\xa7T", 'cloud_secret'); } } \ No newline at end of file diff --git a/src/test/php/security/credentials/unittest/FromKeePassTest.class.php b/src/test/php/security/credentials/unittest/FromKeePassTest.class.php index e1a3475..73cc100 100755 --- a/src/test/php/security/credentials/unittest/FromKeePassTest.class.php +++ b/src/test/php/security/credentials/unittest/FromKeePassTest.class.php @@ -2,13 +2,14 @@ use lang\ClassLoader; use security\credentials\FromKeePass; -use unittest\{Test, Values}; +use test\Assert; +use test\{Test, Values}; use util\Secret; class FromKeePassTest extends AbstractSecretsTest { /** @return security.vault.Secrets */ - protected function newFixture($group= '/') { + protected function newFixture($name, $group= '/') { return new FromKeePass( ClassLoader::getDefault()->getResourceAsStream('keepass/unittest.kdbx'), new Secret('test'), @@ -18,11 +19,11 @@ protected function newFixture($group= '/') { #[Test, Values(['xp/app', '/xp/app', '/xp/app/'])] public function using_group($group) { - $this->assertCredential($this->newFixture($group), 'test', 'mysql'); + $this->assertCredential($this->newFixture(__FUNCTION__, $group), 'test', 'mysql'); } #[Test, Values(['xp/app', '/xp/app', '/xp/app/'])] public function all_in_group($group) { - $this->assertCredentials($this->newFixture($group), ['mysql' => 'test'], '*'); + $this->assertCredentials($this->newFixture(__FUNCTION__, $group), ['mysql' => 'test'], '*'); } } \ No newline at end of file diff --git a/src/test/php/security/credentials/unittest/FromStreamTest.class.php b/src/test/php/security/credentials/unittest/FromStreamTest.class.php index 4b45d90..8aaa074 100755 --- a/src/test/php/security/credentials/unittest/FromStreamTest.class.php +++ b/src/test/php/security/credentials/unittest/FromStreamTest.class.php @@ -3,13 +3,14 @@ use io\File; use io\streams\{MemoryInputStream, TextReader}; use security\credentials\FromStream; -use unittest\{Test, Values}; +use test\Assert; +use test\{Test, Values}; use util\Secret; class FromStreamTest extends AbstractSecretsTest { /** @return security.vault.Secrets */ - protected function newFixture() { + protected function newFixture($name) { return new FromStream(new MemoryInputStream( "test_db_password=db\n". "test_ldap_password=ldap\n". @@ -26,7 +27,7 @@ private function streams() { yield ['filename', 'filenames']; } - #[Test, Values('streams')] + #[Test, Values(from: 'streams')] public function can_create($arg, $from) { new FromStream($arg); } diff --git a/src/test/php/security/credentials/unittest/FromVaultTest.class.php b/src/test/php/security/credentials/unittest/FromVaultTest.class.php index 596800e..bf7b47e 100755 --- a/src/test/php/security/credentials/unittest/FromVaultTest.class.php +++ b/src/test/php/security/credentials/unittest/FromVaultTest.class.php @@ -5,7 +5,8 @@ use peer\URL; use peer\http\HttpResponse; use security\credentials\FromVault; -use unittest\{Expect, Test, Values}; +use test\Assert; +use test\{Expect, Test, Values}; use util\Secret; use webservices\rest\{Endpoint, RestRequest, RestResponse}; @@ -28,8 +29,8 @@ class FromVaultTest extends AbstractSecretsTest { ]; /** @return security.vault.Secrets */ - protected function newFixture() { - $answers= &self::$answers[$this->getName()]; + protected function newFixture($name) { + $answers= &self::$answers[$name]; return new FromVault(newinstance(Endpoint::class, ['http://test/'], [ 'execute' => function(RestRequest $request) use(&$answers) { $answer= array_shift($answers); @@ -52,7 +53,7 @@ private function endpoints() { } - #[Test, Values('endpoints')] + #[Test, Values(from: 'endpoints')] public function can_create_with($arg) { new FromVault($arg); } @@ -105,7 +106,7 @@ public function all_on_vault_error() { iterator_count((new FromVault($endpoint))->all('group*')); } - #[Test, Values(['map' => ['/' => '/', '/vendor/name' => '/vendor/name/', '/vendor/name/' => '/vendor/name/', 'vendor/name' => '/vendor/name/', 'vendor/name/' => '/vendor/name/',]])] + #[Test, Values([['/', '/'], ['/vendor/name', '/vendor/name/'], ['/vendor/name/', '/vendor/name/'], ['vendor/name', '/vendor/name/'], ['vendor/name/', '/vendor/name/']])] public function using_group($group, $path) { $endpoint= newinstance(Endpoint::class, ['http://test/'], [ 'execute' => function(RestRequest $request) use(&$requested) { @@ -115,6 +116,6 @@ public function using_group($group, $path) { ]); (new FromVault($endpoint, 'SECRET_VAULT_TOKEN', $group))->named('credential'); - $this->assertEquals('/v1/secret'.$path, $requested); + Assert::equals('/v1/secret'.$path, $requested); } } \ No newline at end of file diff --git a/src/test/php/security/credentials/unittest/PropertiesTest.class.php b/src/test/php/security/credentials/unittest/PropertiesTest.class.php index 5958be5..e209c88 100755 --- a/src/test/php/security/credentials/unittest/PropertiesTest.class.php +++ b/src/test/php/security/credentials/unittest/PropertiesTest.class.php @@ -2,10 +2,11 @@ use io\streams\MemoryInputStream; use security\credentials\{Credentials, Secrets}; -use unittest\{Test, TestCase}; +use test\Assert; +use test\{Test, TestCase}; use util\{Properties, Secret}; -class PropertiesTest extends TestCase { +class PropertiesTest { #[Test] public function expanding() { @@ -20,6 +21,6 @@ public function expanding() { $prop= $credentials->expanding(new Properties()); $prop->load(new MemoryInputStream('pass=${secret.test}')); - $this->assertEquals($secret->reveal(), $prop->readString(null, 'pass')); + Assert::equals($secret->reveal(), $prop->readString(null, 'pass')); } } \ No newline at end of file