/* * 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.SourceMapConsumerV1; import com.google.debugging.sourcemap.SourceMapParseException; import com.google.debugging.sourcemap.proto.Mapping.OriginalMapping; import junit.framework.TestCase; public class SourceMapConsumerV1Test extends TestCase { public SourceMapConsumerV1Test() { } public SourceMapConsumerV1Test(String name) { super(name); } public void testGetMappingForLine() throws Exception { StringBuilder sb = new StringBuilder(); sb.append("/** Begin line maps. **/{ count : 2 }\n"); sb.append("[0,,,,1,,2]\n"); sb.append("[3,,,,,,,]\n"); sb.append("/** Begin file information. **/\n"); sb.append("['test.js']\n"); sb.append("['foo.js']\n"); sb.append("/** Begin mapping definitions. **/\n"); sb.append("['test.js', 0, 1]\n"); sb.append("['bleg.js', 5, 8, 'hello']\n"); sb.append("['bleg.js', 12, 78]\n"); sb.append("['foo.js', 15, 16, 'yo!']"); SourceMapConsumerV1 sourceMap = new SourceMapConsumerV1(); sourceMap.parse(sb.toString()); OriginalMapping mapping = sourceMap.getMappingForLine(1, 1); assertNotNull(mapping); assertEquals("test.js", mapping.getOriginalFile()); assertEquals(0, mapping.getLineNumber()); assertEquals(1, mapping.getColumnPosition()); assertEquals("", mapping.getIdentifier()); mapping = sourceMap.getMappingForLine(1, 6); assertNotNull(mapping); assertEquals("bleg.js", mapping.getOriginalFile()); assertEquals(5, mapping.getLineNumber()); assertEquals(8, mapping.getColumnPosition()); assertEquals("hello", mapping.getIdentifier()); mapping = sourceMap.getMappingForLine(2, 4); assertNotNull(mapping); assertEquals("foo.js", mapping.getOriginalFile()); assertEquals(15, mapping.getLineNumber()); assertEquals(16, mapping.getColumnPosition()); assertEquals("yo!", mapping.getIdentifier()); assertNull(sourceMap.getMappingForLine(Integer.MAX_VALUE, 1)); assertNotNull(sourceMap.getMappingForLine(1, Integer.MAX_VALUE)); } public void testLineEdges() throws Exception { StringBuilder sb = new StringBuilder(); sb.append("/** Begin line maps. **/{ count : 2 }\n"); sb.append("[100]\n"); sb.append("[200]\n"); sb.append("/** Begin file information. **/\n"); sb.append("['test.js']\n"); sb.append("['foo.js']\n"); sb.append("/** Begin mapping definitions. **/\n"); for (int i = 0; i <= 200; i++) { sb.append("['foo.js', ").append(i).append(", 1]\n"); } SourceMapConsumerV1 sourceMap = new SourceMapConsumerV1(); sourceMap.parse(sb.toString()); OriginalMapping mapping = sourceMap.getMappingForLine(-1, 1); assertNull(mapping); mapping = sourceMap.getMappingForLine(0, 1); assertNull(mapping); mapping = sourceMap.getMappingForLine(1, 1); assertEquals(100, mapping.getLineNumber()); mapping = sourceMap.getMappingForLine(2, 1); assertEquals(200, mapping.getLineNumber()); mapping = sourceMap.getMappingForLine(3, 1); assertNull(mapping); } public void testColumnEdges() throws Exception { StringBuilder sb = new StringBuilder(); sb.append("/** Begin line maps. **/{ count : 1 }\n"); sb.append("[100, 101]\n"); sb.append("/** Begin file information. **/\n"); sb.append("\n"); sb.append("/** Begin mapping definitions. **/\n"); for (int i = 0; i <= 200; i++) { sb.append("['foo.js', ").append(i).append(", 1]\n"); } SourceMapConsumerV1 sourceMap = new SourceMapConsumerV1(); sourceMap.parse(sb.toString()); OriginalMapping mapping = sourceMap.getMappingForLine(1, -1); assertNull(mapping); mapping = sourceMap.getMappingForLine(1, 0); assertNull(mapping); mapping = sourceMap.getMappingForLine(1, 1); assertEquals(100, mapping.getLineNumber()); mapping = sourceMap.getMappingForLine(1, 2); assertEquals(101, mapping.getLineNumber()); // Columns beyond the end of the line are treated the same // as the last column. mapping = sourceMap.getMappingForLine(1, 3); assertEquals(101, mapping.getLineNumber()); } public void testNegativeOneInLineMap() throws Exception { StringBuilder sb = new StringBuilder(); sb.append("/** Begin line maps. **/{ count : 1 }\n"); sb.append("[200,-1,199,-1]\n"); sb.append("/** Begin file information. **/\n"); sb.append("\n"); sb.append("/** Begin mapping definitions. **/\n"); for (int i = 0; i <= 200; i++) { sb.append("['foo.js', 1, ").append(i).append("]\n"); } SourceMapConsumerV1 sourceMap = new SourceMapConsumerV1(); sourceMap.parse(sb.toString()); OriginalMapping mapping = sourceMap.getMappingForLine(1, 2); assertNull(mapping); mapping = sourceMap.getMappingForLine(1, 4); assertNull(mapping); } public void testSimpleParse() throws Exception { StringBuilder sb = new StringBuilder(); sb.append("/** Begin line maps. **/{ count : 1 }\n"); sb.append("[0,,,,1,2]\n"); sb.append("/** Begin file information. **/\n"); sb.append("['test.js']\n"); sb.append("/** Begin mapping definitions. **/\n"); sb.append("['test.js', 0, 1]\n"); sb.append("['test.js', 0, 1, 'hello']\n"); sb.append("['test.js', 0, 1]"); SourceMapConsumerV1 sourceMap = new SourceMapConsumerV1(); sourceMap.parse(sb.toString()); } public void testBlankLine() throws Exception { StringBuilder sb = new StringBuilder(); sb.append("/** Begin line maps. **/{ count : 1 }\n"); sb.append("\n"); sb.append("/** Begin file information. **/\n"); sb.append("\n"); sb.append("/** Begin mapping definitions. **/\n"); SourceMapConsumerV1 sourceMap = new SourceMapConsumerV1(); sourceMap.parse(sb.toString()); } public void testCountFailure() throws Exception { StringBuilder sb = new StringBuilder(); sb.append("/** Begin line maps. **/{ counter : 1 }\n"); assertException("Missing 'count'", sb); } public void testInvalidCountFailure() throws Exception { StringBuilder sb = new StringBuilder(); sb.append("/** Begin line maps. **/{ count : 0 }\n"); assertException("Count must be >= 1", sb); } public void testInvalidJSONFailure() throws Exception { StringBuilder sb = new StringBuilder(); sb.append("/** Begin line maps. **/{ count : 2 }\n"); sb.append("[0,,,,2\n"); assertExceptionStartsWith("JSON parse exception: org.json.JSONException: " + "Expected a ',' or ']' at ", sb); } public void testInvalidHeaderFailure() throws Exception { StringBuilder sb = new StringBuilder(); sb.append("/** Begin line maps. **/{ count : 1 }\n"); sb.append("[0,,,1]\n"); sb.append("[3,,,4]\n"); assertException( "Expected /** Begin file information. **/ got [3,,,4]", sb); } public void testInvalidPostHeaderToken() throws Exception { StringBuilder sb = new StringBuilder(); sb.append("/** Begin line maps. **/{ count : 1 }\n"); sb.append("[0,,,1]\n"); sb.append("/** Begin file information. **/f\n"); assertException("Expected /** Begin file information. **/" + " got /** Begin file information. **/f", sb); } public void testInvalidMappingArrayFailure() throws Exception { StringBuilder sb = new StringBuilder(); sb.append("/** Begin line maps. **/{ count : 1 }\n"); sb.append("[0,,,,1,2]\n"); sb.append("/** Begin file information. **/\n"); sb.append("['test.js']\n"); sb.append("/** Begin mapping definitions. **/\n"); sb.append("['test.js', 0]\n"); assertException("Invalid mapping array", sb); } public void testMultipleLineFragments() throws Exception { StringBuilder sb = new StringBuilder(); sb.append("/** Begin line maps. **/{ count : 1 }\n"); sb.append("[0,1,2,3,260,261,262]\n"); sb.append("/** Begin file information. **/\n"); sb.append("\n"); sb.append("/** Begin mapping definitions. **/\n"); for (int i = 0; i < 262; i++) { sb.append("['frog/test" + i + ".js', " + i + ", 1]\n"); } sb.append("['frog/testigloo.js', 500, 1]"); SourceMapConsumerV1 sourceMap = new SourceMapConsumerV1(); sourceMap.parse(sb.toString()); OriginalMapping mapping = sourceMap.getMappingForLine(1, 1); assertNotNull(mapping); assertEquals("frog/test0.js", mapping.getOriginalFile()); assertEquals(0, mapping.getLineNumber()); assertEquals(1, mapping.getColumnPosition()); assertEquals("", mapping.getIdentifier()); mapping = sourceMap.getMappingForLine(1, 6); assertNotNull(mapping); assertEquals("frog/test261.js", mapping.getOriginalFile()); assertEquals(261, mapping.getLineNumber()); assertEquals(1, mapping.getColumnPosition()); } public void testMultipleMappingFragments() throws Exception { StringBuilder sb = new StringBuilder(); sb.append("/** Begin line maps. **/{ count : 1 }\n"); sb.append("[0,1,2,3,260,261,262,1023]\n"); sb.append("/** Begin file information. **/\n"); sb.append("\n"); sb.append("/** Begin mapping definitions. **/\n"); for (int i = 0; i < 2000; i++) { sb.append("['frog/test" + (i / 100) + ".js', " + i + ", 1]\n"); } sb.append("['frog/testigloo.js', 500, 1]"); SourceMapConsumerV1 sourceMap = new SourceMapConsumerV1(); sourceMap.parse(sb.toString()); OriginalMapping mapping = sourceMap.getMappingForLine(1, 1); assertNotNull(mapping); assertEquals("frog/test0.js", mapping.getOriginalFile()); assertEquals(0, mapping.getLineNumber()); assertEquals(1, mapping.getColumnPosition()); assertEquals("", mapping.getIdentifier()); mapping = sourceMap.getMappingForLine(1, 6); assertNotNull(mapping); assertEquals("frog/test2.js", mapping.getOriginalFile()); assertEquals(261, mapping.getLineNumber()); assertEquals(1, mapping.getColumnPosition()); mapping = sourceMap.getMappingForLine(1, 8); assertNotNull(mapping); assertEquals("frog/test10.js", mapping.getOriginalFile()); assertEquals(1023, mapping.getLineNumber()); assertEquals(1, mapping.getColumnPosition()); } private void assertException(String exception, StringBuilder sb) { boolean exceptionRaised = false; try { SourceMapConsumerV1 sourceMap = new SourceMapConsumerV1(); sourceMap.parse(sb.toString()); } catch (SourceMapParseException pe) { assertEquals(exception, pe.getMessage()); exceptionRaised = true; } assertTrue(exceptionRaised); } private void assertExceptionStartsWith(String exception, StringBuilder sb) { boolean exceptionRaised = false; try { SourceMapConsumerV1 sourceMap = new SourceMapConsumerV1(); sourceMap.parse(sb.toString()); } catch (SourceMapParseException pe) { assertTrue( "expected <" + exception +"> but was <"+ pe.getMessage() +">", pe.getMessage().startsWith(exception)); exceptionRaised = true; } assertTrue(exceptionRaised); } }