Pin pip to 20.3.3 and disable tmpfs in DIB
[ta/build-tools.git] / tools / convert_test.py
1 # Copyright 2019 Nokia
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 # pylint: disable=invalid-name
16 from collections import OrderedDict
17
18 import pytest
19
20 from tools.convert import to_json, CsvConverter
21
22
23 class TestJson(object):
24     @staticmethod
25     def test_json():
26         _input = dict(b=1, a=2)
27         expected = '\n'.join(['{',
28                               '    "a": 2, ',
29                               '    "b": 1',
30                               '}'])
31         assert to_json(_input) == expected
32
33
34 class TestCsv(object):
35     @staticmethod
36     @pytest.mark.parametrize('_input, expected', [
37         ([], ''),
38         ([{}], '\r\n'),
39         ([dict(a=1)], '\r\n'.join(['"a"',
40                                    '"1"'])),
41         ([dict(a=1), dict(a=2)], '\r\n'.join(['"a"',
42                                               '"1"',
43                                               '"2"'])),
44         ([dict(a=1, b=2), dict(a=3, b=4)], '\r\n'.join(['"a","b"',
45                                                         '"1","2"',
46                                                         '"3","4"'])),
47         ([dict(x=OrderedDict({'b': 1, 'a': 2})),
48           dict(x={'a': 2, 'b': 1})], '\r\n'.join(['"x"',
49                                                   '"{""a"": 2, ""b"": 1}"',
50                                                   '"{""a"": 2, ""b"": 1}"']))
51
52     ])
53     def test_csv(_input, expected):
54         assert str(CsvConverter(_input)) == expected
55
56     @staticmethod
57     def test_str():
58         _input = [dict(a=1)]
59         assert str(CsvConverter(_input)) == CsvConverter(_input).convert()
60
61     @staticmethod
62     @pytest.mark.parametrize('_input, exception_re', [
63         ('boom', r'NOT a list'),
64         ([['boom']], r'NOT a dict')
65     ])
66     def test_to_csv_fail(_input, exception_re):
67         with pytest.raises(Exception, match=exception_re):
68             str(CsvConverter(_input))
69
70     @staticmethod
71     def test_newlines_are_escaped():
72         """
73         ...in order to get properly formatted file when written
74         """
75         _input = [dict(a='1"2')]
76         expected = '\r\n'.join(['"a"',
77                                 '"1""2"'])
78         assert CsvConverter(_input).convert() == expected
79
80     @staticmethod
81     def test_missing_fields_are_filled_with_none():
82         _input = [dict(a='1"2')]
83         expected = '\r\n'.join(['"a"',
84                                 '"1""2"'])
85         assert CsvConverter(_input).convert() == expected
86
87     @staticmethod
88     def test_double_quote_is_escaped_with_double_quote():
89         """
90         RFC 4180
91         """
92         _input = [dict(a='1"2')]
93         expected = '\r\n'.join(['"a"',
94                                 '"1""2"'])
95         assert CsvConverter(_input).convert() == expected
96
97     @staticmethod
98     @pytest.mark.parametrize('_input, expected', [
99         ([dict(a=1, b=2)], '\r\n'.join(['"b","a"', '"2","1"'])),
100         ([dict(a=1, c=2)], '\r\n'.join(['"a","c"', '"1","2"']))
101     ])
102     def test_csv_preferred_order(_input, expected):
103         assert CsvConverter(_input, preferred_field_order=['b', 'a']).convert() == expected
104
105     @staticmethod
106     @pytest.mark.parametrize('_input, expected', [
107         ([dict(a='Copyright \xc2\xa9 2014')], '\r\n'.join(['"a"',
108                                                            '"Copyright \xc2\xa9 2014"'])),
109         ([dict(a=u'Copyright \xa9 2014')], '\r\n'.join(['"a"',
110                                                         '"Copyright \xc2\xa9 2014"'])),
111     ])
112     def test_unicode_input(_input, expected):
113         assert str(CsvConverter(_input)) == expected
114
115
116 class TestCsvMSExcel(object):
117     @staticmethod
118     def test_ms_excel_format():
119         """
120         MS Excel treats CSV files with 'sep=,' as the first line to get automatically columnized
121         """
122         _input = [dict(a=1, b=2)]
123         expected = '\r\n'.join(['sep=,',
124                                 '"a","b"',
125                                 '"1","2"'])
126         assert CsvConverter(_input).convert_to_ms_excel() == expected
127
128     @staticmethod
129     def test_text_fields():
130         """
131         MS Excel CSV fields prefixed with '=' will be treated as equations to string.
132         This makes it possible to e.g. to have all RPM version strings treated equally instead
133         of making some of them treated as generic and some of them as integers.
134         """
135         _input = [dict(a=1, b=2)]
136         expected = '\r\n'.join(['sep=,',
137                                 '"a",="b"',
138                                 '"1",="2"'])
139         assert CsvConverter(_input).convert_to_ms_excel(text_fields=['b']) == expected
140
141     @staticmethod
142     def test_field_with_beginning_minus_is_prefixed():
143         """
144         MS Excel CSV fields beginning with '-' are treated as an equation even they would be
145         essentially just strings. Make sure to escape the beginning signs with something in order
146         not to get field braking equation.
147         """
148         _input = [dict(a=-1), dict(a="-2a")]
149         expected = '\r\n'.join(['sep=,',
150                                 '"a"',
151                                 '"-1"',
152                                 r'"\-2a"'])
153         assert CsvConverter(_input).convert_to_ms_excel() == expected
154
155     @staticmethod
156     def test_too_big_cell_is_truncated():
157         """
158         MS Excel has ~32k character limit per cell. BOM information can easily exceed this.
159         """
160         _input = [dict(a='1' * 32000), dict(a='2' * 32001)]
161         expected = '\r\n'.join(['sep=,',
162                                 '"a"',
163                                 '"{}"'.format('1' * 32000),
164                                 '"{}...{}"'.format('2' * 16000, '2' * 16000)])
165         assert CsvConverter(_input).convert_to_ms_excel() == expected