Skip to content

Commit b418b3e

Browse files
committed
Improve unit-test for indexed endpoints
1 parent 532795e commit b418b3e

8 files changed

Lines changed: 334 additions & 101 deletions

src/SAML2/XML/idpdisc/DiscoveryResponse.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace SimpleSAML\SAML2\XML\idpdisc;
66

7+
use SimpleSAML\Assert\Assert;
78
use SimpleSAML\SAML2\Constants as C;
89
use SimpleSAML\SAML2\XML\md\AbstractIndexedEndpointType;
910

@@ -21,4 +22,36 @@ final class DiscoveryResponse extends AbstractIndexedEndpointType
2122

2223
/** @var string */
2324
public const NS_PREFIX = 'idpdisc';
25+
26+
27+
/**
28+
* DiscoveryResponse constructor.
29+
*
30+
* This is an endpoint with one restriction: it cannot contain a ResponseLocation.
31+
*
32+
* @param int $index
33+
* @param string $binding
34+
* @param string $location
35+
* @param bool|null $isDefault
36+
* @param string|null $unused
37+
* @param list<\SimpleSAML\XML\Attribute> $attributes
38+
* @param array $children
39+
*
40+
* @throws \SimpleSAML\Assert\AssertionFailedException
41+
*/
42+
public function __construct(
43+
int $index,
44+
string $binding,
45+
string $location,
46+
?bool $isDefault = null,
47+
?string $unused = null,
48+
array $attributes = [],
49+
array $children = [],
50+
) {
51+
Assert::null(
52+
$unused,
53+
'The \'ResponseLocation\' attribute must be omitted for idpdisc:DiscoveryResponse.',
54+
);
55+
parent::__construct($index, $binding, $location, $isDefault, null, $attributes, $children);
56+
}
2457
}

src/SAML2/XML/md/ArtifactResolutionService.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ final class ArtifactResolutionService extends AbstractIndexedEndpointType
2424
* @param bool|null $isDefault
2525
* @param string|null $unused
2626
* @param list<\SimpleSAML\XML\Attribute> $attributes
27-
* @param array children
27+
* @param array $children
2828
*
2929
* @throws \SimpleSAML\Assert\AssertionFailedException
3030
*/

tests/SAML2/XML/idpdisc/DiscoveryResponseTest.php

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
use SimpleSAML\Assert\AssertionFailedException;
1010
use SimpleSAML\SAML2\XML\idpdisc\DiscoveryResponse;
1111
use SimpleSAML\Test\SAML2\Constants as C;
12+
use SimpleSAML\XML\Attribute as XMLAttribute;
13+
use SimpleSAML\XML\Chunk;
1214
use SimpleSAML\XML\DOMDocumentFactory;
1315
use SimpleSAML\XML\Exception\InvalidDOMElementException;
1416
use SimpleSAML\XML\Exception\MissingAttributeException;
17+
use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait;
1518
use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait;
1619
use SimpleSAML\XML\TestUtils\SerializableElementTestTrait;
1720

