Merge "Add scale out TCs with availability zone support"
[yardstick.git] / yardstick / tests / unit / network_services / helpers / test_iniparser.py
1 # Copyright (c) 2017 Intel Corporation
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain 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,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 #
15
16 import unittest
17 from contextlib import contextmanager
18 import mock
19
20 from yardstick.tests import STL_MOCKS
21
22
23 STLClient = mock.MagicMock()
24 stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
25 stl_patch.start()
26
27 if stl_patch:
28     from yardstick.network_services.helpers.iniparser import ParseError
29     from yardstick.network_services.helpers.iniparser import LineParser
30     from yardstick.network_services.helpers.iniparser import BaseParser
31     from yardstick.network_services.helpers.iniparser import ConfigParser
32
33 PARSE_TEXT_1 = """\
34
35 [section1]
36 key1=value1
37 list1: value2
38        value3
39        value4
40 key3='single quote value'  ; comment here
41 key4=
42
43 [section2]  ; comment with #2 other symbol
44 # here is a comment line
45 list2: value5
46 key with no value  # mixed comment ; symbols
47 ; another comment line
48 key5=
49
50 [section1]  ; reopen a section!
51 key2="double quote value"
52 """
53
54 PARSE_TEXT_2 = """\
55 [section1]
56 list1 = item1
57         item2
58         ended by eof"""
59
60 PARSE_TEXT_BAD_1 = """\
61 key1=value1
62 """
63
64 PARSE_TEXT_BAD_2 = """\
65 [section1
66 """
67
68 PARSE_TEXT_BAD_3 = """\
69 []
70 """
71
72 PARSE_TEXT_BAD_4 = """\
73 [section1]
74     bad continuation
75 """
76
77 PARSE_TEXT_BAD_5 = """\
78 [section1]
79 =value with no key
80 """
81
82
83 class TestParseError(unittest.TestCase):
84
85     def test___str__(self):
86         error = ParseError('a', 2, 'c')
87         self.assertEqual(str(error), "at line 2, a: 'c'")
88
89
90 class TestLineParser(unittest.TestCase):
91
92     def test___repr__(self):
93         line_parser = LineParser('', 101)
94         self.assertIsNotNone(repr(line_parser))
95
96     def test_error_invalid_assignment(self):
97         line_parser = LineParser('', 101)
98         self.assertIsNotNone(line_parser.error_invalid_assignment())
99
100
101 class TestBaseParser(unittest.TestCase):
102
103     @staticmethod
104     def make_open(text_blob):
105         @contextmanager
106         def internal_open(*args):
107             yield text_blob.split('\n')
108
109         return internal_open
110
111     def test_parse(self):
112         parser = BaseParser()
113         parser.parse()
114
115     def test_parse_empty_string(self):
116         parser = BaseParser()
117         self.assertIsNone(parser.parse(''))
118
119     def test_not_implemented_methods(self):
120         parser = BaseParser()
121
122         with self.assertRaises(NotImplementedError):
123             parser.assignment('key', 'value', LineParser('', 100))
124
125         with self.assertRaises(NotImplementedError):
126             parser.new_section('section')
127
128         with self.assertRaises(NotImplementedError):
129             parser.comment('comment')
130
131
132 class TestConfigParser(unittest.TestCase):
133
134     @staticmethod
135     def make_open(text_blob):
136         @contextmanager
137         def internal_open(*args):
138             yield text_blob.split('\n')
139
140         return internal_open
141
142     @mock.patch('yardstick.network_services.helpers.iniparser.open')
143     def test_parse(self, mock_open):
144         mock_open.side_effect = self.make_open(PARSE_TEXT_1)
145
146         existing_data = [['section0', [['key0', 'value0']]]]
147         config_parser = ConfigParser('my_file', existing_data)
148         config_parser.parse()
149
150         expected = [
151             [
152                 'section0',
153                 [
154                     ['key0', 'value0'],
155                 ],
156             ],
157             [
158                 'section1',
159                 [
160                     ['key1', 'value1'],
161                     ['list1', 'value2\nvalue3\nvalue4'],
162                     ['key3', 'single quote value'],
163                     ['key4', ''],
164                     ['key2', 'double quote value'],
165                 ],
166             ],
167             [
168                 'section2',
169                 [
170                     ['list2', 'value5'],
171                     ['key with no value', '@'],
172                     ['key5', ''],
173                 ],
174             ],
175         ]
176
177         self.assertEqual(config_parser.sections, expected)
178         self.assertIsNotNone(config_parser.find_section('section1'))
179         self.assertIsNone(config_parser.find_section('section3'))
180         self.assertEqual(config_parser.find_section_index('section1'), 1)
181         self.assertEqual(config_parser.find_section_index('section3'), -1)
182
183     @mock.patch('yardstick.network_services.helpers.iniparser.open')
184     def test_parse_2(self, mock_open):
185         mock_open.side_effect = self.make_open(PARSE_TEXT_2)
186
187         config_parser = ConfigParser('my_file')
188         config_parser.parse()
189
190         expected = [
191             [
192                 'section1',
193                 [
194                     ['list1', 'item1\nitem2\nended by eof'],
195                 ],
196             ],
197         ]
198
199         self.assertEqual(config_parser.sections, expected)
200
201     @mock.patch('yardstick.network_services.helpers.iniparser.open')
202     def test_parse_negative(self, mock_open):
203         bad_text_dict = {
204             'no section': PARSE_TEXT_BAD_1,
205             'incomplete section': PARSE_TEXT_BAD_2,
206             'empty section name': PARSE_TEXT_BAD_3,
207             'bad_continuation': PARSE_TEXT_BAD_4,
208             'value with no key': PARSE_TEXT_BAD_5,
209         }
210
211         for bad_reason, bad_text in bad_text_dict.items():
212             mock_open.side_effect = self.make_open(bad_text)
213
214             config_parser = ConfigParser('my_file', [])
215
216             try:
217                 # TODO: replace with assertRaises, when the UT framework supports
218                 # advanced messages when exceptions fail to occur
219                 config_parser.parse()
220             except ParseError:
221                 pass
222             else:
223                 self.fail('\n'.join([bad_reason, bad_text, str(config_parser.sections)]))