1#!/usr/bin/env python3
2#
3# Copyright (c) 2023 Red Hat, Inc.
4#
5# SPDX-License-Identifier: MIT
6"""Unit tests for xml-preprocess"""
7
8import contextlib
9import importlib
10import os
11import platform
12import subprocess
13import tempfile
14import unittest
15from io import StringIO
16
17xmlpp = importlib.import_module("xml-preprocess")
18
19
20class TestXmlPreprocess(unittest.TestCase):
21    """Tests for xml-preprocess.Preprocessor"""
22
23    def test_preprocess_xml(self):
24        with tempfile.NamedTemporaryFile(mode="w", delete=False) as temp_file:
25            temp_file.write("<root></root>")
26            temp_file_name = temp_file.name
27        result = xmlpp.preprocess_xml(temp_file_name)
28        self.assertEqual(result, "<root></root>")
29        os.remove(temp_file_name)
30
31    def test_save_xml(self):
32        with tempfile.NamedTemporaryFile(mode="w", delete=False) as temp_file:
33            temp_file_name = temp_file.name
34            xmlpp.save_xml("<root></root>", temp_file_name)
35        self.assertTrue(os.path.isfile(temp_file_name))
36        os.remove(temp_file_name)
37
38    def test_include(self):
39        with tempfile.NamedTemporaryFile(mode="w", delete=False) as inc_file:
40            inc_file.write("<included>Content from included file</included>")
41            inc_file_name = inc_file.name
42        xml_str = f"<?include {inc_file_name} ?>"
43        expected = "<included>Content from included file</included>"
44        xpp = xmlpp.Preprocessor()
45        result = xpp.preprocess(xml_str)
46        self.assertEqual(result, expected)
47        os.remove(inc_file_name)
48        self.assertRaises(FileNotFoundError, xpp.preprocess, xml_str)
49
50    def test_envvar(self):
51        os.environ["TEST_ENV_VAR"] = "TestValue"
52        xml_str = "<root>$(env.TEST_ENV_VAR)</root>"
53        expected = "<root>TestValue</root>"
54        xpp = xmlpp.Preprocessor()
55        result = xpp.preprocess(xml_str)
56        self.assertEqual(result, expected)
57        self.assertRaises(KeyError, xpp.preprocess, "$(env.UNKNOWN)")
58
59    def test_sys_var(self):
60        xml_str = "<root>$(sys.ARCH)</root>"
61        expected = f"<root>{platform.architecture()[0]}</root>"
62        xpp = xmlpp.Preprocessor()
63        result = xpp.preprocess(xml_str)
64        self.assertEqual(result, expected)
65        self.assertRaises(KeyError, xpp.preprocess, "$(sys.UNKNOWN)")
66
67    def test_cus_var(self):
68        xml_str = "<root>$(var.USER)</root>"
69        expected = "<root></root>"
70        xpp = xmlpp.Preprocessor()
71        result = xpp.preprocess(xml_str)
72        self.assertEqual(result, expected)
73        xml_str = "<?define USER=FOO?><root>$(var.USER)</root>"
74        expected = "<root>FOO</root>"
75        xpp = xmlpp.Preprocessor()
76        result = xpp.preprocess(xml_str)
77        self.assertEqual(result, expected)
78
79    def test_error_warning(self):
80        xml_str = "<root><?warning \"test warn\"?></root>"
81        expected = "<root></root>"
82        xpp = xmlpp.Preprocessor()
83        out = StringIO()
84        with contextlib.redirect_stdout(out):
85            result = xpp.preprocess(xml_str)
86        self.assertEqual(result, expected)
87        self.assertEqual(out.getvalue(), "[Warning]: test warn\n")
88        self.assertRaises(RuntimeError, xpp.preprocess, "<?error \"test\"?>")
89
90    def test_cmd(self):
91        xpp = xmlpp.Preprocessor()
92        result = xpp.preprocess('<root><?cmd "echo hello world"?></root>')
93        self.assertEqual(result, "<root>hello world</root>")
94        self.assertRaises(
95            subprocess.CalledProcessError,
96            xpp.preprocess, '<?cmd "test-unknown-cmd"?>'
97        )
98
99    def test_foreach(self):
100        xpp = xmlpp.Preprocessor()
101        result = xpp.preprocess(
102            '<root><?foreach x in a;b;c?>$(var.x)<?endforeach?></root>'
103        )
104        self.assertEqual(result, "<root>abc</root>")
105
106    def test_if_elseif(self):
107        xpp = xmlpp.Preprocessor()
108        result = xpp.preprocess('<root><?if True?>ok<?endif?></root>')
109        self.assertEqual(result, "<root>ok</root>")
110        result = xpp.preprocess('<root><?if False?>ok<?endif?></root>')
111        self.assertEqual(result, "<root></root>")
112        result = xpp.preprocess('<root><?if True?>ok<?else?>ko<?endif?></root>')
113        self.assertEqual(result, "<root>ok</root>")
114        result = xpp.preprocess('<root><?if False?>ok<?else?>ko<?endif?></root>')
115        self.assertEqual(result, "<root>ko</root>")
116        result = xpp.preprocess(
117            '<root><?if False?>ok<?elseif True?>ok2<?else?>ko<?endif?></root>'
118        )
119        self.assertEqual(result, "<root>ok2</root>")
120        result = xpp.preprocess(
121            '<root><?if False?>ok<?elseif False?>ok<?else?>ko<?endif?></root>'
122        )
123        self.assertEqual(result, "<root>ko</root>")
124
125    def test_ifdef(self):
126        xpp = xmlpp.Preprocessor()
127        result = xpp.preprocess('<root><?ifdef USER?>ok<?else?>ko<?endif?></root>')
128        self.assertEqual(result, "<root>ko</root>")
129        result = xpp.preprocess(
130            '<?define USER=FOO?><root><?ifdef USER?>ok<?else?>ko<?endif?></root>'
131        )
132        self.assertEqual(result, "<root>ok</root>")
133
134
135if __name__ == "__main__":
136    unittest.main()
137