This repository has been archived on 2023-06-18. You can view files and clone it, but cannot push or open issues or pull requests.
ima02/resources/defects4j-checkout-closure-1f/test/com/google/javascript/jscomp/InstrumentFunctionsTest.java

264 lines
8.7 KiB
Java
Raw Permalink Normal View History

2023-04-25 11:33:41 +00:00
/*
* Copyright 2008 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.ImmutableList;
import com.google.javascript.rhino.Node;
import java.io.StringReader;
import java.util.List;
/**
* Tests for {@link InstrumentFunctions}
*
*/
public class InstrumentFunctionsTest extends CompilerTestCase {
private String instrumentationPb;
public InstrumentFunctionsTest() {
this.instrumentationPb = null;
}
@Override
protected void setUp() {
super.enableLineNumberCheck(false);
this.instrumentationPb = null;
}
@Override
protected CompilerPass getProcessor(Compiler compiler) {
return new NameAndInstrumentFunctions(compiler);
}
@Override
protected int getNumRepetitions() {
// This pass is not idempotent.
return 1;
}
public void testInstrument() {
final String kPreamble =
"var $$toRemoveDefinition1, $$notToRemove;\n" +
"var $$toRemoveDefinition2, $$toRemoveDefinition3;\n";
// build instrumentation template and init code strings for use in
// tests below.
List<String> initCodeList = ImmutableList.of(
"var $$Table = [];",
"function $$TestDefine(id) {",
" $$Table[id] = 0;",
"};",
"function $$TestInstrument(id) {",
" $$Table[id]++;",
"};");
StringBuilder initCodeBuilder = new StringBuilder();
StringBuilder pbBuilder = new StringBuilder();
for (String line : initCodeList) {
initCodeBuilder.append(line).append("\n");
pbBuilder.append("init: \"").append(line).append("\"\n");
}
pbBuilder.append("report_call: \"$$testInstrument\"")
.append("report_defined: \"$$testDefine\"")
.append("declaration_to_remove: \"$$toRemoveDefinition1\"")
.append("declaration_to_remove: \"$$toRemoveDefinition2\"")
.append("declaration_to_remove: \"$$toRemoveDefinition3\"");
final String initCode = initCodeBuilder.toString();
this.instrumentationPb = pbBuilder.toString();
// Test basic instrumentation
test("function a(){b}",
initCode + "$$testDefine(0);" +
"function a(){$$testInstrument(0);b}");
// Test declaration_to_remove
test(kPreamble + "function a(){b}",
initCode +
"$$testDefine(0);" +
"var $$notToRemove;" +
"function a(){$$testInstrument(0);b}");
// Test object literal declarations
test(kPreamble + "var a = { b: function(){c} }",
initCode +
"var $$notToRemove;" +
"$$testDefine(0);" +
"var a = { b: function(){$$testInstrument(0);c} }");
// Test multiple object literal declarations
test(kPreamble +
"var a = { b: function(){c}, d: function(){e} }",
initCode +
"var $$notToRemove;" +
"$$testDefine(0);" +
"$$testDefine(1);" +
"var a={b:function(){$$testInstrument(0);c}," +
"d:function(){$$testInstrument(1);e}}");
// Test recursive object literal declarations
test(kPreamble +
"var a = { b: { f: function(){c} }, d: function(){e} }",
initCode +
"var $$notToRemove;" +
"$$testDefine(0);" +
"$$testDefine(1);" +
"var a={b:{f:function(){$$testInstrument(0);c}}," +
"d:function(){$$testInstrument(1);e}}");
}
public void testEmpty() {
this.instrumentationPb = "";
test("function a(){b}", "function a(){b}");
}
public void testAppNameSetter() {
this.instrumentationPb = "app_name_setter: \"setAppName\"";
test("function a(){b}", "setAppName(\"testfile.js\");function a(){b}");
}
public void testInit() {
this.instrumentationPb = "init: \"var foo = 0;\"\n" +
"init: \"function f(){g();}\"\n";
test("function a(){b}",
"var foo = 0;function f(){g()}function a(){b}");
}
public void testDeclare() {
this.instrumentationPb = "report_defined: \"$$testDefine\"";
test("function a(){b}", "$$testDefine(0);function a(){b}");
}
public void testCall() {
this.instrumentationPb = "report_call: \"$$testCall\"";
test("function a(){b}", "function a(){$$testCall(0);b}");
}
public void testNested() {
this.instrumentationPb = "report_call: \"$$testCall\"\n" +
"report_defined: \"$$testDefine\"";
test("function a(){ function b(){}}",
"$$testDefine(1);$$testDefine(0);" +
"function a(){$$testCall(1);function b(){$$testCall(0)}}");
}
public void testExitPaths() {
this.instrumentationPb = "report_exit: \"$$testExit\"";
test("function a(){return}",
"function a(){return $$testExit(0)}");
test("function b(){return 5}",
"function b(){return $$testExit(0, 5)}");
test("function a(){if(2 != 3){return}else{return 5}}",
"function a(){if(2!=3){return $$testExit(0)}" +
"else{return $$testExit(0,5)}}");
test("function a(){if(2 != 3){return}else{return 5}}b()",
"function a(){if(2!=3){return $$testExit(0)}" +
"else{return $$testExit(0,5)}}b()");
test("function a(){if(2 != 3){return}else{return 5}}",
"function a(){if(2!=3){return $$testExit(0)}" +
"else{return $$testExit(0,5)}}");
}
public void testExitNoReturn() {
this.instrumentationPb = "report_exit: \"$$testExit\"";
test("function a(){}",
"function a(){$$testExit(0);}");
test("function a(){b()}",
"function a(){b();$$testExit(0);}");
}
public void testPartialExitPaths() {
this.instrumentationPb = "report_exit: \"$$testExit\"";
test("function a(){if (2 != 3) {return}}",
"function a(){if (2 != 3){return $$testExit(0)}$$testExit(0)}");
}
public void testExitTry() {
this.instrumentationPb = "report_exit: \"$$testExit\"";
test("function a(){try{return}catch(err){}}",
"function a(){try{return $$testExit(0)}catch(err){}$$testExit(0)}");
test("function a(){try{}catch(err){return}}",
"function a(){try{}catch(err){return $$testExit(0)}$$testExit(0)}");
test("function a(){try{return}finally{}}",
"function a(){try{return $$testExit(0)}finally{}$$testExit(0)}");
test("function a(){try{return}catch(err){}finally{}}",
"function a(){try{return $$testExit(0)}catch(err){}finally{}" +
"$$testExit(0)}");
test("function a(){try{return 1}catch(err){return 2}}",
"function a(){try{return $$testExit(0, 1)}" +
"catch(err){return $$testExit(0,2)}}");
test("function a(){try{return 1}catch(err){return 2}finally{}}",
"function a(){try{return $$testExit(0, 1)}" +
"catch(err){return $$testExit(0,2)}" +
"finally{}$$testExit(0)}");
test("function a(){try{return 1}catch(err){return 2}finally{return}}",
"function a(){try{return $$testExit(0, 1)}" +
"catch(err){return $$testExit(0,2)}finally{return $$testExit(0)}}");
test("function a(){try{}catch(err){}finally{return}}",
"function a(){try{}catch(err){}finally{return $$testExit(0)}}");
}
public void testNestedExit() {
this.instrumentationPb = "report_exit: \"$$testExit\"\n" +
"report_defined: \"$$testDefine\"";
test("function a(){ return function(){ return c;}}",
"$$testDefine(1);function a(){$$testDefine(0);" +
"return $$testExit(1, function(){return $$testExit(0, c);});}");
}
public void testProtobuffParseFail() {
this.instrumentationPb = "not an ascii pb\n";
test("function a(){b}", "", RhinoErrorReporter.PARSE_ERROR);
}
public void testInitJsParseFail() {
this.instrumentationPb = "init: \"= assignWithNoLhs();\"";
test("function a(){b}", "", RhinoErrorReporter.PARSE_ERROR);
}
private class NameAndInstrumentFunctions implements CompilerPass {
private final Compiler compiler;
NameAndInstrumentFunctions(Compiler compiler) {
this.compiler = compiler;
}
@Override
public void process(Node externs, Node root) {
FunctionNames functionNames = new FunctionNames(compiler);
functionNames.process(externs, root);
InstrumentFunctions instrumentation =
new InstrumentFunctions(compiler, functionNames,
"test init code", "testfile.js",
new StringReader(instrumentationPb));
instrumentation.process(externs, root);
}
}
}