mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
542 lines
16 KiB
Python
542 lines
16 KiB
Python
from unittest import TestCase
|
|
|
|
from symbolic.sourcemap import SourceMapTokenMatch, SourceMapView
|
|
|
|
from sentry.utils import json
|
|
|
|
sourcemap = b"""{
|
|
"version":3,
|
|
"file":"file.min.js",
|
|
"sources":["file1.js","file2.js"],
|
|
"names":["add","a","b","multiply","divide","c","e","Raven","captureException"],
|
|
"mappings":"AAAA,QAASA,KAAIC,EAAGC,GACf,YACA,OAAOD,GAAIC,ECFZ,QAASC,UAASF,EAAGC,GACpB,YACA,OAAOD,GAAIC,EAEZ,QAASE,QAAOH,EAAGC,GAClB,YACA,KACC,MAAOC,UAASH,IAAIC,EAAGC,GAAID,EAAGC,GAAKG,EAClC,MAAOC,GACRC,MAAMC,iBAAiBF",
|
|
"sourceRoot": "foo"
|
|
}"""
|
|
|
|
indexed_sourcemap_example = json.dumps(
|
|
{
|
|
"version": 3,
|
|
"file": "min.js",
|
|
"sections": [
|
|
{
|
|
"offset": {"line": 0, "column": 0},
|
|
"map": {
|
|
"version": 3,
|
|
"sources": ["one.js"],
|
|
"sourcesContent": [
|
|
" ONE.foo = function (bar) {\n" + " return baz(bar);\n" + " };"
|
|
],
|
|
"names": ["bar", "baz"],
|
|
"mappings": "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID",
|
|
"file": "min.js",
|
|
"sourceRoot": "/the/root",
|
|
},
|
|
},
|
|
{
|
|
"offset": {"line": 1, "column": 0},
|
|
"map": {
|
|
"version": 3,
|
|
"sources": ["two.js"],
|
|
"sourcesContent": [
|
|
" TWO.inc = function (n) {\n" + " return n + 1;\n" + " };"
|
|
],
|
|
"names": ["n"],
|
|
"mappings": "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOA",
|
|
"file": "min.js",
|
|
"sourceRoot": "/the/root",
|
|
},
|
|
},
|
|
],
|
|
}
|
|
).encode("utf-8")
|
|
|
|
|
|
class FindSourceTest(TestCase):
|
|
def test_simple(self):
|
|
smap_view = SourceMapView.from_json_bytes(sourcemap)
|
|
|
|
result = smap_view.lookup(0, 56)
|
|
assert result == SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=50,
|
|
src="foo/file2.js",
|
|
src_line=0,
|
|
src_col=9,
|
|
src_id=1,
|
|
name="multiply",
|
|
)
|
|
|
|
# Start of minified file (exact match first line/col tuple)
|
|
result = smap_view.lookup(0, 0)
|
|
assert result == SourceMapTokenMatch(
|
|
dst_line=0, dst_col=0, src="foo/file1.js", src_line=0, src_col=0, src_id=0, name=None
|
|
)
|
|
|
|
# Last character in mapping
|
|
result = smap_view.lookup(0, 36)
|
|
assert result == SourceMapTokenMatch(
|
|
dst_line=0, dst_col=30, src="foo/file1.js", src_line=2, src_col=1, src_id=0, name=None
|
|
)
|
|
|
|
# First character in mapping (exact match line/col tuple)
|
|
result = smap_view.lookup(0, 37)
|
|
assert result == SourceMapTokenMatch(
|
|
dst_line=0, dst_col=37, src="foo/file1.js", src_line=2, src_col=8, src_id=0, name="a"
|
|
)
|
|
|
|
# End of minified file (character *beyond* last line/col tuple)
|
|
result = smap_view.lookup(0, 192)
|
|
assert result == SourceMapTokenMatch(
|
|
dst_line=0, dst_col=191, src="foo/file2.js", src_line=9, src_col=25, src_id=1, name="e"
|
|
)
|
|
|
|
|
|
class IterSourcesTest(TestCase):
|
|
def test_basic(self):
|
|
smap_view = SourceMapView.from_json_bytes(sourcemap)
|
|
assert list(smap_view.iter_sources()) == [(0, "foo/file1.js"), (1, "foo/file2.js")]
|
|
|
|
|
|
class GetSourceContentsTest(TestCase):
|
|
def test_no_inline(self):
|
|
# basic sourcemap fixture has no inlined sources, so expect None
|
|
smap_view = SourceMapView.from_json_bytes(sourcemap)
|
|
|
|
source = smap_view.get_sourceview(0)
|
|
assert source is None
|
|
|
|
def test_indexed_inline(self):
|
|
smap_view = SourceMapView.from_json_bytes(indexed_sourcemap_example)
|
|
sview_0 = smap_view.get_sourceview(0)
|
|
assert sview_0 is not None
|
|
assert sview_0.get_source() == (
|
|
" ONE.foo = function (bar) {\n" + " return baz(bar);\n" + " };"
|
|
)
|
|
sview_1 = smap_view.get_sourceview(1)
|
|
assert sview_1 is not None
|
|
assert sview_1.get_source() == (
|
|
" TWO.inc = function (n) {\n" + " return n + 1;\n" + " };"
|
|
)
|
|
|
|
|
|
class ParseSourcemapTest(TestCase):
|
|
def test_basic(self):
|
|
index = SourceMapView.from_json_bytes(sourcemap)
|
|
|
|
assert list(index) == [
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=0,
|
|
src="foo/file1.js",
|
|
src_line=0,
|
|
src_col=0,
|
|
src_id=0,
|
|
name=None,
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=8,
|
|
src="foo/file1.js",
|
|
src_line=0,
|
|
src_col=9,
|
|
src_id=0,
|
|
name="add",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=13,
|
|
src="foo/file1.js",
|
|
src_line=0,
|
|
src_col=13,
|
|
src_id=0,
|
|
name="a",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=15,
|
|
src="foo/file1.js",
|
|
src_line=0,
|
|
src_col=16,
|
|
src_id=0,
|
|
name="b",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=18,
|
|
src="foo/file1.js",
|
|
src_line=1,
|
|
src_col=1,
|
|
src_id=0,
|
|
name=None,
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=30,
|
|
src="foo/file1.js",
|
|
src_line=2,
|
|
src_col=1,
|
|
src_id=0,
|
|
name=None,
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=37,
|
|
src="foo/file1.js",
|
|
src_line=2,
|
|
src_col=8,
|
|
src_id=0,
|
|
name="a",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=40,
|
|
src="foo/file1.js",
|
|
src_line=2,
|
|
src_col=12,
|
|
src_id=0,
|
|
name="b",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=42,
|
|
src="foo/file2.js",
|
|
src_line=0,
|
|
src_col=0,
|
|
src_id=1,
|
|
name=None,
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=50,
|
|
src="foo/file2.js",
|
|
src_line=0,
|
|
src_col=9,
|
|
src_id=1,
|
|
name="multiply",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=60,
|
|
src="foo/file2.js",
|
|
src_line=0,
|
|
src_col=18,
|
|
src_id=1,
|
|
name="a",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=62,
|
|
src="foo/file2.js",
|
|
src_line=0,
|
|
src_col=21,
|
|
src_id=1,
|
|
name="b",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=65,
|
|
src="foo/file2.js",
|
|
src_line=1,
|
|
src_col=1,
|
|
src_id=1,
|
|
name=None,
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=77,
|
|
src="foo/file2.js",
|
|
src_line=2,
|
|
src_col=1,
|
|
src_id=1,
|
|
name=None,
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=84,
|
|
src="foo/file2.js",
|
|
src_line=2,
|
|
src_col=8,
|
|
src_id=1,
|
|
name="a",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=87,
|
|
src="foo/file2.js",
|
|
src_line=2,
|
|
src_col=12,
|
|
src_id=1,
|
|
name="b",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=89,
|
|
src="foo/file2.js",
|
|
src_line=4,
|
|
src_col=0,
|
|
src_id=1,
|
|
name=None,
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=97,
|
|
src="foo/file2.js",
|
|
src_line=4,
|
|
src_col=9,
|
|
src_id=1,
|
|
name="divide",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=105,
|
|
src="foo/file2.js",
|
|
src_line=4,
|
|
src_col=16,
|
|
src_id=1,
|
|
name="a",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=107,
|
|
src="foo/file2.js",
|
|
src_line=4,
|
|
src_col=19,
|
|
src_id=1,
|
|
name="b",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=110,
|
|
src="foo/file2.js",
|
|
src_line=5,
|
|
src_col=1,
|
|
src_id=1,
|
|
name=None,
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=122,
|
|
src="foo/file2.js",
|
|
src_line=6,
|
|
src_col=1,
|
|
src_id=1,
|
|
name=None,
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=127,
|
|
src="foo/file2.js",
|
|
src_line=7,
|
|
src_col=2,
|
|
src_id=1,
|
|
name=None,
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=133,
|
|
src="foo/file2.js",
|
|
src_line=7,
|
|
src_col=9,
|
|
src_id=1,
|
|
name="multiply",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=143,
|
|
src="foo/file2.js",
|
|
src_line=7,
|
|
src_col=18,
|
|
src_id=1,
|
|
name="add",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=147,
|
|
src="foo/file2.js",
|
|
src_line=7,
|
|
src_col=22,
|
|
src_id=1,
|
|
name="a",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=149,
|
|
src="foo/file2.js",
|
|
src_line=7,
|
|
src_col=25,
|
|
src_id=1,
|
|
name="b",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=152,
|
|
src="foo/file2.js",
|
|
src_line=7,
|
|
src_col=29,
|
|
src_id=1,
|
|
name="a",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=154,
|
|
src="foo/file2.js",
|
|
src_line=7,
|
|
src_col=32,
|
|
src_id=1,
|
|
name="b",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=157,
|
|
src="foo/file2.js",
|
|
src_line=7,
|
|
src_col=37,
|
|
src_id=1,
|
|
name="c",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=159,
|
|
src="foo/file2.js",
|
|
src_line=8,
|
|
src_col=3,
|
|
src_id=1,
|
|
name=None,
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=165,
|
|
src="foo/file2.js",
|
|
src_line=8,
|
|
src_col=10,
|
|
src_id=1,
|
|
name="e",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=168,
|
|
src="foo/file2.js",
|
|
src_line=9,
|
|
src_col=2,
|
|
src_id=1,
|
|
name="Raven",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=174,
|
|
src="foo/file2.js",
|
|
src_line=9,
|
|
src_col=8,
|
|
src_id=1,
|
|
name="captureException",
|
|
),
|
|
SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=191,
|
|
src="foo/file2.js",
|
|
src_line=9,
|
|
src_col=25,
|
|
src_id=1,
|
|
name="e",
|
|
),
|
|
]
|
|
|
|
|
|
class ParseIndexedSourcemapTest(TestCase):
|
|
# Tests lookups that fall exactly on source map token boundaries
|
|
# https://github.com/mozilla/source-map/blob/master/test/test-source-map-consumer.js#138
|
|
def test_exact_mappings(self):
|
|
smap_view = SourceMapView.from_json_bytes(indexed_sourcemap_example)
|
|
|
|
# one.js
|
|
assert smap_view.lookup(0, 1) == SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=1,
|
|
src="/the/root/one.js",
|
|
src_line=0,
|
|
src_col=1,
|
|
src_id=0,
|
|
name=None,
|
|
)
|
|
assert smap_view.lookup(0, 18) == SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=18,
|
|
src="/the/root/one.js",
|
|
src_line=0,
|
|
src_col=21,
|
|
src_id=0,
|
|
name="bar",
|
|
)
|
|
assert smap_view.lookup(0, 28) == SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=28,
|
|
src="/the/root/one.js",
|
|
src_line=1,
|
|
src_col=10,
|
|
src_id=0,
|
|
name="baz",
|
|
)
|
|
|
|
# two.js
|
|
assert smap_view.lookup(1, 18) == SourceMapTokenMatch(
|
|
dst_line=1,
|
|
dst_col=18,
|
|
src="/the/root/two.js",
|
|
src_line=0,
|
|
src_col=21,
|
|
src_id=1,
|
|
name="n",
|
|
)
|
|
assert smap_view.lookup(1, 21) == SourceMapTokenMatch(
|
|
dst_line=1,
|
|
dst_col=21,
|
|
src="/the/root/two.js",
|
|
src_line=1,
|
|
src_col=3,
|
|
src_id=1,
|
|
name=None,
|
|
)
|
|
assert smap_view.lookup(1, 21) == SourceMapTokenMatch(
|
|
dst_line=1,
|
|
dst_col=21,
|
|
src="/the/root/two.js",
|
|
src_line=1,
|
|
src_col=3,
|
|
src_id=1,
|
|
name=None,
|
|
)
|
|
|
|
# Tests lookups that fall inside source map token boundaries
|
|
# https://github.com/mozilla/source-map/blob/master/test/test-source-map-consumer.js#181
|
|
def test_fuzzy_mapping(self):
|
|
smap_view = SourceMapView.from_json_bytes(indexed_sourcemap_example)
|
|
|
|
# one.js
|
|
assert smap_view.lookup(0, 20) == SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=18,
|
|
src="/the/root/one.js",
|
|
src_line=0,
|
|
src_col=21,
|
|
src_id=0,
|
|
name="bar",
|
|
)
|
|
assert smap_view.lookup(0, 30) == SourceMapTokenMatch(
|
|
dst_line=0,
|
|
dst_col=28,
|
|
src="/the/root/one.js",
|
|
src_line=1,
|
|
src_col=10,
|
|
src_id=0,
|
|
name="baz",
|
|
)
|
|
assert smap_view.lookup(1, 12) == SourceMapTokenMatch(
|
|
dst_line=1,
|
|
dst_col=9,
|
|
src="/the/root/two.js",
|
|
src_line=0,
|
|
src_col=11,
|
|
src_id=1,
|
|
name=None,
|
|
)
|