From 5f0eef5f2e34fb65218468ba83fb33cbb8c497e6 Mon Sep 17 00:00:00 2001 From: James Westman Date: Sun, 31 Oct 2021 23:29:07 -0500 Subject: [PATCH] Add compilation tests Added a set of test inputs and expected outputs, for regression testing. --- gtkblueprinttool/ast.py | 24 +++++++--- gtkblueprinttool/extensions/gtk_menu.py | 4 +- tests/samples/binding.blp | 7 +++ tests/samples/binding.ui | 8 ++++ tests/samples/child_type.blp | 7 +++ tests/samples/child_type.ui | 9 ++++ tests/samples/layout.blp | 10 ++++ tests/samples/layout.ui | 14 ++++++ tests/samples/menu.blp | 20 ++++++++ tests/samples/menu.ui | 28 ++++++++++++ tests/samples/property.blp | 5 ++ tests/samples/property.ui | 7 +++ tests/samples/signal.blp | 6 +++ tests/samples/signal.ui | 8 ++++ tests/samples/style.blp | 5 ++ tests/samples/style.ui | 10 ++++ tests/samples/template.blp | 3 ++ tests/samples/template.ui | 5 ++ tests/samples/using.blp | 4 ++ tests/samples/using.ui | 5 ++ tests/test_samples.py | 61 +++++++++++++++++++++++++ 21 files changed, 241 insertions(+), 9 deletions(-) create mode 100644 tests/samples/binding.blp create mode 100644 tests/samples/binding.ui create mode 100644 tests/samples/child_type.blp create mode 100644 tests/samples/child_type.ui create mode 100644 tests/samples/layout.blp create mode 100644 tests/samples/layout.ui create mode 100644 tests/samples/menu.blp create mode 100644 tests/samples/menu.ui create mode 100644 tests/samples/property.blp create mode 100644 tests/samples/property.ui create mode 100644 tests/samples/signal.blp create mode 100644 tests/samples/signal.ui create mode 100644 tests/samples/style.blp create mode 100644 tests/samples/style.ui create mode 100644 tests/samples/template.blp create mode 100644 tests/samples/template.ui create mode 100644 tests/samples/using.blp create mode 100644 tests/samples/using.ui create mode 100644 tests/test_samples.py diff --git a/gtkblueprinttool/ast.py b/gtkblueprinttool/ast.py index 06146cb..ab90536 100644 --- a/gtkblueprinttool/ast.py +++ b/gtkblueprinttool/ast.py @@ -21,7 +21,7 @@ import typing as T from .ast_utils import * from .errors import assert_true, AlreadyCaughtError, CompileError, CompilerBugError, MultipleErrors -from .gir import GirContext, get_namespace +from . import gir from .lsp_utils import Completion, CompletionItemKind from .tokenizer import Token from .utils import lazy_prop @@ -33,21 +33,21 @@ class UI(AstNode): @property def gir(self): - gir = GirContext() + gir_ctx = gir.GirContext() self._gir_errors = [] try: - gir.add_namespace(self.children[GtkDirective][0].gir_namespace) + gir_ctx.add_namespace(self.children[GtkDirective][0].gir_namespace) except CompileError as e: self._gir_errors.append(e) for i in self.children[Import]: try: - gir.add_namespace(i.gir_namespace) + gir_ctx.add_namespace(i.gir_namespace) except CompileError as e: self._gir_errors.append(e) - return gir + return gir_ctx @validate() @@ -86,7 +86,7 @@ class GtkDirective(AstNode): @property def gir_namespace(self): - return get_namespace("Gtk", self.tokens["version"]) + return gir.get_namespace("Gtk", self.tokens["version"]) def emit_xml(self, xml: XmlEmitter): @@ -95,8 +95,18 @@ class GtkDirective(AstNode): class Import(AstNode): @validate("namespace", "version") + def namespace_exists(self): + gir.get_namespace(self.tokens["namespace"], self.tokens["version"]) + + @property def gir_namespace(self): - return get_namespace(self.tokens["namespace"], self.tokens["version"]) + try: + return gir.get_namespace(self.tokens["namespace"], self.tokens["version"]) + except CompileError: + return None + + def emit_xml(self, xml): + pass class Template(AstNode): diff --git a/gtkblueprinttool/extensions/gtk_menu.py b/gtkblueprinttool/extensions/gtk_menu.py index 205cfe5..6524c77 100644 --- a/gtkblueprinttool/extensions/gtk_menu.py +++ b/gtkblueprinttool/extensions/gtk_menu.py @@ -30,7 +30,7 @@ class Menu(AstNode): def emit_xml(self, xml: XmlEmitter): xml.start_tag(self.tokens["tag"], id=self.tokens["id"]) for child in self.children: - child.emit_xml() + child.emit_xml(xml) xml.end_tag() @@ -96,7 +96,7 @@ menu_item_shorthand = Group( )), Optional(Group( MenuAttribute, - Sequence(UseLiteral("name", "verb-icon-name"), value), + Sequence(UseLiteral("name", "icon"), value), )), StmtEnd().expected("`;`"), ) diff --git a/tests/samples/binding.blp b/tests/samples/binding.blp new file mode 100644 index 0000000..e4b4a88 --- /dev/null +++ b/tests/samples/binding.blp @@ -0,0 +1,7 @@ +using Gtk 4.0; + +Box { + visible: bind box2.visible sync-create; +} + +Box box2 {} diff --git a/tests/samples/binding.ui b/tests/samples/binding.ui new file mode 100644 index 0000000..7d20e8c --- /dev/null +++ b/tests/samples/binding.ui @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tests/samples/child_type.blp b/tests/samples/child_type.blp new file mode 100644 index 0000000..8d9f4d7 --- /dev/null +++ b/tests/samples/child_type.blp @@ -0,0 +1,7 @@ +using Gtk 4.0; + +Window { + [titlebar] + HeaderBar { + } +} diff --git a/tests/samples/child_type.ui b/tests/samples/child_type.ui new file mode 100644 index 0000000..2961bfd --- /dev/null +++ b/tests/samples/child_type.ui @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tests/samples/layout.blp b/tests/samples/layout.blp new file mode 100644 index 0000000..01e5f5b --- /dev/null +++ b/tests/samples/layout.blp @@ -0,0 +1,10 @@ +using Gtk 4.0; + +Grid { + Label { + layout { + column: 0; + row: 1; + } + } +} diff --git a/tests/samples/layout.ui b/tests/samples/layout.ui new file mode 100644 index 0000000..027d010 --- /dev/null +++ b/tests/samples/layout.ui @@ -0,0 +1,14 @@ + + + + + + + + 0 + 1 + + + + + diff --git a/tests/samples/menu.blp b/tests/samples/menu.blp new file mode 100644 index 0000000..d4f25dc --- /dev/null +++ b/tests/samples/menu.blp @@ -0,0 +1,20 @@ +using Gtk 4.0; + +menu { + label: _("menu label"); + test-custom-attribute: 3.1415; + + submenu { + section { + label: "test section"; + } + + item { + label: "test item"; + } + + item "test item shorthand 1"; + item "test item shorthand 2" "app.test-action"; + item "test item shorthand 3" "app.test-action" "test-symbolic"; + } +} diff --git a/tests/samples/menu.ui b/tests/samples/menu.ui new file mode 100644 index 0000000..d008200 --- /dev/null +++ b/tests/samples/menu.ui @@ -0,0 +1,28 @@ + + + + + menu label + 3.1415 + +
+ test section +
+ + test item + + + test item shorthand 1 + + + test item shorthand 2 + app.test-action + + + test item shorthand 3 + app.test-action + test-symbolic + +
+
+
diff --git a/tests/samples/property.blp b/tests/samples/property.blp new file mode 100644 index 0000000..4e7e6f4 --- /dev/null +++ b/tests/samples/property.blp @@ -0,0 +1,5 @@ +using Gtk 4.0; + +Box { + orientation: VERTICAL; +} diff --git a/tests/samples/property.ui b/tests/samples/property.ui new file mode 100644 index 0000000..225ae65 --- /dev/null +++ b/tests/samples/property.ui @@ -0,0 +1,7 @@ + + + + + VERTICAL + + diff --git a/tests/samples/signal.blp b/tests/samples/signal.blp new file mode 100644 index 0000000..beda854 --- /dev/null +++ b/tests/samples/signal.blp @@ -0,0 +1,6 @@ +using Gtk 4.0; + +Button { + clicked => on_button_clicked() swapped; + notify::visible => on_button_notify_visible(); +} diff --git a/tests/samples/signal.ui b/tests/samples/signal.ui new file mode 100644 index 0000000..41c0df3 --- /dev/null +++ b/tests/samples/signal.ui @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tests/samples/style.blp b/tests/samples/style.blp new file mode 100644 index 0000000..6d47e49 --- /dev/null +++ b/tests/samples/style.blp @@ -0,0 +1,5 @@ +using Gtk 4.0; + +Label { + style "class-1", "class-2"; +} diff --git a/tests/samples/style.ui b/tests/samples/style.ui new file mode 100644 index 0000000..a216fdb --- /dev/null +++ b/tests/samples/style.ui @@ -0,0 +1,10 @@ + + + + + + + diff --git a/tests/samples/template.blp b/tests/samples/template.blp new file mode 100644 index 0000000..bcfce82 --- /dev/null +++ b/tests/samples/template.blp @@ -0,0 +1,3 @@ +using Gtk 4.0; + +template TestTemplate : ApplicationWindow {} diff --git a/tests/samples/template.ui b/tests/samples/template.ui new file mode 100644 index 0000000..1485a06 --- /dev/null +++ b/tests/samples/template.ui @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/samples/using.blp b/tests/samples/using.blp new file mode 100644 index 0000000..8b11013 --- /dev/null +++ b/tests/samples/using.blp @@ -0,0 +1,4 @@ +using Gtk 4.0; +using GObject 2.0; + +GObject.Object {} diff --git a/tests/samples/using.ui b/tests/samples/using.ui new file mode 100644 index 0000000..5b81551 --- /dev/null +++ b/tests/samples/using.ui @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/test_samples.py b/tests/test_samples.py new file mode 100644 index 0000000..cf5498a --- /dev/null +++ b/tests/test_samples.py @@ -0,0 +1,61 @@ +# test_samples.py +# +# Copyright 2021 James Westman +# +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program. If not, see . +# +# SPDX-License-Identifier: LGPL-3.0-or-later + + +import difflib # I love Python +from pathlib import Path +import unittest + +from gtkblueprinttool import tokenizer, parser +from gtkblueprinttool.errors import PrintableError +from gtkblueprinttool.tokenizer import Token, TokenType, tokenize + + +class TestSamples(unittest.TestCase): + def assert_sample(self, name): + with open((Path(__file__).parent / f"samples/{name}.blp").resolve()) as f: + blueprint = f.read() + with open((Path(__file__).parent / f"samples/{name}.ui").resolve()) as f: + expected = f.read() + + tokens = tokenizer.tokenize(blueprint) + ast, errors = parser.parse(tokens) + + if errors: + raise errors + if len(ast.errors): + raise MultipleErrors(ast.errors) + + actual = ast.generate() + if actual.strip() != expected.strip(): + diff = difflib.unified_diff(expected.splitlines(), actual.splitlines()) + print("\n".join(diff)) + raise AssertionError() + + + def test_samples(self): + self.assert_sample("binding") + self.assert_sample("child_type") + self.assert_sample("layout") + self.assert_sample("menu") + self.assert_sample("property") + self.assert_sample("signal") + self.assert_sample("style") + self.assert_sample("template") + self.assert_sample("using")