Home | History | Annotate | Download | only in build
      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 import unittest
      6 
      7 import parse_deps
      8 import os
      9 
     10 srcdir = os.path.join(os.path.dirname(__file__), '../src')
     11 
     12 class JSStripTests(unittest.TestCase):
     13   def test_tokenize_0(self):
     14     tokens = list(parse_deps._tokenize_js(''))
     15     self.assertEquals([], tokens)
     16 
     17   def test_tokenize_nl(self):
     18     tokens = list(parse_deps._tokenize_js('\n'))
     19     self.assertEquals(['\n'], tokens)
     20 
     21   def test_tokenize_slashslash_comment(self):
     22     tokens = list(parse_deps._tokenize_js('A // foo'))
     23     self.assertEquals(['A ', '//', ' foo'], tokens)
     24 
     25   def test_tokenize_slashslash_comment_then_newline2(self):
     26     tokens = list(parse_deps._tokenize_js("""A // foo
     27 bar"""
     28 ))
     29     self.assertEquals(['A ', '//', ' foo', '\n', 'bar'], tokens)
     30 
     31   def test_tokenize_cstyle_comment(self):
     32     tokens = list(parse_deps._tokenize_js("""A /* foo */"""))
     33     self.assertEquals(['A ', '/*', ' foo ', '*/'], tokens)
     34 
     35   def test_tokenize_cstyle_comment(self):
     36     tokens = list(parse_deps._tokenize_js("""A /* foo
     37 *bar
     38 */"""))
     39     self.assertEquals(['A ', '/*', ' foo', '\n', '*bar', '\n', '*/'], tokens)
     40 
     41   def test_strip_comments(self):
     42     self.assertEquals('A ', parse_deps._strip_js_comments('A // foo'))
     43 
     44     self.assertEquals('A  b', parse_deps._strip_js_comments('A /* foo */ b'))
     45     self.assertEquals('A  b', parse_deps._strip_js_comments("""A /* foo
     46  */ b"""))
     47 
     48 
     49 class ValidateTests(unittest.TestCase):
     50   def test_validate_1(self):
     51     text = """// blahblahblah
     52 
     53 'use strict';
     54 
     55 base.require('dependency1');
     56 """
     57     module = parse_deps.Module('myModule')
     58     stripped_text = parse_deps._strip_js_comments(text)
     59     module.validate_uses_strict_mode_(stripped_text)
     60 
     61   def test_validate_2(self):
     62     text = """// blahblahblah
     63 
     64 base.require('dependency1');
     65 """
     66     module = parse_deps.Module('myModule')
     67     stripped_text = parse_deps._strip_js_comments(text)
     68     self.assertRaises(lambda: module.validate_uses_strict_mode_(stripped_text))
     69 
     70 class ParseTests(unittest.TestCase):
     71   def test_parse_definition_1(self):
     72     text = """// blahblahblah
     73 'use strict';
     74 base.require('dependency1');
     75 base.require('dependency2');
     76 base.requireStylesheet('myStylesheet');
     77 """
     78     module = parse_deps.Module('myModule')
     79     stripped_text = parse_deps._strip_js_comments(text)
     80     module.parse_definition_(stripped_text)
     81     self.assertEquals(['myStylesheet'], module.style_sheet_names);
     82     self.assertEquals(['dependency1', 'dependency2'],
     83                       module.dependent_module_names);
     84 
     85   def test_parse_definition_missing_semis(self):
     86     text = """// blahblahblah
     87 'use strict';
     88 base.require('dependency1')
     89 base.require('dependency2');
     90 base.requireStylesheet('myStylesheet')
     91 """
     92     module = parse_deps.Module('myModule')
     93     stripped_text = parse_deps._strip_js_comments(text)
     94     module.parse_definition_(stripped_text)
     95     self.assertEquals(['myStylesheet'], module.style_sheet_names);
     96     self.assertEquals(['dependency1', 'dependency2'],
     97                       module.dependent_module_names);
     98 
     99   def test_parse_definition_with_deps_and_stylesheet_swapped(self):
    100     text = """// blahblahblah
    101 'use strict';
    102 base.require('dependency1');
    103 base.requireStylesheet('myStylesheet');
    104 base.require('dependency2');
    105 """
    106     module = parse_deps.Module('myModule')
    107     stripped_text = parse_deps._strip_js_comments(text)
    108     module.parse_definition_(stripped_text)
    109     self.assertEquals(['myStylesheet'], module.style_sheet_names);
    110     self.assertEquals(['dependency1', 'dependency2'],
    111                       module.dependent_module_names);
    112 
    113   def test_parse_empty_definition(self):
    114     text = """// blahblahblah
    115 'use strict';
    116 """
    117     module = parse_deps.Module('myModule')
    118     stripped_text = parse_deps._strip_js_comments(text)
    119     module.parse_definition_(stripped_text, decl_required=False)
    120     self.assertEquals([], module.style_sheet_names);
    121     self.assertEquals([], module.dependent_module_names);
    122 
    123   def test_parse_definition_3(self):
    124     text = """// blahblahblah
    125 'use strict';
    126 base.require('dependency1');
    127 //base.require('dependency2');
    128 """
    129     module = parse_deps.Module('myModule')
    130     stripped_text = parse_deps._strip_js_comments(text)
    131     module.parse_definition_(stripped_text)
    132     self.assertEquals([], module.style_sheet_names);
    133     self.assertEquals(['dependency1'], module.dependent_module_names);
    134 
    135   def test_parse_definition_4(self):
    136     text = """// Copyright (c) 2012 The Chromium Authors. All rights reserved.
    137 // Use of this source code is governed by a BSD-style license that can be
    138 // found in the LICENSE file.
    139 
    140 'use strict';
    141 
    142 /**
    143  * @fileoverview TimelineView visualizes TRACE_EVENT events using the
    144  * tracing.TimelineTrackView component and adds in selection summary and
    145  * control buttons.
    146  */
    147 base.requireStylesheet('timeline_view')
    148 base.require('timeline_track_view');
    149 base.require('timeline_analysis');
    150 base.require('overlay');
    151 base.require('trace_event_importer');
    152 base.require('linux_perf_importer');
    153 base.exportsTo('tracing', function() {"""
    154 
    155     module = parse_deps.Module('timeline_view')
    156     stripped_text = parse_deps._strip_js_comments(text)
    157     module.parse_definition_(stripped_text)
    158     self.assertEquals(['timeline_view'], module.style_sheet_names);
    159     self.assertEquals(['timeline_track_view',
    160                        'timeline_analysis',
    161                        'overlay',
    162                        'trace_event_importer',
    163                        'linux_perf_importer'], module.dependent_module_names);
    164 
    165   def test_parse_definition_with_definition_in_comments(self):
    166     text = """// SomeComment
    167 /*
    168  * All subclasses should depend on linux_perf_parser, e.g.
    169  *
    170  * base.require('linux_perf_parser');
    171  * base.exportTo('tracing', function() { });
    172  *
    173  */
    174 'use strict';
    175 base.require('dependency1');
    176 base.require('dependency2');
    177 """
    178     module = parse_deps.Module('myModule')
    179     stripped_text = parse_deps._strip_js_comments(text)
    180     module.parse_definition_(stripped_text)
    181     self.assertEquals([], module.style_sheet_names);
    182     self.assertEquals(['dependency1', 'dependency2'],
    183                       module.dependent_module_names);
    184 
    185   def test_parse_dependency_with_slashes(self):
    186     text = """base.require('foo/dependency1')
    187 """
    188     module = parse_deps.Module('myModule')
    189     self.assertRaises(parse_deps.DepsException,
    190                       lambda: module.parse_definition_(text))
    191 
    192   def test_parse_dependency_with_dots(self):
    193     text = """base.require('foo.dependency1')
    194 """
    195     module = parse_deps.Module('myModule')
    196     stripped_text = parse_deps._strip_js_comments(text)
    197     module.parse_definition_(stripped_text)
    198     self.assertEquals([], module.style_sheet_names);
    199     self.assertEquals(['foo.dependency1'],
    200                       module.dependent_module_names);
    201 
    202 
    203 class ResourceFinderStub(object):
    204   def __init__(self):
    205     self.modules = {}
    206 
    207   def add_module(self, name, filename, contents):
    208     module = {'filename': filename,
    209               'contents': contents}
    210     self.modules[name] = module
    211 
    212   def find_and_load_module(self, current_module, requested_module_name):
    213     if requested_module_name not in self.modules:
    214       return None
    215     return (self.modules[requested_module_name]['filename'],
    216             self.modules[requested_module_name]['contents'])
    217 
    218 
    219 x_contents = """
    220 'use strict';
    221 base.require('y');
    222 base.require('z');
    223 base.exportTo('xyz', function() { });
    224 """
    225 
    226 y_contents = """
    227 'use strict';
    228 base.require('z');
    229 base.exportsTo('xyz', function() { });
    230 """
    231 
    232 z_contents = """
    233 'use strict';
    234 base.exportsTo('xyz', function() { });
    235 """
    236 
    237 class FlattenTests(unittest.TestCase):
    238   def test_module(self):
    239     resource_finder = ResourceFinderStub()
    240     resource_finder.add_module('y', 'y.js', y_contents);
    241     resource_finder.add_module('z', 'z.js', z_contents);
    242 
    243     x_module = parse_deps.Module('x')
    244     x_module.load_and_parse('x.js', x_contents)
    245 
    246     all_resources = {}
    247     x_module.resolve(all_resources, resource_finder)
    248 
    249     self.assertEquals([all_resources['scripts']['y'],
    250                        all_resources['scripts']['z']],
    251                       x_module.dependent_modules)
    252 
    253     already_loaded_set = set()
    254     load_sequence = []
    255     x_module.compute_load_sequence_recursive(load_sequence, already_loaded_set)
    256 
    257     self.assertEquals([all_resources['scripts']['z'],
    258                        all_resources['scripts']['y'],
    259                        x_module],
    260                       load_sequence)
    261 
    262 
    263 class ResourceFinderTest(unittest.TestCase):
    264   def test_basic(self):
    265 
    266     resource_finder = parse_deps.ResourceFinder(srcdir)
    267     module = parse_deps.Module('guid')
    268     module.load_and_parse(os.path.join(srcdir, 'base', 'guid.js'))
    269     filename, contents = resource_finder.find_and_load_module(module, 'base')
    270 
    271     self.assertTrue(os.path.samefile(filename, os.path.join(srcdir, 'base.js')))
    272     expected_contents = ''
    273     with open(os.path.join(srcdir, 'base.js')) as f:
    274       expected_contents = f.read()
    275     self.assertEquals(contents, expected_contents)
    276 
    277   def test_dependency_in_subdir(self):
    278     resource_finder = parse_deps.ResourceFinder(srcdir)
    279     module = parse_deps.Module('base.guid')
    280     module.load_and_parse(os.path.join(srcdir, 'base', 'guid.js'))
    281     filename, contents = resource_finder.find_and_load_module(
    282         module, 'tracing.tracks.track')
    283 
    284     assert filename
    285 
    286     self.assertTrue(os.path.samefile(filename, os.path.join(
    287       srcdir, 'tracing', 'tracks', 'track.js')))
    288     expected_contents = ''
    289     with open(os.path.join(srcdir, 'tracing', 'tracks', 'track.js')) as f:
    290       expected_contents = f.read()
    291     self.assertEquals(contents, expected_contents)
    292 
    293 
    294 class CalcLoadSequenceTest(unittest.TestCase):
    295   def test_one_toplevel_nodeps(self):
    296     load_sequence = parse_deps.calc_load_sequence(
    297       [os.path.join(srcdir, 'base', 'guid.js')], srcdir)
    298     name_sequence = [x.name for x in load_sequence]
    299     self.assertEquals(['base.guid'], name_sequence)
    300 
    301   # Tests that we resolve deps between toplevels.
    302   def test_calc_load_sequence_two_toplevels(self):
    303     pass
    304 
    305 if __name__ == '__main__':
    306   unittest.main()
    307