diff options
Diffstat (limited to 'tools/closure_linter-2.3.4/closure_linter/closurizednamespacesinfo_test.py')
-rwxr-xr-x | tools/closure_linter-2.3.4/closure_linter/closurizednamespacesinfo_test.py | 451 |
1 files changed, 451 insertions, 0 deletions
diff --git a/tools/closure_linter-2.3.4/closure_linter/closurizednamespacesinfo_test.py b/tools/closure_linter-2.3.4/closure_linter/closurizednamespacesinfo_test.py new file mode 100755 index 0000000..9a4c578 --- /dev/null +++ b/tools/closure_linter-2.3.4/closure_linter/closurizednamespacesinfo_test.py @@ -0,0 +1,451 @@ +#!/usr/bin/env python +# +# Copyright 2010 The Closure Linter Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS-IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Unit tests for ClosurizedNamespacesInfo.""" + + + +import unittest as googletest +from closure_linter import closurizednamespacesinfo +from closure_linter import javascriptstatetracker +from closure_linter import javascripttokenizer +from closure_linter import javascripttokens +from closure_linter import tokenutil + +# pylint: disable-msg=C6409 +TokenType = javascripttokens.JavaScriptTokenType + + +class ClosurizedNamespacesInfoTest(googletest.TestCase): + """Tests for ClosurizedNamespacesInfo.""" + + _test_cases = { + 'goog.global.anything': None, + 'package.CONSTANT': 'package', + 'package.methodName': 'package', + 'package.subpackage.methodName': 'package.subpackage', + 'package.subpackage.methodName.apply': 'package.subpackage', + 'package.ClassName.something': 'package.ClassName', + 'package.ClassName.Enum.VALUE.methodName': 'package.ClassName', + 'package.ClassName.CONSTANT': 'package.ClassName', + 'package.namespace.CONSTANT.methodName': 'package.namespace', + 'package.ClassName.inherits': 'package.ClassName', + 'package.ClassName.apply': 'package.ClassName', + 'package.ClassName.methodName.apply': 'package.ClassName', + 'package.ClassName.methodName.call': 'package.ClassName', + 'package.ClassName.prototype.methodName': 'package.ClassName', + 'package.ClassName.privateMethod_': 'package.ClassName', + 'package.className.privateProperty_': 'package.className', + 'package.className.privateProperty_.methodName': 'package.className', + 'package.ClassName.PrivateEnum_': 'package.ClassName', + 'package.ClassName.prototype.methodName.apply': 'package.ClassName', + 'package.ClassName.property.subProperty': 'package.ClassName', + 'package.className.prototype.something.somethingElse': 'package.className' + } + + _tokenizer = javascripttokenizer.JavaScriptTokenizer() + + def testGetClosurizedNamespace(self): + """Tests that the correct namespace is returned for various identifiers.""" + namespaces_info = closurizednamespacesinfo.ClosurizedNamespacesInfo( + closurized_namespaces=['package'], ignored_extra_namespaces=[]) + for identifier, expected_namespace in self._test_cases.items(): + actual_namespace = namespaces_info._GetClosurizedNamespace(identifier) + self.assertEqual( + expected_namespace, + actual_namespace, + 'expected namespace "' + str(expected_namespace) + + '" for identifier "' + str(identifier) + '" but was "' + + str(actual_namespace) + '"') + + def testIgnoredExtraNamespaces(self): + """Tests that ignored_extra_namespaces are ignored.""" + token = self._GetRequireTokens('package.Something') + namespaces_info = closurizednamespacesinfo.ClosurizedNamespacesInfo( + closurized_namespaces=['package'], + ignored_extra_namespaces=['package.Something']) + + self.assertFalse(namespaces_info.IsExtraRequire(token), + 'Should be valid since it is in ignored namespaces.') + + namespaces_info = closurizednamespacesinfo.ClosurizedNamespacesInfo( + ['package'], []) + + self.assertTrue(namespaces_info.IsExtraRequire(token), + 'Should be invalid since it is not in ignored namespaces.') + + def testIsExtraProvide_created(self): + """Tests that provides for created namespaces are not extra.""" + input_lines = [ + 'goog.provide(\'package.Foo\');', + 'package.Foo = function() {};' + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertFalse(namespaces_info.IsExtraProvide(token), + 'Should not be extra since it is created.') + + def testIsExtraProvide_createdIdentifier(self): + """Tests that provides for created identifiers are not extra.""" + input_lines = [ + 'goog.provide(\'package.Foo.methodName\');', + 'package.Foo.methodName = function() {};' + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertFalse(namespaces_info.IsExtraProvide(token), + 'Should not be extra since it is created.') + + def testIsExtraProvide_notCreated(self): + """Tests that provides for non-created namespaces are extra.""" + input_lines = ['goog.provide(\'package.Foo\');'] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertTrue(namespaces_info.IsExtraProvide(token), + 'Should be extra since it is not created.') + + def testIsExtraProvide_duplicate(self): + """Tests that providing a namespace twice makes the second one extra.""" + input_lines = [ + 'goog.provide(\'package.Foo\');', + 'goog.provide(\'package.Foo\');', + 'package.Foo = function() {};' + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + # Advance to the second goog.provide token. + token = tokenutil.Search(token.next, TokenType.IDENTIFIER) + + self.assertTrue(namespaces_info.IsExtraProvide(token), + 'Should be extra since it is already provided.') + + def testIsExtraProvide_notClosurized(self): + """Tests that provides of non-closurized namespaces are not extra.""" + input_lines = ['goog.provide(\'notclosurized.Foo\');'] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertFalse(namespaces_info.IsExtraProvide(token), + 'Should not be extra since it is not closurized.') + + def testIsExtraRequire_used(self): + """Tests that requires for used namespaces are not extra.""" + input_lines = [ + 'goog.require(\'package.Foo\');', + 'var x = package.Foo.methodName();' + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertFalse(namespaces_info.IsExtraRequire(token), + 'Should not be extra since it is used.') + + def testIsExtraRequire_usedIdentifier(self): + """Tests that requires for used methods on classes are extra.""" + input_lines = [ + 'goog.require(\'package.Foo.methodName\');', + 'var x = package.Foo.methodName();' + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertTrue(namespaces_info.IsExtraRequire(token), + 'Should require the package, not the method specifically.') + + def testIsExtraRequire_notUsed(self): + """Tests that requires for unused namespaces are extra.""" + input_lines = ['goog.require(\'package.Foo\');'] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertTrue(namespaces_info.IsExtraRequire(token), + 'Should be extra since it is not used.') + + def testIsExtraRequire_notClosurized(self): + """Tests that requires of non-closurized namespaces are not extra.""" + input_lines = ['goog.require(\'notclosurized.Foo\');'] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertFalse(namespaces_info.IsExtraRequire(token), + 'Should not be extra since it is not closurized.') + + def testIsExtraRequire_objectOnClass(self): + """Tests that requiring an object on a class is extra.""" + input_lines = [ + 'goog.require(\'package.Foo.Enum\');', + 'var x = package.Foo.Enum.VALUE1;', + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertTrue(namespaces_info.IsExtraRequire(token), + 'The whole class, not the object, should be required.'); + + def testIsExtraRequire_constantOnClass(self): + """Tests that requiring a constant on a class is extra.""" + input_lines = [ + 'goog.require(\'package.Foo.CONSTANT\');', + 'var x = package.Foo.CONSTANT', + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertTrue(namespaces_info.IsExtraRequire(token), + 'The class, not the constant, should be required.'); + + def testIsExtraRequire_constantNotOnClass(self): + """Tests that requiring a constant not on a class is OK.""" + input_lines = [ + 'goog.require(\'package.subpackage.CONSTANT\');', + 'var x = package.subpackage.CONSTANT', + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertFalse(namespaces_info.IsExtraRequire(token), + 'Constants can be required except on classes.'); + + def testIsExtraRequire_methodNotOnClass(self): + """Tests that requiring a method not on a class is OK.""" + input_lines = [ + 'goog.require(\'package.subpackage.method\');', + 'var x = package.subpackage.method()', + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertFalse(namespaces_info.IsExtraRequire(token), + 'Methods can be required except on classes.'); + + def testIsExtraRequire_defaults(self): + """Tests that there are no warnings about extra requires for test utils""" + input_lines = ['goog.require(\'goog.testing.jsunit\');'] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['goog'], []) + + self.assertFalse(namespaces_info.IsExtraRequire(token), + 'Should not be extra since it is for testing.') + + def testGetMissingProvides_provided(self): + """Tests that provided functions don't cause a missing provide.""" + input_lines = [ + 'goog.provide(\'package.Foo\');', + 'package.Foo = function() {};' + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertEquals(0, len(namespaces_info.GetMissingProvides())) + + def testGetMissingProvides_providedIdentifier(self): + """Tests that provided identifiers don't cause a missing provide.""" + input_lines = [ + 'goog.provide(\'package.Foo.methodName\');', + 'package.Foo.methodName = function() {};' + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertEquals(0, len(namespaces_info.GetMissingProvides())) + + def testGetMissingProvides_providedParentIdentifier(self): + """Tests that provided identifiers on a class don't cause a missing provide + on objects attached to that class.""" + input_lines = [ + 'goog.provide(\'package.foo.ClassName\');', + 'package.foo.ClassName.methodName = function() {};', + 'package.foo.ClassName.ObjectName = 1;', + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertEquals(0, len(namespaces_info.GetMissingProvides())) + + def testGetMissingProvides_unprovided(self): + """Tests that unprovided functions cause a missing provide.""" + input_lines = ['package.Foo = function() {};'] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertEquals(1, len(namespaces_info.GetMissingProvides())) + self.assertTrue('package.Foo' in namespaces_info.GetMissingProvides()) + + def testGetMissingProvides_privatefunction(self): + """Tests that unprovided private functions don't cause a missing provide.""" + input_lines = ['package.Foo_ = function() {};'] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertEquals(0, len(namespaces_info.GetMissingProvides())) + + def testGetMissingProvides_required(self): + """Tests that required namespaces don't cause a missing provide.""" + input_lines = [ + 'goog.require(\'package.Foo\');', + 'package.Foo.methodName = function() {};' + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertEquals(0, len(namespaces_info.GetMissingProvides())) + + def testGetMissingRequires_required(self): + """Tests that required namespaces don't cause a missing require.""" + input_lines = [ + 'goog.require(\'package.Foo\');', + 'package.Foo();' + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertEquals(0, len(namespaces_info.GetMissingProvides())) + + def testGetMissingRequires_requiredIdentifier(self): + """Tests that required namespaces satisfy identifiers on that namespace.""" + input_lines = [ + 'goog.require(\'package.Foo\');', + 'package.Foo.methodName();' + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertEquals(0, len(namespaces_info.GetMissingProvides())) + + def testGetMissingRequires_requiredParentClass(self): + """Tests that requiring a parent class of an object is sufficient to prevent + a missing require on that object.""" + input_lines = [ + 'goog.require(\'package.Foo\');', + 'package.Foo.methodName();', + 'package.Foo.methodName(package.Foo.ObjectName);' + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertEquals(0, len(namespaces_info.GetMissingRequires())) + + def testGetMissingRequires_unrequired(self): + """Tests that unrequired namespaces cause a missing require.""" + input_lines = ['package.Foo();'] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertEquals(1, len(namespaces_info.GetMissingRequires())) + self.assertTrue('package.Foo' in namespaces_info.GetMissingRequires()) + + def testGetMissingRequires_provided(self): + """Tests that provided namespaces satisfy identifiers on that namespace.""" + input_lines = [ + 'goog.provide(\'package.Foo\');', + 'package.Foo.methodName();' + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertEquals(0, len(namespaces_info.GetMissingRequires())) + + def testGetMissingRequires_created(self): + """Tests that created namespaces do not satisfy usage of an identifier.""" + input_lines = [ + 'package.Foo = function();', + 'package.Foo.methodName();' + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertEquals(1, len(namespaces_info.GetMissingRequires())) + self.assertTrue('package.Foo' in namespaces_info.GetMissingRequires()) + + def testGetMissingRequires_createdIdentifier(self): + """Tests that created identifiers satisfy usage of the identifier.""" + input_lines = [ + 'package.Foo.methodName = function();', + 'package.Foo.methodName();' + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertEquals(0, len(namespaces_info.GetMissingRequires())) + + def testGetMissingRequires_objectOnClass(self): + """Tests that we should require a class, not the object on the class.""" + input_lines = [ + 'goog.require(\'package.Foo.Enum\');', + 'var x = package.Foo.Enum.VALUE1;', + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertEquals(1, len(namespaces_info.GetMissingRequires()), + 'The whole class, not the object, should be required.'); + + def testIsFirstProvide(self): + """Tests operation of the isFirstProvide method.""" + input_lines = [ + 'goog.provide(\'package.Foo\');', + 'package.Foo.methodName();' + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = self._GetInitializedNamespacesInfo(token, ['package'], []) + + self.assertTrue(namespaces_info.IsFirstProvide(token)) + + def testGetWholeIdentifierString(self): + """Tests that created identifiers satisfy usage of the identifier.""" + input_lines = [ + 'package.Foo.', + ' veryLong.', + ' identifier;' + ] + token = self._tokenizer.TokenizeFile(input_lines) + namespaces_info = closurizednamespacesinfo.ClosurizedNamespacesInfo([], []) + + self.assertEquals('package.Foo.veryLong.identifier', + namespaces_info._GetWholeIdentifierString(token)) + self.assertEquals(None, + namespaces_info._GetWholeIdentifierString(token.next)) + + def _GetInitializedNamespacesInfo(self, token, closurized_namespaces, + ignored_extra_namespaces): + """Returns a namespaces info initialized with the given token stream.""" + namespaces_info = closurizednamespacesinfo.ClosurizedNamespacesInfo( + closurized_namespaces=closurized_namespaces, + ignored_extra_namespaces=ignored_extra_namespaces) + state_tracker = javascriptstatetracker.JavaScriptStateTracker() + + while token: + namespaces_info.ProcessToken(token, state_tracker) + token = token.next + + return namespaces_info + + def _GetProvideTokens(self, namespace): + """Returns a list of tokens for a goog.require of the given namespace.""" + line_text = 'goog.require(\'' + namespace + '\');\n' + return javascripttokenizer.JavaScriptTokenizer().TokenizeFile([line_text]) + + def _GetRequireTokens(self, namespace): + """Returns a list of tokens for a goog.require of the given namespace.""" + line_text = 'goog.require(\'' + namespace + '\');\n' + return javascripttokenizer.JavaScriptTokenizer().TokenizeFile([line_text]) + +if __name__ == '__main__': + googletest.main() |