diff --git a/resources/schemas/ws-securitypolicy-1.2.xsd b/resources/schemas/ws-securitypolicy-1.2.xsd index 7270463b..b52f120d 100644 --- a/resources/schemas/ws-securitypolicy-1.2.xsd +++ b/resources/schemas/ws-securitypolicy-1.2.xsd @@ -101,7 +101,7 @@ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - + 4.3.2 RequiredParts Assertion diff --git a/src/Utils/XPath.php b/src/Utils/XPath.php new file mode 100644 index 00000000..cba95d16 --- /dev/null +++ b/src/Utils/XPath.php @@ -0,0 +1,41 @@ +registerNamespace('addr', C::NS_ADDR); + $xp->registerNamespace('auth', C::NS_AUTH); + $xp->registerNamespace('fed', C::NS_FED); + $xp->registerNamespace('trust', C::NS_TRUST); + $xp->registerNamespace('policy', C::NS_POLICY); + $xp->registerNamespace('sp', C::NS_SEC_POLICY); + $xp->registerNamespace('wsse', C::NS_SEC_EXT); + $xp->registerNamespace('wsu', C::NS_SEC_UTIL); + + return $xp; + } +} diff --git a/src/XML/sp/AbstractEmptyType.php b/src/XML/sp/AbstractEmptyType.php index 817f645b..d9b15daf 100644 --- a/src/XML/sp/AbstractEmptyType.php +++ b/src/XML/sp/AbstractEmptyType.php @@ -6,10 +6,6 @@ use DOMElement; use SimpleSAML\Assert\Assert; -/use SimpleSAML\XML\Exception\InvalidDOMElementException; -//use SimpleSAML\XML\Exception\SchemaViolationException; -use SimpleSAML\XML\ExtendableAttributesTrait; -use SimpleSAML\XML\XsNamespace as NS; use function sprintf; @@ -20,26 +16,16 @@ */ abstract class AbstractEmptyType extends AbstractSpElement { - use ExtendableAttributesTrait; - - /** The namespace-attribute for the xs:anyAttribute element */ - public const XS_ANY_ATTR_NAMESPACE = NS::ANY; - - /** - * AbstractQNameAssertionType constructor. - * - * @param list<\SimpleSAML\XML\Attribute> $namespacedAttributes + * AbstractEmptyType constructor. */ final public function __construct( - array $namespacedAttributes = [] ) { - $this->setAttributesNS($namespacedAttributes); } /** - * Initialize an QNameAssertionType. + * Initialize an EmptyType. * * Note: this method cannot be used when extending this class, if the constructor has a different signature. * @@ -55,12 +41,12 @@ public static function fromXML(DOMElement $xml): static Assert::eq( $xml->localName, $qualifiedName, - sprintf('Unexpected name for Empty: %s. Expected: %s.', $xml->localName, $qualifiedName), + sprintf('Unexpected name for EmptyType: %s. Expected: %s.', $xml->localName, $qualifiedName), InvalidDOMElementException::class ); - return new static(self::getAttributesNSFromXML($xml)); + return new static(); } @@ -72,12 +58,6 @@ public static function fromXML(DOMElement $xml): static */ public function toXML(DOMElement $parent = null): DOMElement { - $e = $this->instantiateParentElement($parent); - - foreach ($this->getAttributesNS() as $attr) { - $attr->toXML($e); - } - - return $e; + return $this->instantiateParentElement($parent); } } diff --git a/src/XML/sp/AbstractHeaderType.php b/src/XML/sp/AbstractHeaderType.php new file mode 100644 index 00000000..4d323b8d --- /dev/null +++ b/src/XML/sp/AbstractHeaderType.php @@ -0,0 +1,128 @@ + $namespacedAttributes + */ + final public function __construct( + protected string $namespace, + protected ?string $name = null, + array $namespacedAttributes = [] + ) { + Assert::nullOrValidURI($namespace); + Assert::validQName($name); + + $this->setAttributesNS($namespacedAttributes); + } + + + /** + * Collect the value of the Name property. + * + * @return string + */ + public function getName(): string + { + return $this->name; + } + + + /** + * Collect the value of the Namespace property. + * + * @return string + */ + public function getNamespace(): string + { + return $this->namespace; + } + + + /** + * Initialize an HeaderType. + * + * Note: this method cannot be used when extending this class, if the constructor has a different signature. + * + * @param \DOMElement $xml The XML element we should load. + * @return static + * + * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * if the qualified name of the supplied element is wrong + */ + public static function fromXML(DOMElement $xml): static + { + $qualifiedName = static::getClassName(static::class); + Assert::eq( + $xml->localName, + $qualifiedName, + sprintf('Unexpected name for HeaderType: %s. Expected: %s.', $xml->localName, $qualifiedName), + InvalidDOMElementException::class + ); + + $namespacedAttributes = self::getAttributesNSFromXML($xml); + foreach ($namespacedAttributes as $i => $attr) { + if ($attr->getNamespaceURI() === null) { + if ($attr->getAttrName() === 'Name' || $attr->getAttrName() === 'Namespace') { + unset($namespacedAttributes[$i]); + } + } + } + + return new static( + self::getAttribute($xml, 'Namespace'), + self::getOptionalAttribute($xml, 'Name', null), + $namespacedAttributes, + ); + } + + + /** + * Convert this element to XML. + * + * @param \DOMElement|null $parent The element we should append this element to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = $this->instantiateParentElement($parent); + + if ($this->getName() !== null) { + $e->setAttribute('Name', $this->getName()); + } + + $e->setAttribute('Namespace', $this->getNamespace()); + + foreach ($this->getAttributesNS() as $attr) { + $attr->toXML($e); + } + + return $e; + } +} diff --git a/src/XML/sp/AbstractReqPartsType.php b/src/XML/sp/AbstractReqPartsType.php new file mode 100644 index 00000000..a08639a7 --- /dev/null +++ b/src/XML/sp/AbstractReqPartsType.php @@ -0,0 +1,142 @@ +setElements($details); + $this->setAttributesNS($namespacedAttributes); + } + + + /** + * Collect the Header + * + * @return \SimpleSAML\WSSecurity\XML\sp\Header[] + */ + public function getHeader(): array + { + return $this->header; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + return empty($this->getElements()) + && empty($this->getHeader()) + && empty($this->getAttributesNS()); + } + + + /** + * Initialize an ReqPartsType. + * + * Note: this method cannot be used when extending this class, if the constructor has a different signature. + * + * @param \DOMElement $xml The XML element we should load. + * @return static + * + * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * if the qualified name of the supplied element is wrong + */ + public static function fromXML(DOMElement $xml): static + { + $qualifiedName = static::getClassName(static::class); + Assert::eq( + $xml->localName, + $qualifiedName, + sprintf('Unexpected name for Empty: %s. Expected: %s.', $xml->localName, $qualifiedName), + InvalidDOMElementException::class + ); + + $header = Header::getChildrenOfClass($xml); + Assert::maxcount($header, 1, TooManyElementsException::class); + + $details = []; + foreach ($xml->childNodes as $detail) { + if (!($detail instanceof DOMElement)) { + continue; + } elseif ($detail->namespaceURI === static::NS) { + continue; + } + + $details[] = new Chunk($detail); + } + + return new static( + $header, + $details, + self::getAttributesNSFromXML($xml), + ); + } + + + /** + * Convert this element to XML. + * + * @param \DOMElement|null $parent The element we should append this element to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = $this->instantiateParentElement($parent); + + foreach ($this->getHeader() as $header) { + $header->toXML($e); + } + + foreach ($this->getElements() as $elt) { + $elt->toXML($e); + } + + foreach ($this->getAttributesNS() as $attr) { + $attr->toXML($e); + } + + return $e; + } +} diff --git a/src/XML/sp/AbstractSePartsType.php b/src/XML/sp/AbstractSePartsType.php new file mode 100644 index 00000000..c1a61492 --- /dev/null +++ b/src/XML/sp/AbstractSePartsType.php @@ -0,0 +1,184 @@ +setElements($details); + $this->setAttributesNS($namespacedAttributes); + } + + + /** + * Collect the Body + * + * @return \SimpleSAML\WSSecurity\XML\sp\Body|null + */ + public function getBody(): ?Body + { + return $this->body; + } + + + /** + * Collect the Header + * + * @return \SimpleSAML\WSSecurity\XML\sp\Header[] + */ + public function getHeader(): array + { + return $this->header; + } + + + /** + * Collect the Attachments + * + * @return \SimpleSAML\WSSecurity\XML\sp\Attachments|null + */ + public function getAttachments(): ?Attachments + { + return $this->attachments; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + return empty($this->getElements()) + && empty($this->getBody()) + && empty($this->getHeader()) + && empty($this->getAttachments()) + && empty($this->getAttributesNS()); + } + + + /** + * Initialize an SePartsType. + * + * Note: this method cannot be used when extending this class, if the constructor has a different signature. + * + * @param \DOMElement $xml The XML element we should load. + * @return static + * + * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * if the qualified name of the supplied element is wrong + */ + public static function fromXML(DOMElement $xml): static + { + $qualifiedName = static::getClassName(static::class); + Assert::eq( + $xml->localName, + $qualifiedName, + sprintf('Unexpected name for Empty: %s. Expected: %s.', $xml->localName, $qualifiedName), + InvalidDOMElementException::class + ); + + $body = Body::getChildrenOfClass($xml); + + $header = Header::getChildrenOfClass($xml); + Assert::maxcount($header, 1, TooManyElementsException::class); + + $attachments = Attachments::getChildrenOfClass($xml); + + $details = []; + foreach ($xml->childNodes as $detail) { + if (!($detail instanceof DOMElement)) { + continue; + } elseif ($detail->namespaceURI === static::NS) { + continue; + } + + $details[] = new Chunk($detail); + } + + return new static( + array_pop($body), + $header, + array_pop($attachments), + $details, + self::getAttributesNSFromXML($xml), + ); + } + + + /** + * Convert this element to XML. + * + * @param \DOMElement|null $parent The element we should append this element to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = $this->instantiateParentElement($parent); + + if ($this->getBody() !== null) { + $this->getBody()->toXML($e); + } + + foreach ($this->getHeader() as $header) { + $header->toXML($e); + } + + if ($this->getAttachments() !== null) { + $this->getAttachments()->toXML($e); + } + + foreach ($this->getElements() as $elt) { + $elt->toXML($e); + } + + foreach ($this->getAttributesNS() as $attr) { + $attr->toXML($e); + } + + return $e; + } +} diff --git a/src/XML/sp/Attachments.php b/src/XML/sp/Attachments.php new file mode 100644 index 00000000..65d7b910 --- /dev/null +++ b/src/XML/sp/Attachments.php @@ -0,0 +1,14 @@ +assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($attachments), + ); + } + + + // test unmarshalling + + + /** + * Test that creating an Attachments from XML succeeds. + */ + public function testUnmarshalling(): void + { + $attachments = Attachments::fromXML(self::$xmlRepresentation->documentElement); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($attachments), + ); + } +} diff --git a/tests/WSSecurity/XML/sp/BodyTest.php b/tests/WSSecurity/XML/sp/BodyTest.php index b9403040..bf4c6f85 100644 --- a/tests/WSSecurity/XML/sp/BodyTest.php +++ b/tests/WSSecurity/XML/sp/BodyTest.php @@ -6,9 +6,9 @@ use DOMDocument; use PHPUnit\Framework\TestCase; +use SimpleSAML\Test\WSSecurity\Constants as C; use SimpleSAML\WSSecurity\XML\sp\Body; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; use function dirname; @@ -17,13 +17,13 @@ * Class \SimpleSAML\WSSecurity\XML\sp\BodyTest * * @covers \SimpleSAML\WSSecurity\XML\sp\Body + * @covers \SimpleSAML\WSSecurity\XML\sp\AbstractEmptyType * @covers \SimpleSAML\WSSecurity\XML\sp\AbstractSpElement * * @package tvdijen/ws-security */ final class BodyTest extends TestCase { - use SchemaValidationTestTrait; use SerializableElementTestTrait; @@ -31,8 +31,6 @@ final class BodyTest extends TestCase */ public static function setUpBeforeClass(): void { - self::$schemaFile = dirname(__FILE__, 5) . '/resources/schemas/ws-securitypolicy-1.2.xsd'; - self::$testedClass = Body::class; self::$xmlRepresentation = DOMDocumentFactory::fromFile( @@ -45,16 +43,15 @@ public static function setUpBeforeClass(): void /** - * Test that creating a QNameAssertionType from scratch works. + * Test that creating a Body from scratch works. */ public function testMarshalling(): void { - $attr = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', 'value1'); - $qns = new static::$testedClass([$attr]); + $body = new Body(); $this->assertEquals( - static::$xmlRepresentation->saveXML(static::$xmlRepresentation->documentElement), - strval($qns), + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($body), ); } @@ -63,15 +60,15 @@ public function testMarshalling(): void /** - * Test that creating a QNameAssertionType from XML succeeds. + * Test that creating a Body from XML succeeds. */ public function testUnmarshalling(): void { - $qna = static::$testedClass::fromXML(static::$xmlRepresentation->documentElement); + $body = Body::fromXML(self::$xmlRepresentation->documentElement); $this->assertEquals( - static::$xmlRepresentation->saveXML(static::$xmlRepresentation->documentElement), - strval($qna), + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($body), ); } } diff --git a/tests/WSSecurity/XML/sp/EncryptedPartsTest.php b/tests/WSSecurity/XML/sp/EncryptedPartsTest.php new file mode 100644 index 00000000..42981886 --- /dev/null +++ b/tests/WSSecurity/XML/sp/EncryptedPartsTest.php @@ -0,0 +1,137 @@ +some' + )->documentElement); + + $EncryptedParts = new EncryptedParts($body, [$header], $attachments, [$chunk], [$attr]); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($EncryptedParts), + ); + } + + + /** + * Adding an empty EncryptedParts element should yield an empty element. + */ + public function testMarshallingEmptyElement(): void + { + $spns = C::NS_SEC_POLICY; + $encryptedParts = new EncryptedParts(); + $this->assertEquals( + "", + strval($encryptedParts), + ); + $this->assertTrue($encryptedParts->isEmptyElement()); + } + + + /** + */ + public function testMarshallingElementOrdering(): void + { + $attr = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', 'value1'); + $body = new Body(); + $header = new Header('urn:x-simplesamlphp:namespace', 'ssp:name', [$attr]); + $attachments = new Attachments(); + $chunk = new Chunk(DOMDocumentFactory::fromString( + 'some' + )->documentElement); + + $EncryptedParts = new EncryptedParts($body, [$header], $attachments, [$chunk], [$attr]); + $EncryptedPartsElement = $EncryptedParts->toXML(); + + // Test for a Body + $xpCache = XPath::getXPath($EncryptedPartsElement); + $EncryptedPartsElements = XPath::xpQuery($EncryptedPartsElement, './sp:Body', $xpCache); + $this->assertCount(1, $EncryptedPartsElements); + + // Test ordering of EncryptedParts contents + /** @psalm-var \DOMElement[] $EncryptedPartsElements */ + $EncryptedPartsElements = XPath::xpQuery($EncryptedPartsElement, './sp:Body/following-sibling::*', $xpCache); + $this->assertCount(3, $EncryptedPartsElements); + $this->assertEquals('sp:Header', $EncryptedPartsElements[0]->tagName); + $this->assertEquals('sp:Attachments', $EncryptedPartsElements[1]->tagName); + $this->assertEquals('ssp:Chunk', $EncryptedPartsElements[2]->tagName); + } + + + // test unmarshalling + + + /** + * Test that creating a EncryptedParts from XML succeeds. + */ + public function testUnmarshalling(): void + { + $EncryptedParts = EncryptedParts::fromXML(self::$xmlRepresentation->documentElement); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($EncryptedParts), + ); + } +} diff --git a/tests/WSSecurity/XML/sp/HeaderTest.php b/tests/WSSecurity/XML/sp/HeaderTest.php new file mode 100644 index 00000000..5cfdf543 --- /dev/null +++ b/tests/WSSecurity/XML/sp/HeaderTest.php @@ -0,0 +1,76 @@ +assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($header), + ); + } + + + // test unmarshalling + + + /** + * Test that creating a Header from XML succeeds. + */ + public function testUnmarshalling(): void + { + $header = Header::fromXML(self::$xmlRepresentation->documentElement); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($header), + ); + } +} diff --git a/tests/WSSecurity/XML/sp/RequiredPartsTest.php b/tests/WSSecurity/XML/sp/RequiredPartsTest.php new file mode 100644 index 00000000..ed1defbf --- /dev/null +++ b/tests/WSSecurity/XML/sp/RequiredPartsTest.php @@ -0,0 +1,128 @@ +assertEquals( + "", + strval($requiredParts), + ); + $this->assertTrue($requiredParts->isEmptyElement()); + } + + + /** + */ + public function testMarshallingElementOrdering(): void + { + $attr = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', 'value1'); + $header = new Header('urn:x-simplesamlphp:namespace', 'ssp:name', [$attr]); + $chunk = new Chunk(DOMDocumentFactory::fromString( + 'some' + )->documentElement); + + $RequiredParts = new RequiredParts([$header], [$chunk], [$attr]); + $RequiredPartsElement = $RequiredParts->toXML(); + + // Test for a Header + $xpCache = XPath::getXPath($RequiredPartsElement); + $RequiredPartsElements = XPath::xpQuery($RequiredPartsElement, './sp:Header', $xpCache); + $this->assertCount(1, $RequiredPartsElements); + + // Test ordering of RequiredParts contents + /** @psalm-var \DOMElement[] $RequiredPartsElements */ + $RequiredPartsElements = XPath::xpQuery($RequiredPartsElement, './sp:Header/following-sibling::*', $xpCache); + $this->assertCount(1, $RequiredPartsElements); + $this->assertEquals('ssp:Chunk', $RequiredPartsElements[0]->tagName); + } + + + // test marshalling + + + /** + * Test that creating a RequiredParts from scratch works. + */ + public function testMarshalling(): void + { + $attr = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', 'value1'); + $header = new Header('urn:x-simplesamlphp:namespace', 'ssp:name', [$attr]); + $chunk = new Chunk(DOMDocumentFactory::fromString( + 'some' + )->documentElement); + + $RequiredParts = new RequiredParts([$header], [$chunk], [$attr]); + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($RequiredParts), + ); + } + + + // test unmarshalling + + + /** + * Test that creating a RequiredParts from XML succeeds. + */ + public function testUnmarshalling(): void + { + $RequiredParts = RequiredParts::fromXML(self::$xmlRepresentation->documentElement); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($RequiredParts), + ); + } +} diff --git a/tests/WSSecurity/XML/sp/SignedPartsTest.php b/tests/WSSecurity/XML/sp/SignedPartsTest.php new file mode 100644 index 00000000..acadca5f --- /dev/null +++ b/tests/WSSecurity/XML/sp/SignedPartsTest.php @@ -0,0 +1,137 @@ +assertEquals( + "", + strval($signedParts), + ); + $this->assertTrue($signedParts->isEmptyElement()); + } + + + // test marshalling + + + /** + * Test that creating a SignedParts from scratch works. + */ + public function testMarshalling(): void + { + $attr = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', 'value1'); + $body = new Body(); + $header = new Header('urn:x-simplesamlphp:namespace', 'ssp:name', [$attr]); + $attachments = new Attachments(); + $chunk = new Chunk(DOMDocumentFactory::fromString( + 'some' + )->documentElement); + + $signedParts = new SignedParts($body, [$header], $attachments, [$chunk], [$attr]); + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($signedParts), + ); + } + + + /** + */ + public function testMarshallingElementOrdering(): void + { + $attr = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', 'value1'); + $body = new Body(); + $header = new Header('urn:x-simplesamlphp:namespace', 'ssp:name', [$attr]); + $attachments = new Attachments(); + $chunk = new Chunk(DOMDocumentFactory::fromString( + 'some' + )->documentElement); + + $SignedParts = new SignedParts($body, [$header], $attachments, [$chunk], [$attr]); + $SignedPartsElement = $SignedParts->toXML(); + + // Test for a Body + $xpCache = XPath::getXPath($SignedPartsElement); + $SignedPartsElements = XPath::xpQuery($SignedPartsElement, './sp:Body', $xpCache); + $this->assertCount(1, $SignedPartsElements); + + // Test ordering of SignedParts contents + /** @psalm-var \DOMElement[] $SignedartsElements */ + $SignedPartsElements = XPath::xpQuery($SignedPartsElement, './sp:Body/following-sibling::*', $xpCache); + $this->assertCount(3, $SignedPartsElements); + $this->assertEquals('sp:Header', $SignedPartsElements[0]->tagName); + $this->assertEquals('sp:Attachments', $SignedPartsElements[1]->tagName); + $this->assertEquals('ssp:Chunk', $SignedPartsElements[2]->tagName); + } + + + + // test unmarshalling + + + /** + * Test that creating a SignedParts from XML succeeds. + */ + public function testUnmarshalling(): void + { + $signedParts = SignedParts::fromXML(self::$xmlRepresentation->documentElement); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($signedParts), + ); + } +} diff --git a/tests/resources/xml/sp_Attachments.xml b/tests/resources/xml/sp_Attachments.xml new file mode 100644 index 00000000..e0295d5a --- /dev/null +++ b/tests/resources/xml/sp_Attachments.xml @@ -0,0 +1 @@ + diff --git a/tests/resources/xml/sp_Body.xml b/tests/resources/xml/sp_Body.xml new file mode 100644 index 00000000..f4468dab --- /dev/null +++ b/tests/resources/xml/sp_Body.xml @@ -0,0 +1 @@ + diff --git a/tests/resources/xml/sp_EncryptedParts.xml b/tests/resources/xml/sp_EncryptedParts.xml new file mode 100644 index 00000000..c9ce63b1 --- /dev/null +++ b/tests/resources/xml/sp_EncryptedParts.xml @@ -0,0 +1,6 @@ + + + + + some + diff --git a/tests/resources/xml/sp_Header.xml b/tests/resources/xml/sp_Header.xml new file mode 100644 index 00000000..56ef7fc3 --- /dev/null +++ b/tests/resources/xml/sp_Header.xml @@ -0,0 +1 @@ + diff --git a/tests/resources/xml/sp_RequiredParts.xml b/tests/resources/xml/sp_RequiredParts.xml new file mode 100644 index 00000000..45ddb1e9 --- /dev/null +++ b/tests/resources/xml/sp_RequiredParts.xml @@ -0,0 +1,4 @@ + + + some + diff --git a/tests/resources/xml/sp_SignedParts.xml b/tests/resources/xml/sp_SignedParts.xml new file mode 100644 index 00000000..87c91e57 --- /dev/null +++ b/tests/resources/xml/sp_SignedParts.xml @@ -0,0 +1,6 @@ + + + + + some +