diff --git a/src/Assert/AnyURITrait.php b/src/Assert/AnyURITrait.php new file mode 100644 index 0000000..c358c89 --- /dev/null +++ b/src/Assert/AnyURITrait.php @@ -0,0 +1,35 @@ + ['regexp' => self::$entities_regex]]) === false) { + throw new InvalidArgumentException(sprintf( + $message ?: '\'%s\' is not a valid xs:ENTITIES', + $value, + )); + } + } +} diff --git a/src/Assert/EntityTrait.php b/src/Assert/EntityTrait.php new file mode 100644 index 0000000..3c5b5eb --- /dev/null +++ b/src/Assert/EntityTrait.php @@ -0,0 +1,35 @@ + ['regexp' => self::$idrefs_regex]]) === false) { + throw new InvalidArgumentException(sprintf( + $message ?: '\'%s\' is not a valid xs:IDREFS', + $value, + )); + } + } +} diff --git a/src/Assert/IDTrait.php b/src/Assert/IDTrait.php new file mode 100644 index 0000000..2c98c6a --- /dev/null +++ b/src/Assert/IDTrait.php @@ -0,0 +1,35 @@ + ['regexp' => self::$lang_regex]]) === false) { + throw new InvalidArgumentException(sprintf( + $message ?: '\'%s\' is not a valid xs:language', + $value, + )); + } + } +} diff --git a/src/Assert/NamesTrait.php b/src/Assert/NCNameTrait.php similarity index 62% rename from src/Assert/NamesTrait.php rename to src/Assert/NCNameTrait.php index 3254913..474edee 100644 --- a/src/Assert/NamesTrait.php +++ b/src/Assert/NCNameTrait.php @@ -12,13 +12,10 @@ /** * @package simplesamlphp/xml-common */ -trait NamesTrait +trait NCNameTrait { /** @var string */ - private static string $ncname_regex = '/^[a-zA-Z_][\w.-]*$/D'; - - /** @var string */ - private static string $qname_regex = '/^[a-zA-Z_][\w.-]*:[a-zA-Z_][\w.-]*$/D'; + private static string $ncname_regex = '/^[\p{L}a-zA-Z-][\w.-]+$/Du'; /*********************************************************************************** * NOTE: Custom assertions may be added below this line. * @@ -42,22 +39,4 @@ protected static function validNCName(string $value, string $message = ''): void )); } } - - - /** - * @param string $value - * @param string $message - */ - protected static function validQName(string $value, string $message = ''): void - { - if ( - filter_var($value, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => self::$qname_regex]]) === false && - filter_var($value, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => self::$ncname_regex]]) === false - ) { - throw new InvalidArgumentException(sprintf( - $message ?: '\'%s\' is not a valid qualified name (QName)', - $value, - )); - } - } } diff --git a/src/Assert/NMTokenTrait.php b/src/Assert/NMTokenTrait.php new file mode 100644 index 0000000..a0c2e9d --- /dev/null +++ b/src/Assert/NMTokenTrait.php @@ -0,0 +1,42 @@ + ['regexp' => self::$nmtoken_regex]]) === false) { + throw new InvalidArgumentException(sprintf( + $message ?: '\'%s\' is not a valid xs:NMTOKEN', + $value, + )); + } + } +} diff --git a/src/Assert/TokensTrait.php b/src/Assert/NMTokensTrait.php similarity index 71% rename from src/Assert/TokensTrait.php rename to src/Assert/NMTokensTrait.php index 9ea6b1e..b1cc459 100644 --- a/src/Assert/TokensTrait.php +++ b/src/Assert/NMTokensTrait.php @@ -12,11 +12,8 @@ /** * @package simplesamlphp/xml-common */ -trait TokensTrait +trait NMTokensTrait { - /** @var string */ - private static string $nmtoken_regex = '/^[\w.:-]+$/Du'; - /** @var string */ private static string $nmtokens_regex = '/^([\w.:-]+)([\s][\w.:-]+)*$/Du'; @@ -29,21 +26,6 @@ trait TokensTrait ***********************************************************************************/ - /** - * @param string $value - * @param string $message - */ - protected static function validNMToken(string $value, string $message = ''): void - { - if (filter_var($value, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => self::$nmtoken_regex]]) === false) { - throw new InvalidArgumentException(sprintf( - $message ?: '\'%s\' is not a valid xs:NMTOKEN', - $value, - )); - } - } - - /** * @param string $value * @param string $message diff --git a/src/Assert/NameTrait.php b/src/Assert/NameTrait.php new file mode 100644 index 0000000..1a7d997 --- /dev/null +++ b/src/Assert/NameTrait.php @@ -0,0 +1,42 @@ + ['regexp' => self::$name_regex]]) === false) { + throw new InvalidArgumentException(sprintf( + $message ?: '\'%s\' is not a valid xs:Name', + $value, + )); + } + } +} diff --git a/src/Assert/QNameTrait.php b/src/Assert/QNameTrait.php new file mode 100644 index 0000000..58a47df --- /dev/null +++ b/src/Assert/QNameTrait.php @@ -0,0 +1,44 @@ + ['regexp' => self::$qname_regex]]) === false + ) { + Assert::validNCName( + $value, + $message ?: '\'%s\' is not a valid qualified name (QName)', + InvalidArgumentException::class, + ); + } + } +} diff --git a/src/Type/AbstractValueType.php b/src/Type/AbstractValueType.php new file mode 100644 index 0000000..3ced6c3 --- /dev/null +++ b/src/Type/AbstractValueType.php @@ -0,0 +1,100 @@ +validateValue($value); + } + + + /** + * Get the value. + * + * @return string + */ + public function getValue(): string + { + return $this->sanitizeValue($this->getRawValue()); + } + + + /** + * Get the raw unsanitized value. + * + * @return string + */ + public function getRawValue(): string + { + return $this->value; + } + + + /** + * Sanitize the value. + * + * @param string $value The value + * @throws \Exception on failure + * @return string + */ + protected function sanitizeValue(string $value): string + { + /** + * Perform no sanitation by default. + * Override this method on the implementing class to perform content sanitation. + */ + return $value; + } + + + /** + * Validate the value. + * + * @param string $value The value + * @throws \Exception on failure + * @return void + */ + protected function validateValue(/** @scrutinizer ignore-unused */ string $value): void + { + /** + * Perform no validation by default. + * Override this method on the implementing class to perform validation. + */ + } + + + /** + * @param string $value + * @return \SimpleSAML\XML\Type\ValueTypeInterface + */ + public static function fromString(string $value): ValueTypeInterface + { + return new static($value); + } + + + /** + * Output the value as a string + * + * @return string + */ + public function __toString(): string + { + return $this->getValue(); + } +} diff --git a/src/Type/AnyURIValue.php b/src/Type/AnyURIValue.php new file mode 100644 index 0000000..8d31657 --- /dev/null +++ b/src/Type/AnyURIValue.php @@ -0,0 +1,26 @@ +sanitizeValue($value), SchemaViolationException::class); + } +} diff --git a/src/Type/DateTimeValue.php b/src/Type/DateTimeValue.php new file mode 100644 index 0000000..783d442 --- /dev/null +++ b/src/Type/DateTimeValue.php @@ -0,0 +1,26 @@ +sanitizeValue($value), SchemaViolationException::class); + } +} diff --git a/src/Type/EntityValue.php b/src/Type/EntityValue.php new file mode 100644 index 0000000..6970a3e --- /dev/null +++ b/src/Type/EntityValue.php @@ -0,0 +1,12 @@ +sanitizeValue($value), + '/([0-9A-F]{2})*/i', + SchemaViolationException::class, + ); + } +} diff --git a/src/Type/IDRefValue.php b/src/Type/IDRefValue.php new file mode 100644 index 0000000..bc4ebe8 --- /dev/null +++ b/src/Type/IDRefValue.php @@ -0,0 +1,12 @@ +sanitizeValue($value), SchemaViolationException::class); + } +} diff --git a/src/Type/IDValue.php b/src/Type/IDValue.php new file mode 100644 index 0000000..1863014 --- /dev/null +++ b/src/Type/IDValue.php @@ -0,0 +1,12 @@ +sanitizeValue($value), SchemaViolationException::class); + } +} diff --git a/src/Type/NCNameValue.php b/src/Type/NCNameValue.php new file mode 100644 index 0000000..8571249 --- /dev/null +++ b/src/Type/NCNameValue.php @@ -0,0 +1,27 @@ +sanitizeValue($value), SchemaViolationException::class); + } +} diff --git a/src/Type/NMTokenValue.php b/src/Type/NMTokenValue.php new file mode 100644 index 0000000..704f66d --- /dev/null +++ b/src/Type/NMTokenValue.php @@ -0,0 +1,27 @@ +sanitizeValue($value), SchemaViolationException::class); + } +} diff --git a/src/Type/NMTokensValue.php b/src/Type/NMTokensValue.php new file mode 100644 index 0000000..71c8394 --- /dev/null +++ b/src/Type/NMTokensValue.php @@ -0,0 +1,27 @@ +sanitizeValue($value), SchemaViolationException::class); + } +} diff --git a/src/Type/NameValue.php b/src/Type/NameValue.php new file mode 100644 index 0000000..6e8a8ae --- /dev/null +++ b/src/Type/NameValue.php @@ -0,0 +1,27 @@ +sanitizeValue($value), SchemaViolationException::class); + } +} diff --git a/src/Type/NormalizedStringValue.php b/src/Type/NormalizedStringValue.php new file mode 100644 index 0000000..1aa1ee8 --- /dev/null +++ b/src/Type/NormalizedStringValue.php @@ -0,0 +1,24 @@ +sanitizeValue($value), SchemaViolationException::class); + } +} diff --git a/src/Type/StringValue.php b/src/Type/StringValue.php new file mode 100644 index 0000000..b4bf799 --- /dev/null +++ b/src/Type/StringValue.php @@ -0,0 +1,12 @@ +assertTrue($shouldPass); + } catch (AssertionFailedException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideEntities(): array + { + return [ + [true, 'Snoopy'], + [true, 'CMS'], + [true, 'fööbár'], + [true, '-1950-10-04'], + [false, '0836217462 0836217463'], + [true, 'foo bar'], + // Quotes are forbidden + [false, 'foo "bar" baz'], + // Commas are forbidden + [false, 'foo,bar'], + // Trailing newlines are forbidden + [false, "foobar\n"], + ]; + } +} diff --git a/tests/Assert/EntityTest.php b/tests/Assert/EntityTest.php new file mode 100644 index 0000000..b7488f8 --- /dev/null +++ b/tests/Assert/EntityTest.php @@ -0,0 +1,56 @@ +assertTrue($shouldPass); + } catch (AssertionFailedException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideEntity(): array + { + return [ + [true, 'Snoopy'], + [true, 'CMS'], + [true, 'fööbár'], + [true, '-1950-10-04'], + [false, '0836217462'], + // Spaces are forbidden + [false, 'foo bar'], + // Commas are forbidden + [false, 'foo,bar'], + // Trailing newlines are forbidden + [false, "foobar\n"], + ]; + } +} diff --git a/tests/Assert/HexBinTest.php b/tests/Assert/HexBinaryTest.php similarity index 97% rename from tests/Assert/HexBinTest.php rename to tests/Assert/HexBinaryTest.php index 042e7ce..76deff6 100644 --- a/tests/Assert/HexBinTest.php +++ b/tests/Assert/HexBinaryTest.php @@ -7,8 +7,8 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\Assert; use SimpleSAML\Assert\AssertionFailedException; +use SimpleSAML\XML\Assert\Assert; /** * Class \SimpleSAML\Test\Assert\HexBinaryTest diff --git a/tests/Assert/IDRefTest.php b/tests/Assert/IDRefTest.php new file mode 100644 index 0000000..c5c25cf --- /dev/null +++ b/tests/Assert/IDRefTest.php @@ -0,0 +1,56 @@ +assertTrue($shouldPass); + } catch (AssertionFailedException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideIDRef(): array + { + return [ + [true, 'Snoopy'], + [true, 'CMS'], + [true, 'fööbár'], + [true, '-1950-10-04'], + [false, '0836217462'], + // Spaces are forbidden + [false, 'foo bar'], + // Commas are forbidden + [false, 'foo,bar'], + // Trailing newlines are forbidden + [false, "foobar\n"], + ]; + } +} diff --git a/tests/Assert/IDRefsTest.php b/tests/Assert/IDRefsTest.php new file mode 100644 index 0000000..d12cc73 --- /dev/null +++ b/tests/Assert/IDRefsTest.php @@ -0,0 +1,57 @@ +assertTrue($shouldPass); + } catch (AssertionFailedException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideIDRefs(): array + { + return [ + [true, 'Snoopy'], + [true, 'CMS'], + [true, 'fööbár'], + [true, '-1950-10-04'], + [false, '0836217462 0836217463'], + [true, 'foo bar'], + // Quotes are forbidden + [false, 'foo "bar" baz'], + // Commas are forbidden + [false, 'foo,bar'], + // Trailing newlines are forbidden + [false, "foobar\n"], + ]; + } +} diff --git a/tests/Assert/IDTest.php b/tests/Assert/IDTest.php new file mode 100644 index 0000000..d333c2e --- /dev/null +++ b/tests/Assert/IDTest.php @@ -0,0 +1,56 @@ +assertTrue($shouldPass); + } catch (AssertionFailedException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideID(): array + { + return [ + [true, 'Snoopy'], + [true, 'CMS'], + [true, 'fööbár'], + [true, '-1950-10-04'], + [false, '0836217462'], + // Spaces are forbidden + [false, 'foo bar'], + // Commas are forbidden + [false, 'foo,bar'], + // Trailing newlines are forbidden + [false, "foobar\n"], + ]; + } +} diff --git a/tests/Assert/LangTest.php b/tests/Assert/LangTest.php new file mode 100644 index 0000000..25468a6 --- /dev/null +++ b/tests/Assert/LangTest.php @@ -0,0 +1,51 @@ +assertTrue($shouldPass); + } catch (AssertionFailedException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideLang(): array + { + return [ + 'one part' => [true, 'lang'], + 'two parts' => [true, 'en-US'], + 'too many parts' => [false, 'not-a-lang'], + 'too long' => [false, 'toolonglanguage'], + 'x-case' => [true, 'x-klingon'], + 'i-case' => [true, 'i-sami-no'], + ]; + } +} diff --git a/tests/Assert/NCNameTest.php b/tests/Assert/NCNameTest.php index f3df64e..3d81db4 100644 --- a/tests/Assert/NCNameTest.php +++ b/tests/Assert/NCNameTest.php @@ -41,9 +41,12 @@ public static function provideNCName(): array { return [ [true, 'Test'], - [true, '_Test'], + [true, 'Te.st'], + [false, '_Test'], + [true, '-1950-10-04-10-00'], + [true, 'fööbár'], // Prefixed v4 UUID - [true, '_5425e58e-e799-4884-92cc-ca64ecede32f'], + [false, '_5425e58e-e799-4884-92cc-ca64ecede32f'], // An empty value is not valid, unless xsi:nil is used [false, ''], [false, 'Te*st'], diff --git a/tests/Assert/NMTokensTest.php b/tests/Assert/NMTokensTest.php index f943be7..e74fea9 100644 --- a/tests/Assert/NMTokensTest.php +++ b/tests/Assert/NMTokensTest.php @@ -50,7 +50,7 @@ public static function provideNMTokens(): array [false, 'foo "bar" baz'], // Commas are forbidden [false, 'foo,bar'], - // Trailing newlines are forbidden + // Trailing whitespace is forbidden [false, "foobar\n"], ]; } diff --git a/tests/Assert/NameTest.php b/tests/Assert/NameTest.php new file mode 100644 index 0000000..6f3adbc --- /dev/null +++ b/tests/Assert/NameTest.php @@ -0,0 +1,57 @@ +assertTrue($shouldPass); + } catch (AssertionFailedException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideName(): array + { + return [ + [true, 'Snoopy'], + [true, ':CMS'], + [true, 'fööbár'], + [true, '-1950-10-04'], + // Must start with a letter, a dash or a colon + [false, '0836217462'], + // Spaces are forbidden + [false, 'foo bar'], + // Commas are forbidden + [false, 'foo,bar'], + // Trailing newlines are forbidden + [false, "foobar\n"], + ]; + } +} diff --git a/tests/Assert/QNameTest.php b/tests/Assert/QNameTest.php index bf69747..344dc79 100644 --- a/tests/Assert/QNameTest.php +++ b/tests/Assert/QNameTest.php @@ -41,8 +41,8 @@ public static function provideQName(): array { return [ [true, 'some:Test'], - [true, 'some:_Test'], - [true, '_some:_Test'], + [true, 'some:-Test'], + [true, '-some:-Test'], [true, 'Test'], // Cannot start with a colon [false, ':test'], diff --git a/tests/Type/DateTimeValueTest.php b/tests/Type/DateTimeValueTest.php new file mode 100644 index 0000000..cf49024 --- /dev/null +++ b/tests/Type/DateTimeValueTest.php @@ -0,0 +1,55 @@ +assertTrue($shouldPass); + } catch (SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideDateTime(): array + { + return [ + 'datetime' => [true, '2001-10-26T21:32:52'], + 'datetime with numeric difference' => [true, '2001-10-26T21:32:52+02:00'], + 'datetime with Zulu' => [true, '2001-10-26T19:32:52Z'], + 'datetime with 00:00 difference' => [true, '2001-10-26T19:32:52+00:00'], + 'datetime with negative value' => [true, '-2001-10-26T21:32:52'], + 'datetime with subseconds' => [true, '2001-10-26T21:32:52.12679'], + 'date' => [false, '2001-10-26'], + 'datetime without seconds' => [false, '2001-10-26T21:32'], + 'datetime with invalid hour' => [false, '2001-10-26T25:32:52+02:00'], + 'invalid date format' => [false, '01-10-26T21:32'], + ]; + } +} diff --git a/tests/Type/DurationValueTest.php b/tests/Type/DurationValueTest.php new file mode 100644 index 0000000..0548847 --- /dev/null +++ b/tests/Type/DurationValueTest.php @@ -0,0 +1,66 @@ +assertTrue($shouldPass); + } catch (SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideDuration(): array + { + return [ + [true, 'P2Y6M5DT12H35M30S'], + [true, 'P1DT2H'], + [true, 'P1W'], + [true, 'P20M'], + [true, 'PT20M'], + [true, 'P0Y20M0D'], + [true, 'P0Y'], + [true, '-P60D'], + [true, 'PT1M30.5S'], + [true, 'P15.5Y'], + [true, 'P15,5Y'], + [false, 'P-20M'], + [false, 'P20MT'], + [false, 'P1YM5D'], + [false, 'P1D2H'], + [false, '1Y2M'], + [false, 'P2M1Y'], + [false, 'P'], + [false, 'PT15.S'], + // Trailing newlines are forbidden + [false, "P20M\n"], + ]; + } +} diff --git a/tests/Type/EntitiesValueTest.php b/tests/Type/EntitiesValueTest.php new file mode 100644 index 0000000..b7a4101 --- /dev/null +++ b/tests/Type/EntitiesValueTest.php @@ -0,0 +1,55 @@ +assertTrue($shouldPass); + } catch (SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideEntities(): array + { + return [ + 'valid' => [true, 'Snoopy foobar'], + 'diacritical' => [true, 'Snööpy fööbár'], + 'start with colon' => [false, 'foobar :CMS'], + 'start with dash' => [true, '-1950-10-04 foobar'], + 'invalid first char' => [false, '0836217462 1378943'], + 'space' => [true, 'foo bar'], + 'colon' => [false, 'foo:bar'], + 'comma' => [false, 'foo,bar'], + 'whitespace collapse' => [true, "foobar\n"], + 'normalization' => [true, ' foobar '], + ]; + } +} diff --git a/tests/Type/EntityValueTest.php b/tests/Type/EntityValueTest.php new file mode 100644 index 0000000..50f78a7 --- /dev/null +++ b/tests/Type/EntityValueTest.php @@ -0,0 +1,55 @@ +assertTrue($shouldPass); + } catch (SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideEntity(): array + { + return [ + 'valid' => [true, 'Snoopy'], + 'diacritical' => [true, 'fööbár'], + 'start with colon' => [false, ':CMS'], + 'start with dash' => [true, '-1950-10-04'], + 'invalid first char' => [false, '0836217462'], + 'space' => [false, 'foo bar'], + 'colon' => [false, 'foo:bar'], + 'comma' => [false, 'foo,bar'], + 'whitespace collapse' => [true, "foobar\n"], + 'normalization' => [true, ' foobar '], + ]; + } +} diff --git a/tests/Type/IDRefValueTest.php b/tests/Type/IDRefValueTest.php new file mode 100644 index 0000000..2865b7d --- /dev/null +++ b/tests/Type/IDRefValueTest.php @@ -0,0 +1,55 @@ +assertTrue($shouldPass); + } catch (SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideIDRef(): array + { + return [ + 'valid' => [true, 'Snoopy'], + 'diacritical' => [true, 'fööbár'], + 'start with colon' => [false, ':CMS'], + 'start with dash' => [true, '-1950-10-04'], + 'invalid first char' => [false, '0836217462'], + 'space' => [false, 'foo bar'], + 'colon' => [false, 'foo:bar'], + 'comma' => [false, 'foo,bar'], + 'whitespace collapse' => [true, "foobar\n"], + 'normalization' => [true, ' foobar '], + ]; + } +} diff --git a/tests/Type/IDRefsValueTest.php b/tests/Type/IDRefsValueTest.php new file mode 100644 index 0000000..8c8d8d4 --- /dev/null +++ b/tests/Type/IDRefsValueTest.php @@ -0,0 +1,55 @@ +assertTrue($shouldPass); + } catch (SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideIDRefs(): array + { + return [ + 'valid' => [true, 'Snoopy foobar'], + 'diacritical' => [true, 'Snööpy fööbár'], + 'start with colon' => [false, 'foobar :CMS'], + 'start with dash' => [true, '-1950-10-04 foobar'], + 'invalid first char' => [false, '0836217462 1378943'], + 'space' => [true, 'foo bar'], + 'colon' => [false, 'foo:bar'], + 'comma' => [false, 'foo,bar'], + 'whitespace collapse' => [true, "foobar\n"], + 'normalization' => [true, ' foobar '], + ]; + } +} diff --git a/tests/Type/IDValueTest.php b/tests/Type/IDValueTest.php new file mode 100644 index 0000000..b8745d1 --- /dev/null +++ b/tests/Type/IDValueTest.php @@ -0,0 +1,55 @@ +assertTrue($shouldPass); + } catch (SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideID(): array + { + return [ + 'valid' => [true, 'Snoopy'], + 'diacritical' => [true, 'fööbár'], + 'start with colon' => [false, ':CMS'], + 'start with dash' => [true, '-1950-10-04'], + 'invalid first char' => [false, '0836217462'], + 'space' => [false, 'foo bar'], + 'colon' => [false, 'foo:bar'], + 'comma' => [false, 'foo,bar'], + 'whitespace collapse' => [true, "foobar\n"], + 'normalization' => [true, ' foobar '], + ]; + } +} diff --git a/tests/Type/LangValueTest.php b/tests/Type/LangValueTest.php new file mode 100644 index 0000000..7333dd5 --- /dev/null +++ b/tests/Type/LangValueTest.php @@ -0,0 +1,52 @@ +assertTrue($shouldPass); + } catch (SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideLang(): array + { + return [ + 'one part' => [true, 'lang'], + 'two parts' => [true, 'en-US'], + 'too many parts' => [false, 'not-a-lang'], + 'too long' => [false, 'toolonglanguage'], + 'x-case' => [true, 'x-klingon'], + 'i-case' => [true, 'i-sami-no'], + 'normalization' => [true, ' en-US '], + ]; + } +} diff --git a/tests/Type/NCNameValueTest.php b/tests/Type/NCNameValueTest.php new file mode 100644 index 0000000..4097abc --- /dev/null +++ b/tests/Type/NCNameValueTest.php @@ -0,0 +1,55 @@ +assertTrue($shouldPass); + } catch (SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideNCName(): array + { + return [ + 'valid' => [true, 'Snoopy'], + 'diacritical' => [true, 'fööbár'], + 'start with colon' => [false, ':CMS'], + 'start with dash' => [true, '-1950-10-04'], + 'invalid first char' => [false, '0836217462'], + 'space' => [false, 'foo bar'], + 'colon' => [false, 'foo:bar'], + 'comma' => [false, 'foo,bar'], + 'whitespace collapse' => [true, "foobar\n"], + 'normalization' => [true, ' foobar '], + ]; + } +} diff --git a/tests/Type/NMTokenValueTest.php b/tests/Type/NMTokenValueTest.php new file mode 100644 index 0000000..bff0fcd --- /dev/null +++ b/tests/Type/NMTokenValueTest.php @@ -0,0 +1,54 @@ +assertTrue($shouldPass); + } catch (SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideNMToken(): array + { + return [ + 'valid' => [true, 'Snoopy'], + 'diacritical' => [true, 'fööbár'], + 'start with colon' => [true, ':CMS'], + 'start with dash' => [true, '-1950-10-04'], + 'numeric first char' => [true, '0836217462'], + 'space' => [false, 'foo bar'], + 'comma' => [false, 'foo,bar'], + 'whitespace collapse' => [true, "foobar\n"], + 'normalization' => [true, ' foobar '], + ]; + } +} diff --git a/tests/Type/NMTokensValueTest.php b/tests/Type/NMTokensValueTest.php new file mode 100644 index 0000000..be055f0 --- /dev/null +++ b/tests/Type/NMTokensValueTest.php @@ -0,0 +1,53 @@ +assertTrue($shouldPass); + } catch (SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideNMTokens(): array + { + return [ + 'valid' => [true, 'Snoopy foobar'], + 'diacritical' => [true, 'Snoopy fööbár'], + 'start with colon' => [true, ':CMS :ABC'], + 'start with dash' => [true, '-1950-10-04 -1984-11-07'], + 'numeric first char' => [true, '0836217462'], + 'comma' => [false, 'foo,bar'], + 'whitespace collapse' => [true, "foobar\n"], + 'normalization' => [true, ' foobar nmtoken '], + ]; + } +} diff --git a/tests/Type/NameValueTest.php b/tests/Type/NameValueTest.php new file mode 100644 index 0000000..ce3fdb2 --- /dev/null +++ b/tests/Type/NameValueTest.php @@ -0,0 +1,54 @@ +assertTrue($shouldPass); + } catch (SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideName(): array + { + return [ + 'valid' => [true, 'Snoopy'], + 'diacritical' => [true, 'fööbár'], + 'start with colon' => [true, ':CMS'], + 'start with dash' => [true, '-1950-10-04'], + 'invalid first char' => [false, '0836217462'], + 'space' => [false, 'foo bar'], + 'comma' => [false, 'foo,bar'], + 'whitespace collapse' => [true, "foobar\n"], + 'normalization' => [true, ' foobar '], + ]; + } +} diff --git a/tests/Type/NormalizedStringValueTest.php b/tests/Type/NormalizedStringValueTest.php new file mode 100644 index 0000000..b0e6781 --- /dev/null +++ b/tests/Type/NormalizedStringValueTest.php @@ -0,0 +1,43 @@ +assertEquals($normalizedString, $value->getValue()); + $this->assertEquals($str, $value->getRawValue()); + } + + + /** + * @return array + */ + public static function provideString(): array + { + return [ + 'preserve spaces' => [' Snoopy ', ' Snoopy '], + 'replace whitespace' => [" Snoopy\t\n\rrulez ", ' Snoopy rulez '], + ]; + } +} diff --git a/tests/Type/QNameValueTest.php b/tests/Type/QNameValueTest.php new file mode 100644 index 0000000..527b9ad --- /dev/null +++ b/tests/Type/QNameValueTest.php @@ -0,0 +1,55 @@ +assertTrue($shouldPass); + } catch (SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideQName(): array + { + return [ + 'valid' => [true, 'some:Test'], + 'start 2nd part with dash' => [true, 'some:-Test'], + 'start both parts with dash' => [true, '-some:-Test'], + 'no colon' => [true, 'Test'], + 'start with colon' => [false, ':test'], + 'multiple colons' => [false, 'test:test:test'], + 'start with digit' => [false, '1Test'], + 'wildcard' => [false, 'Te*st'], + 'prefixed newline' => [false, "\nsome:Test"], + 'trailing newline' => [false, "some:Test\n"], + ]; + } +} diff --git a/tests/Type/TokenValueTest.php b/tests/Type/TokenValueTest.php new file mode 100644 index 0000000..bf01ca5 --- /dev/null +++ b/tests/Type/TokenValueTest.php @@ -0,0 +1,44 @@ +assertEquals($normalizedString, $value->getValue()); + $this->assertEquals($str, $value->getRawValue()); + } + + + /** + * @return array + */ + public static function provideString(): array + { + return [ + 'trim' => [' Snoopy ', 'Snoopy'], + 'replace whitespace' => ["Snoopy\trulez", 'Snoopy rulez'], + 'collapse' => ["Snoopy\t\n\rrulez", 'Snoopy rulez'], + ]; + } +} diff --git a/tests/Type/URIValueTest.php b/tests/Type/URIValueTest.php new file mode 100644 index 0000000..ae7549b --- /dev/null +++ b/tests/Type/URIValueTest.php @@ -0,0 +1,54 @@ +assertTrue($shouldPass); + } catch (SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideURI(): array + { + return [ + 'urn' => [true, 'urn:x-simplesamlphp:phpunit'], + 'same-doc' => [true, '#_53d830ab1be17291a546c95c7f1cdf8d3d23c959e6'], + 'url' => [true, 'https://www.simplesamlphp.org'], + 'diacritical' => [true, 'https://aä.com'], + 'spn' => [true, 'spn:a4cf592f-a64c-46ff-a788-b260f474525b'], + 'typos' => [true, 'https//www.uni.l/en/'], + 'spaces' => [true, 'this is silly'], + 'empty' => [true, ''], + 'azure-common' => [true, 'https://sts.windows.net/{tenantid}/'], + ]; + } +}