diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml
index a5b6b66..7caf4df 100644
--- a/.github/workflows/php.yml
+++ b/.github/workflows/php.yml
@@ -25,16 +25,18 @@ jobs:
fetch-depth: 0
- name: Lint Code Base
- uses: github/super-linter/slim@v5
+ uses: github/super-linter/slim@v6
env:
# To report GitHub Actions status checks
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
LINTER_RULES_PATH: 'tools/linters'
+ LOG_LEVEL: NOTICE
VALIDATE_ALL_CODEBASE: true
+ VALIDATE_CSS: true
+ VALIDATE_JAVASCRIPT_ES: true
VALIDATE_JSON: true
VALIDATE_PHP_BUILTIN: true
VALIDATE_YAML: true
- VALIDATE_XML: true
VALIDATE_GITHUB_ACTIONS: true
quality:
@@ -74,13 +76,14 @@ jobs:
- name: Install Composer dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- #- name: Check code for hard dependencies missing in composer.json
- # run: composer-require-checker check composer.json
+ - name: Check code for hard dependencies missing in composer.json
+ run: composer-require-checker check --config-file tools/composer-require-checker.json composer.json
- name: Check code for unused dependencies in composer.json
run: |
composer-unused \
- --excludePackage=slevomat/coding-standard
+ --excludePackage=slevomat/coding-standard \
+ --excludePackage=symfony/phpunit-bridge
- name: PHP Code Sniffer
run: phpcs
@@ -140,3 +143,150 @@ jobs:
- name: Security check for updated dependencies
run: composer audit
+
+ unit-tests-linux:
+ name: "Unit tests, PHP ${{ matrix.php-versions }}, ${{ matrix.operating-system }}"
+ runs-on: ${{ matrix.operating-system }}
+ needs: [linter, quality, security]
+ strategy:
+ fail-fast: false
+ matrix:
+ operating-system: [ubuntu-latest]
+ php-versions: ['8.1', '8.2', '8.3']
+
+ steps:
+ - name: Setup PHP, with composer and extensions
+ # https://github.com/shivammathur/setup-php
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php-versions }}
+ extensions: ctype, date, dom, fileinfo, filter, hash, json, mbstring, mysql, openssl, pcre,\
+ pdo, pdo_sqlite, posix, soap, spl, xdebug, xml
+ tools: composer
+ ini-values: error_reporting=E_ALL, pcov.directory=.
+ coverage: pcov
+
+ - name: Setup problem matchers for PHP
+ run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
+
+ - name: Setup problem matchers for PHPUnit
+ run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
+
+ - name: Set git to use LF
+ run: |
+ git config --global core.autocrlf false
+ git config --global core.eol lf
+
+ - uses: actions/checkout@v4
+
+ - name: Get composer cache directory
+ run: echo COMPOSER_CACHE="$(composer config cache-files-dir)" >> "$GITHUB_ENV"
+
+ - name: Cache composer dependencies
+ uses: actions/cache@v4
+ with:
+ path: $COMPOSER_CACHE
+ key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
+ restore-keys: ${{ runner.os }}-composer-
+
+ - name: Install Composer dependencies
+ run: composer install --no-progress --prefer-dist --optimize-autoloader
+
+ - name: Run unit tests with coverage
+ if: ${{ matrix.php-versions == '8.3' }}
+ run: vendor/bin/phpunit
+
+ - name: Run unit tests (no coverage)
+ if: ${{ matrix.php-versions != '8.3' }}
+ run: vendor/bin/phpunit --no-coverage
+
+ - name: Save coverage data
+ if: ${{ matrix.php-versions == '8.3' }}
+ uses: actions/upload-artifact@v4
+ with:
+ name: coverage-data
+ path: ${{ github.workspace }}/build
+
+ unit-tests-windows:
+ name: "Unit tests, PHP ${{ matrix.php-versions }}, ${{ matrix.operating-system }}"
+ runs-on: ${{ matrix.operating-system }}
+ needs: [linter, quality, security]
+ strategy:
+ fail-fast: true
+ matrix:
+ operating-system: [windows-latest]
+ php-versions: ['8.1', '8.2', '8.3']
+
+ steps:
+ - name: Setup PHP, with composer and extensions
+ # https://github.com/shivammathur/setup-php
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php-versions }}
+ extensions: ctype, dom, date, fileinfo, filter, hash, json, mbstring, mysql, openssl, pcre, \
+ pdo, pdo_sqlite, posix, soap, spl, xdebug, xml
+ tools: composer
+ ini-values: error_reporting=E_ALL
+ coverage: none
+
+ - name: Setup problem matchers for PHP
+ run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
+
+ - name: Setup problem matchers for PHPUnit
+ run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
+
+ - name: Set git to use LF
+ run: |
+ git config --global core.autocrlf false
+ git config --global core.eol lf
+
+ - uses: actions/checkout@v4
+
+ - name: Get composer cache directory
+ run: echo COMPOSER_CACHE="$(composer config cache-files-dir)" >> "$env:GITHUB_ENV"
+
+ - name: Cache composer dependencies
+ uses: actions/cache@v4
+ with:
+ path: $COMPOSER_CACHE
+ key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
+ restore-keys: ${{ runner.os }}-composer-
+
+ - name: Install Composer dependencies
+ run: composer install --no-progress --prefer-dist --optimize-autoloader --ignore-platform-req=ext-posix
+
+ - name: Run unit tests
+ run: vendor/bin/phpunit --no-coverage
+
+ coverage:
+ name: Code coverage
+ runs-on: [ubuntu-latest]
+ needs: [unit-tests-linux]
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/download-artifact@v4
+ with:
+ name: coverage-data
+ path: ${{ github.workspace }}/build
+
+ - name: Codecov
+ uses: codecov/codecov-action@v4
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ fail_ci_if_error: true
+ verbose: true
+
+ cleanup:
+ name: Cleanup artifacts
+ needs: [unit-tests-linux, coverage]
+ runs-on: [ubuntu-latest]
+ if: |
+ always() &&
+ needs.coverage.result == 'success' ||
+ (needs.unit-tests-linux == 'success' && needs.coverage == 'skipped')
+
+ steps:
+ - uses: geekyeggo/delete-artifact@v5
+ with:
+ name: coverage-data
diff --git a/composer.json b/composer.json
index d4231c4..0c0a296 100644
--- a/composer.json
+++ b/composer.json
@@ -15,15 +15,21 @@
"SimpleSAML\\TestUtils\\": "lib/"
}
},
+ "autoload-dev": {
+ "psr-4": {
+ "SimpleSAML\\Test\\TestUtils\\": "tests/src/"
+ }
+ },
"require": {
+ "php": "^8.1",
+ "ext-curl": "*",
+
"phpunit/phpunit": "^10.0 || ^11.0",
+ "psr/log": "^2.0 || ^3.0",
"slevomat/coding-standard": "^8.15",
"symfony/phpunit-bridge": "^6.4 || ^7.0"
},
"require-dev": {
- "php": "^8.1",
- "ext-curl": "*",
-
"simplesamlphp/simplesamlphp": "^2.2.0"
},
"support": {
diff --git a/lib/InMemoryStore.php b/lib/InMemoryStore.php
new file mode 100644
index 0000000..05fec37
--- /dev/null
+++ b/lib/InMemoryStore.php
@@ -0,0 +1,81 @@
+delete($type, $key);
+ return null;
+ }
+ return $item['value'];
+ }
+ return null;
+ }
+
+
+ /**
+ * Save a value to the data store.
+ *
+ * @param string $type The data type.
+ * @param string $key The key.
+ * @param mixed $value The value.
+ * @param int|null $expire The expiration time (unix timestamp), or null if it never expires.
+ */
+ public function set(string $type, string $key, mixed $value, ?int $expire = null): void
+ {
+ self::$store[$key] = [
+ 'type' => $type,
+ 'value' => $value,
+ 'expire' => $expire
+ ];
+ }
+
+
+ /**
+ * Delete a value from the data store.
+ *
+ * @param string $type The data type.
+ * @param string $key The key.
+ */
+ public function delete(string $type, string $key): void
+ {
+ unset(self::$store[$key]);
+ }
+
+
+ /**
+ * Clear any cached internal state.
+ */
+ public static function clearInternalState(): void
+ {
+ self::$store = [];
+ }
+}
diff --git a/phpcs-simplesamlphp.xml b/phpcs-simplesamlphp.xml
index 20925bf..8801d71 100644
--- a/phpcs-simplesamlphp.xml
+++ b/phpcs-simplesamlphp.xml
@@ -17,4 +17,7 @@
+
+
+
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..6971499
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+ ./tests
+
+
+
+
+
+ ./lib
+ ./src
+
+
+
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
new file mode 100644
index 0000000..28c2413
--- /dev/null
+++ b/tests/bootstrap.php
@@ -0,0 +1,6 @@
+ 'SimpleSAML\TestUtils\InMemoryStore',
+ ];
+ Configuration::loadFromArray($config, '[ARRAY]', 'simplesaml');
+
+ // when: getting the store
+ $store = StoreFactory::getInstance('SimpleSAML\TestUtils\InMemoryStore');
+
+ // then: will give us the right type of store
+ $this->assertInstanceOf(InMemoryStore::class, $store);
+
+ // and: we can store stuff
+ $this->assertNull($store->get('string', 'key'), 'Key does not exist yet');
+ $store->set('string', 'key', 'value');
+ $this->assertEquals('value', $store->get('string', 'key'));
+ $store->delete('string', 'key');
+ $this->assertNull($store->get('string', 'key'), 'Key was removed');
+ }
+
+
+ public function testExpiration(): void
+ {
+ $store = new InMemoryStore();
+ $store->set('string', 'key', 'value', time() + 1);
+ $this->assertEquals('value', $store->get('string', 'key'));
+ $this->assertEquals('value', $store->get('string', 'key'));
+ sleep(2);
+ $this->assertNull($store->get('string', 'key'));
+ }
+}
diff --git a/tools/composer-require-checker.json b/tools/composer-require-checker.json
new file mode 100644
index 0000000..eed71aa
--- /dev/null
+++ b/tools/composer-require-checker.json
@@ -0,0 +1,4 @@
+{
+ "symbol-whitelist": [
+ ]
+}