446 lines
17 KiB
Java
446 lines
17 KiB
Java
/*
|
|
* Copyright 2009 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.debugging.sourcemap;
|
|
|
|
import com.google.debugging.sourcemap.SourceMapGeneratorV2.LineMapEncoder;
|
|
import com.google.javascript.jscomp.SourceMap;
|
|
import com.google.javascript.jscomp.SourceMap.Format;
|
|
|
|
import java.io.IOException;
|
|
|
|
/**
|
|
* Tests for {@link SourceMap}.
|
|
*
|
|
*/
|
|
public class SourceMapGeneratorV2Test extends SourceMapTestCase {
|
|
|
|
public SourceMapGeneratorV2Test() {
|
|
disableColumnValidation();
|
|
}
|
|
|
|
@Override
|
|
protected SourceMapConsumer getSourceMapConsumer() {
|
|
return new SourceMapConsumerV2();
|
|
}
|
|
|
|
@Override
|
|
protected Format getSourceMapFormat() {
|
|
return SourceMap.Format.V2;
|
|
}
|
|
|
|
@Override
|
|
public void setUp() {
|
|
detailLevel = SourceMap.DetailLevel.ALL;
|
|
}
|
|
|
|
public void testBasicMapping() throws Exception {
|
|
compileAndCheck("function __BASIC__() { }");
|
|
}
|
|
|
|
public void testBasicMappingGoldenOutput() throws Exception {
|
|
// Empty source map test
|
|
checkSourceMap("function __BASIC__() { }",
|
|
|
|
//"/** Source Map **/\n" +
|
|
"{\n" +
|
|
"\"version\":2,\n" +
|
|
"\"file\":\"testcode\",\n" +
|
|
"\"lineCount\":1,\n" +
|
|
"\"lineMaps\":[\"cAkBEBEB\"],\n" +
|
|
"\"mappings\":[[0,1,0,0],\n" +
|
|
"[0,1,9,0],\n" +
|
|
"[0,1,18],\n" +
|
|
"[0,1,21],\n" +
|
|
"],\n" +
|
|
"\"sources\":[\"testcode\"],\n" +
|
|
"\"names\":[\"__BASIC__\"]\n" +
|
|
"}\n");
|
|
}
|
|
|
|
public void testLiteralMappings() throws Exception {
|
|
compileAndCheck("function __BASIC__(__PARAM1__, __PARAM2__) { " +
|
|
"var __VAR__ = '__STR__'; }");
|
|
}
|
|
|
|
public void testLiteralMappingsGoldenOutput() throws Exception {
|
|
// Empty source map test
|
|
checkSourceMap("function __BASIC__(__PARAM1__, __PARAM2__) { " +
|
|
"var __VAR__ = '__STR__'; }",
|
|
|
|
//"/** Source Map **/\n" +
|
|
"{\n" +
|
|
"\"version\":2,\n" +
|
|
"\"file\":\"testcode\",\n" +
|
|
"\"lineCount\":1,\n" +
|
|
"\"lineMaps\":[\"cAkBABkBA/kCA+ADMBcBgBA9\"],\n" +
|
|
"\"mappings\":[[0,1,0,0],\n" +
|
|
"[0,1,9,0],\n" +
|
|
"[0,1,18],\n" +
|
|
"[0,1,19,1],\n" +
|
|
"[0,1,31,2],\n" +
|
|
"[0,1,43],\n" +
|
|
"[0,1,45],\n" +
|
|
"[0,1,49,3],\n" +
|
|
"[0,1,59],\n" +
|
|
"],\n" +
|
|
"\"sources\":[\"testcode\"],\n" +
|
|
"\"names\":[" +
|
|
"\"__BASIC__\",\"__PARAM1__\",\"__PARAM2__\"," +
|
|
"\"__VAR__\"]\n" +
|
|
"}\n");
|
|
}
|
|
|
|
public void testMultilineMapping() throws Exception {
|
|
compileAndCheck("function __BASIC__(__PARAM1__, __PARAM2__) {\n" +
|
|
"var __VAR__ = '__STR__';\n" +
|
|
"var __ANO__ = \"__STR2__\";\n" +
|
|
"}");
|
|
}
|
|
|
|
public void testMultiFunctionMapping() throws Exception {
|
|
compileAndCheck("function __BASIC__(__PARAM1__, __PARAM2__) {\n" +
|
|
"var __VAR__ = '__STR__';\n" +
|
|
"var __ANO__ = \"__STR2__\";\n" +
|
|
"}\n\n" +
|
|
|
|
"function __BASIC2__(__PARAM3__, __PARAM4__) {\n" +
|
|
"var __VAR2__ = '__STR2__';\n" +
|
|
"var __ANO2__ = \"__STR3__\";\n" +
|
|
"}\n\n");
|
|
}
|
|
|
|
public void testGoldenOutput0() throws Exception {
|
|
// Empty source map test
|
|
checkSourceMap("",
|
|
|
|
"{\n" +
|
|
"\"version\":2,\n" +
|
|
"\"file\":\"testcode\",\n" +
|
|
"\"lineCount\":1,\n" +
|
|
"\"lineMaps\":[\"\"],\n" +
|
|
"\"mappings\":[],\n" +
|
|
"\"sources\":[\"testcode\"],\n" +
|
|
"\"names\":[]\n" +
|
|
"}\n");
|
|
}
|
|
|
|
public void testGoldenOutput1() throws Exception {
|
|
detailLevel = SourceMap.DetailLevel.ALL;
|
|
|
|
checkSourceMap(
|
|
"function f(foo, bar) { foo = foo + bar + 2; return foo; }",
|
|
|
|
"{\n" +
|
|
"\"version\":2,\n" +
|
|
"\"file\":\"testcode\",\n" +
|
|
"\"lineCount\":1,\n" +
|
|
"\"lineMaps\":[\"cAEBABIBA/ICA+ADICA/ICA+IDA9AEYBMBA5\"],\n" +
|
|
"\"mappings\":[[0,1,0,0],\n" +
|
|
"[0,1,9,0],\n" +
|
|
"[0,1,10],\n" +
|
|
"[0,1,11,1],\n" +
|
|
"[0,1,16,2],\n" +
|
|
"[0,1,21],\n" +
|
|
"[0,1,23],\n" +
|
|
"[0,1,23,1],\n" +
|
|
"[0,1,29,1],\n" +
|
|
"[0,1,35,2],\n" +
|
|
"[0,1,41],\n" +
|
|
"[0,1,44],\n" +
|
|
"[0,1,51,1],\n" +
|
|
"],\n" +
|
|
"\"sources\":[\"testcode\"],\n" +
|
|
"\"names\":[\"f\",\"foo\",\"bar\"]\n" +
|
|
"}\n");
|
|
|
|
detailLevel = SourceMap.DetailLevel.SYMBOLS;
|
|
|
|
checkSourceMap("function f(foo, bar) { foo = foo + bar + 2; return foo; }",
|
|
|
|
"{\n" +
|
|
"\"version\":2,\n" +
|
|
"\"file\":\"testcode\",\n" +
|
|
"\"lineCount\":1,\n" +
|
|
"\"lineMaps\":[\"cAEBA/ICA+IDE9IEA8IFA7IGg6MHA5\"],\n" +
|
|
"\"mappings\":[[0,1,0,0],\n" +
|
|
"[0,1,9,0],\n" +
|
|
"[0,1,11,1],\n" +
|
|
"[0,1,16,2],\n" +
|
|
"[0,1,23,1],\n" +
|
|
"[0,1,29,1],\n" +
|
|
"[0,1,35,2],\n" +
|
|
"[0,1,51,1],\n" +
|
|
"],\n" +
|
|
"\"sources\":[\"testcode\"],\n" +
|
|
"\"names\":[\"f\",\"foo\",\"bar\"]\n" +
|
|
"}\n");
|
|
}
|
|
|
|
public void testGoldenOutput2() throws Exception {
|
|
checkSourceMap("function f(foo, bar) {\r\n\n\n\nfoo = foo + bar + foo;" +
|
|
"\nreturn foo;\n}",
|
|
|
|
"{\n" +
|
|
"\"version\":2,\n" +
|
|
"\"file\":\"testcode\",\n" +
|
|
"\"lineCount\":1,\n" +
|
|
"\"lineMaps\":[" +
|
|
"\"cAEBABIBA/ICA+ADICA/ICA+IDA9IEYBMBA5\"],\n" +
|
|
"\"mappings\":[[0,1,0,0],\n" +
|
|
"[0,1,9,0],\n" +
|
|
"[0,1,10],\n" +
|
|
"[0,1,11,1],\n" +
|
|
"[0,1,16,2],\n" +
|
|
"[0,1,21],\n" +
|
|
"[0,5,0],\n" +
|
|
"[0,5,0,1],\n" +
|
|
"[0,5,6,1],\n" +
|
|
"[0,5,12,2],\n" +
|
|
"[0,5,18,1],\n" +
|
|
"[0,6,0],\n" +
|
|
"[0,6,7,1],\n" +
|
|
"],\n" +
|
|
"\"sources\":[\"testcode\"],\n" +
|
|
"\"names\":[\"f\",\"foo\",\"bar\"]\n" +
|
|
"}\n");
|
|
}
|
|
|
|
public void testGoldenOutput3() throws Exception {
|
|
checkSourceMap("c:\\myfile.js",
|
|
"foo;",
|
|
|
|
"{\n" +
|
|
"\"version\":2,\n" +
|
|
"\"file\":\"testcode\",\n" +
|
|
"\"lineCount\":1,\n" +
|
|
"\"lineMaps\":[\"IA\"],\n" +
|
|
"\"mappings\":[[0,1,0,0],\n" +
|
|
"],\n" +
|
|
"\"sources\":[\"c:\\\\myfile.js\"],\n" +
|
|
"\"names\":[\"foo\"]\n" +
|
|
"}\n");
|
|
}
|
|
|
|
public void testGoldenOutput4() throws Exception {
|
|
checkSourceMap("c:\\myfile.js",
|
|
"foo; boo; goo;",
|
|
|
|
"{\n" +
|
|
"\"version\":2,\n" +
|
|
"\"file\":\"testcode\",\n" +
|
|
"\"lineCount\":1,\n" +
|
|
"\"lineMaps\":[\"IAMBMB\"],\n" +
|
|
"\"mappings\":[[0,1,0,0],\n" +
|
|
"[0,1,7,1],\n" +
|
|
"[0,1,14,2],\n" +
|
|
"],\n" +
|
|
"\"sources\":[\"c:\\\\myfile.js\"],\n" +
|
|
"\"names\":[\"foo\",\"boo\",\"goo\"]\n" +
|
|
"}\n");
|
|
}
|
|
|
|
public void testGoldenOutput5() throws Exception {
|
|
detailLevel = SourceMap.DetailLevel.ALL;
|
|
|
|
checkSourceMap("c:\\myfile.js",
|
|
"/** @preserve\n" +
|
|
" * this is a test.\n" +
|
|
" */\n" +
|
|
"var foo=a + 'this is a really long line that will force the"
|
|
+ " mapping to span multiple lines 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ "' + c + d + e;",
|
|
|
|
"{\n" +
|
|
"\"version\":2,\n" +
|
|
"\"file\":\"testcode\",\n" +
|
|
"\"lineCount\":6,\n" +
|
|
"\"lineMaps\":[\"\",\n" +
|
|
"\"\",\n" +
|
|
"\"\",\n" +
|
|
"\"\",\n" +
|
|
"\"MAMBABA/!!AUSC\",\n" +
|
|
"\"AEA9AEA8AF\"],\n" +
|
|
"\"mappings\":[[0,4,0],\n" +
|
|
"[0,4,4,0],\n" +
|
|
"[0,4,8,1],\n" +
|
|
"[0,4,12],\n" +
|
|
"[0,4,1314,2],\n" +
|
|
"[0,4,1318,3],\n" +
|
|
"[0,4,1322,4],\n" +
|
|
"],\n" +
|
|
"\"sources\":[\"c:\\\\myfile.js\"],\n" +
|
|
"\"names\":[\"foo\",\"a\",\"c\",\"d\",\"e\"]\n" +
|
|
"}\n");
|
|
|
|
detailLevel = SourceMap.DetailLevel.SYMBOLS;
|
|
|
|
checkSourceMap("c:\\myfile.js",
|
|
"/** @preserve\n" +
|
|
" * this is a test.\n" +
|
|
" */\n" +
|
|
"var foo=a + 'this is a really long line that will force the"
|
|
+ " mapping to span multiple lines 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ " 123456789 123456789 123456789 123456789 123456789"
|
|
+ "' + c + d + e;",
|
|
|
|
"{\n" +
|
|
"\"version\":2,\n" +
|
|
"\"file\":\"testcode\",\n" +
|
|
"\"lineCount\":6,\n" +
|
|
"\"lineMaps\":[\"\",\n" +
|
|
"\"\",\n" +
|
|
"\"\",\n" +
|
|
"\"\",\n" +
|
|
"\"M/MBAB\",\n" +
|
|
"\"ACA+ADA9AE\"],\n" +
|
|
"\"mappings\":[[0,4,4,0],\n" +
|
|
"[0,4,8,1],\n" +
|
|
"[0,4,1314,2],\n" +
|
|
"[0,4,1318,3],\n" +
|
|
"[0,4,1322,4],\n" +
|
|
"],\n" +
|
|
"\"sources\":[\"c:\\\\myfile.js\"],\n" +
|
|
"\"names\":[\"foo\",\"a\",\"c\",\"d\",\"e\"]\n" +
|
|
"}\n");
|
|
}
|
|
|
|
public void testBasicDeterminism() throws Exception {
|
|
RunResult result1 = compile("file1", "foo;", "file2", "bar;");
|
|
RunResult result2 = compile("file2", "foo;", "file1", "bar;");
|
|
|
|
String map1 = getSourceMap(result1);
|
|
String map2 = getSourceMap(result2);
|
|
|
|
// Assert that the files section of the maps are the same. The actual
|
|
// entries will differ, so we cannot do a simple full comparison.
|
|
|
|
// Line 5 has the file information.
|
|
String files1 = map1.split("\n")[4];
|
|
String files2 = map2.split("\n")[4];
|
|
|
|
assertEquals(files1, files2);
|
|
}
|
|
|
|
private int getRelativeId(int id, int lastId) {
|
|
int length = LineMapEncoder.getRelativeMappingIdLength(id, lastId);
|
|
int result = LineMapEncoder.getRelativeMappingId(id, length, lastId);
|
|
int inverse = SourceMapLineDecoder.getIdFromRelativeId(
|
|
result, length, lastId);
|
|
assertEquals(id, inverse);
|
|
return result;
|
|
}
|
|
|
|
public void testEncodingRelativeId() {
|
|
assertEquals(0, getRelativeId(0, 0));
|
|
assertEquals(64 + (-1), getRelativeId(-1, 0));
|
|
assertEquals(64 + (-32), getRelativeId(0, 32));
|
|
assertEquals(31, getRelativeId(31, 0));
|
|
assertEquals(4096 + (-33), getRelativeId(0, 33));
|
|
assertEquals(32, getRelativeId(32, 0));
|
|
}
|
|
|
|
public void testEncodingIdLength() {
|
|
assertEquals(1, LineMapEncoder.getRelativeMappingIdLength(0, 0));
|
|
assertEquals(1, LineMapEncoder.getRelativeMappingIdLength(-1, 0));
|
|
assertEquals(1, LineMapEncoder.getRelativeMappingIdLength(0, 32));
|
|
assertEquals(1, LineMapEncoder.getRelativeMappingIdLength(31, 0));
|
|
assertEquals(2, LineMapEncoder.getRelativeMappingIdLength(0, 33));
|
|
assertEquals(2, LineMapEncoder.getRelativeMappingIdLength(32, 0));
|
|
|
|
assertEquals(2, LineMapEncoder.getRelativeMappingIdLength(2047, 0));
|
|
assertEquals(3, LineMapEncoder.getRelativeMappingIdLength(2048, 0));
|
|
assertEquals(2, LineMapEncoder.getRelativeMappingIdLength(0, 2048));
|
|
assertEquals(3, LineMapEncoder.getRelativeMappingIdLength(0, 2049));
|
|
}
|
|
|
|
private String getEntry(int id, int lastId, int reps) throws IOException {
|
|
StringBuilder sb = new StringBuilder();
|
|
LineMapEncoder.encodeEntry(sb, id, lastId, reps);
|
|
return sb.toString();
|
|
}
|
|
|
|
public void testEncoding() throws IOException {
|
|
assertEquals("AA", getEntry(0, 0, 1));
|
|
assertEquals("EA", getEntry(0, 0, 2));
|
|
assertEquals("8A", getEntry(0, 0, 16));
|
|
assertEquals("!AQA", getEntry(0, 0, 17));
|
|
assertEquals("!ARA", getEntry(0, 0, 18));
|
|
assertEquals("!A+A", getEntry(0, 0, 63));
|
|
assertEquals("!A/A", getEntry(0, 0, 64));
|
|
assertEquals("!!ABAA", getEntry(0, 0, 65));
|
|
assertEquals("!!A//A", getEntry(0, 0, 4096));
|
|
assertEquals("!!!ABAAA", getEntry(0, 0, 4097));
|
|
|
|
assertEquals("Af", getEntry(31, 0, 1));
|
|
assertEquals("BAg", getEntry(32, 0, 1));
|
|
assertEquals("AB", getEntry(32, 31, 1));
|
|
|
|
assertEquals("!AQf", getEntry(31, 0, 17));
|
|
assertEquals("!BQAg", getEntry(32, 0, 17));
|
|
assertEquals("!AQB", getEntry(32, 31, 17));
|
|
|
|
assertEquals("!A/B", getEntry(32, 31, 64));
|
|
assertEquals("!!ABAB", getEntry(32, 31, 65));
|
|
}
|
|
}
|