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