1#!/usr/bin/env python
2# Copyright (c) 2012 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import os
7import unittest
8
9from future import Future
10from reference_resolver import ReferenceResolver
11from test_object_store import TestObjectStore
12from test_util import Server2Path
13from third_party.json_schema_compiler.model import Namespace
14
15
16_TEST_DATA = {
17  'baz': {
18    'namespace': 'baz',
19    'description': '',
20    'types': [
21      {
22        'id': 'baz_t1',
23        'type': 'any',
24      },
25      {
26        'id': 'baz_t2',
27        'type': 'any',
28      },
29      {
30        'id': 'baz_t3',
31        'type': 'any',
32      }
33    ],
34    'functions': [
35      {
36        'name': 'baz_f1',
37        'type': 'function'
38      },
39      {
40        'name': 'baz_f2',
41        'type': 'function'
42      },
43      {
44        'name': 'baz_f3',
45        'type': 'function'
46      }
47    ],
48    'events': [
49      {
50        'name': 'baz_e1',
51        'type': 'function'
52      },
53      {
54        'name': 'baz_e2',
55        'type': 'function'
56      },
57      {
58        'name': 'baz_e3',
59        'type': 'function'
60      }
61    ],
62    'properties': {
63      'baz_p1': {'type': 'any'},
64      'baz_p2': {'type': 'any'},
65      'baz_p3': {'type': 'any'}
66    }
67  },
68  'bar.bon': {
69    'namespace': 'bar.bon',
70    'description': '',
71    'types': [
72      {
73        'id': 'bar_bon_t1',
74        'type': 'any',
75      },
76      {
77        'id': 'bar_bon_t2',
78        'type': 'any',
79      },
80      {
81        'id': 'bar_bon_t3',
82        'type': 'any',
83      }
84    ],
85    'functions': [
86      {
87        'name': 'bar_bon_f1',
88        'type': 'function'
89      },
90      {
91        'name': 'bar_bon_f2',
92        'type': 'function'
93      },
94      {
95        'name': 'bar_bon_f3',
96        'type': 'function'
97      }
98    ],
99    'events': [
100      {
101        'name': 'bar_bon_e1',
102        'type': 'function'
103      },
104      {
105        'name': 'bar_bon_e2',
106        'type': 'function'
107      },
108      {
109        'name': 'bar_bon_e3',
110        'type': 'function'
111      }
112    ],
113    'properties': {
114      'bar_bon_p1': {'type': 'any'},
115      'bar_bon_p2': {'type': 'any'},
116      'bar_bon_p3': {'type': 'any'}
117    }
118  },
119  'bar': {
120    'namespace': 'bar',
121    'description': '',
122    'types': [
123      {
124        'id': 'bar_t1',
125        'type': 'any',
126        'properties': {
127          'bar_t1_p1': {
128            'type': 'any'
129          }
130        }
131      },
132      {
133        'id': 'bar_t2',
134        'type': 'any',
135        'properties': {
136          'bar_t2_p1': {
137            'type': 'any'
138          }
139        }
140      },
141      {
142        'id': 'bar_t3',
143        'type': 'any',
144      },
145      {
146        'id': 'bon',
147        'type': 'any'
148      }
149    ],
150    'functions': [
151      {
152        'name': 'bar_f1',
153        'type': 'function'
154      },
155      {
156        'name': 'bar_f2',
157        'type': 'function'
158      },
159      {
160        'name': 'bar_f3',
161        'type': 'function'
162      }
163    ],
164    'events': [
165      {
166        'name': 'bar_e1',
167        'type': 'function'
168      },
169      {
170        'name': 'bar_e2',
171        'type': 'function'
172      },
173      {
174        'name': 'bar_e3',
175        'type': 'function'
176      }
177    ],
178    'properties': {
179      'bar_p1': {'type': 'any'},
180      'bar_p2': {'type': 'any'},
181      'bar_p3': {'$ref': 'bar_t1'}
182    }
183  },
184  'foo': {
185    'namespace': 'foo',
186    'description': '',
187    'types': [
188      {
189        'id': 'foo_t1',
190        'type': 'any',
191      },
192      {
193        'id': 'foo_t2',
194        'type': 'any',
195      },
196      {
197        'id': 'foo_t3',
198        'type': 'any',
199        'events': [
200          {
201            'name': 'foo_t3_e1',
202            'type': 'function'
203          }
204        ]
205      }
206    ],
207    'functions': [
208      {
209        'name': 'foo_f1',
210        'type': 'function'
211      },
212      {
213        'name': 'foo_f2',
214        'type': 'function'
215      },
216      {
217        'name': 'foo_f3',
218        'type': 'function'
219      }
220    ],
221    'events': [
222      {
223        'name': 'foo_e1',
224        'type': 'function'
225      },
226      {
227        'name': 'foo_e2',
228        'type': 'function'
229      },
230      {
231        'name': 'foo_e3',
232        'type': 'function'
233      }
234    ],
235    'properties': {
236      'foo_p1': {'$ref': 'foo_t3'},
237      'foo_p2': {'type': 'any'},
238      'foo_p3': {'type': 'any'}
239    }
240  }
241}
242
243
244class _FakePlatformBundle(object):
245  def __init__(self):
246    self.platforms = ('apps', 'extensions')
247
248  def GetAPIModels(self, platform):
249    if platform == 'apps':
250      return _FakeAPIModels(_TEST_DATA)
251    # Only includes some of the data in the 'extensions' APIModels.
252    # ReferenceResolver will have to look at other platforms to resolve 'foo'.
253    return _FakeAPIModels({
254      'bar': _TEST_DATA['bar'],
255      'bar.bon': _TEST_DATA['bar.bon'],
256      'baz': _TEST_DATA['baz']
257    })
258
259
260class _FakeAPIModels(object):
261  def __init__(self, apis):
262    self._apis = apis
263
264  def GetNames(self):
265    return self._apis.keys()
266
267  def GetModel(self, name):
268    return Future(value=Namespace(self._apis[name], 'fake/path.json'))
269
270
271class ReferenceResolverTest(unittest.TestCase):
272  def setUp(self):
273    self._base_path = Server2Path('test_data', 'test_json')
274
275  def _ReadLocalFile(self, filename):
276    with open(os.path.join(self._base_path, filename), 'r') as f:
277      return f.read()
278
279  def testGetLink(self):
280    apps_resolver = ReferenceResolver(
281        _FakePlatformBundle().GetAPIModels('apps'),
282        TestObjectStore('apps/test'))
283    extensions_resolver = ReferenceResolver(
284        _FakePlatformBundle().GetAPIModels('extensions'),
285        TestObjectStore('extensions/test'))
286
287    self.assertEqual({
288      'href': 'foo',
289      'text': 'foo',
290      'name': 'foo'
291    }, apps_resolver.GetLink('foo', namespace='baz'))
292    self.assertEqual({
293      'href': 'foo#type-foo_t1',
294      'text': 'foo.foo_t1',
295      'name': 'foo_t1'
296    }, apps_resolver.GetLink('foo.foo_t1', namespace='baz'))
297    self.assertEqual({
298      'href': 'baz#event-baz_e1',
299      'text': 'baz_e1',
300      'name': 'baz_e1'
301    }, apps_resolver.GetLink('baz.baz_e1', namespace='baz'))
302    self.assertEqual({
303      'href': 'baz#event-baz_e1',
304      'text': 'baz_e1',
305      'name': 'baz_e1'
306    }, apps_resolver.GetLink('baz_e1', namespace='baz'))
307    self.assertEqual({
308      'href': 'foo#method-foo_f1',
309      'text': 'foo.foo_f1',
310      'name': 'foo_f1'
311    }, apps_resolver.GetLink('foo.foo_f1', namespace='baz'))
312    self.assertEqual({
313      'href': 'foo#property-foo_p3',
314      'text': 'foo.foo_p3',
315      'name': 'foo_p3'
316    }, apps_resolver.GetLink('foo.foo_p3', namespace='baz'))
317    self.assertEqual({
318      'href': 'bar.bon#type-bar_bon_t3',
319      'text': 'bar.bon.bar_bon_t3',
320      'name': 'bar_bon_t3'
321    }, apps_resolver.GetLink('bar.bon.bar_bon_t3', namespace='baz'))
322    self.assertEqual({
323      'href': 'bar.bon#property-bar_bon_p3',
324      'text': 'bar_bon_p3',
325      'name': 'bar_bon_p3'
326    }, apps_resolver.GetLink('bar_bon_p3', namespace='bar.bon'))
327    self.assertEqual({
328      'href': 'bar.bon#property-bar_bon_p3',
329      'text': 'bar_bon_p3',
330      'name': 'bar_bon_p3'
331    }, apps_resolver.GetLink('bar.bon.bar_bon_p3', namespace='bar.bon'))
332    self.assertEqual({
333      'href': 'bar#event-bar_e2',
334      'text': 'bar_e2',
335      'name': 'bar_e2'
336    }, apps_resolver.GetLink('bar.bar_e2', namespace='bar'))
337    self.assertEqual({
338      'href': 'bar#type-bon',
339      'text': 'bon',
340      'name': 'bon'
341    }, apps_resolver.GetLink('bar.bon', namespace='bar'))
342    self.assertEqual({
343      'href': 'foo#event-foo_t3-foo_t3_e1',
344      'text': 'foo_t3.foo_t3_e1',
345      'name': 'foo_t3_e1'
346    }, apps_resolver.GetLink('foo_t3.foo_t3_e1', namespace='foo'))
347    self.assertEqual({
348      'href': 'foo#event-foo_t3-foo_t3_e1',
349      'text': 'foo_t3.foo_t3_e1',
350      'name': 'foo_t3_e1'
351    }, apps_resolver.GetLink('foo.foo_t3.foo_t3_e1', namespace='foo'))
352    self.assertEqual({
353      'href': 'foo#event-foo_t3-foo_t3_e1',
354      'text': 'foo_t3.foo_t3_e1',
355      'name': 'foo_t3_e1'
356    }, apps_resolver.GetLink('foo.foo_p1.foo_t3_e1', namespace='foo'))
357    self.assertEqual({
358      'href': 'bar#property-bar_t1-bar_t1_p1',
359      'text': 'bar.bar_t1.bar_t1_p1',
360      'name': 'bar_t1_p1'
361    }, apps_resolver.GetLink('bar.bar_p3.bar_t1_p1', namespace='foo'))
362    # Test extensions_resolver.
363    self.assertEqual({
364      'href': 'bar#property-bar_t1-bar_t1_p1',
365      'text': 'bar.bar_t1.bar_t1_p1',
366      'name': 'bar_t1_p1'
367    }, extensions_resolver.GetLink('bar.bar_p3.bar_t1_p1', namespace='foo'))
368    self.assertEqual({
369      'href': 'bar#property-bar_t1-bar_t1_p1',
370      'text': 'bar_t1.bar_t1_p1',
371      'name': 'bar_t1_p1'
372    }, apps_resolver.GetLink('bar_p3.bar_t1_p1', namespace='bar'))
373    self.assertEqual(
374        None,
375        apps_resolver.GetLink('bar.bar_p3.bar_t2_p1', namespace='bar'))
376    self.assertEqual(
377        None,
378        apps_resolver.GetLink('bar.bon.bar_e3', namespace='bar'))
379    self.assertEqual(
380        None,
381        apps_resolver.GetLink('bar_p3', namespace='baz.bon'))
382    self.assertEqual(
383        None,
384        apps_resolver.GetLink('falafel.faf', namespace='a'))
385    self.assertEqual(
386        None,
387        apps_resolver.GetLink('bar_p3', namespace='foo'))
388    # Exists in apps but not extensions.
389    self.assertEqual(
390        None,
391        extensions_resolver.GetLink('foo.foo_p3', namespace='baz'))
392
393if __name__ == '__main__':
394  unittest.main()
395