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