From 71176122872e7d200167cd77d48ed30fda95b3ae Mon Sep 17 00:00:00 2001
From: Laria Carolin Chabowski <laria@laria.me>
Date: Tue, 15 Sep 2020 22:21:04 +0200
Subject: Add some unit tests for the parser

So far only testing success, we should also test failing parse inputs.
---
 src/ste/Parser.php        |   9 ++-
 src/ste/TagNode.php       |   6 +-
 src/ste/VariableNode.php  |  16 ++++-
 tests/unit/ParserTest.php | 176 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 202 insertions(+), 5 deletions(-)
 create mode 100644 tests/unit/ParserTest.php

diff --git a/src/ste/Parser.php b/src/ste/Parser.php
index a588203..a2f966c 100644
--- a/src/ste/Parser.php
+++ b/src/ste/Parser.php
@@ -443,12 +443,15 @@ class Parser
      */
     private function parse_var(int $openedat, bool $curly): VariableNode
     {
-        $varnode = new VariableNode($this->name, $openedat);
-        $varnode->name = $this->get_name();
+        $varname = $this->get_name();
+
+        $arrayfields = [];
         if (!$this->eof()) {
-            $varnode->arrayfields = $this->parse_array();
+            $arrayfields = $this->parse_array();
         }
 
+        $varnode = new VariableNode($this->name, $openedat, $varname, $arrayfields);
+
         if ($curly && ($this->next() != "}")) {
             throw new ParseCompileError("Unclosed '\${'", $this->name, $openedat);
         }
diff --git a/src/ste/TagNode.php b/src/ste/TagNode.php
index 4adcad8..ce713c0 100644
--- a/src/ste/TagNode.php
+++ b/src/ste/TagNode.php
@@ -17,10 +17,14 @@ class TagNode extends ASTNode
      * @param string $tpl
      * @param int $off
      * @param string $name
+     * @param ASTNode[][] $params
+     * @param ASTNode[] $sub
      */
-    public function __construct(string $tpl, int $off, string $name = "")
+    public function __construct(string $tpl, int $off, string $name = "", array $params = [], array $sub = [])
     {
         parent::__construct($tpl, $off);
         $this->name = $name;
+        $this->params = $params;
+        $this->sub = $sub;
     }
 }
diff --git a/src/ste/VariableNode.php b/src/ste/VariableNode.php
index f5a0b26..cdffc3f 100644
--- a/src/ste/VariableNode.php
+++ b/src/ste/VariableNode.php
@@ -8,7 +8,21 @@ class VariableNode extends ASTNode
     public $name;
 
     /** @var ASTNode[][] */
