1 # Copyright 2016 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
13 class UnitTest(unittest.TestCase):
14 def test_ToGNString(self):
16 (42, '42', '42'), ('foo', '"foo"', '"foo"'), (True, 'true', 'true'),
17 (False, 'false', 'false'), ('', '""', '""'),
18 ('\\$"$\\', '"\\\\\\$\\"\\$\\\\"', '"\\\\\\$\\"\\$\\\\"'),
19 (' \t\r\n', '" $0x09$0x0D$0x0A"', '" $0x09$0x0D$0x0A"'),
20 (u'\u2713', '"$0xE2$0x9C$0x93"', '"$0xE2$0x9C$0x93"'),
21 ([], '[ ]', '[]'), ([1], '[ 1 ]', '[\n 1\n]\n'),
22 ([3, 1, 4, 1], '[ 3, 1, 4, 1 ]', '[\n 3,\n 1,\n 4,\n 1\n]\n'),
23 (['a', True, 2], '[ "a", true, 2 ]', '[\n "a",\n true,\n 2\n]\n'),
26 }, 'single = "item"\n', 'single = "item"\n'),
29 '_42A_Zaz_': [False, True]
30 }, '_42A_Zaz_ = [ false, true ]\nkEy = 137\n',
31 '_42A_Zaz_ = [\n false,\n true\n]\nkEy = 137\n'),
33 ['"thr,.$\\', True, False, [],
34 u'(\u2713)']], '[ 1, "two", [ "\\"thr,.\\$\\\\", true, false, ' +
35 '[ ], "($0xE2$0x9C$0x93)" ] ]', '''[
52 }, 'a = [ 3, "x" ]\nb = true\nn = 42\ns = "foo"\n',
53 'a = [\n 3,\n "x"\n]\nb = true\nn = 42\ns = "foo"\n'),
56 '[ [ [ ], [ [ ] ] ], [ ] ]',
57 '[\n [\n [],\n [\n []\n ]\n ],\n []\n]\n',
67 '[ { a = 1\nb = [ ]\nc = { z = 8 } } ]\n',
68 '[\n {\n a = 1\n b = []\n c = {\n' +
69 ' z = 8\n }\n }\n]\n',
72 for obj, exp_ugly, exp_pretty in test_cases:
73 out_ugly = gn_helpers.ToGNString(obj)
74 self.assertEqual(exp_ugly, out_ugly)
75 out_pretty = gn_helpers.ToGNString(obj, pretty=True)
76 self.assertEqual(exp_pretty, out_pretty)
78 def test_UnescapeGNString(self):
79 # Backslash followed by a \, $, or " means the folling character without
80 # the special meaning. Backslash followed by everything else is a literal.
82 gn_helpers.UnescapeGNString('\\as\\$\\\\asd\\"'),
85 def test_FromGNString(self):
87 gn_helpers.FromGNString('[1, -20, true, false,["as\\"", []]]'),
88 [ 1, -20, True, False, [ 'as"', [] ] ])
90 with self.assertRaises(gn_helpers.GNError):
91 parser = gn_helpers.GNValueParser('123 456')
94 def test_ParseBool(self):
95 parser = gn_helpers.GNValueParser('true')
96 self.assertEqual(parser.Parse(), True)
98 parser = gn_helpers.GNValueParser('false')
99 self.assertEqual(parser.Parse(), False)
101 def test_ParseNumber(self):
102 parser = gn_helpers.GNValueParser('123')
103 self.assertEqual(parser.ParseNumber(), 123)
105 with self.assertRaises(gn_helpers.GNError):
106 parser = gn_helpers.GNValueParser('')
108 with self.assertRaises(gn_helpers.GNError):
109 parser = gn_helpers.GNValueParser('a123')
112 def test_ParseString(self):
113 parser = gn_helpers.GNValueParser('"asdf"')
114 self.assertEqual(parser.ParseString(), 'asdf')
116 with self.assertRaises(gn_helpers.GNError):
117 parser = gn_helpers.GNValueParser('') # Empty.
119 with self.assertRaises(gn_helpers.GNError):
120 parser = gn_helpers.GNValueParser('asdf') # Unquoted.
122 with self.assertRaises(gn_helpers.GNError):
123 parser = gn_helpers.GNValueParser('"trailing') # Unterminated.
126 def test_ParseList(self):
127 parser = gn_helpers.GNValueParser('[1,]') # Optional end comma OK.
128 self.assertEqual(parser.ParseList(), [ 1 ])
130 with self.assertRaises(gn_helpers.GNError):
131 parser = gn_helpers.GNValueParser('') # Empty.
133 with self.assertRaises(gn_helpers.GNError):
134 parser = gn_helpers.GNValueParser('asdf') # No [].
136 with self.assertRaises(gn_helpers.GNError):
137 parser = gn_helpers.GNValueParser('[1, 2') # Unterminated
139 with self.assertRaises(gn_helpers.GNError):
140 parser = gn_helpers.GNValueParser('[1 2]') # No separating comma.
143 def test_ParseScope(self):
144 parser = gn_helpers.GNValueParser('{a = 1}')
145 self.assertEqual(parser.ParseScope(), {'a': 1})
147 with self.assertRaises(gn_helpers.GNError):
148 parser = gn_helpers.GNValueParser('') # Empty.
150 with self.assertRaises(gn_helpers.GNError):
151 parser = gn_helpers.GNValueParser('asdf') # No {}.
153 with self.assertRaises(gn_helpers.GNError):
154 parser = gn_helpers.GNValueParser('{a = 1') # Unterminated.
156 with self.assertRaises(gn_helpers.GNError):
157 parser = gn_helpers.GNValueParser('{"a" = 1}') # Not identifier.
159 with self.assertRaises(gn_helpers.GNError):
160 parser = gn_helpers.GNValueParser('{a = }') # No value.
163 def test_FromGNArgs(self):
164 # Booleans and numbers should work; whitespace is allowed works.
165 self.assertEqual(gn_helpers.FromGNArgs('foo = true\nbar = 1\n'),
166 {'foo': True, 'bar': 1})
168 # Whitespace is not required; strings should also work.
169 self.assertEqual(gn_helpers.FromGNArgs('foo="bar baz"'),
172 # Comments should work (and be ignored).
174 '# Top-level comment.',
176 'bar = 1 # In-line comment followed by whitespace.',
180 self.assertEqual(gn_helpers.FromGNArgs('\n'.join(gn_args_lines)), {
187 self.assertEqual(gn_helpers.FromGNArgs('foo=[1, 2, 3]'),
190 # Empty strings should return an empty dict.
191 self.assertEqual(gn_helpers.FromGNArgs(''), {})
192 self.assertEqual(gn_helpers.FromGNArgs(' \n '), {})
194 # Comments should work everywhere (and be ignored).
196 '# Top-level comment.',
198 '# Variable comment.',
201 ' # Value comment in list.',
206 'baz # Comment anywhere, really',
210 self.assertEqual(gn_helpers.FromGNArgs('\n'.join(gn_args_lines)), {
216 # Scope should be parsed, even empty ones.
228 self.assertEqual(gn_helpers.FromGNArgs('\n'.join(gn_args_lines)),
239 # Non-identifiers should raise an exception.
240 with self.assertRaises(gn_helpers.GNError):
241 gn_helpers.FromGNArgs('123 = true')
243 # References to other variables should raise an exception.
244 with self.assertRaises(gn_helpers.GNError):
245 gn_helpers.FromGNArgs('foo = bar')
247 # References to functions should raise an exception.
248 with self.assertRaises(gn_helpers.GNError):
249 gn_helpers.FromGNArgs('foo = exec_script("//build/baz.py")')
251 # Underscores in identifiers should work.
252 self.assertEqual(gn_helpers.FromGNArgs('_foo = true'),
254 self.assertEqual(gn_helpers.FromGNArgs('foo_bar = true'),
256 self.assertEqual(gn_helpers.FromGNArgs('foo_=true'),
259 def test_ReplaceImports(self):
260 # Should be a no-op on args inputs without any imports.
261 parser = gn_helpers.GNValueParser(
266 parser.ReplaceImports()
274 # A single "import(...)" line should be replaced with the contents of the
275 # file being imported.
276 parser = gn_helpers.GNValueParser(
279 import("//some/args/file.gni")
282 fake_import = 'some_imported_arg = "imported_val"'
283 builtin_var = '__builtin__' if sys.version_info.major < 3 else 'builtins'
284 open_fun = '{}.open'.format(builtin_var)
285 with mock.patch(open_fun, mock.mock_open(read_data=fake_import)):
286 parser.ReplaceImports()
291 some_imported_arg = "imported_val"
295 # No trailing parenthesis should raise an exception.
296 with self.assertRaises(gn_helpers.GNError):
297 parser = gn_helpers.GNValueParser(
298 textwrap.dedent('import("//some/args/file.gni"'))
299 parser.ReplaceImports()
301 # No double quotes should raise an exception.
302 with self.assertRaises(gn_helpers.GNError):
303 parser = gn_helpers.GNValueParser(
304 textwrap.dedent('import(//some/args/file.gni)'))
305 parser.ReplaceImports()
307 # A path that's not source absolute should raise an exception.
308 with self.assertRaises(gn_helpers.GNError):
309 parser = gn_helpers.GNValueParser(
310 textwrap.dedent('import("some/relative/args/file.gni")'))
311 parser.ReplaceImports()
314 if __name__ == '__main__':