From 36f229c8acd1b1f9ae09cea5e72fcd991b920455 Mon Sep 17 00:00:00 2001 From: Andrej Rypo Date: Fri, 26 Jan 2024 23:20:41 +0100 Subject: [PATCH] improved tests --- tests/iterators.phpt | 60 ++++++++++++++------------------------ tests/nodes.phpt | 15 +++------- tests/setup.php | 68 ++++++++++++++++++++++++++++++++++++++------ tests/tool.phpt | 46 ++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+), 58 deletions(-) create mode 100644 tests/tool.phpt diff --git a/tests/iterators.phpt b/tests/iterators.phpt index 6a2f72d..0cd1af9 100644 --- a/tests/iterators.phpt +++ b/tests/iterators.phpt @@ -10,7 +10,6 @@ use Dakujem\Oliva\Iterator\Native; use Dakujem\Oliva\Iterator\PostOrderTraversal; use Dakujem\Oliva\Iterator\PreOrderTraversal; use Dakujem\Oliva\Iterator\Support\Counter; -use Dakujem\Oliva\Node; use Dakujem\Oliva\TreeNodeContract; use RecursiveIteratorIterator; use Tester\Assert; @@ -25,75 +24,51 @@ require_once __DIR__ . '/setup.php'; Assert::same(2, $counter->current()); Assert::same(3, $counter->next()); Assert::same(3, $counter->current()); +})(); +(function () { $counter = new Counter(5); Assert::same(5, $counter->current()); +})(); - - $a = new Node('A'); - $b = new Node('B'); - $c = new Node('C'); - $d = new Node('D'); - $e = new Node('E'); - $f = new Node('F'); - $g = new Node('G'); - $h = new Node('H'); - $i = new Node('I'); - - $edge = function (Node $from, Node $to): void { - $from->addChild($to); - $to->setParent($from); - }; - - // Tree from here: - // https://en.wikipedia.org/wiki/Tree_traversal - $root = $f; - $edge($f, $b); - $edge($b, $a); - $edge($b, $d); - $edge($d, $c); - $edge($d, $e); - $edge($f, $g); - $edge($g, $i); - $edge($i, $h); +(function () { + $root = Preset::wikiTree(); $iterator = new PreOrderTraversal($root); $str = ''; foreach ($iterator as $node) { $str .= $node->data(); } -//echo $str; -//echo "\n"; Assert::same('FBADCEGIH', $str); + Assert::same('FBADCEGIH', TreeTesterTool::append($iterator)); $iterator = new PostOrderTraversal($root); $str = ''; foreach ($iterator as $node) { $str .= $node->data(); } -//echo $str; -//echo "\n"; Assert::same('ACEDBHIGF', $str); + Assert::same('ACEDBHIGF', TreeTesterTool::append($iterator)); $iterator = new LevelOrderTraversal($root); $str = ''; foreach ($iterator as $i => $node) { $str .= $node->data(); } -//echo $str; -//echo "\n"; Assert::same('FBGADICEH', $str); + Assert::same('FBGADICEH', TreeTesterTool::append($iterator)); -//echo "\n"; Assert::type(PreOrderTraversal::class, $root->getIterator()); $str = ''; foreach ($root as $node) { $str .= $node->data(); } -//echo $str; Assert::same('FBADCEGIH', $str); -//echo "\n"; + Assert::same('FBADCEGIH', TreeTesterTool::append($root->getIterator())); +})(); +(function () { + $root = Preset::wikiTree(); $iterator = new PreOrderTraversal( node: $root, @@ -166,7 +141,10 @@ require_once __DIR__ . '/setup.php'; 'a.b.1.0.0' => 'H', ]; Assert::same($expected, array_map(fn(DataNodeContract $node) => $node->data(), iterator_to_array($iterator))); +})(); +(function () { + $root = Preset::wikiTree(); $iterator = new PostOrderTraversal($root); $expected = [ @@ -199,8 +177,10 @@ require_once __DIR__ . '/setup.php'; 'a.b' => 'F', ]; Assert::same($expected, array_map(fn(DataNodeContract $node) => $node->data(), iterator_to_array($iterator))); +})(); - +(function () { + $root = Preset::wikiTree(); $iterator = new LevelOrderTraversal($root); $expected = [ @@ -233,8 +213,12 @@ require_once __DIR__ . '/setup.php'; 'a.b.1.0.0' => 'H', ]; Assert::same($expected, array_map(fn(DataNodeContract $node) => $node->data(), iterator_to_array($iterator))); +})(); +(function () { + $root = Preset::wikiTree(); + // level-order (?), leaves only (the default) $str = []; foreach (new RecursiveIteratorIterator(new Native($root)) as $node) { diff --git a/tests/nodes.phpt b/tests/nodes.phpt index fac2686..144a30b 100644 --- a/tests/nodes.phpt +++ b/tests/nodes.phpt @@ -32,13 +32,10 @@ require_once __DIR__ . '/setup.php'; ]); // pre-order - $str = []; - foreach ($root as $node) { - $str[] = $node->data(); - } - Assert::same('F,B,A,D,C,E,G,I,H', implode(',', $str)); - + Assert::same('FBADCEGIH', TreeTesterTool::flatten($root)); +})(); +(function () { // Tree from here: // https://en.wikipedia.org/wiki/Tree_traversal $data = [ @@ -82,9 +79,5 @@ require_once __DIR__ . '/setup.php'; $root = $wrapper->wrap($data); // pre-order - $str = []; - foreach ($root as $node) { - $str[] = $node->data(); - } - Assert::same('F,B,A,D,C,E,G,I,H', implode(',', $str)); + Assert::same('FBADCEGIH', TreeTesterTool::flatten($root)); })(); diff --git a/tests/setup.php b/tests/setup.php index 24e21a3..372b381 100644 --- a/tests/setup.php +++ b/tests/setup.php @@ -6,6 +6,8 @@ use Dakujem\Oliva\DataNodeContract; use Dakujem\Oliva\Iterator\PreOrderTraversal; +use Dakujem\Oliva\MovableNodeContract; +use Dakujem\Oliva\Node; use Dakujem\Oliva\TreeNodeContract; use Tester\Environment; @@ -15,27 +17,34 @@ final class TreeTesterTool { - public static function concatTree( + public static function flatten( TreeNodeContract $node, string $traversalClass = PreOrderTraversal::class, - string $delimiter = '', + string $glue = '', ): string { - return self::concat( + return self::append( new $traversalClass($node), - $delimiter, + $glue, ); } - public static function concat(iterable $traversal, string $delimiter = ''): string - { + public static function append( + iterable $traversal, + string $glue = '', + ?callable $extractor = null, + ): string { + $extractor ??= fn(DataNodeContract $item) => $item->data(); return self::reduce( $traversal, - fn(string $carry, DataNodeContract $item) => $carry . $delimiter . $item->data(), + fn(string $carry, DataNodeContract $item) => $carry . $glue . $extractor($item), ); } - public static function reduce(iterable $traversal, callable $reducer, string $carry = ''): string - { + public static function reduce( + iterable $traversal, + callable $reducer, + string $carry = '', + ): string { foreach ($traversal as $node) { $carry = $reducer($carry, $node); } @@ -43,3 +52,44 @@ public static function reduce(iterable $traversal, callable $reducer, string $ca } } +final class Manipulator +{ + public static function edge(MovableNodeContract $parent, MovableNodeContract $child): void + { + $parent->addChild($child); + $child->setParent($parent); + } +} + +final class Preset +{ + /** + * Returns manually built tree from Wikipedia: + * @link https://en.wikipedia.org/wiki/Tree_traversal + */ + public static function wikiTree(): Node + { + $a = new Node('A'); + $b = new Node('B'); + $c = new Node('C'); + $d = new Node('D'); + $e = new Node('E'); + $f = new Node('F'); + $g = new Node('G'); + $h = new Node('H'); + $i = new Node('I'); + + + $root = $f; + Manipulator::edge($f, $b); + Manipulator::edge($b, $a); + Manipulator::edge($b, $d); + Manipulator::edge($d, $c); + Manipulator::edge($d, $e); + Manipulator::edge($f, $g); + Manipulator::edge($g, $i); + Manipulator::edge($i, $h); + + return $root; + } +} diff --git a/tests/tool.phpt b/tests/tool.phpt new file mode 100644 index 0000000..6745901 --- /dev/null +++ b/tests/tool.phpt @@ -0,0 +1,46 @@ +parent()); + Assert::same($b, $a->child(0)); +})(); + +(function () { + Assert::same('', TreeTesterTool::append([])); + Assert::same('ABC', TreeTesterTool::append([ + new Node('A'), + new Node('B'), + new Node('C'), + ])); + Assert::same('', TreeTesterTool::append([], '.')); + Assert::same('.A.B.C', TreeTesterTool::append([ + new Node('A'), + new Node('B'), + new Node('C'), + ], '.')); +})(); + + +(function () { + $tree = Preset::wikiTree(); + Assert::same('FBADCEGIH', TreeTesterTool::flatten($tree)); + Assert::same('FBADCEGIH', TreeTesterTool::flatten($tree, PreOrderTraversal::class)); + Assert::same('ACEDBHIGF', TreeTesterTool::flatten($tree, PostOrderTraversal::class)); + Assert::same('FBGADICEH', TreeTesterTool::flatten($tree, LevelOrderTraversal::class)); +})(); \ No newline at end of file