From 9b286e76c858bb015c70261cc85f34952ba1d155 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Tue, 6 Jun 2023 15:56:41 +0400 Subject: scripts: add a XML preprocessor script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gdbus-codegen doesn't support conditions or pre-processing. Rather than duplicating D-Bus interfaces for win32 adaptation, let's have a preprocess step, so we can have platform-specific interfaces. The python script is based on https://github.com/peitaosu/XML-Preprocessor, with bug fixes, some testing and replacing lxml dependency with the built-in xml module. This preprocessing syntax style is not very common, but is similar to the one provided by WiX (https://wixtoolset.org/docs/v3/overview/preprocessor/) or wixl, that we adopted in QEMU for packaging the guest agent. Signed-off-by: Marc-André Lureau Message-Id: <20230606115658.677673-5-marcandre.lureau@redhat.com> --- scripts/xml-preprocess-test.py | 136 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 scripts/xml-preprocess-test.py (limited to 'scripts/xml-preprocess-test.py') diff --git a/scripts/xml-preprocess-test.py b/scripts/xml-preprocess-test.py new file mode 100644 index 0000000000..dd92579969 --- /dev/null +++ b/scripts/xml-preprocess-test.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2023 Red Hat, Inc. +# +# SPDX-License-Identifier: MIT +"""Unit tests for xml-preprocess""" + +import contextlib +import importlib +import os +import platform +import subprocess +import tempfile +import unittest +from io import StringIO + +xmlpp = importlib.import_module("xml-preprocess") + + +class TestXmlPreprocess(unittest.TestCase): + """Tests for xml-preprocess.Preprocessor""" + + def test_preprocess_xml(self): + with tempfile.NamedTemporaryFile(mode="w", delete=False) as temp_file: + temp_file.write("") + temp_file_name = temp_file.name + result = xmlpp.preprocess_xml(temp_file_name) + self.assertEqual(result, "") + os.remove(temp_file_name) + + def test_save_xml(self): + with tempfile.NamedTemporaryFile(mode="w", delete=False) as temp_file: + temp_file_name = temp_file.name + xmlpp.save_xml("", temp_file_name) + self.assertTrue(os.path.isfile(temp_file_name)) + os.remove(temp_file_name) + + def test_include(self): + with tempfile.NamedTemporaryFile(mode="w", delete=False) as inc_file: + inc_file.write("Content from included file") + inc_file_name = inc_file.name + xml_str = f"" + expected = "Content from included file" + xpp = xmlpp.Preprocessor() + result = xpp.preprocess(xml_str) + self.assertEqual(result, expected) + os.remove(inc_file_name) + self.assertRaises(FileNotFoundError, xpp.preprocess, xml_str) + + def test_envvar(self): + os.environ["TEST_ENV_VAR"] = "TestValue" + xml_str = "$(env.TEST_ENV_VAR)" + expected = "TestValue" + xpp = xmlpp.Preprocessor() + result = xpp.preprocess(xml_str) + self.assertEqual(result, expected) + self.assertRaises(KeyError, xpp.preprocess, "$(env.UNKNOWN)") + + def test_sys_var(self): + xml_str = "$(sys.ARCH)" + expected = f"{platform.architecture()[0]}" + xpp = xmlpp.Preprocessor() + result = xpp.preprocess(xml_str) + self.assertEqual(result, expected) + self.assertRaises(KeyError, xpp.preprocess, "$(sys.UNKNOWN)") + + def test_cus_var(self): + xml_str = "$(var.USER)" + expected = "" + xpp = xmlpp.Preprocessor() + result = xpp.preprocess(xml_str) + self.assertEqual(result, expected) + xml_str = "$(var.USER)" + expected = "FOO" + xpp = xmlpp.Preprocessor() + result = xpp.preprocess(xml_str) + self.assertEqual(result, expected) + + def test_error_warning(self): + xml_str = "" + expected = "" + xpp = xmlpp.Preprocessor() + out = StringIO() + with contextlib.redirect_stdout(out): + result = xpp.preprocess(xml_str) + self.assertEqual(result, expected) + self.assertEqual(out.getvalue(), "[Warning]: test warn\n") + self.assertRaises(RuntimeError, xpp.preprocess, "") + + def test_cmd(self): + xpp = xmlpp.Preprocessor() + result = xpp.preprocess('') + self.assertEqual(result, "hello world") + self.assertRaises( + subprocess.CalledProcessError, + xpp.preprocess, '' + ) + + def test_foreach(self): + xpp = xmlpp.Preprocessor() + result = xpp.preprocess( + '$(var.x)' + ) + self.assertEqual(result, "abc") + + def test_if_elseif(self): + xpp = xmlpp.Preprocessor() + result = xpp.preprocess('ok') + self.assertEqual(result, "ok") + result = xpp.preprocess('ok') + self.assertEqual(result, "") + result = xpp.preprocess('okko') + self.assertEqual(result, "ok") + result = xpp.preprocess('okko') + self.assertEqual(result, "ko") + result = xpp.preprocess( + 'okok2ko' + ) + self.assertEqual(result, "ok2") + result = xpp.preprocess( + 'okokko' + ) + self.assertEqual(result, "ko") + + def test_ifdef(self): + xpp = xmlpp.Preprocessor() + result = xpp.preprocess('okko') + self.assertEqual(result, "ko") + result = xpp.preprocess( + 'okko' + ) + self.assertEqual(result, "ok") + + +if __name__ == "__main__": + unittest.main() -- cgit 1.4.1