-    public $arrayfields = [];
+    public $arrayfields;
+
+    /**
+     * @param string $tpl
+     * @param int $off
+     * @param string $name
+     * @param ASTNode[][] $arrayfields
+     */
+    public function __construct(string $tpl, int $off, string $name, array $arrayfields)
+    {
+        parent::__construct($tpl, $off);
+
+        $this->name = $name;
+        $this->arrayfields = $arrayfields;
+    }
 
     /**
      * @return string
diff --git a/tests/unit/ParserTest.php b/tests/unit/ParserTest.php
new file mode 100644
index 0000000..0a5ccb8
--- /dev/null
+++ b/tests/unit/ParserTest.php
@@ -0,0 +1,176 @@
+<?php
+
+
+namespace tests\unit;
+
+use PHPUnit\Framework\TestCase;
+use kch42\ste\Parser;
+use kch42\ste\TextNode;
+use kch42\ste\VariableNode;
+use kch42\ste\TagNode;
+
+class ParserTest extends TestCase
+{
+    /**
+     * @dataProvider successfulParsingDataProvider
+     */
+    public function testSuccessfulParsing(string $source, array $expected)
+    {
+        $actual = Parser::parse($source, '-');
+
+        self::assertEquals($expected, $actual);
+    }
+
+    public function successfulParsingDataProvider()
+    {
+        return [
+            ['', []],
+
+            ['Hello', [
+                new TextNode('-', 0, 'Hello'),
+            ]],
+
+            ['$foo', [
+                new VariableNode('-', 0, 'foo', []),
+            ]],
+
+            //01234567890
+            ['foo$bar$baz', [
+                new TextNode('-', 0, 'foo'),
+                new VariableNode('-', 3, 'bar', []),
+                new VariableNode('-', 7, 'baz', []),
+            ]],
+
+            //012345678
+            ['${foo}bar', [
+                new VariableNode('-', 0, 'foo', []),
+                new TextNode('-', 6, 'bar'),
+            ]],
+
+            //012345678
+            ['$foo[bar]', [
+                new VariableNode('-', 0, 'foo', [
+                    [new TextNode('-', 5, 'bar')],
+                ]),
+            ]],
+
+            //01234567890
+            ['${foo[bar]}', [
+                new VariableNode('-', 0, 'foo', [
+                    [new TextNode('-', 6, 'bar')],
+                ]),
+            ]],
+
+            //012345678
+            ['$foo[$bar]', [
+                new VariableNode('-', 0, 'foo', [
+                    [new VariableNode('-', 5, 'bar', [])],
+                ]),
+            ]],
+
+            //012345678901234
+            ['$foo[$bar[baz]]', [
+                new VariableNode('-', 0, 'foo', [
+                    [new VariableNode('-', 5, 'bar', [
+                        [new TextNode('-', 10, 'baz')],
+                    ])],
+                ]),
+            ]],
+
+            //012345678901234
+            ['$foo[$bar][baz]', [
+                new VariableNode('-', 0, 'foo', [
+                    [new VariableNode('-', 5, 'bar', [])],
+                    [new TextNode('-', 11, 'baz')]
+                ]),
+            ]],
+
+            //0123456789012345678901
+            ['a${b[c$d[e${f}g]][h]}i', [
+                new TextNode('-', 0, 'a'),
+                new VariableNode('-', 1, 'b', [
+                    [
+                        new TextNode('-', 5, 'c'),
+                        new VariableNode('-', 6, 'd', [
+                            [
+                                new TextNode('-', 9, 'e'),
+                                new VariableNode('-', 10, 'f', []),
+                                new TextNode('-', 14, 'g')
+                            ]
+                        ])
+                    ],
+                    [new TextNode('-', 18, 'h')],
+                ]),
+                new TextNode('-', 21, 'i'),
+            ]],
+
+            ['<ste:foo />', [
+                new TagNode('-', 0, 'foo'),
+            ]],
+
+            ['<ste:foo></ste:foo>', [
+                new TagNode('-', 0, 'foo'),
+            ]],
+
+            //0123456789012345678901
+            ['<ste:foo>bar</ste:foo>', [
+                new TagNode('-', 0, 'foo', [], [
+                    new TextNode('-', 9, 'bar'),
+                ]),
+            ]],
+
+            //0         1         2         3         4         5         6         7         8         9         0
+            //012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234
+            ['<ste:foo a="$b[0][$x]" c="\"" d="${e}f"><ste:foo><ste:xyz>abc</ste:xyz><ste:foo />$x</ste:foo></ste:foo>x', [
+                new TagNode('-', 0, 'foo', [
+                    'a' => [
+                        new VariableNode('-', 12, 'b', [
+                            [new TextNode('-', 15, '0')],
+                            [new VariableNode('-', 18, 'x', [])],
+                        ]),
+                    ],
+                    'c' => [
+                        new TextNode('-', 26, '"'),
+                    ],
+                    'd' => [
+                        new VariableNode('-', 33, 'e', []),
+                        new TextNode('-', 37, 'f'),
+                    ]
+                ], [
+                    new TagNode('-', 40, 'foo', [], [
+                        new TagNode('-', 49, 'xyz', [], [
+                            new TextNode('-', 58, 'abc'),
+                        ]),
+                        new TagNode('-', 71, 'foo'),
+                        new VariableNode('-', 82, 'x', []),
+                    ]),
+                ]),
+                new TextNode('-', 104, 'x'),
+            ]],
+
+            //0         1         2         3
+            //01234567890123456789012345678901234567
+            ['foo?{~{$x|eq|\}$y}|b|<ste:foo/>\}}$bar', [
+                new TextNode('-', 0, 'foo'),
+                new TagNode('-', 3, 'if', [], [
+                    new TagNode('-', 5, 'cmp', [
+                        'text_a' => [new VariableNode('-', 7, 'x', [])],
+                        'op' => [new TextNode('-', 10, 'eq')],
+                        'text_b' => [
+                            new TextNode('-', 13, '}'),
+                            new VariableNode('-', 15, 'y', []),
+                        ],
+                    ], []),
+                    new TagNode('-', 3, 'then', [], [
+                        new TextNode('-', 19, 'b'),
+                    ]),
+                    new TagNode('-', 3, 'else', [], [
+                        new TagNode('-', 21, 'foo'),
+                        new TextNode('-', 31, '}'),
+                    ]),
+                ]),
+                new VariableNode('-', 34, 'bar', []),
+            ]],
+        ];
+    }
+}
-- 
cgit v1.2.3-70-g09d2