From e98d64987668b256d24735386ef0913dcc5ffa9c Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Fri, 18 Sep 2020 21:25:29 +0200 Subject: [PATCH] impl. tests and graph --- Message/Mail/Mail.php | 112 ++++++ Stdlib/Graph/Edge.php | 22 +- Stdlib/Graph/Graph.php | 69 +++- Stdlib/Graph/Node.php | 21 +- Uri/UriFactory.php | 11 +- .../Client/NullClientConnectionTest.php | 7 +- tests/Stdlib/Graph/EdgeTest.php | 24 +- tests/Stdlib/Graph/GraphTest.php | 334 +++++++++++++++--- tests/Stdlib/Graph/NodeTest.php | 82 +++++ tests/Uri/UriFactoryTest.php | 2 +- tests/Views/ViewTest.php | 2 +- 11 files changed, 609 insertions(+), 77 deletions(-) diff --git a/Message/Mail/Mail.php b/Message/Mail/Mail.php index 0adfa264c..4f892f1e5 100644 --- a/Message/Mail/Mail.php +++ b/Message/Mail/Mail.php @@ -194,6 +194,8 @@ class Mail */ protected ?\DateTime $messageDate = null; + + /** * Should confirm reading * @@ -1366,6 +1368,116 @@ class Mail return \str_replace(' ', '_', $encoded); } + protected function hasCid(string $cid) : bool + { + foreach ($this->attachment as $attachment) { + if ($attachment['disposition'] === DispositionType::INLINE && $attachment['id'] === $cid) { + return true; + } + } + + return false; + } + + public function hasInlineImage() : bool + { + foreach ($this->attachment as $attachment) { + if ($attachment['disposition'] === DispositionType::INLINE) { + return true; + } + } + + return false; + } + + public function hasAttachment() : bool + { + foreach ($this->attachment as $attachmnet) { + if ($attachment['disposition'] === DispositionType::ATTACHMENT) { + return true; + } + } + + return false; + } + + public function hasAlternative() : bool + { + return !empty($this->bodyAlt); + } + + public function clearAddresses() : void + { + $this->to = []; + $this->cc = []; + $this->bcc = []; + } + + public function clearAllCC() : void + { + $this->cc = []; + } + + public function clearAllTo() : void + { + $this->to = []; + } + + public function clearAllBCC() : void + { + $this->bcc = []; + } + + public function clearAttachments() : void + { + $this->attachment = []; + } + + public function clearCustomHeaders() : void + { + $this->header = []; + } + + protected function serverHostname() : string + { + if (!empty($this->hostname)) { + return $this->hostname; + } elseif (isset($_SERVER, $_SERVER['SERVER_NAME'])) { + return $_SERVER['SERVER_NAME']; + } + + return ($host = \gethostname()) === false ? 'localhost.localdomain' : $host; + } + + public function addHeader(string $name, string $value = nulll) : bool + { + if ($vallue === null && \strpos($name, ':') !== false) { + list($name, $value) = \explode(':', $name, 2); + } + + $name = \trim($name); + $value = \trim($value); + + if (empty($name) || \strbrk($name . $value, "\r\n") !== false) { + return false; + } + + // todo: consider to add by name and make the name an array -> multiple values per name + $this->header[] = [$name, $value]; + + return true; + } + + public function getHeader() : array + { + return $this->header; + } + + public function msgHtml(string $message, string $baseDir = '') : string + { + + } + /** * Set signing files * diff --git a/Stdlib/Graph/Edge.php b/Stdlib/Graph/Edge.php index be6b786e4..bce98bdd2 100644 --- a/Stdlib/Graph/Edge.php +++ b/Stdlib/Graph/Edge.php @@ -32,7 +32,7 @@ class Edge * @var Node * @since 1.0.0 */ - private $node1 = null; + private Node $node1; /** * Node2. @@ -42,7 +42,7 @@ class Edge * @var Node * @since 1.0.0 */ - private $node2 = null; + private Node $node2; /** * Is graph/edge directed @@ -50,7 +50,7 @@ class Edge * @var bool * @since 1.0.0 */ - private $isDirected = false; + private bool $isDirected = false; /** * Edge weight @@ -58,7 +58,7 @@ class Edge * @var float * @since 1.0.0 */ - private $weight = 0.0; + private float $weight = 0.0; /** * Constructor. @@ -90,6 +90,20 @@ class Edge return [$this->node1, $this->node2]; } + /** + * Set weight + * + * @param float $weight Weight + * + * @return void + * + * @since 1.0.0 + */ + public function setWeight(float $weight) : void + { + $this->weight = $weight; + } + /** * Get node of the edge. * diff --git a/Stdlib/Graph/Graph.php b/Stdlib/Graph/Graph.php index c1fa02bf1..e1c166d1b 100644 --- a/Stdlib/Graph/Graph.php +++ b/Stdlib/Graph/Graph.php @@ -53,7 +53,7 @@ class Graph * @var Node[] * @since 1.0.0 */ - protected $nodes = []; + protected array $nodes = []; /** * Directed @@ -61,7 +61,7 @@ class Graph * @var bool * @since 1.0.0 */ - protected $isDirected = false; + protected bool $isDirected = false; /** * Set node to graph. @@ -93,6 +93,21 @@ class Graph return $this->nodes[$key] ?? null; } + /** + * Define a relationship between two nodes + * + * @param Node $node1 First node + * @param Node $node2 Second node + * + * @return Edge + * + * @since 1.0.0 + */ + public function setNodeRelative(Node $node1, Node $node2) : Edge + { + return $node1->setNodeRelative($node2, null, true); + } + /** * Graph has node * @@ -190,6 +205,37 @@ class Graph return $edges; } + /** + * Get the edge between two nodes + * + * @param string $id1 Node id + * @param string $id2 Node id + * + * @return null|Edge + * + * @since 1.0.0 + */ + public function getEdge(string $id1, string $id2) : ?Edge + { + foreach ($this->nodes as $node) { + if ($node->getId() !== $id1 && $node->getId() !== $id2) { + continue; + } + + $nodeEdges = $node->getEdges(); + + foreach ($nodeEdges as $edge) { + if (($edge->getNode1()->getId() === $id1 || $edge->getNode1()->getId() === $id2) + && ($edge->getNode2()->getId() === $id1 || $edge->getNode2()->getId() === $id2) + ) { + return $edge; + } + } + } + + return null; + } + /** * Get all bridges. * @@ -289,19 +335,26 @@ class Graph } /** @var Node $node1 */ - $node1 = $graph->hasNode($edge->getNode1()->getId()) ? $graph->getNode($edge->getNode1()->getId()) : clone $edge->getNode1(); + $node1 = $graph->hasNode($edge->getNode1()->getId()) + ? $graph->getNode($edge->getNode1()->getId()) + : clone $edge->getNode1(); + /** @var Node $node2 */ - $node2 = $graph->hasNode($edge->getNode2()->getId()) ? $graph->getNode($edge->getNode2()->getId()) : clone $edge->getNode2(); + $node2 = $graph->hasNode($edge->getNode2()->getId()) + ? $graph->getNode($edge->getNode2()->getId()) + : clone $edge->getNode2(); - $node1->setNodeRelative($node2); - - if (!$graph->hasNode($edge->getNode1()->getId())) { + if (!$graph->hasNode($node1->getId())) { + $node1->removeEdges(); $graph->setNode($node1); } - if (!$graph->hasNode($edge->getNode2()->getId())) { + if (!$graph->hasNode($node2->getId())) { + $node2->removeEdges(); $graph->setNode($node2); } + + $node1->setNodeRelative($node2)->setWeight($this->getEdge($node1->getId(), $node2->getId())->getWeight()); } return $graph; diff --git a/Stdlib/Graph/Node.php b/Stdlib/Graph/Node.php index 82ff423d9..069c47b88 100644 --- a/Stdlib/Graph/Node.php +++ b/Stdlib/Graph/Node.php @@ -117,16 +117,17 @@ class Node /** * Set a relative undirected node. * - * @param Node $node Graph node - * @param int $key Index for absolute position + * @param Node $node Graph node + * @param int $key Index for absolute position + * @param booll $isDirected Is directed * * @return Edge * * @since 1.0.0 */ - public function setNodeRelative(self $node, int $key = null) : Edge + public function setNodeRelative(self $node, int $key = null, bool $isDirected = false) : Edge { - $edge = new Edge($this, $node); + $edge = new Edge($this, $node, 0.0, $isDirected); $this->setEdge($edge, $key); if (!$edge->isDirected()) { @@ -183,6 +184,18 @@ class Node return $this->edges; } + /** + * Removes all edges / neighbours from the node + * + * @return void + * + * @since 1.0.0 + */ + public function removeEdges() : void + { + $this->edges = []; + } + /** * Get all node neighbors. * diff --git a/Uri/UriFactory.php b/Uri/UriFactory.php index 1eb4d3967..ff27ce57e 100644 --- a/Uri/UriFactory.php +++ b/Uri/UriFactory.php @@ -207,7 +207,16 @@ final class UriFactory } if (isset($urlStructure['query'])) { - \parse_str(\str_replace('?', '&', $urlStructure['query']), $urlStructure['query']); + $len = \strlen($urlStructure['query']); + for ($i = 0; $i < $len; ++$i) { + if ($urlStructure['query'][$i] === '?') { + $urlStructure['query'] = \substr_replace($urlStructure['query'], '&', $i, 1); + } elseif ($urlStructure['query'][$i] === '\\') { + ++$i; + } + } + + \parse_str($urlStructure['query'], $urlStructure['query']); } $escaped = diff --git a/tests/Socket/Client/NullClientConnectionTest.php b/tests/Socket/Client/NullClientConnectionTest.php index f05e11804..a2f0e37aa 100644 --- a/tests/Socket/Client/NullClientConnectionTest.php +++ b/tests/Socket/Client/NullClientConnectionTest.php @@ -14,13 +14,16 @@ declare(strict_types=1); namespace phpOMS\tests\Socket\Client; +use phpOMS\Socket\Client\NullClientConnection; +use phpOMS\Socket\Client\ClientConnection; + /** * @internal */ final class NullClientConnectionTest extends \PHPUnit\Framework\TestCase { - public function testPlaceholder() : void + public function testDefault() : void { - self::markTestIncomplete(); + self::assertInstanceOf(ClientConnection::class, new NullClientConnection()); } } diff --git a/tests/Stdlib/Graph/EdgeTest.php b/tests/Stdlib/Graph/EdgeTest.php index 4163de405..d10ee0df3 100644 --- a/tests/Stdlib/Graph/EdgeTest.php +++ b/tests/Stdlib/Graph/EdgeTest.php @@ -51,13 +51,33 @@ class EdgeTest extends \PHPUnit\Framework\TestCase } /** - * @testdox An edge can have a weight + * @testdox An edge weight can be set and returned * @covers phpOMS\Stdlib\Graph\Edge * @group framework */ - public function testWeight() : void + public function testWeightInputOutput() : void { $edge = new Edge(new Node('7'), new Node('8'), 1.0, true); self::assertEquals(1.0, $edge->getWeight()); + + $edge = new Edge(new Node('7'), new Node('8'), 1.0); + $edge->setWeight(3.0); + self::assertEquals(3.0, $edge->getWeight()); + } + + /** + * @testdox Two edge weights can be compared + * @covers phpOMS\Stdlib\Graph\Edge + * @group framework + */ + public function testWeightComparison() : void + { + $edge1 = new Edge(new Node('7'), new Node('8'), 1.0, true); + $edge2 = new Edge(new Node('7'), new Node('8'), 1.0, true); + $edge3 = new Edge(new Node('7'), new Node('8'), 2.0, true); + + self::assertEquals(0, Edge::compare($edge1, $edge2)); + self::assertEquals(-1, Edge::compare($edge1, $edge3)); + self::assertEquals(1, Edge::compare($edge3, $edge1)); } } diff --git a/tests/Stdlib/Graph/GraphTest.php b/tests/Stdlib/Graph/GraphTest.php index de5de18b4..a8ea49b77 100644 --- a/tests/Stdlib/Graph/GraphTest.php +++ b/tests/Stdlib/Graph/GraphTest.php @@ -24,6 +24,13 @@ use phpOMS\Stdlib\Graph\Node; */ class GraphTest extends \PHPUnit\Framework\TestCase { + protected Graph $graph; + + protected function setUp() : void + { + $this->graph = new Graph(); + } + /** * @testdox The graph has the expected default values after initialization * @covers phpOMS\Stdlib\Graph\Graph @@ -31,37 +38,81 @@ class GraphTest extends \PHPUnit\Framework\TestCase */ public function testDefault() : void { - $graph = new Graph(); + self::assertNull($this->graph->getNode('invalid')); + self::assertEquals([], $this->graph->getNodes()); - self::assertNull($graph->getNode('invalid')); - self::assertEquals([], $graph->getNodes()); + self::assertEquals(0, $this->graph->getDiameter()); + self::assertEquals(0, $this->graph->getOrder()); + self::assertEquals(0, $this->graph->getSize()); + self::assertEquals(0, $this->graph->getGirth()); + self::assertEquals(0, $this->graph->getCircuitRank()); + self::assertEquals(0, $this->graph->getNodeConnectivity()); + self::assertEquals(0, $this->graph->getEdgeConnectivity()); - self::assertEquals(0, $graph->getDiameter()); - self::assertEquals(0, $graph->getOrder()); - self::assertEquals(0, $graph->getSize()); - self::assertEquals(0, $graph->getGirth()); - self::assertEquals(0, $graph->getCircuitRank()); - self::assertEquals(0, $graph->getNodeConnectivity()); - self::assertEquals(0, $graph->getEdgeConnectivity()); + self::assertTrue($this->graph->isConnected()); + self::assertTrue($this->graph->isBipartite()); + self::assertTrue($this->graph->isTriangleFree()); + self::assertFalse($this->graph->isDirected()); + self::assertFalse($this->graph->hasCycle()); - self::assertTrue($graph->isConnected()); - self::assertTrue($graph->isBipartite()); - self::assertTrue($graph->isTriangleFree()); + self::assertEquals([], $this->graph->getBridges()); + self::assertEquals([], $this->graph->getFloydWarshallShortestPath()); + self::assertEquals([], $this->graph->getDijkstraShortestPath()); + self::assertEquals([], $this->graph->depthFirstTraversal()); + self::assertEquals([], $this->graph->breadthFirstTraversal()); + self::assertEquals([], $this->graph->longestPath()); + self::assertEquals([], $this->graph->longestPathBetweenNodes('invalid1', 'invalid2')); + self::assertEquals([], $this->graph->getUnconnected()); - self::assertEquals([], $graph->getBridges()); - self::assertEquals([], $graph->getFloydWarshallShortestPath()); - self::assertEquals([], $graph->getDijkstraShortestPath()); - self::assertEquals([], $graph->depthFirstTraversal()); - self::assertEquals([], $graph->breadthFirstTraversal()); - self::assertEquals([], $graph->longestPath()); - self::assertEquals([], $graph->longestPathBetweenNodes('invalid1', 'invalid2')); - self::assertEquals([], $graph->getUnconnected()); + self::assertEquals(0, $this->graph->getCost()); + self::assertEquals($this->graph, $this->graph->getKruskalMinimalSpanningTree()); } + /** + * @testdox A graph can ge set as directed + * @covers phpOMS\Stdlib\Graph\Graph + * @group framework + */ + public function testDirectedInputOutput() : void + { + $this->graph->setDirected(true); + self::assertTrue($this->graph->isDirected()); + } + + /** + * @testdox A node can be add to a graph and returned + * @covers phpOMS\Stdlib\Graph\Graph + * @group framework + */ + public function testNodeInputOutput() : void + { + $node0 = new Node('0'); + $this->graph->setNode($node0); + + self::assertEquals($node0, $this->graph->getNode('0')); + } + + /** + * @testdox The existence of a node in a graph can be checked + * @covers phpOMS\Stdlib\Graph\Graph + * @group framework + */ + public function testNodeExists() : void + { + $node0 = new Node('0'); + $this->graph->setNode($node0); + + self::assertTrue($this->graph->hasNode('0')); + self::assertFalse($this->graph->hasNode('1')); + } + + /** + * @testdox A graph can be checked for bridges + * @covers phpOMS\Stdlib\Graph\Graph + * @group framework + */ public function testGraphWithBridge() : void { - $graph = new Graph(); - $node0 = new Node('0'); $node1 = new Node('1'); $node2 = new Node('2'); @@ -70,13 +121,13 @@ class GraphTest extends \PHPUnit\Framework\TestCase $node5 = new Node('5'); $node6 = new Node('6'); - $graph->setNode($node0); - $graph->setNode($node1); - $graph->setNode($node2); - $graph->setNode($node3); - $graph->setNode($node4); - $graph->setNode($node5); - $graph->setNode($node6); + $this->graph->setNode($node0); + $this->graph->setNode($node1); + $this->graph->setNode($node2); + $this->graph->setNode($node3); + $this->graph->setNode($node4); + $this->graph->setNode($node5); + $this->graph->setNode($node6); $node0->setNodeRelative($node1); $node0->setNodeRelative($node2); @@ -87,58 +138,67 @@ class GraphTest extends \PHPUnit\Framework\TestCase $node3->setNodeRelative($node5); $node4->setNodeRelative($node5); - $bridges = $graph->getBridges(); + $bridges = $this->graph->getBridges(); self::assertCount(1, $bridges); self::assertEquals('1', $bridges[0]->getNode1()->getId()); self::assertEquals('6', $bridges[0]->getNode2()->getId()); } + /** + * @testdox Multiple bridges are correctly identified in a graph + * @covers phpOMS\Stdlib\Graph\Graph + * @group framework + */ public function testGraphWithBridges() : void { - $graph = new Graph(); - $node0 = new Node('0'); $node1 = new Node('1'); $node2 = new Node('2'); $node3 = new Node('3'); - $graph->setNode($node0); - $graph->setNode($node1); - $graph->setNode($node2); - $graph->setNode($node3); + $this->graph->setNode($node0); + $this->graph->setNode($node1); + $this->graph->setNode($node2); + $this->graph->setNode($node3); $node0->setNodeRelative($node1); $node1->setNodeRelative($node2); $node2->setNodeRelative($node3); - $bridges = $graph->getBridges(); + $bridges = $this->graph->getBridges(); self::assertCount(3, $bridges); } + /** + * @testdox A graph without bridges is correctly classified + * @covers phpOMS\Stdlib\Graph\Graph + * @group framework + */ public function testGraphWithoutBridges() : void { - $graph = new Graph(); - $node0 = new Node('0'); $node1 = new Node('1'); $node2 = new Node('2'); - $graph->setNode($node0); - $graph->setNode($node1); - $graph->setNode($node2); + $this->graph->setNode($node0); + $this->graph->setNode($node1); + $this->graph->setNode($node2); $node0->setNodeRelative($node1); $node0->setNodeRelative($node2); $node1->setNodeRelative($node2); - $bridges = $graph->getBridges(); + $bridges = $this->graph->getBridges(); self::assertCount(0, $bridges); } + /** + * @testdox Edges can be add and returned from a graph + * @covers phpOMS\Stdlib\Graph\Graph + * @group framework + */ public function testEdgesInputOutput() : void { - $graph = new Graph(); - $node0 = new Node('0'); $node1 = new Node('1'); $node2 = new Node('2'); @@ -147,13 +207,13 @@ class GraphTest extends \PHPUnit\Framework\TestCase $node5 = new Node('5'); $node6 = new Node('6'); - $graph->setNode($node0); - $graph->setNode($node1); - $graph->setNode($node2); - $graph->setNode($node3); - $graph->setNode($node4); - $graph->setNode($node5); - $graph->setNode($node6); + $this->graph->setNode($node0); + $this->graph->setNode($node1); + $this->graph->setNode($node2); + $this->graph->setNode($node3); + $this->graph->setNode($node4); + $this->graph->setNode($node5); + $this->graph->setNode($node6); $node0->setNodeRelative($node1); $node0->setNodeRelative($node2); @@ -164,7 +224,173 @@ class GraphTest extends \PHPUnit\Framework\TestCase $node3->setNodeRelative($node5); $node4->setNodeRelative($node5); - $edges = $graph->getEdges(); + $edges = $this->graph->getEdges(); self::assertCount(8, $edges); } + + /** + * @testdox An edge can be found by two edge ids + * @covers phpOMS\Stdlib\Graph\Graph + * @group framework + */ + public function testEdgeInputOutput() : void + { + $node0 = new Node('0'); + $node1 = new Node('1'); + $node2 = new Node('2'); + $node3 = new Node('3'); + $node4 = new Node('4'); + $node5 = new Node('5'); + $node6 = new Node('6'); + + $this->graph->setNode($node0); + $this->graph->setNode($node1); + $this->graph->setNode($node2); + $this->graph->setNode($node3); + $this->graph->setNode($node4); + $this->graph->setNode($node5); + $this->graph->setNode($node6); + + $node0->setNodeRelative($node1); + $node0->setNodeRelative($node2); + $node1->setNodeRelative($node2); + $node1->setNodeRelative($node3); + $node1->setNodeRelative($node4); + $node1->setNodeRelative($node6); + $node3->setNodeRelative($node5); + $node4->setNodeRelative($node5); + + self::assertEquals( + $node1->getId(), + $this->graph->getEdge($node1->getId(), $node3->getId())->getNode1()->getId() + ); + + self::assertEquals( + $node3->getId(), + $this->graph->getEdge($node1->getId(), $node3->getId())->getNode2()->getId() + ); + + self::assertEquals(null, $this->graph->getEdge('invalid1', 'invalid2')); + } + + /** + * @testdox The existence of cycles in undirected graphs can be checked + * @covers phpOMS\Stdlib\Graph\Graph + * @group framework + */ + public function testUndirectedCycle() : void + { + $node0 = new Node('0'); + $node1 = new Node('1'); + $node2 = new Node('2'); + $node3 = new Node('3'); + + $this->graph->setNode($node0); + $this->graph->setNode($node1); + $this->graph->setNode($node2); + $this->graph->setNode($node3); + + $node0->setNodeRelative($node1); + $node1->setNodeRelative($node2); + $node2->setNodeRelative($node3); + + self::assertFalse($this->graph->hasCycle()); + + $node3->setNodeRelative($node1); + self::assertTrue($this->graph->hasCycle()); + } + + /** + * @testdox The existence of cycles in directed graphs can be checked + * @covers phpOMS\Stdlib\Graph\Graph + * @group framework + */ + public function testDirectedCycle() : void + { + $this->graph->setDirected(true); + + $node0 = new Node('0'); + $node1 = new Node('1'); + $node2 = new Node('2'); + $node3 = new Node('3'); + + $this->graph->setNode($node0); + $this->graph->setNode($node1); + $this->graph->setNode($node2); + $this->graph->setNode($node3); + + $this->graph->setNodeRelative($node0, $node1); + $this->graph->setNodeRelative($node1, $node2); + $this->graph->setNodeRelative($node2, $node3); + $this->graph->setNodeRelative($node1, $node3); + + self::assertFalse($this->graph->hasCycle()); + + $node3->setNodeRelative($node1); + self::assertTrue($this->graph->hasCycle()); + } + + /** + * @testdox The cost of a graph can be calculated + * @covers phpOMS\Stdlib\Graph\Graph + * @group framework + */ + public function testCost() : void + { + $node0 = new Node('0'); + $node1 = new Node('1'); + $node2 = new Node('2'); + $node3 = new Node('3'); + + $this->graph->setNode($node0); + $this->graph->setNode($node1); + $this->graph->setNode($node2); + $this->graph->setNode($node3); + + $node0->setNodeRelative($node1)->setWeight(2.0); + $node2->setNodeRelative($node3)->setWeight(3.0); + + self::assertEquals(5.0, $this->graph->getCost()); + } + + /** + * @testdox The Kruskal minimal spanning tree can be created + * @covers phpOMS\Stdlib\Graph\Graph + * @group framework + */ + public function testKruskalMinimalSpanningTree() : void + { + $node1 = new Node('1'); + $node2 = new Node('2'); + $node3 = new Node('3'); + $node4 = new Node('4'); + $node5 = new Node('5'); + $node6 = new Node('6'); + + $this->graph->setNode($node1); + $this->graph->setNode($node2); + $this->graph->setNode($node3); + $this->graph->setNode($node4); + $this->graph->setNode($node5); + $this->graph->setNode($node6); + + $node1->setNodeRelative($node5)->setWeight(4.0); + $node1->setNodeRelative($node4)->setWeight(1.0); + $node1->setNodeRelative($node2)->setWeight(2.0); + + $node2->setNodeRelative($node3)->setWeight(3.0); + $node2->setNodeRelative($node4)->setWeight(3.0); + $node2->setNodeRelative($node6)->setWeight(7.0); + + $node3->setNodeRelative($node4)->setWeight(5.0); + $node3->setNodeRelative($node6)->setWeight(8.0); + + $node4->setNodeRelative($node5)->setWeight(9.0); + + $minimalSpanningTree = $this->graph->getKruskalMinimalSpanningTree(); + $nodes = $minimalSpanningTree->getNodes(); + + self::assertCount(6, $nodes); + self::assertEquals(17.0, $minimalSpanningTree->getCost()); + } } diff --git a/tests/Stdlib/Graph/NodeTest.php b/tests/Stdlib/Graph/NodeTest.php index dfcb16349..4b1ac17c7 100644 --- a/tests/Stdlib/Graph/NodeTest.php +++ b/tests/Stdlib/Graph/NodeTest.php @@ -15,6 +15,9 @@ declare(strict_types=1); namespace phpOMS\tests\Stdlib\Graph; use phpOMS\Stdlib\Graph\Node; +use phpOMS\Stdlib\Graph\Edge; + +use function PHPUnit\Framework\assertInstanceOf; /** * @testdox phpOMS\tests\Stdlib\Graph\NodeTest: Node in a graph @@ -80,4 +83,83 @@ class NodeTest extends \PHPUnit\Framework\TestCase self::assertFalse($node->isEqual($node2)); } + + /** + * @testdox An edge for a node can be defined + * @covers phpOMS\Stdlib\Graph\Node + * @group framework + */ + public function testEdgeInputOutput() : void + { + $node = new Node('A', 1); + $node->setEdge(new Edge($node, new Node('B'))); + + self::assertCount(1, $node->getEdges()); + } + + /** + * @testdox Edges can be removed from a node + * @covers phpOMS\Stdlib\Graph\Node + * @group framework + */ + public function testEdgeRemove() : void + { + $node = new Node('A', 1); + $node->setEdge(new Edge($node, new Node('B'))); + $node->removeEdges(); + + self::assertCount(0, $node->getEdges()); + } + + /** + * @testdox An edge for a node can be defined by key + * @covers phpOMS\Stdlib\Graph\Node + * @group framework + */ + public function testEdgeKeyInputOutput() : void + { + $node = new Node('A', 1); + $node->setEdge(new Edge($node, new Node('B')), 3); + + self::assertEquals(null, $node->getEdge(2)); + self::assertInstanceOf(Edge::class, $node->getEdge(3)); + } + + /** + * @testdox A node relationship can be defined + * @covers phpOMS\Stdlib\Graph\Node + * @group framework + */ + public function testNodeRelation() : void + { + $node1 = new Node('A'); + $node2 = new Node('B'); + + self::assertInstanceOf(Edge::class, $edge = $node1->setNodeRelative($node2, null, false)); + self::assertCount(1, $node2->getEdges()); + self::assertFalse($edge->isDirected()); + } + + /** + * @testdox All neighbors of a node can be returned + * @covers phpOMS\Stdlib\Graph\Node + * @group framework + * + * @todo: is there bug where directed graphs return invalid neighbors? + */ + public function testNeighborsInputOutput() : void + { + $node1 = new Node('A'); + $node2 = new Node('B'); + $node3 = new Node('C'); + $node4 = new Node('D'); + + $node3->setNodeRelative($node4); + + $node1->setNodeRelative($node2); + $node1->setNodeRelative($node3); + + self::assertCount(2, $node1->getNeighbors()); + self::assertCount(1, $node4->getNeighbors()); + } } diff --git a/tests/Uri/UriFactoryTest.php b/tests/Uri/UriFactoryTest.php index 32d0c7762..046d89c6d 100644 --- a/tests/Uri/UriFactoryTest.php +++ b/tests/Uri/UriFactoryTest.php @@ -172,7 +172,7 @@ class UriFactoryTest extends \PHPUnit\Framework\TestCase self::assertTrue(UriFactory::setQuery('/valid2', 'query4')); - $expected = 'www.test-uri.com?id=1&test=someString&two=PATH&hash=test&none=%23none&found=%2Fnot%3Fv%3Dquery4'; + $expected = 'www.test-uri.com?id=1&test=someString&two=PATH&hash=test&none=%23none&found=%2Fnot&v=query4'; self::assertEquals($expected, UriFactory::build($uri, $vars)); } diff --git a/tests/Views/ViewTest.php b/tests/Views/ViewTest.php index b75aa1792..2853b2560 100644 --- a/tests/Views/ViewTest.php +++ b/tests/Views/ViewTest.php @@ -73,7 +73,7 @@ class ViewTest extends \PHPUnit\Framework\TestCase } /** - * @testdox The view data can be checked for existance + * @testdox The view data can be checked for existence * @covers phpOMS\Views\View * @group framework */