xref: /aosp_15_r20/external/angle/build/gn_helpers_unittest.py (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*8975f5c5SAndroid Build Coastguard Worker# Copyright 2016 The Chromium Authors
3*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker
6*8975f5c5SAndroid Build Coastguard Workerimport os
7*8975f5c5SAndroid Build Coastguard Workerimport pathlib
8*8975f5c5SAndroid Build Coastguard Workerimport shutil
9*8975f5c5SAndroid Build Coastguard Workerimport sys
10*8975f5c5SAndroid Build Coastguard Workerimport tempfile
11*8975f5c5SAndroid Build Coastguard Workerimport textwrap
12*8975f5c5SAndroid Build Coastguard Workerimport unittest
13*8975f5c5SAndroid Build Coastguard Workerfrom unittest import mock
14*8975f5c5SAndroid Build Coastguard Worker
15*8975f5c5SAndroid Build Coastguard Workerimport gn_helpers
16*8975f5c5SAndroid Build Coastguard Worker
17*8975f5c5SAndroid Build Coastguard Worker
18*8975f5c5SAndroid Build Coastguard Workerclass UnitTest(unittest.TestCase):
19*8975f5c5SAndroid Build Coastguard Worker  def test_ToGNString(self):
20*8975f5c5SAndroid Build Coastguard Worker    test_cases = [
21*8975f5c5SAndroid Build Coastguard Worker        (42, '42', '42'), ('foo', '"foo"', '"foo"'), (True, 'true', 'true'),
22*8975f5c5SAndroid Build Coastguard Worker        (False, 'false', 'false'), ('', '""', '""'),
23*8975f5c5SAndroid Build Coastguard Worker        ('\\$"$\\', '"\\\\\\$\\"\\$\\\\"', '"\\\\\\$\\"\\$\\\\"'),
24*8975f5c5SAndroid Build Coastguard Worker        (' \t\r\n', '" $0x09$0x0D$0x0A"', '" $0x09$0x0D$0x0A"'),
25*8975f5c5SAndroid Build Coastguard Worker        (u'\u2713', '"$0xE2$0x9C$0x93"', '"$0xE2$0x9C$0x93"'),
26*8975f5c5SAndroid Build Coastguard Worker        ([], '[  ]', '[]'), ([1], '[ 1 ]', '[\n  1\n]\n'),
27*8975f5c5SAndroid Build Coastguard Worker        ([3, 1, 4, 1], '[ 3, 1, 4, 1 ]', '[\n  3,\n  1,\n  4,\n  1\n]\n'),
28*8975f5c5SAndroid Build Coastguard Worker        (['a', True, 2], '[ "a", true, 2 ]', '[\n  "a",\n  true,\n  2\n]\n'),
29*8975f5c5SAndroid Build Coastguard Worker        ({
30*8975f5c5SAndroid Build Coastguard Worker            'single': 'item'
31*8975f5c5SAndroid Build Coastguard Worker        }, 'single = "item"\n', 'single = "item"\n'),
32*8975f5c5SAndroid Build Coastguard Worker        ({
33*8975f5c5SAndroid Build Coastguard Worker            'kEy': 137,
34*8975f5c5SAndroid Build Coastguard Worker            '_42A_Zaz_': [False, True]
35*8975f5c5SAndroid Build Coastguard Worker        }, '_42A_Zaz_ = [ false, true ]\nkEy = 137\n',
36*8975f5c5SAndroid Build Coastguard Worker         '_42A_Zaz_ = [\n  false,\n  true\n]\nkEy = 137\n'),
37*8975f5c5SAndroid Build Coastguard Worker        ([1, 'two',
38*8975f5c5SAndroid Build Coastguard Worker          ['"thr,.$\\', True, False, [],
39*8975f5c5SAndroid Build Coastguard Worker           u'(\u2713)']], '[ 1, "two", [ "\\"thr,.\\$\\\\", true, false, ' +
40*8975f5c5SAndroid Build Coastguard Worker         '[  ], "($0xE2$0x9C$0x93)" ] ]', '''[
41*8975f5c5SAndroid Build Coastguard Worker  1,
42*8975f5c5SAndroid Build Coastguard Worker  "two",
43*8975f5c5SAndroid Build Coastguard Worker  [
44*8975f5c5SAndroid Build Coastguard Worker    "\\"thr,.\\$\\\\",
45*8975f5c5SAndroid Build Coastguard Worker    true,
46*8975f5c5SAndroid Build Coastguard Worker    false,
47*8975f5c5SAndroid Build Coastguard Worker    [],
48*8975f5c5SAndroid Build Coastguard Worker    "($0xE2$0x9C$0x93)"
49*8975f5c5SAndroid Build Coastguard Worker  ]
50*8975f5c5SAndroid Build Coastguard Worker]
51*8975f5c5SAndroid Build Coastguard Worker'''),
52*8975f5c5SAndroid Build Coastguard Worker        ({
53*8975f5c5SAndroid Build Coastguard Worker            's': 'foo',
54*8975f5c5SAndroid Build Coastguard Worker            'n': 42,
55*8975f5c5SAndroid Build Coastguard Worker            'b': True,
56*8975f5c5SAndroid Build Coastguard Worker            'a': [3, 'x']
57*8975f5c5SAndroid Build Coastguard Worker        }, 'a = [ 3, "x" ]\nb = true\nn = 42\ns = "foo"\n',
58*8975f5c5SAndroid Build Coastguard Worker         'a = [\n  3,\n  "x"\n]\nb = true\nn = 42\ns = "foo"\n'),
59*8975f5c5SAndroid Build Coastguard Worker        (
60*8975f5c5SAndroid Build Coastguard Worker            [[[], [[]]], []],
61*8975f5c5SAndroid Build Coastguard Worker            '[ [ [  ], [ [  ] ] ], [  ] ]',
62*8975f5c5SAndroid Build Coastguard Worker            '[\n  [\n    [],\n    [\n      []\n    ]\n  ],\n  []\n]\n',
63*8975f5c5SAndroid Build Coastguard Worker        ),
64*8975f5c5SAndroid Build Coastguard Worker        (
65*8975f5c5SAndroid Build Coastguard Worker            [{
66*8975f5c5SAndroid Build Coastguard Worker                'a': 1,
67*8975f5c5SAndroid Build Coastguard Worker                'c': {
68*8975f5c5SAndroid Build Coastguard Worker                    'z': 8
69*8975f5c5SAndroid Build Coastguard Worker                },
70*8975f5c5SAndroid Build Coastguard Worker                'b': []
71*8975f5c5SAndroid Build Coastguard Worker            }],
72*8975f5c5SAndroid Build Coastguard Worker            '[ { a = 1\nb = [  ]\nc = { z = 8 } } ]\n',
73*8975f5c5SAndroid Build Coastguard Worker            '[\n  {\n    a = 1\n    b = []\n    c = {\n' +
74*8975f5c5SAndroid Build Coastguard Worker            '      z = 8\n    }\n  }\n]\n',
75*8975f5c5SAndroid Build Coastguard Worker        )
76*8975f5c5SAndroid Build Coastguard Worker    ]
77*8975f5c5SAndroid Build Coastguard Worker    for obj, exp_ugly, exp_pretty in test_cases:
78*8975f5c5SAndroid Build Coastguard Worker      out_ugly = gn_helpers.ToGNString(obj)
79*8975f5c5SAndroid Build Coastguard Worker      self.assertEqual(exp_ugly, out_ugly)
80*8975f5c5SAndroid Build Coastguard Worker      out_pretty = gn_helpers.ToGNString(obj, pretty=True)
81*8975f5c5SAndroid Build Coastguard Worker      self.assertEqual(exp_pretty, out_pretty)
82*8975f5c5SAndroid Build Coastguard Worker
83*8975f5c5SAndroid Build Coastguard Worker  def test_UnescapeGNString(self):
84*8975f5c5SAndroid Build Coastguard Worker    # Backslash followed by a \, $, or " means the folling character without
85*8975f5c5SAndroid Build Coastguard Worker    # the special meaning. Backslash followed by everything else is a literal.
86*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(
87*8975f5c5SAndroid Build Coastguard Worker        gn_helpers.UnescapeGNString('\\as\\$\\\\asd\\"'),
88*8975f5c5SAndroid Build Coastguard Worker        '\\as$\\asd"')
89*8975f5c5SAndroid Build Coastguard Worker
90*8975f5c5SAndroid Build Coastguard Worker  def test_FromGNString(self):
91*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(
92*8975f5c5SAndroid Build Coastguard Worker        gn_helpers.FromGNString('[1, -20, true, false,["as\\"", []]]'),
93*8975f5c5SAndroid Build Coastguard Worker        [ 1, -20, True, False, [ 'as"', [] ] ])
94*8975f5c5SAndroid Build Coastguard Worker
95*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
96*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser('123 456')
97*8975f5c5SAndroid Build Coastguard Worker      parser.Parse()
98*8975f5c5SAndroid Build Coastguard Worker
99*8975f5c5SAndroid Build Coastguard Worker  def test_ParseBool(self):
100*8975f5c5SAndroid Build Coastguard Worker    parser = gn_helpers.GNValueParser('true')
101*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(parser.Parse(), True)
102*8975f5c5SAndroid Build Coastguard Worker
103*8975f5c5SAndroid Build Coastguard Worker    parser = gn_helpers.GNValueParser('false')
104*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(parser.Parse(), False)
105*8975f5c5SAndroid Build Coastguard Worker
106*8975f5c5SAndroid Build Coastguard Worker  def test_ParseNumber(self):
107*8975f5c5SAndroid Build Coastguard Worker    parser = gn_helpers.GNValueParser('123')
108*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(parser.ParseNumber(), 123)
109*8975f5c5SAndroid Build Coastguard Worker
110*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
111*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser('')
112*8975f5c5SAndroid Build Coastguard Worker      parser.ParseNumber()
113*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
114*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser('a123')
115*8975f5c5SAndroid Build Coastguard Worker      parser.ParseNumber()
116*8975f5c5SAndroid Build Coastguard Worker
117*8975f5c5SAndroid Build Coastguard Worker  def test_ParseString(self):
118*8975f5c5SAndroid Build Coastguard Worker    parser = gn_helpers.GNValueParser('"asdf"')
119*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(parser.ParseString(), 'asdf')
120*8975f5c5SAndroid Build Coastguard Worker
121*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
122*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser('')  # Empty.
123*8975f5c5SAndroid Build Coastguard Worker      parser.ParseString()
124*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
125*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser('asdf')  # Unquoted.
126*8975f5c5SAndroid Build Coastguard Worker      parser.ParseString()
127*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
128*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser('"trailing')  # Unterminated.
129*8975f5c5SAndroid Build Coastguard Worker      parser.ParseString()
130*8975f5c5SAndroid Build Coastguard Worker
131*8975f5c5SAndroid Build Coastguard Worker  def test_ParseList(self):
132*8975f5c5SAndroid Build Coastguard Worker    parser = gn_helpers.GNValueParser('[1,]')  # Optional end comma OK.
133*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(parser.ParseList(), [ 1 ])
134*8975f5c5SAndroid Build Coastguard Worker
135*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
136*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser('')  # Empty.
137*8975f5c5SAndroid Build Coastguard Worker      parser.ParseList()
138*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
139*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser('asdf')  # No [].
140*8975f5c5SAndroid Build Coastguard Worker      parser.ParseList()
141*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
142*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser('[1, 2')  # Unterminated
143*8975f5c5SAndroid Build Coastguard Worker      parser.ParseList()
144*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
145*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser('[1 2]')  # No separating comma.
146*8975f5c5SAndroid Build Coastguard Worker      parser.ParseList()
147*8975f5c5SAndroid Build Coastguard Worker
148*8975f5c5SAndroid Build Coastguard Worker  def test_ParseScope(self):
149*8975f5c5SAndroid Build Coastguard Worker    parser = gn_helpers.GNValueParser('{a = 1}')
150*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(parser.ParseScope(), {'a': 1})
151*8975f5c5SAndroid Build Coastguard Worker
152*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
153*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser('')  # Empty.
154*8975f5c5SAndroid Build Coastguard Worker      parser.ParseScope()
155*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
156*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser('asdf')  # No {}.
157*8975f5c5SAndroid Build Coastguard Worker      parser.ParseScope()
158*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
159*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser('{a = 1')  # Unterminated.
160*8975f5c5SAndroid Build Coastguard Worker      parser.ParseScope()
161*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
162*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser('{"a" = 1}')  # Not identifier.
163*8975f5c5SAndroid Build Coastguard Worker      parser.ParseScope()
164*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
165*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser('{a = }')  # No value.
166*8975f5c5SAndroid Build Coastguard Worker      parser.ParseScope()
167*8975f5c5SAndroid Build Coastguard Worker
168*8975f5c5SAndroid Build Coastguard Worker  def test_FromGNArgs(self):
169*8975f5c5SAndroid Build Coastguard Worker    # Booleans and numbers should work; whitespace is allowed works.
170*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(gn_helpers.FromGNArgs('foo = true\nbar = 1\n'),
171*8975f5c5SAndroid Build Coastguard Worker                     {'foo': True, 'bar': 1})
172*8975f5c5SAndroid Build Coastguard Worker
173*8975f5c5SAndroid Build Coastguard Worker    # Whitespace is not required; strings should also work.
174*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(gn_helpers.FromGNArgs('foo="bar baz"'),
175*8975f5c5SAndroid Build Coastguard Worker                     {'foo': 'bar baz'})
176*8975f5c5SAndroid Build Coastguard Worker
177*8975f5c5SAndroid Build Coastguard Worker    # Comments should work (and be ignored).
178*8975f5c5SAndroid Build Coastguard Worker    gn_args_lines = [
179*8975f5c5SAndroid Build Coastguard Worker        '# Top-level comment.',
180*8975f5c5SAndroid Build Coastguard Worker        'foo = true',
181*8975f5c5SAndroid Build Coastguard Worker        'bar = 1  # In-line comment followed by whitespace.',
182*8975f5c5SAndroid Build Coastguard Worker        ' ',
183*8975f5c5SAndroid Build Coastguard Worker        'baz = false',
184*8975f5c5SAndroid Build Coastguard Worker    ]
185*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(gn_helpers.FromGNArgs('\n'.join(gn_args_lines)), {
186*8975f5c5SAndroid Build Coastguard Worker        'foo': True,
187*8975f5c5SAndroid Build Coastguard Worker        'bar': 1,
188*8975f5c5SAndroid Build Coastguard Worker        'baz': False
189*8975f5c5SAndroid Build Coastguard Worker    })
190*8975f5c5SAndroid Build Coastguard Worker
191*8975f5c5SAndroid Build Coastguard Worker    # Lists should work.
192*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(gn_helpers.FromGNArgs('foo=[1, 2, 3]'),
193*8975f5c5SAndroid Build Coastguard Worker                     {'foo': [1, 2, 3]})
194*8975f5c5SAndroid Build Coastguard Worker
195*8975f5c5SAndroid Build Coastguard Worker    # Empty strings should return an empty dict.
196*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(gn_helpers.FromGNArgs(''), {})
197*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(gn_helpers.FromGNArgs(' \n '), {})
198*8975f5c5SAndroid Build Coastguard Worker
199*8975f5c5SAndroid Build Coastguard Worker    # Comments should work everywhere (and be ignored).
200*8975f5c5SAndroid Build Coastguard Worker    gn_args_lines = [
201*8975f5c5SAndroid Build Coastguard Worker        '# Top-level comment.',
202*8975f5c5SAndroid Build Coastguard Worker        '',
203*8975f5c5SAndroid Build Coastguard Worker        '# Variable comment.',
204*8975f5c5SAndroid Build Coastguard Worker        'foo = true',
205*8975f5c5SAndroid Build Coastguard Worker        'bar = [',
206*8975f5c5SAndroid Build Coastguard Worker        '    # Value comment in list.',
207*8975f5c5SAndroid Build Coastguard Worker        '    1,',
208*8975f5c5SAndroid Build Coastguard Worker        '    2,',
209*8975f5c5SAndroid Build Coastguard Worker        ']',
210*8975f5c5SAndroid Build Coastguard Worker        '',
211*8975f5c5SAndroid Build Coastguard Worker        'baz # Comment anywhere, really',
212*8975f5c5SAndroid Build Coastguard Worker        '  = # also here',
213*8975f5c5SAndroid Build Coastguard Worker        '    4',
214*8975f5c5SAndroid Build Coastguard Worker    ]
215*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(gn_helpers.FromGNArgs('\n'.join(gn_args_lines)), {
216*8975f5c5SAndroid Build Coastguard Worker        'foo': True,
217*8975f5c5SAndroid Build Coastguard Worker        'bar': [1, 2],
218*8975f5c5SAndroid Build Coastguard Worker        'baz': 4
219*8975f5c5SAndroid Build Coastguard Worker    })
220*8975f5c5SAndroid Build Coastguard Worker
221*8975f5c5SAndroid Build Coastguard Worker    # Scope should be parsed, even empty ones.
222*8975f5c5SAndroid Build Coastguard Worker    gn_args_lines = [
223*8975f5c5SAndroid Build Coastguard Worker        'foo = {',
224*8975f5c5SAndroid Build Coastguard Worker        '  a = 1',
225*8975f5c5SAndroid Build Coastguard Worker        '  b = [',
226*8975f5c5SAndroid Build Coastguard Worker        '    { },',
227*8975f5c5SAndroid Build Coastguard Worker        '    {',
228*8975f5c5SAndroid Build Coastguard Worker        '      c = 1',
229*8975f5c5SAndroid Build Coastguard Worker        '    },',
230*8975f5c5SAndroid Build Coastguard Worker        '  ]',
231*8975f5c5SAndroid Build Coastguard Worker        '}',
232*8975f5c5SAndroid Build Coastguard Worker    ]
233*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(gn_helpers.FromGNArgs('\n'.join(gn_args_lines)),
234*8975f5c5SAndroid Build Coastguard Worker                     {'foo': {
235*8975f5c5SAndroid Build Coastguard Worker                         'a': 1,
236*8975f5c5SAndroid Build Coastguard Worker                         'b': [
237*8975f5c5SAndroid Build Coastguard Worker                             {},
238*8975f5c5SAndroid Build Coastguard Worker                             {
239*8975f5c5SAndroid Build Coastguard Worker                                 'c': 1,
240*8975f5c5SAndroid Build Coastguard Worker                             },
241*8975f5c5SAndroid Build Coastguard Worker                         ]
242*8975f5c5SAndroid Build Coastguard Worker                     }})
243*8975f5c5SAndroid Build Coastguard Worker
244*8975f5c5SAndroid Build Coastguard Worker    # Non-identifiers should raise an exception.
245*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
246*8975f5c5SAndroid Build Coastguard Worker      gn_helpers.FromGNArgs('123 = true')
247*8975f5c5SAndroid Build Coastguard Worker
248*8975f5c5SAndroid Build Coastguard Worker    # References to other variables should raise an exception.
249*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
250*8975f5c5SAndroid Build Coastguard Worker      gn_helpers.FromGNArgs('foo = bar')
251*8975f5c5SAndroid Build Coastguard Worker
252*8975f5c5SAndroid Build Coastguard Worker    # References to functions should raise an exception.
253*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
254*8975f5c5SAndroid Build Coastguard Worker      gn_helpers.FromGNArgs('foo = exec_script("//build/baz.py")')
255*8975f5c5SAndroid Build Coastguard Worker
256*8975f5c5SAndroid Build Coastguard Worker    # Underscores in identifiers should work.
257*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(gn_helpers.FromGNArgs('_foo = true'),
258*8975f5c5SAndroid Build Coastguard Worker                     {'_foo': True})
259*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(gn_helpers.FromGNArgs('foo_bar = true'),
260*8975f5c5SAndroid Build Coastguard Worker                     {'foo_bar': True})
261*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(gn_helpers.FromGNArgs('foo_=true'),
262*8975f5c5SAndroid Build Coastguard Worker                     {'foo_': True})
263*8975f5c5SAndroid Build Coastguard Worker
264*8975f5c5SAndroid Build Coastguard Worker  def test_ReplaceImports(self):
265*8975f5c5SAndroid Build Coastguard Worker    # Should be a no-op on args inputs without any imports.
266*8975f5c5SAndroid Build Coastguard Worker    parser = gn_helpers.GNValueParser(
267*8975f5c5SAndroid Build Coastguard Worker        textwrap.dedent("""
268*8975f5c5SAndroid Build Coastguard Worker        some_arg1 = "val1"
269*8975f5c5SAndroid Build Coastguard Worker        some_arg2 = "val2"
270*8975f5c5SAndroid Build Coastguard Worker    """))
271*8975f5c5SAndroid Build Coastguard Worker    parser.ReplaceImports()
272*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(
273*8975f5c5SAndroid Build Coastguard Worker        parser.input,
274*8975f5c5SAndroid Build Coastguard Worker        textwrap.dedent("""
275*8975f5c5SAndroid Build Coastguard Worker        some_arg1 = "val1"
276*8975f5c5SAndroid Build Coastguard Worker        some_arg2 = "val2"
277*8975f5c5SAndroid Build Coastguard Worker    """))
278*8975f5c5SAndroid Build Coastguard Worker
279*8975f5c5SAndroid Build Coastguard Worker    # A single "import(...)" line should be replaced with the contents of the
280*8975f5c5SAndroid Build Coastguard Worker    # file being imported.
281*8975f5c5SAndroid Build Coastguard Worker    parser = gn_helpers.GNValueParser(
282*8975f5c5SAndroid Build Coastguard Worker        textwrap.dedent("""
283*8975f5c5SAndroid Build Coastguard Worker        some_arg1 = "val1"
284*8975f5c5SAndroid Build Coastguard Worker        import("//some/args/file.gni")
285*8975f5c5SAndroid Build Coastguard Worker        some_arg2 = "val2"
286*8975f5c5SAndroid Build Coastguard Worker    """))
287*8975f5c5SAndroid Build Coastguard Worker    fake_import = 'some_imported_arg = "imported_val"'
288*8975f5c5SAndroid Build Coastguard Worker    builtin_var = '__builtin__' if sys.version_info.major < 3 else 'builtins'
289*8975f5c5SAndroid Build Coastguard Worker    open_fun = '{}.open'.format(builtin_var)
290*8975f5c5SAndroid Build Coastguard Worker    with mock.patch(open_fun, mock.mock_open(read_data=fake_import)):
291*8975f5c5SAndroid Build Coastguard Worker      parser.ReplaceImports()
292*8975f5c5SAndroid Build Coastguard Worker    self.assertEqual(
293*8975f5c5SAndroid Build Coastguard Worker        parser.input,
294*8975f5c5SAndroid Build Coastguard Worker        textwrap.dedent("""
295*8975f5c5SAndroid Build Coastguard Worker        some_arg1 = "val1"
296*8975f5c5SAndroid Build Coastguard Worker        some_imported_arg = "imported_val"
297*8975f5c5SAndroid Build Coastguard Worker        some_arg2 = "val2"
298*8975f5c5SAndroid Build Coastguard Worker    """))
299*8975f5c5SAndroid Build Coastguard Worker
300*8975f5c5SAndroid Build Coastguard Worker    # No trailing parenthesis should raise an exception.
301*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
302*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser(
303*8975f5c5SAndroid Build Coastguard Worker          textwrap.dedent('import("//some/args/file.gni"'))
304*8975f5c5SAndroid Build Coastguard Worker      parser.ReplaceImports()
305*8975f5c5SAndroid Build Coastguard Worker
306*8975f5c5SAndroid Build Coastguard Worker    # No double quotes should raise an exception.
307*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
308*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser(
309*8975f5c5SAndroid Build Coastguard Worker          textwrap.dedent('import(//some/args/file.gni)'))
310*8975f5c5SAndroid Build Coastguard Worker      parser.ReplaceImports()
311*8975f5c5SAndroid Build Coastguard Worker
312*8975f5c5SAndroid Build Coastguard Worker    # A path that's not source absolute should raise an exception.
313*8975f5c5SAndroid Build Coastguard Worker    with self.assertRaises(gn_helpers.GNError):
314*8975f5c5SAndroid Build Coastguard Worker      parser = gn_helpers.GNValueParser(
315*8975f5c5SAndroid Build Coastguard Worker          textwrap.dedent('import("some/relative/args/file.gni")'))
316*8975f5c5SAndroid Build Coastguard Worker      parser.ReplaceImports()
317*8975f5c5SAndroid Build Coastguard Worker
318*8975f5c5SAndroid Build Coastguard Worker  def test_CreateBuildCommand(self):
319*8975f5c5SAndroid Build Coastguard Worker    with tempfile.TemporaryDirectory() as temp_dir:
320*8975f5c5SAndroid Build Coastguard Worker      suffix = '.bat' if sys.platform.startswith('win32') else ''
321*8975f5c5SAndroid Build Coastguard Worker      self.assertEqual(f'autoninja{suffix}',
322*8975f5c5SAndroid Build Coastguard Worker                       gn_helpers.CreateBuildCommand(temp_dir)[0])
323*8975f5c5SAndroid Build Coastguard Worker
324*8975f5c5SAndroid Build Coastguard Worker      siso_deps = pathlib.Path(temp_dir) / '.siso_deps'
325*8975f5c5SAndroid Build Coastguard Worker      siso_deps.touch()
326*8975f5c5SAndroid Build Coastguard Worker      self.assertEqual(f'autoninja{suffix}',
327*8975f5c5SAndroid Build Coastguard Worker                       gn_helpers.CreateBuildCommand(temp_dir)[0])
328*8975f5c5SAndroid Build Coastguard Worker
329*8975f5c5SAndroid Build Coastguard Worker      with mock.patch('shutil.which', lambda x: None):
330*8975f5c5SAndroid Build Coastguard Worker        cmd = gn_helpers.CreateBuildCommand(temp_dir)
331*8975f5c5SAndroid Build Coastguard Worker        self.assertIn('third_party', cmd[0])
332*8975f5c5SAndroid Build Coastguard Worker        self.assertIn(f'{os.sep}siso', cmd[0])
333*8975f5c5SAndroid Build Coastguard Worker        self.assertEqual(['ninja', '-C', temp_dir], cmd[1:])
334*8975f5c5SAndroid Build Coastguard Worker
335*8975f5c5SAndroid Build Coastguard Worker      ninja_deps = pathlib.Path(temp_dir) / '.ninja_deps'
336*8975f5c5SAndroid Build Coastguard Worker      ninja_deps.touch()
337*8975f5c5SAndroid Build Coastguard Worker
338*8975f5c5SAndroid Build Coastguard Worker      with self.assertRaisesRegex(Exception, 'Found both'):
339*8975f5c5SAndroid Build Coastguard Worker        gn_helpers.CreateBuildCommand(temp_dir)
340*8975f5c5SAndroid Build Coastguard Worker
341*8975f5c5SAndroid Build Coastguard Worker      siso_deps.unlink()
342*8975f5c5SAndroid Build Coastguard Worker      self.assertEqual(f'autoninja{suffix}',
343*8975f5c5SAndroid Build Coastguard Worker                       gn_helpers.CreateBuildCommand(temp_dir)[0])
344*8975f5c5SAndroid Build Coastguard Worker
345*8975f5c5SAndroid Build Coastguard Worker      with mock.patch('shutil.which', lambda x: None):
346*8975f5c5SAndroid Build Coastguard Worker        cmd = gn_helpers.CreateBuildCommand(temp_dir)
347*8975f5c5SAndroid Build Coastguard Worker        self.assertIn('third_party', cmd[0])
348*8975f5c5SAndroid Build Coastguard Worker        self.assertIn(f'{os.sep}ninja', cmd[0])
349*8975f5c5SAndroid Build Coastguard Worker        self.assertEqual(['-C', temp_dir], cmd[1:])
350*8975f5c5SAndroid Build Coastguard Worker
351*8975f5c5SAndroid Build Coastguard Worker
352*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__':
353*8975f5c5SAndroid Build Coastguard Worker  unittest.main()
354