Browse Source

Unit testing for ini

- modifies custom module ini.py in such a way that its individual
  stages can be easily tested
- tests for this module (test_ini.py) are created

Change-Id: I0250837cc97705a7eb9eb81395aaeba86292bc89
Partial-Bug: #1594785
(cherry picked from commit dcb49e2ee0)
tags/7.4.8^2
Katerina Pilatova 1 year ago
parent
commit
4c7e5b1bc0
2 changed files with 197 additions and 27 deletions
  1. 127
    0
      tripleo_validations/tests/test_ini.py
  2. 70
    27
      validations/library/ini.py

+ 127
- 0
tripleo_validations/tests/test_ini.py View File

@@ -0,0 +1,127 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+# not use this file except in compliance with the License. You may obtain
5
+# a copy of the License at
6
+#
7
+#      http://www.apache.org/licenses/LICENSE-2.0
8
+#
9
+# Unless required by applicable law or agreed to in writing, software
10
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+# License for the specific language governing permissions and limitations
13
+# under the License.
14
+
15
+"""
16
+test_ini
17
+----------------------------------
18
+
19
+Tests for `ini` module.
20
+"""
21
+
22
+
23
+import os
24
+import tempfile
25
+
26
+from tripleo_validations.tests import base
27
+import validations.library.ini as validation
28
+
29
+
30
+invalid_content = '''
31
+[DEFAULT#
32
+    hello =
33
+'''
34
+
35
+valid_content = '''
36
+[DEFAULT]
37
+debug=True
38
+
39
+[dhcp]
40
+dhcp_start=192.168.0.1
41
+dhcp_end=192.168.0.254
42
+
43
+[secrets]
44
+password=1234
45
+'''
46
+
47
+
48
+class TestIni(base.TestCase):
49
+
50
+    def test_check_file_invalid_path(self):
51
+        '''Test ini when path is invalid'''
52
+
53
+        msg = validation.check_file('non/existing/path', False)
54
+        self.assertEqual("Could not open the ini file: 'non/existing/path'",
55
+                         msg)
56
+
57
+    def test_check_file_ignore_missing(self):
58
+        '''Test ini when ignoring missing files'''
59
+
60
+        msg = validation.check_file('non/existing/path', True)
61
+        self.assertEqual("Could not open the ini file: 'non/existing/path'",
62
+                         msg)
63
+
64
+    def test_check_file_valid_path(self):
65
+        '''Test ini when path is valid'''
66
+
67
+        tmpfile = self.create_tmp_ini()
68
+        tmp_name = os.path.relpath(tmpfile.name)
69
+        msg = validation.check_file(tmp_name, False)
70
+        tmpfile.close()
71
+
72
+        self.assertEqual('', msg)
73
+
74
+    def test_get_result_invalid_format(self):
75
+        '''Test ini when file format is valid'''
76
+
77
+        tmpfile = self.create_tmp_ini()
78
+        tmp_name = os.path.relpath(tmpfile.name)
79
+        tmpfile.write(invalid_content.encode('utf-8'))
80
+        tmpfile.seek(0)
81
+        ret, msg, value = validation.get_result(tmp_name, 'section', 'key')
82
+        tmpfile.close()
83
+
84
+        self.assertEqual(validation.ReturnValue.INVALID_FORMAT, ret)
85
+        self.assertEqual("The file '{}' is not in a valid INI format.".format(
86
+                         tmp_name), msg)
87
+        self.assertIsNone(value)
88
+
89
+    def test_get_result_key_not_found(self):
90
+        '''Test ini when key is not found'''
91
+
92
+        tmpfile = self.create_tmp_ini()
93
+        tmp_name = os.path.relpath(tmpfile.name)
94
+        tmpfile.write(valid_content.encode('utf-8'))
95
+        tmpfile.seek(0)
96
+        ret, msg, value = validation.get_result(tmp_name, 'section', 'key')
97
+        tmpfile.close()
98
+
99
+        self.assertEqual(validation.ReturnValue.KEY_NOT_FOUND, ret)
100
+        self.assertEqual(("There is no key 'key' under the section 'section' "
101
+                          "in file {}.").format(tmp_name), msg)
102
+        self.assertIsNone(value)
103
+
104
+    def test_get_result_ok(self):
105
+        '''Test ini when key is not found'''
106
+
107
+        tmpfile = self.create_tmp_ini()
108
+        tmp_name = os.path.relpath(tmpfile.name)
109
+        tmpfile.write(valid_content.encode('utf-8'))
110
+        tmpfile.seek(0)
111
+        ret, msg, value = validation.get_result(tmp_name, 'secrets',
112
+                                                'password')
113
+        tmpfile.close()
114
+
115
+        self.assertEqual(validation.ReturnValue.OK, ret)
116
+        self.assertEqual(("The key 'password' under the section 'secrets'"
117
+                          " in file {} has the value: '1234'").format(
118
+                         tmp_name), msg)
119
+        self.assertEqual('1234', value)
120
+
121
+    def create_tmp_ini(self):
122
+        '''Create temporary tmp.ini file, return its full name'''
123
+
124
+        path = 'tripleo_validations/tests'
125
+        tmpfile = tempfile.NamedTemporaryFile(suffix='.ini', prefix='tmp',
126
+                                              dir=path)
127
+        return tmpfile

