425 lines
14 KiB
Java
425 lines
14 KiB
Java
/*
|
|
* Copyright 2007 The Closure Compiler Authors.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
package com.google.javascript.jscomp;
|
|
|
|
import com.google.common.collect.Sets;
|
|
|
|
import java.util.Set;
|
|
|
|
/**
|
|
* Tests for {@link StripCode}.
|
|
*
|
|
*/
|
|
public class StripCodeTest extends CompilerTestCase {
|
|
|
|
private static final String EXTERNS = "";
|
|
|
|
public StripCodeTest() {
|
|
super(EXTERNS, true);
|
|
}
|
|
|
|
/**
|
|
* Creates an instance for removing logging code.
|
|
*
|
|
* @param compiler The Compiler
|
|
* @return A new {@link StripCode} instance
|
|
*/
|
|
private static StripCode createLoggerInstance(Compiler compiler) {
|
|
Set<String> stripTypes = Sets.newHashSet(
|
|
"goog.debug.DebugWindow",
|
|
"goog.debug.FancyWindow",
|
|
"goog.debug.Formatter",
|
|
"goog.debug.HtmlFormatter",
|
|
"goog.debug.TextFormatter",
|
|
"goog.debug.Logger",
|
|
"goog.debug.LogManager",
|
|
"goog.debug.LogRecord",
|
|
"goog.net.BrowserChannel.LogSaver",
|
|
"GA_GoogleDebugger");
|
|
|
|
Set<String> stripNames = Sets.newHashSet(
|
|
"logger",
|
|
"logger_",
|
|
"debugWindow",
|
|
"debugWindow_",
|
|
"logFormatter_",
|
|
"logBuffer_");
|
|
|
|
Set<String> stripNamePrefixes = Sets.newHashSet("trace");
|
|
Set<String> stripTypePrefixes = Sets.newHashSet("e.f.Trace");
|
|
|
|
return new StripCode(compiler, stripTypes, stripNames, stripTypePrefixes,
|
|
stripNamePrefixes);
|
|
}
|
|
|
|
@Override public CompilerPass getProcessor(Compiler compiler) {
|
|
return createLoggerInstance(compiler);
|
|
}
|
|
|
|
public void testLoggerDefinedInConstructor() {
|
|
test("a.b.c = function() {" +
|
|
" this.logger = goog.debug.Logger.getLogger('a.b.c');" +
|
|
"};",
|
|
"a.b.c=function(){}");
|
|
}
|
|
|
|
public void testLoggerDefinedInPrototype1() {
|
|
test("a.b.c = function() {};" +
|
|
"a.b.c.prototype.logger = goog.debug.Logger.getLogger('a.b.c');",
|
|
"a.b.c=function(){}");
|
|
}
|
|
|
|
public void testLoggerDefinedInPrototype2() {
|
|
test("a.b.c = function() {};" +
|
|
"a.b.c.prototype = {logger: goog.debug.Logger.getLogger('a.b.c')}",
|
|
"a.b.c = function() {};" +
|
|
"a.b.c.prototype = {}");
|
|
}
|
|
|
|
public void testLoggerDefinedInPrototype3() {
|
|
test("a.b.c = function() {};" +
|
|
"a.b.c.prototype = { " +
|
|
" get logger() {return goog.debug.Logger.getLogger('a.b.c')}" +
|
|
"}",
|
|
"a.b.c = function() {};" +
|
|
"a.b.c.prototype = {}");
|
|
}
|
|
|
|
public void testLoggerDefinedInPrototype4() {
|
|
test("a.b.c = function() {};" +
|
|
"a.b.c.prototype = { " +
|
|
" set logger(a) {this.x = goog.debug.Logger.getLogger('a.b.c')}" +
|
|
"}",
|
|
"a.b.c = function() {};" +
|
|
"a.b.c.prototype = {}");
|
|
}
|
|
|
|
public void testLoggerDefinedInPrototype5() {
|
|
test("a.b.c = function() {};" +
|
|
"a.b.c.prototype = { " +
|
|
" get f() {return this.x;}," +
|
|
" set f(a) {this.x = goog.debug.Logger.getLogger('a.b.c')}" +
|
|
"}",
|
|
"a.b.c = function() {};" +
|
|
"a.b.c.prototype = { " +
|
|
" get f() {return this.x;}," +
|
|
" set f(a) {this.x = null}" +
|
|
"}");
|
|
}
|
|
|
|
public void testLoggerDefinedStatically() {
|
|
test("a.b.c = function() {};" +
|
|
"a.b.c.logger = goog.debug.Logger.getLogger('a.b.c');",
|
|
"a.b.c=function(){}");
|
|
}
|
|
|
|
public void testLoggerDefinedInObjectLiteral1() {
|
|
test("a.b.c = {" +
|
|
" x: 0," +
|
|
" logger: goog.debug.Logger.getLogger('a.b.c')" +
|
|
"};",
|
|
"a.b.c={x:0}");
|
|
}
|
|
|
|
public void testLoggerDefinedInObjectLiteral2() {
|
|
test("a.b.c = {" +
|
|
" x: 0," +
|
|
" get logger() {return goog.debug.Logger.getLogger('a.b.c')}" +
|
|
"};",
|
|
"a.b.c={x:0}");
|
|
}
|
|
|
|
public void testLoggerDefinedInObjectLiteral3() {
|
|
test("a.b.c = {" +
|
|
" x: null," +
|
|
" get logger() {return this.x}," +
|
|
" set logger(a) {this.x = goog.debug.Logger.getLogger(a)}" +
|
|
"};",
|
|
"a.b.c={x:null}");
|
|
}
|
|
|
|
public void testLoggerDefinedInObjectLiteral4() {
|
|
test("a.b.c = {" +
|
|
" x: null," +
|
|
" get y() {return this.x}," +
|
|
" set y(a) {this.x = goog.debug.Logger.getLogger(a)}" +
|
|
"};",
|
|
"a.b.c = {" +
|
|
" x: null," +
|
|
" get y() {return this.x}," +
|
|
" set y(a) {this.x = null}" +
|
|
"};");
|
|
}
|
|
|
|
public void testLoggerDefinedInPrototypeAndUsedInConstructor() {
|
|
test("a.b.c = function(level) {" +
|
|
" if (!this.logger.isLoggable(level)) {" +
|
|
" this.logger.setLevel(level);" +
|
|
" }" +
|
|
" this.logger.log(level, 'hi');" +
|
|
"};" +
|
|
"a.b.c.prototype.logger = goog.debug.Logger.getLogger('a.b.c');" +
|
|
"a.b.c.prototype.go = function() { this.logger.finer('x'); };",
|
|
"a.b.c=function(level){if(!null);};" +
|
|
"a.b.c.prototype.go=function(){}");
|
|
}
|
|
|
|
public void testLoggerDefinedStaticallyAndUsedInConstructor() {
|
|
test("a.b.c = function(level) {" +
|
|
" if (!a.b.c.logger.isLoggable(level)) {" +
|
|
" a.b.c.logger.setLevel(level);" +
|
|
" }" +
|
|
" a.b.c.logger.log(level, 'hi');" +
|
|
"};" +
|
|
"a.b.c.logger = goog.debug.Logger.getLogger('a.b.c');",
|
|
"a.b.c=function(level){if(!null);}");
|
|
}
|
|
|
|
public void testLoggerVarDeclaration() {
|
|
test("var logger = opt_logger || goog.debug.LogManager.getRoot();", "");
|
|
}
|
|
|
|
public void testLoggerMethodCallByVariableType() {
|
|
test("var x = goog.debug.Logger.getLogger('a.b.c'); y.info(a); x.info(a);",
|
|
"y.info(a)");
|
|
}
|
|
|
|
public void testSubPropertyAccessByVariableName() {
|
|
test("var x, y = goog.debug.Logger.getLogger('a.b.c');" +
|
|
"var logger = x;" +
|
|
"var curlevel = logger.level_ ? logger.getLevel().name : 3;",
|
|
"var x;var curlevel=null?null:3");
|
|
}
|
|
|
|
public void testPrefixedVariableName() {
|
|
test("this.blcLogger_ = goog.debug.Logger.getLogger('a.b.c');" +
|
|
"this.blcLogger_.fine('Raised dirty states.');", "");
|
|
}
|
|
|
|
public void testPrefixedPropertyName() {
|
|
test("a.b.c.staticLogger_ = goog.debug.Logger.getLogger('a.b.c');" +
|
|
"a.b.c.staticLogger_.fine('-' + a.b.c.d_())", "");
|
|
}
|
|
|
|
public void testPrefixedClassName() {
|
|
test("a.b.MyLogger = function(logger) {" +
|
|
" this.logger_ = logger;" +
|
|
"};" +
|
|
"a.b.MyLogger.prototype.shout = function(msg, opt_x) {" +
|
|
" this.logger_.log(goog.debug.Logger.Level.SHOUT, msg, opt_x);" +
|
|
"};",
|
|
"a.b.MyLogger=function(logger){};" +
|
|
"a.b.MyLogger.prototype.shout=function(msg,opt_x){}");
|
|
}
|
|
|
|
public void testLoggerClassDefinition() {
|
|
test("goog.debug.Logger=function(name){this.name_=name}", "");
|
|
}
|
|
|
|
public void testStaticLoggerPropertyDefinition() {
|
|
test("goog.debug.Logger.Level.SHOUT=" +
|
|
"new goog.debug.Logger.Level(x,1200)", "");
|
|
}
|
|
|
|
public void testStaticLoggerMethodDefinition() {
|
|
test("goog.debug.Logger.getLogger=function(name){" +
|
|
"return goog.debug.LogManager.getLogger(name)" +
|
|
"};", "");
|
|
}
|
|
|
|
public void testPrototypeFieldDefinition() {
|
|
test("goog.debug.Logger.prototype.level_=null;", "");
|
|
}
|
|
|
|
public void testPrototypeFieldDefinitionWithoutAssignment() {
|
|
test("goog.debug.Logger.prototype.level_;", "");
|
|
}
|
|
|
|
public void testPrototypeMethodDefinition() {
|
|
test("goog.debug.Logger.prototype.addHandler=" +
|
|
"function(handler){this.handlers_.push(handler)};", "");
|
|
}
|
|
|
|
public void testPublicPropertyAssignment() {
|
|
// We don't eliminate property assignments on vars/properties that we
|
|
// remove, since the debugging classes should have setter methods instead
|
|
// of public properties.
|
|
testSame("rootLogger.someProperty=3");
|
|
testSame("this.blcLogger_.level=x");
|
|
testSame("goog.ui.Component.logger.prop=y");
|
|
}
|
|
|
|
public void testGlobalCallWithStrippedType() {
|
|
testSame("window.alert(goog.debug.Logger)");
|
|
}
|
|
|
|
public void testClassDefiningCallWithStripType1() {
|
|
test("goog.debug.Logger.inherits(Object)", "");
|
|
}
|
|
|
|
public void testClassDefiningCallWithStripType2() {
|
|
test("goog.formatter=function(){};" +
|
|
"goog.inherits(goog.debug.Formatter,goog.formatter)",
|
|
"goog.formatter=function(){}");
|
|
}
|
|
|
|
public void testClassDefiningCallWithStripType3() {
|
|
test("goog.formatter=function(){};" +
|
|
"goog.inherits(goog.formatter,goog.debug.Formatter)",
|
|
null, StripCode.STRIP_TYPE_INHERIT_ERROR);
|
|
}
|
|
|
|
public void testClassDefiningCallWithStripType4() {
|
|
test("goog.formatter=function(){};" +
|
|
"goog.formatter.inherits(goog.debug.Formatter)",
|
|
null, StripCode.STRIP_TYPE_INHERIT_ERROR);
|
|
}
|
|
|
|
public void testClassDefiningCallWithStripType5() {
|
|
testSame("goog.formatter=function(){};" +
|
|
"goog.formatter.inherits(goog.debug.FormatterFoo)");
|
|
}
|
|
|
|
public void testClassDefiningCallWithStripType6() {
|
|
test("goog.formatter=function(){};" +
|
|
"goog.formatter.inherits(goog.debug.Formatter.Foo)",
|
|
null, StripCode.STRIP_TYPE_INHERIT_ERROR);
|
|
}
|
|
|
|
public void testClassDefiningCallWithStripType7() {
|
|
test("goog.inherits(goog.debug.TextFormatter,goog.debug.Formatter)", "");
|
|
}
|
|
|
|
public void testClassDefiningCallWithStripType8() {
|
|
// listed types should be removed.
|
|
test("goog.debug.DebugWindow = function(){}", "");
|
|
test("goog.inherits(goog.debug.DebugWindow,Base)", "");
|
|
|
|
// types that happen to have strip types as prefix should not be
|
|
// stripped.
|
|
testSame("goog.debug.DebugWindowFoo=function(){}");
|
|
testSame("goog.inherits(goog.debug.DebugWindowFoo,Base)");
|
|
testSame("goog.debug.DebugWindowFoo");
|
|
testSame("goog.debug.DebugWindowFoo=1");
|
|
|
|
// qualified subtypes should be removed.
|
|
test("goog.debug.DebugWindow.Foo=function(){}", "");
|
|
test("goog.inherits(goog.debug.DebugWindow.Foo,Base)", "");
|
|
test("goog.debug.DebugWindow.Foo", "");
|
|
test("goog.debug.DebugWindow.Foo=1", "");
|
|
}
|
|
|
|
public void testPropertyWithEmptyStringKey() {
|
|
test("goog.format.NUMERIC_SCALES_BINARY_ = {'': 1};",
|
|
"goog.format.NUMERIC_SCALES_BINARY_={\"\":1}");
|
|
}
|
|
|
|
public void testVarinIf() {
|
|
test("if(x)var logger=null;else foo()", "if(x);else foo()");
|
|
}
|
|
|
|
public void testGetElemInIf() {
|
|
test("var logger=null;if(x)logger[f];else foo()", "if(x);else foo()");
|
|
}
|
|
|
|
public void testAssignInIf() {
|
|
test("var logger=null;if(x)logger=1;else foo()",
|
|
"if(x);else foo()");
|
|
}
|
|
|
|
public void testNamePrefix() {
|
|
test("a = function(traceZZZ) {}; a.prototype.traceXXX = {x: 1};" +
|
|
"a.prototype.z = function() { this.traceXXX.f(); };" +
|
|
"var traceYYY = 0;",
|
|
"a=function(traceZZZ){};a.prototype.z=function(){}");
|
|
}
|
|
|
|
public void testTypePrefix() {
|
|
test("e.f.TraceXXX = function() {}; " +
|
|
"e.f.TraceXXX.prototype.yyy = 2;", "");
|
|
}
|
|
|
|
public void testStripCallsToStrippedNames() {
|
|
test("a = function() { this.logger_ = function(msg){}; };" +
|
|
"a.prototype.b = function() { this.logger_('hi'); }",
|
|
"a=function(){};a.prototype.b=function(){}");
|
|
test("a = function() {};" +
|
|
"a.prototype.logger_ = function(msg) {};" +
|
|
"a.prototype.b = function() { this.logger_('hi'); }",
|
|
"a=function(){};a.prototype.b=function(){}");
|
|
}
|
|
|
|
public void testStripVarsInitializedFromStrippedNames() {
|
|
test("a = function() { this.logger_ = function() { return 1; }; };" +
|
|
"a.prototype.b = function() { " +
|
|
" var one = this.logger_(); if (one) foo() }",
|
|
"a=function(){};a.prototype.b=function(){if(null)foo()}");
|
|
}
|
|
|
|
public void testReportErrorOnStripInNestedAssignment() {
|
|
// Strip name
|
|
test("(foo.logger_ = 7) + 8",
|
|
"(foo.logger_ = 7) + 8",
|
|
StripCode.STRIP_ASSIGNMENT_ERROR);
|
|
|
|
// Strip namespaced type
|
|
test("(goog.debug.Logger.foo = 7) + 8",
|
|
"(goog.debug.Logger.foo = 7) + 8",
|
|
StripCode.STRIP_ASSIGNMENT_ERROR);
|
|
|
|
// Strip non-namespaced type
|
|
test("(GA_GoogleDebugger.foo = 7) + 8",
|
|
"(GA_GoogleDebugger.foo = 7) + 8",
|
|
StripCode.STRIP_ASSIGNMENT_ERROR);
|
|
}
|
|
|
|
public void testNewOperatior1() {
|
|
test("function foo() {} foo.bar = new goog.debug.Logger();",
|
|
"function foo() {} foo.bar = null;");
|
|
}
|
|
|
|
public void testNewOperatior2() {
|
|
test("function foo() {} foo.bar = (new goog.debug.Logger()).foo();",
|
|
"function foo() {} foo.bar = null;");
|
|
}
|
|
|
|
public void testCrazyNesting1() {
|
|
test("var x = {}; x[new goog.debug.Logger()] = 3;",
|
|
"var x = {}; x[null] = 3;");
|
|
}
|
|
|
|
public void testCrazyNesting2() {
|
|
test("var x = {}; x[goog.debug.Logger.getLogger()] = 3;",
|
|
"var x = {}; x[null] = 3;");
|
|
}
|
|
|
|
public void testCrazyNesting3() {
|
|
test("var x = function() {}; x(new goog.debug.Logger());",
|
|
"var x = function() {}; x(null);");
|
|
}
|
|
|
|
public void testCrazyNesting4() {
|
|
test("var x = function() {}; x(goog.debug.Logger.getLogger());",
|
|
"var x = function() {}; x(null);");
|
|
}
|
|
|
|
public void testCrazyNesting5() {
|
|
test("var x = function() {}; var y = {}; " +
|
|
"var z = goog.debug.Logger.getLogger(); x(y[z['foo']]);",
|
|
"var x = function() {}; var y = {}; x(y[null]);");
|
|
}
|
|
}
|