mirror of https://github.com/status-im/metro.git
Add tests for source map generator
Summary: This adds test for our high-perf source map generator. Reviewed By: cpojer Differential Revision: D4455547 fbshipit-source-id: 293bfe09c9c020259ae3daa4fa52f829248cca3c
This commit is contained in:
parent
7eef41bc00
commit
f6e068bcf0
|
@ -45,6 +45,9 @@ class B64Builder {
|
|||
* Adds `n` markers for generated lines to the mappings.
|
||||
*/
|
||||
markLines(n: number) {
|
||||
if (n < 1) {
|
||||
return this;
|
||||
}
|
||||
this.hasSegment = false;
|
||||
if (this.pos + n >= this.buffer.length) {
|
||||
this._realloc();
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/**
|
||||
* Copyright (c) 2017-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
jest.disableAutomock();
|
||||
|
||||
const B64Builder = require('../B64Builder');
|
||||
|
||||
let builder;
|
||||
beforeEach(() => {
|
||||
builder = new B64Builder();
|
||||
});
|
||||
|
||||
it('exposes a fluent interface', () => {
|
||||
expect(builder.markLines(0)).toBe(builder);
|
||||
expect(builder.markLines(3)).toBe(builder);
|
||||
expect(builder.startSegment()).toBe(builder);
|
||||
expect(builder.append(4)).toBe(builder);
|
||||
});
|
||||
|
||||
it('can create an empty string', () => {
|
||||
expect(builder.toString()).toEqual('');
|
||||
});
|
||||
|
||||
it('can mark a new line in the generated code', () => {
|
||||
builder.markLines(1);
|
||||
expect(builder.toString()).toEqual(';');
|
||||
});
|
||||
|
||||
it('can mark multiple new lines in the generated code', () => {
|
||||
builder.markLines(4);
|
||||
expect(builder.toString()).toEqual(';;;;');
|
||||
});
|
||||
|
||||
it('can mark zero new lines in the generated code', () => {
|
||||
builder.markLines(0);
|
||||
expect(builder.toString()).toEqual('');
|
||||
});
|
||||
|
||||
it('does not add commas when just starting a segment', () => {
|
||||
builder.startSegment(0);
|
||||
expect(builder.toString()).toEqual('A');
|
||||
});
|
||||
|
||||
it('adds a comma when starting a segment after another segment', () => {
|
||||
builder.startSegment(0);
|
||||
builder.startSegment(1);
|
||||
expect(builder.toString()).toEqual('A,C');
|
||||
});
|
||||
|
||||
it('does not add a comma when starting a segment after marking a line', () => {
|
||||
builder.startSegment(0);
|
||||
builder.markLines(1);
|
||||
builder.startSegment(0);
|
||||
expect(builder.toString()).toEqual('A;A');
|
||||
});
|
||||
|
||||
it('adds a comma when starting a segment after calling `markLines(0)`', () => {
|
||||
builder.startSegment(0);
|
||||
builder.markLines(0);
|
||||
builder.startSegment(1);
|
||||
expect(builder.toString()).toEqual('A,C');
|
||||
});
|
||||
|
||||
it('can append values that fit within 5 bits (including sign bit)', () => {
|
||||
builder.append(0b1111);
|
||||
builder.append(-0b1111);
|
||||
expect(builder.toString()).toEqual('ef');
|
||||
});
|
||||
|
||||
it('can append values that fit within 10 bits (including sign bit)', () => {
|
||||
builder.append(0b111100110);
|
||||
builder.append(-0b110110011);
|
||||
expect(builder.toString()).toEqual('senb');
|
||||
});
|
||||
|
||||
it('can append values that fit within 15 bits (including sign bit)', () => {
|
||||
builder.append(0b10011111011001);
|
||||
builder.append(-0b11001010001001);
|
||||
expect(builder.toString()).toEqual('y9TzoZ');
|
||||
});
|
||||
|
||||
it('can append values that fit within 20 bits (including sign bit)', () => {
|
||||
builder.append(0b1110010011101110110);
|
||||
builder.append(-0b1011000010100100110);
|
||||
expect(builder.toString()).toEqual('s3zctyiW');
|
||||
});
|
||||
|
||||
it('can append values that fit within 25 bits (including sign bit)', () => {
|
||||
builder.append(0b100010001111011010110111);
|
||||
builder.append(-0b100100111100001110101111);
|
||||
expect(builder.toString()).toEqual('ur7jR/6hvS');
|
||||
});
|
||||
|
||||
it('can append values that fit within 30 bits (including sign bit)', () => {
|
||||
builder.append(0b10001100100001101010001011111);
|
||||
builder.append(-0b11111000011000111110011111101);
|
||||
expect(builder.toString()).toEqual('+lqjyR7v+xhf');
|
||||
});
|
||||
|
||||
it('can append values that fit within 32 bits (including sign bit)', () => {
|
||||
builder.append(0b1001100101000101001011111110011);
|
||||
builder.append(-0b1101101101011000110011001110000);
|
||||
expect(builder.toString()).toEqual('m/rq0sChnzx1tD');
|
||||
});
|
||||
|
||||
it('can handle multiple operations', () => {
|
||||
builder
|
||||
.markLines(3)
|
||||
.startSegment(4)
|
||||
.append(2)
|
||||
.append(2)
|
||||
.append(0)
|
||||
.append(2345)
|
||||
.startSegment(12)
|
||||
.append(987543)
|
||||
.markLines(1)
|
||||
.startSegment(0);
|
||||
expect(builder.toString()).toEqual(';;;IEEAyyE,Yu5o8B;A');
|
||||
});
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* Copyright (c) 2017-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
jest.disableAutomock();
|
||||
|
||||
const Generator = require('../Generator');
|
||||
|
||||
const {objectContaining} = expect;
|
||||
|
||||
let generator;
|
||||
beforeEach(() => {
|
||||
generator = new Generator();
|
||||
});
|
||||
|
||||
it('adds file name and source code when starting a file', () => {
|
||||
const file1 = 'just/a/file';
|
||||
const file2 = 'another/file';
|
||||
const source1 = 'var a = 1;';
|
||||
const source2 = 'var a = 2;';
|
||||
|
||||
generator.startFile(file1, source1);
|
||||
generator.startFile(file2, source2);
|
||||
|
||||
expect(generator.toMap())
|
||||
.toEqual(objectContaining({
|
||||
sources: [file1, file2],
|
||||
sourcesContent: [source1, source2],
|
||||
}));
|
||||
});
|
||||
|
||||
it('throws when adding a mapping without starting a file', () => {
|
||||
expect(() => generator.addSimpleMapping(1, 2)).toThrow();
|
||||
});
|
||||
|
||||
it('throws when adding a mapping after ending a file', () => {
|
||||
generator.startFile('apples', 'pears');
|
||||
generator.endFile();
|
||||
expect(() => generator.addSimpleMapping(1, 2)).toThrow();
|
||||
});
|
||||
|
||||
it('can add a mapping for generated code without corresponding original source', () => {
|
||||
generator.startFile('apples', 'pears');
|
||||
generator.addSimpleMapping(12, 87);
|
||||
expect(generator.toMap())
|
||||
.toEqual(objectContaining({
|
||||
mappings: ';;;;;;;;;;;uF',
|
||||
}));
|
||||
});
|
||||
|
||||
it('can add a mapping with corresponding location in the original source', () => {
|
||||
generator.startFile('apples', 'pears');
|
||||
generator.addSourceMapping(2, 3, 456, 7);
|
||||
expect(generator.toMap())
|
||||
.toEqual(objectContaining({
|
||||
mappings: ';GAucO',
|
||||
}));
|
||||
});
|
||||
|
||||
it('can add a mapping with source location and symbol name', () => {
|
||||
generator.startFile('apples', 'pears');
|
||||
generator.addNamedSourceMapping(9, 876, 54, 3, 'arbitrary');
|
||||
expect(generator.toMap())
|
||||
.toEqual(objectContaining({
|
||||
mappings: ';;;;;;;;42BAqDGA',
|
||||
names: ['arbitrary'],
|
||||
}));
|
||||
});
|
||||
|
||||
describe('full map generation', () => {
|
||||
beforeEach(() => {
|
||||
generator.startFile('apples', 'pears');
|
||||
generator.addSimpleMapping(1, 2);
|
||||
generator.addNamedSourceMapping(3, 4, 5, 6, 'plums');
|
||||
generator.endFile();
|
||||
generator.startFile('lemons', 'oranges');
|
||||
generator.addNamedSourceMapping(7, 8, 9, 10, 'tangerines');
|
||||
generator.addNamedSourceMapping(11, 12, 13, 14, 'tangerines');
|
||||
generator.addSimpleMapping(15, 16);
|
||||
});
|
||||
|
||||
it('can add multiple mappings for each file', () => {
|
||||
expect(generator.toMap()).toEqual({
|
||||
version: 3,
|
||||
mappings: 'E;;IAIMA;;;;QCIIC;;;;YAIIA;;;;gB',
|
||||
sources: ['apples', 'lemons'],
|
||||
sourcesContent: ['pears', 'oranges'],
|
||||
names: ['plums', 'tangerines'],
|
||||
});
|
||||
});
|
||||
|
||||
it('can add a `file` property to the map', () => {
|
||||
expect(generator.toMap('arbitrary'))
|
||||
.toEqual(objectContaining({
|
||||
file: 'arbitrary',
|
||||
}));
|
||||
});
|
||||
|
||||
it('supports direct JSON serialization', () => {
|
||||
expect(JSON.parse(generator.toString())).toEqual(generator.toMap());
|
||||
});
|
||||
|
||||
it('supports direct JSON serialization with a file name', () => {
|
||||
const file = 'arbitrary/file';
|
||||
expect(JSON.parse(generator.toString(file))).toEqual(generator.toMap(file));
|
||||
});
|
||||
});
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* Copyright (c) 2017-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
jest.disableAutomock();
|
||||
|
||||
const Generator = require('../Generator');
|
||||
const {compactMapping, fromRawMappings} = require('..');
|
||||
|
||||
describe('flattening mappings / compacting', () => {
|
||||
it('flattens simple mappings', () => {
|
||||
expect(compactMapping({generated: {line: 12, column: 34}}))
|
||||
.toEqual([12, 34]);
|
||||
});
|
||||
|
||||
it('flattens mappings with a source location', () => {
|
||||
expect(compactMapping({
|
||||
generated: {column: 34, line: 12},
|
||||
original: {column: 78, line: 56},
|
||||
})).toEqual([12, 34, 56, 78]);
|
||||
});
|
||||
|
||||
it('flattens mappings with a source location and a symbol name', () => {
|
||||
expect(compactMapping({
|
||||
generated: {column: 34, line: 12},
|
||||
name: 'arbitrary',
|
||||
original: {column: 78, line: 56},
|
||||
})).toEqual([12, 34, 56, 78, 'arbitrary']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('build map from raw mappings', () => {
|
||||
it('returns a `Generator` instance', () => {
|
||||
expect(fromRawMappings([])).toBeInstanceOf(Generator);
|
||||
});
|
||||
|
||||
it('returns a working source map containing all mappings', () => {
|
||||
const input = [{
|
||||
code: lines(11),
|
||||
map: [
|
||||
[1, 2],
|
||||
[3, 4, 5, 6, 'apples'],
|
||||
[7, 8, 9, 10],
|
||||
[11, 12, 13, 14, 'pears']
|
||||
],
|
||||
sourceCode: 'code1',
|
||||
sourcePath: 'path1',
|
||||
}, {
|
||||
code: lines(3),
|
||||
map: [
|
||||
[1, 2],
|
||||
[3, 4, 15, 16, 'bananas'],
|
||||
],
|
||||
sourceCode: 'code2',
|
||||
sourcePath: 'path2',
|
||||
}, {
|
||||
code: lines(23),
|
||||
map: [
|
||||
[11, 12],
|
||||
[13, 14, 15, 16, 'bananas'],
|
||||
[17, 18, 19, 110],
|
||||
[21, 112, 113, 114, 'pears']
|
||||
],
|
||||
sourceCode: 'code3',
|
||||
sourcePath: 'path3',
|
||||
}];
|
||||
|
||||
expect(fromRawMappings(input).toMap())
|
||||
.toEqual({
|
||||
mappings: 'E;;IAIMA;;;;QAII;;;;YAIIC;E;;ICEEC;;;;;;;;;;;Y;;cCAAA;;;;kBAI8F;;;;gHA8FID',
|
||||
names: ['apples', 'pears', 'bananas'],
|
||||
sources: ['path1', 'path2', 'path3'],
|
||||
sourcesContent: ['code1', 'code2', 'code3'],
|
||||
version: 3,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const lines = n => Array(n).join('\n');
|
Loading…
Reference in New Issue