Add a new cnfvar2 API
[pyi2ncommon] / test / cnfvar / test_binary.py
1 # The software in this package is distributed under the GNU General
2 # Public License version 2 (with a special exception described below).
3 #
4 # A copy of GNU General Public License (GPL) is included in this distribution,
5 # in the file COPYING.GPL.
6 #
7 # As a special exception, if other files instantiate templates or use macros
8 # or inline functions from this file, or you compile this file and link it
9 # with other works to produce a work based on this file, this file
10 # does not by itself cause the resulting work to be covered
11 # by the GNU General Public License.
12 #
13 # However the source code for this file must still be made available
14 # in accordance with section (3) of the GNU General Public License.
15 #
16 # This exception does not invalidate any other reasons why a work based
17 # on this file might be covered by the GNU General Public License.
18 #
19 # Copyright (c) 2016-2022 Intra2net AG <info@intra2net.com>
20
21 """
22 test_binary.py: unit tests for cnfvar/binary.py.
23
24 Tests classes and functions in cnfvar/binary.py
25
26 For help see :py:mod:`unittest`
27 """
28
29 import unittest
30 from textwrap import dedent
31 from types import SimpleNamespace
32 from unittest.mock import patch, ANY
33
34 from src.cnfvar import binary
35 from src.cnfvar.binary import CnfBinary
36
37
38 class CnfBinaryTest(unittest.TestCase):
39     """Test class CnfBinary."""
40
41     #: return value for the run method
42     CMD_STDOUT = ""
43     CMD_STDERR = ""
44
45     def setUp(self):
46         """Set up mocks."""
47         self.CMD_STDOUT = ""
48         self.CMD_STDERR = ""
49         self._proc_patch = patch.object(binary.subprocess, "run", side_effect=self._fake_subprocess_run)
50         self._proc_mock = self._proc_patch.start()
51
52     def tearDown(self):
53         """Clean up mocks."""
54         self._proc_patch.stop()
55         self._proc_mock = None
56         self.CMD_STDOUT = ""
57         self.CMD_STDERR = ""
58
59     def test_basic_get_cnf(self):
60         """Tests basic functionality of the get_cnf wrapper."""
61         self.CMD_STDOUT = dedent("""\
62             1 USER,1: "jake"
63             2    (1) USER_DISABLED,0: "0"
64             3    (1) USER_FULLNAME,0: "Jake"
65             4    (1) USER_GROUPWARE_FOLDER_DRAFTS,0: "INBOX/Entwürfe"
66             5    (1) USER_GROUPWARE_FOLDER_OUTBOX,0: "INBOX/Gesendete Objekte"
67             6    (1) USER_GROUPWARE_FOLDER_TRASH,0: "INBOX/Gelöschte Elemente"
68             7    (1) USER_GROUP_MEMBER_REF,0: "100"
69             8    (1) USER_GROUP_MEMBER_REF,1: "2"
70             9    (1) USER_PASSWORD,0: "test1234"
71             11 USER,2: "jill"
72             12    (11) USER_DISABLED,0: "0"
73             13    (11) USER_FULLNAME,0: "Jill"
74             14    (11) USER_GROUPWARE_FOLDER_DRAFTS,0: "INBOX/Entwürfe"
75             15    (11) USER_GROUPWARE_FOLDER_OUTBOX,0: "INBOX/Gesendete Objekte"
76             16    (11) USER_GROUPWARE_FOLDER_TRASH,0: "INBOX/Gelöschte Elemente"
77             17    (11) USER_GROUP_MEMBER_REF,0: "100"
78             18    (11) USER_GROUP_MEMBER_REF,1: "2"
79             19    (11) USER_PASSWORD,0: "test1234"
80             """)
81
82         output = CnfBinary.get_cnf("USER", 10)
83         self.assertEqual(self.CMD_STDOUT.splitlines(), output.splitlines())
84         self._proc_mock.assert_called_once_with(["/usr/intranator/bin/get_cnf", "USER", "10"],
85                                                 input=ANY, check=ANY, capture_output=ANY,
86                                                 encoding='latin1', timeout=ANY)
87
88     def test_get_cnf_error_handling(self):
89         """Test that the get cnf method does some sanity checks."""
90         # cannot pass an instance without a name
91         with self.assertRaises(ValueError):
92             CnfBinary.get_cnf(None, 10)
93
94         # cannot pass an instance of an invalid type
95         with self.assertRaises(TypeError):
96             CnfBinary.get_cnf("USER", 18.45)
97
98     def test_basic_set_cnf(self):
99         """Test basic set cnf operation."""
100         input_str = """\
101             1  FIREWALL_SERVICEGROUP,1: "http"
102             2     (1) FIREWALL_SERVICEGROUP_PREDEFINED_ID,0: "1"
103             3     (1) FIREWALL_SERVICEGROUP_TYPE,0: "TCP"
104             4        (3) FIREWALL_SERVICEGROUP_TYPE_COMMENT,0: ""
105             5        (3) FIREWALL_SERVICEGROUP_TYPE_TCPUDP_DST_PORT,0: "80"
106         """
107
108         CnfBinary.set_cnf(input_str)
109         self._proc_mock.assert_called_once_with(
110             ["/usr/intranator/bin/set_cnf"],
111             input=input_str, check=ANY, capture_output=ANY,
112             encoding="latin1", timeout=ANY)
113
114     def test_set_cnf_extra_args(self):
115         """Test that we can pass extra arguments to the set_cnf binary."""
116         input_str = """\
117         {
118             "cnf" :
119             [
120                 {
121                     "data" : "0",
122                     "instance" : 0,
123                     "number" : 1,
124                     "varname" : "ACME_DEBUG_ENABLE"
125                 }
126             ]
127         }
128         """
129
130         CnfBinary.set_cnf(input_str, as_json=True, fix_problems=True, discard_queue=True)
131         self._proc_mock.assert_called_once_with(
132             ["/usr/intranator/bin/set_cnf", "--json", "--fix-problems", "--discard-queue"],
133             input=input_str, check=ANY, capture_output=ANY,
134             encoding="utf8", timeout=ANY)
135
136     def _fake_subprocess_run(self, *args, **kwargs):
137         return SimpleNamespace(args=args[0], stdout=self.CMD_STDOUT,
138                                stderr=self.CMD_STDERR, returncode=0)
139
140
141 if __name__ == '__main__':
142     unittest.main()