1# Copyright 2018 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.
4
5import imp
6import os
7import sys
8import unittest
9
10
11def _GetDirAbove(dirname):
12  """Returns the directory "above" this file containing |dirname| (which must
13  also be "above" this file)."""
14  path = os.path.abspath(__file__)
15  while True:
16    path, tail = os.path.split(path)
17    assert tail
18    if tail == dirname:
19      return path
20
21
22try:
23  imp.find_module('mojom')
24except ImportError:
25  sys.path.append(os.path.join(_GetDirAbove('pylib'), 'pylib'))
26import mojom.parse.ast as ast
27import mojom.parse.conditional_features as conditional_features
28import mojom.parse.parser as parser
29
30ENABLED_FEATURES = frozenset({'red', 'green', 'blue'})
31
32
33class ConditionalFeaturesTest(unittest.TestCase):
34  """Tests |mojom.parse.conditional_features|."""
35
36  def parseAndAssertEqual(self, source, expected_source):
37    definition = parser.Parse(source, "my_file.mojom")
38    conditional_features.RemoveDisabledDefinitions(definition, ENABLED_FEATURES)
39    expected = parser.Parse(expected_source, "my_file.mojom")
40    self.assertEquals(definition, expected)
41
42  def testFilterConst(self):
43    """Test that Consts are correctly filtered."""
44    const_source = """
45      [EnableIf=blue]
46      const int kMyConst1 = 1;
47      [EnableIf=orange]
48      const double kMyConst2 = 2;
49      const int kMyConst3 = 3;
50    """
51    expected_source = """
52      [EnableIf=blue]
53      const int kMyConst1 = 1;
54      const int kMyConst3 = 3;
55    """
56    self.parseAndAssertEqual(const_source, expected_source)
57
58  def testFilterEnum(self):
59    """Test that EnumValues are correctly filtered from an Enum."""
60    enum_source = """
61      enum MyEnum {
62        [EnableIf=purple]
63        VALUE1,
64        [EnableIf=blue]
65        VALUE2,
66        VALUE3,
67      };
68    """
69    expected_source = """
70      enum MyEnum {
71        [EnableIf=blue]
72        VALUE2,
73        VALUE3
74      };
75    """
76    self.parseAndAssertEqual(enum_source, expected_source)
77
78  def testFilterImport(self):
79    """Test that imports are correctly filtered from a Mojom."""
80    import_source = """
81      [EnableIf=blue]
82      import "foo.mojom";
83      import "bar.mojom";
84      [EnableIf=purple]
85      import "baz.mojom";
86    """
87    expected_source = """
88      [EnableIf=blue]
89      import "foo.mojom";
90      import "bar.mojom";
91    """
92    self.parseAndAssertEqual(import_source, expected_source)
93
94  def testFilterInterface(self):
95    """Test that definitions are correctly filtered from an Interface."""
96    interface_source = """
97      interface MyInterface {
98        [EnableIf=blue]
99        enum MyEnum {
100          [EnableIf=purple]
101          VALUE1,
102          VALUE2,
103        };
104        [EnableIf=blue]
105        const int32 kMyConst = 123;
106        [EnableIf=purple]
107        MyMethod();
108      };
109    """
110    expected_source = """
111      interface MyInterface {
112        [EnableIf=blue]
113        enum MyEnum {
114          VALUE2,
115        };
116        [EnableIf=blue]
117        const int32 kMyConst = 123;
118      };
119    """
120    self.parseAndAssertEqual(interface_source, expected_source)
121
122  def testFilterMethod(self):
123    """Test that Parameters are correctly filtered from a Method."""
124    method_source = """
125      interface MyInterface {
126        [EnableIf=blue]
127        MyMethod([EnableIf=purple] int32 a) => ([EnableIf=red] int32 b);
128      };
129    """
130    expected_source = """
131      interface MyInterface {
132        [EnableIf=blue]
133        MyMethod() => ([EnableIf=red] int32 b);
134      };
135    """
136    self.parseAndAssertEqual(method_source, expected_source)
137
138  def testFilterStruct(self):
139    """Test that definitions are correctly filtered from a Struct."""
140    struct_source =  """
141      struct MyStruct {
142        [EnableIf=blue]
143        enum MyEnum {
144          VALUE1,
145          [EnableIf=purple]
146          VALUE2,
147        };
148        [EnableIf=yellow]
149        const double kMyConst = 1.23;
150        [EnableIf=green]
151        int32 a;
152        double b;
153        [EnableIf=purple]
154        int32 c;
155        [EnableIf=blue]
156        double d;
157        int32 e;
158        [EnableIf=orange]
159        double f;
160      };
161    """
162    expected_source = """
163      struct MyStruct {
164        [EnableIf=blue]
165        enum MyEnum {
166          VALUE1,
167        };
168        [EnableIf=green]
169        int32 a;
170        double b;
171        [EnableIf=blue]
172        double d;
173        int32 e;
174      };
175    """
176    self.parseAndAssertEqual(struct_source, expected_source)
177
178  def testFilterUnion(self):
179    """Test that UnionFields are correctly filtered from a Union."""
180    union_source = """
181      union MyUnion {
182        [EnableIf=yellow]
183        int32 a;
184        [EnableIf=red]
185        bool b;
186      };
187    """
188    expected_source = """
189      union MyUnion {
190        [EnableIf=red]
191        bool b;
192      };
193    """
194    self.parseAndAssertEqual(union_source, expected_source)
195
196  def testSameNameFields(self):
197    mojom_source = """
198      enum Foo {
199        [EnableIf=red]
200        VALUE1 = 5,
201        [EnableIf=yellow]
202        VALUE1 = 6,
203      };
204      [EnableIf=red]
205      const double kMyConst = 1.23;
206      [EnableIf=yellow]
207      const double kMyConst = 4.56;
208    """
209    expected_source = """
210      enum Foo {
211        [EnableIf=red]
212        VALUE1 = 5,
213      };
214      [EnableIf=red]
215      const double kMyConst = 1.23;
216    """
217    self.parseAndAssertEqual(mojom_source, expected_source)
218
219  def testMultipleEnableIfs(self):
220    source = """
221      enum Foo {
222        [EnableIf=red,EnableIf=yellow]
223        kBarValue = 5,
224      };
225    """
226    definition = parser.Parse(source, "my_file.mojom")
227    self.assertRaises(conditional_features.EnableIfError,
228      conditional_features.RemoveDisabledDefinitions,
229      definition, ENABLED_FEATURES)
230
231if __name__ == '__main__':
232  unittest.main()
233