+ 70
- 27
validations/library/ini.py View File

@@ -25,11 +25,60 @@
25 25
 #
26 26
 # You can register the result and use it later with `{{ my_ini.value }}`
27 27
 
28
-import ConfigParser
29
-from os import path
28
+try:
29
+    import configparser as ConfigParser
30
+except ImportError:
31
+    import ConfigParser
32
+
33
+from enum import Enum
34
+import os
30 35
 
31 36
 from ansible.module_utils.basic import *  # NOQA
32 37
 
38
+
39
+# Possible return values
40
+class ReturnValue(Enum):
41
+    OK = 0
42
+    INVALID_FORMAT = 1
43
+    KEY_NOT_FOUND = 2
44
+
45
+
46
+def check_file(path, ignore_missing):
47
+    '''Validate entered path'''
48
+
49
+    if not (os.path.exists(path) and os.path.isfile(path)):
50
+        return "Could not open the ini file: '{}'".format(path)
51
+    else:
52
+        return ''
53
+
54
+
55
+def get_result(path, section, key):
56
+    '''Get value based on section and key'''
57
+
58
+    msg = ''
59
+    value = None
60
+    config = ConfigParser.SafeConfigParser()
61
+
62
+    try:
63
+        config.read(path)
64
+    except Exception:
65
+        msg = "The file '{}' is not in a valid INI format.".format(path)
66
+        ret = ReturnValue.INVALID_FORMAT
67
+        return (ret, msg, value)
68
+
69
+    try:
70
+        value = config.get(section, key)
71
+        msg = ("The key '{}' under the section '{}' in file {} "
72
+               "has the value: '{}'").format(key, section, path, value)
73
+        ret = ReturnValue.OK
74
+        return (ret, msg, value)
75
+    except ConfigParser.Error:
76
+        value = None
77
+        msg = "There is no key '{}' under the section '{}' in file {}.".format(
78
+              key, section, path)
79
+        ret = ReturnValue.KEY_NOT_FOUND
80
+        return (ret, msg, value)
81
+
33 82
 DOCUMENTATION = '''
34 83
 ---
35 84
 module: ini
@@ -77,36 +126,30 @@ def main():
77 126
     ))
78 127
 
79 128
     ini_file_path = module.params.get('path')
129
+    ignore_missing = module.params.get('ignore_missing_file')
80 130
 
81
-    if path.exists(ini_file_path) and path.isfile(ini_file_path):
82
-        config = ConfigParser.SafeConfigParser()
83
-        try:
84
-            config.read(ini_file_path)
85
-        except Exception:
86
-            module.fail_json(msg="The file '{}' is not in a valid INI format."
87
-                             .format(ini_file_path))
131
+    # Check that file exists
132
+    msg = check_file(ini_file_path, ignore_missing)
88 133
 
134
+    if msg != '':
135
+        # Opening file failed
136
+        if ignore_missing:
137
+            module.exit_json(msg=msg, changed=False, value=None)
138
+        else:
139
+            module.fail_json(msg=msg)
140
+    else:
141
+        # Try to parse the result from ini file
89 142
         section = module.params.get('section')
90 143
         key = module.params.get('key')
91
-        try:
92
-            value = config.get(section, key)
93
-            msg = ("The key '{}' under the section '{}' in file {} "
94
-                   "has the value: '{}'"
95
-                   .format(key, section, ini_file_path, value))
96
-            module.exit_json(msg=msg, changed=False, value=value)
97
-        except ConfigParser.Error:
98
-            msg = ("There is no key '{}' under the section '{}' in file {}."
99
-                   .format(key, section, ini_file_path))
100
-            module.exit_json(msg=msg, changed=False, value=None)
101 144
 
102
-    else:
103
-        missing_file_message = "Could not open the ini file: '{}'".format(
104
-            ini_file_path)
105
-        if module.params.get('ignore_missing_file'):
106
-            module.exit_json(msg=missing_file_message, changed=False,
107
-                             value=None)
108
-        else:
109
-            module.fail_json(msg=missing_file_message)
145
+        ret, msg, value = get_result(ini_file_path, section, key)
146
+
147
+        if ret == ReturnValue.INVALID_FORMAT:
148
+            module.fail_json(msg=msg)
149
+        elif ret == ReturnValue.KEY_NOT_FOUND:
150
+            module.exit_json(msg=msg, changed=False, value=None)
151
+        elif ret == ReturnValue.OK:
152
+            module.exit_json(msg=msg, changed=False, value=value)
110 153
 
111 154
 
112 155
 if __name__ == '__main__':

Loading…
Cancel
Save