@@ -28,9 +31,16 @@
2831
*/
2932
final class DiscoveryResponseTest extends TestCase
3033
{
34+
use ArrayizableElementTestTrait;
3135
use SchemaValidationTestTrait;
3236
use SerializableElementTestTrait;
3337

38+
/** @var \SimpleSAML\XML\Chunk */
39+
protected Chunk $ext;
40+
41+
/** @var \SimpleSAML\XML\Attribute */
42+
protected XMLAttribute $attr;
43+
3444

3545
/**
3646
*/
@@ -40,6 +50,22 @@ protected function setUp(): void
4050

4151
$this->testedClass = DiscoveryResponse::class;
4252

53+
$this->attr = new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr1', 'testval1');
54+
55+
$this->ext = new Chunk(DOMDocumentFactory::fromString(
56+
'<some:Ext xmlns:some="urn:mace:some:metadata:1.0">SomeExtension</some:Ext>'
57+
)->documentElement);
58+
59+
$this->arrayRepresentation = [
60+
'index' => 1,
61+
'Binding' => C::BINDING_HTTP_POST,
62+
'Location' => 'https://whatever/',
63+
'isDefault' => true,
64+
//'ResponseLocation' => null,
65+
'Extensions' => [$this->ext],
66+
'attributes' => [$this->attr->toArray()],
67+
];
68+
4369
$this->xmlRepresentation = DOMDocumentFactory::fromFile(
4470
dirname(__FILE__, 4) . '/resources/xml/idpdisc_DiscoveryResponse.xml',
4571
);
@@ -54,7 +80,15 @@ protected function setUp(): void
5480
*/
5581
public function testMarshalling(): void
5682
{
57-
$discoResponse = new DiscoveryResponse(43, C::BINDING_HTTP_POST, C::LOCATION_A, false);
83+
$discoResponse = new DiscoveryResponse(
84+
43,
85+
C::BINDING_HTTP_POST,
86+
C::LOCATION_A,
87+
false,
88+
null,
89+
[$this->attr],
90+
[$this->ext],
91+
);
5892

5993
$this->assertEquals(
6094
$this->xmlRepresentation->saveXML($this->xmlRepresentation->documentElement),
@@ -64,17 +98,15 @@ public function testMarshalling(): void
6498

6599

66100
/**
67-
* Test that creating a DiscoveryResponse from scratch without specifying isDefault works.
101+
* Test that creating a DiscoveryResponseService from scratch with a ResponseLocation fails.
68102
*/
69-
public function testMarshallingWithoutIsDefault(): void
103+
public function testMarshallingWithResponseLocation(): void
70104
{
71-
$discoResponse = new DiscoveryResponse(43, C::BINDING_HTTP_POST, C::LOCATION_A);
72-
$this->xmlRepresentation->documentElement->removeAttribute('isDefault');
73-
$this->assertEquals(
74-
$this->xmlRepresentation->saveXML($this->xmlRepresentation->documentElement),
75-
strval($discoResponse),
105+
$this->expectException(AssertionFailedException::class);
106+
$this->expectExceptionMessage(
107+
'The \'ResponseLocation\' attribute must be omitted for idpdisc:DiscoveryResponse.',
76108
);
77-
$this->assertNull($discoResponse->getIsDefault());
109+
new DiscoveryResponse(42, C::BINDING_HTTP_ARTIFACT, C::LOCATION_A, false, 'https://response.location/');
78110
}
79111

80112

@@ -93,4 +125,23 @@ public function testUnmarshalling(): void
93125
strval($discoResponse),
94126
);
95127
}
128+
129+
130+
/**
131+
* Test that creating a DiscoveryResponse from XML fails when ResponseLocation is present.
132+
*/
133+
public function testUnmarshallingWithResponseLocation(): void
134+
{
135+
$this->expectException(AssertionFailedException::class);
136+
$this->expectExceptionMessage(
137+
'The \'ResponseLocation\' attribute must be omitted for idpdisc:DiscoveryResponse.',
138+
);
139+
$this->xmlRepresentation->documentElement->setAttribute('ResponseLocation', 'https://response.location/');
140+
141+
DiscoveryResponse::fromXML($this->xmlRepresentation->documentElement);
142+
DiscoveryResponse::fromArray(array_merge(
143+
$this->arrayRepresentation,
144+
['ResponseLocation', 'https://response.location'],
145+
));
146+
}
96147
}

tests/SAML2/XML/md/ArtifactResolutionServiceTest.php

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,43 +12,61 @@
1212
use SimpleSAML\XML\Attribute as XMLAttribute;
1313
use SimpleSAML\XML\Chunk;
1414
use SimpleSAML\XML\DOMDocumentFactory;
15+
use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait;
1516
use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait;
1617
use SimpleSAML\XML\TestUtils\SerializableElementTestTrait;
1718

19+
use function array_merge;
1820
use function dirname;
1921
use function strval;
2022

2123
/**
2224
* Tests for md:ArtifactResolutionService.
2325
*
2426
* @covers \SimpleSAML\SAML2\XML\md\AbstractMdElement
27+
* @covers \SimpleSAML\SAML2\XML\md\AbstractIndexedEndpointType
2528
* @covers \SimpleSAML\SAML2\XML\md\ArtifactResolutionService
2629
* @package simplesamlphp/saml2
2730
*/
2831
final class ArtifactResolutionServiceTest extends TestCase
2932
{
33+
use ArrayizableElementTestTrait;
3034
use SchemaValidationTestTrait;
3135
use SerializableElementTestTrait;
3236

33-
/** @var \DOMDocument */
34-
protected DOMDocument $ext;
37+
/** @var \SimpleSAML\XML\Chunk */
38+
protected Chunk $ext;
39+
40+
/** @var \SimpleSAML\XML\Attribute */
41+
protected XMLAttribute $attr;
3542

3643

3744
/**
3845
*/
3946
protected function setUp(): void
4047
{
48+
$this->ext = new Chunk(DOMDocumentFactory::fromString(
49+
'<some:Ext xmlns:some="urn:mace:some:metadata:1.0">SomeExtension</some:Ext>'
50+
)->documentElement);
51+
52+
$this->attr = new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr1', 'testval1');
53+
4154
$this->schema = dirname(__FILE__, 5) . '/resources/schemas/saml-schema-metadata-2.0.xsd';
4255

4356
$this->testedClass = ArtifactResolutionService::class;
4457

58+
$this->arrayRepresentation = [
59+
'index' => 1,
60+
'Binding' => C::BINDING_HTTP_ARTIFACT,
61+
'Location' => 'https://whatever/',
62+
'isDefault' => true,
63+
'Extensions' => [$this->ext],
64+
'attributes' => [$this->attr->toArray()],
65+
];
66+
4567
$this->xmlRepresentation = DOMDocumentFactory::fromFile(
4668
dirname(__FILE__, 4) . '/resources/xml/md_ArtifactResolutionService.xml',
4769
);
48-
49-
$this->ext = DOMDocumentFactory::fromString(
50-
'<some:Ext xmlns:some="urn:mace:some:metadata:1.0">SomeExtension</some:Ext>'
51-
);
5270
}
5371

5472

@@ -60,16 +78,14 @@ protected function setUp(): void
6078
*/
6179
public function testMarshalling(): void
6280
{
63-
$attr = new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr1', 'testval1');
64-
6581
$ars = new ArtifactResolutionService(
6682
42,
6783
C::BINDING_HTTP_ARTIFACT,
6884
'https://simplesamlphp.org/some/endpoint',
6985
false,
7086
null,
71-
[$attr],
72-
[new Chunk($this->ext->documentElement)],
87+
[$this->attr],
88+
[$this->ext],
7389
);
7490

7591
$this->assertEquals(
@@ -119,6 +135,11 @@ public function testUnmarshallingWithResponseLocation(): void
119135
'The \'ResponseLocation\' attribute must be omitted for md:ArtifactResolutionService.',
120136
);
121137
$this->xmlRepresentation->documentElement->setAttribute('ResponseLocation', 'https://response.location/');
138+
122139
ArtifactResolutionService::fromXML($this->xmlRepresentation->documentElement);
140+
ArtifactResolutionService::fromArray(array_merge(
141+
$this->arrayRepresentation,
142+
['ResponseLocation', 'https://response.location'],
143+
));
123144
}
124145
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\Test\SAML2\XML\md;
6+
7+
use DOMDocument;
8+
use PHPUnit\Framework\TestCase;
9+
use SimpleSAML\SAML2\XML\md\AssertionConsumerService;
10+
use SimpleSAML\Test\SAML2\Constants as C;
11+
use SimpleSAML\XML\Attribute as XMLAttribute;
12+
use SimpleSAML\XML\DOMDocumentFactory;
13+
use SimpleSAML\XML\Chunk;
14+
use SimpleSAML\XML\Exception\InvalidDOMElementException;
15+
use SimpleSAML\XML\Exception\MissingAttributeException;
16+
use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait;
17+
use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait;
18+
use SimpleSAML\XML\TestUtils\SerializableElementTestTrait;
19+
20+
use function dirname;
21+
use function strval;
22+
23+
/**
24+
* Class \SimpleSAML\SAML2\XML\md\AssertionConsumerServiceTest
25+
*
26+
* @covers \SimpleSAML\SAML2\XML\md\AssertionConsumerService
27+
* @covers \SimpleSAML\SAML2\XML\md\AbstractIndexedEndpointType
28+
* @covers \SimpleSAML\SAML2\XML\md\AbstractMdElement
29+
* @package simplesamlphp/saml2
30+
*/
31+
final class AssertionConsumerServiceTest extends TestCase
32+
{
33+
use ArrayizableElementTestTrait;
34+
use SchemaValidationTestTrait;
35+
use SerializableElementTestTrait;
36+
37+
/** @var \SimpleSAML\XML\Chunk */
38+
protected Chunk $ext;
39+
40+
/** @var \SimpleSAML\XML\Attribute */
41+
protected XMLAttribute $attr;
42+
43+
44+
/**
45+
*/
46+
protected function setUp(): void
47+
{
48+
$this->ext = new Chunk(DOMDocumentFactory::fromString(
49+
'<some:Ext xmlns:some="urn:mace:some:metadata:1.0">SomeExtension</some:Ext>',
50+
)->documentElement);
51+
52+
$this->attr = new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr1', 'testval1');
53+
54+
$this->schema = dirname(__FILE__, 5) . '/resources/schemas/saml-schema-metadata-2.0.xsd';
55+
56+
$this->testedClass = AssertionConsumerService::class;
57+
58+
$this->arrayRepresentation = [
59+
'index' => 1,
60+
'Binding' => C::BINDING_HTTP_POST,
61+
'Location' => 'https://whatever/',
62+
'isDefault' => true,
63+
'ResponseLocation' => 'https://foo.bar/',
64+
'Extensions' => [$this->ext],
65+
'attributes' => [$this->attr->toArray()],
66+
];
67+
68+
$this->xmlRepresentation = DOMDocumentFactory::fromFile(
69+
dirname(__FILE__, 4) . '/resources/xml/md_AssertionConsumerService.xml',
70+
);
71+
}
72+
73+
74+
// test marshalling
75+
76+
77+
/**
78+
* Test creating an IndexedEndpointType from scratch.
79+
*/
80+
public function testMarshalling(): void
81+
{
82+
$idxep = new AssertionConsumerService(
83+
42,
84+
C::BINDING_HTTP_POST,
85+
C::LOCATION_A,
86+
false,
87+
'https://foo.bar/',
88+
[$this->attr],
89+
[$this->ext],
90+
);
91+
92+
$this->assertEquals(
93+
$this->xmlRepresentation->saveXML($this->xmlRepresentation->documentElement),
94+
strval($idxep),
95+
);
96+
}
97+
98+
99+
// test unmarshalling
100+
101+
102+
/**
103+
* Test creating an IndexedEndpointType from XML.
104+
*/
105+
public function testUnmarshalling(): void
106+
{
107+
$idxep = AssertionConsumerService::fromXML($this->xmlRepresentation->documentElement);
108+
109+
$this->assertEquals(
110+
$this->xmlRepresentation->saveXML($this->xmlRepresentation->documentElement),
111+
strval($idxep),
112+
);
113+
}
114+
}

0 commit comments

Comments
 (0)