Write more unit tests for the lexer and the parser

Moreover, group the lexer unit tests per method. This matches what we
do for other classes and makes it more easily visible which methods
we don't or insufficiently unit test.

The parser itself is not unit tested yet, so this patch provides a start
for doing so. The `inlineStreamSkipEI` method is used in other end
marker detection methods, so it's important that its functionality is
correct for proper parsing.
This commit is contained in:
Tim van der Meij 2019-03-10 15:33:45 +01:00
parent 2ee299a62b
commit 4a4b197b9d
No known key found for this signature in database
GPG Key ID: 8C3FD2925A5F2762

View File

@ -14,13 +14,79 @@
*/ */
/* eslint no-var: error */ /* eslint no-var: error */
import { Lexer, Linearization } from '../../src/core/parser'; import { Lexer, Linearization, Parser } from '../../src/core/parser';
import { FormatError } from '../../src/shared/util'; import { FormatError } from '../../src/shared/util';
import { Name } from '../../src/core/primitives'; import { Name } from '../../src/core/primitives';
import { StringStream } from '../../src/core/stream'; import { StringStream } from '../../src/core/stream';
describe('parser', function() { describe('parser', function() {
describe('Parser', function() {
describe('inlineStreamSkipEI', function() {
it('should skip over the EI marker if it is found', function() {
const string = 'q 1 0 0 1 0 0 cm BI /W 10 /H 10 /BPC 1 ' +
'/F /A85 ID abc123~> EI Q';
const input = new StringStream(string);
const lexer = new Lexer(input);
const parser = new Parser(lexer, /* allowStreams = */ true,
/* xref = */ null);
parser.inlineStreamSkipEI(input);
expect(input.pos).toEqual(string.indexOf('Q'));
expect(input.peekByte()).toEqual(0x51); // 'Q'
});
it('should skip to the end of stream if the EI marker is not found',
function() {
const string = 'q 1 0 0 1 0 0 cm BI /W 10 /H 10 /BPC 1 ' +
'/F /A85 ID abc123~> Q';
const input = new StringStream(string);
const lexer = new Lexer(input);
const parser = new Parser(lexer, /* allowStreams = */ true,
/* xref = */ null);
parser.inlineStreamSkipEI(input);
expect(input.pos).toEqual(string.length);
expect(input.peekByte()).toEqual(-1);
});
});
});
describe('Lexer', function() { describe('Lexer', function() {
describe('nextChar', function() {
it('should return and set -1 when the end of the stream is reached',
function() {
const input = new StringStream('');
const lexer = new Lexer(input);
expect(lexer.nextChar()).toEqual(-1);
expect(lexer.currentChar).toEqual(-1);
});
it('should return and set the character after the current position',
function() {
const input = new StringStream('123');
const lexer = new Lexer(input);
expect(lexer.nextChar()).toEqual(0x32); // '2'
expect(lexer.currentChar).toEqual(0x32); // '2'
});
});
describe('peekChar', function() {
it('should only return -1 when the end of the stream is reached',
function() {
const input = new StringStream('');
const lexer = new Lexer(input);
expect(lexer.peekChar()).toEqual(-1);
expect(lexer.currentChar).toEqual(-1);
});
it('should only return the character after the current position',
function() {
const input = new StringStream('123');
const lexer = new Lexer(input);
expect(lexer.peekChar()).toEqual(0x32); // '2'
expect(lexer.currentChar).toEqual(0x31); // '1'
});
});
describe('getNumber', function() {
it('should stop parsing numbers at the end of stream', function() { it('should stop parsing numbers at the end of stream', function() {
const input = new StringStream('11.234'); const input = new StringStream('11.234');
const lexer = new Lexer(input); const lexer = new Lexer(input);
@ -83,7 +149,9 @@ describe('parser', function() {
// The lexer must not have consumed the 'E' // The lexer must not have consumed the 'E'
expect(lexer.currentChar).toEqual(0x45); // 'E' expect(lexer.currentChar).toEqual(0x45); // 'E'
}); });
});
describe('getString', function() {
it('should stop parsing strings at the end of stream', function() { it('should stop parsing strings at the end of stream', function() {
const input = new StringStream('(1$4)'); const input = new StringStream('(1$4)');
input.getByte = function(super_getByte) { input.getByte = function(super_getByte) {
@ -95,21 +163,26 @@ describe('parser', function() {
expect(lexer.getString()).toEqual('1'); expect(lexer.getString()).toEqual('1');
}); });
it('should not throw exception on bad input', function() {
// '7 0 2 15 5 2 2 2 4 3 2 4' should be parsed as '70 21 55 22 24 32'.
const input = new StringStream('<7 0 2 15 5 2 2 2 4 3 2 4>');
const lexer = new Lexer(input);
expect(lexer.getHexString()).toEqual('p!U"$2');
});
it('should ignore escaped CR and LF', function() { it('should ignore escaped CR and LF', function() {
// '(\101\<CR><LF>\102)' should be parsed as 'AB'. // '(\101\<CR><LF>\102)' should be parsed as 'AB'.
const input = new StringStream('(\\101\\\r\n\\102\\\r\\103\\\n\\104)'); const input = new StringStream('(\\101\\\r\n\\102\\\r\\103\\\n\\104)');
const lexer = new Lexer(input); const lexer = new Lexer(input);
expect(lexer.getString()).toEqual('ABCD'); expect(lexer.getString()).toEqual('ABCD');
}); });
});
it('should handle Names with invalid usage of NUMBER SIGN (#)', function() { describe('getHexString', function() {
it('should not throw exception on bad input', function() {
// '7 0 2 15 5 2 2 2 4 3 2 4' should be parsed as '70 21 55 22 24 32'.
const input = new StringStream('<7 0 2 15 5 2 2 2 4 3 2 4>');
const lexer = new Lexer(input);
expect(lexer.getHexString()).toEqual('p!U"$2');
});
});
describe('getName', function() {
it('should handle Names with invalid usage of NUMBER SIGN (#)',
function() {
const inputNames = ['/# 680 0 R', '/#AQwerty', '/#A<</B']; const inputNames = ['/# 680 0 R', '/#AQwerty', '/#A<</B'];
const expectedNames = ['#', '#AQwerty', '#A']; const expectedNames = ['#', '#AQwerty', '#A'];
@ -120,6 +193,7 @@ describe('parser', function() {
} }
}); });
}); });
});
describe('Linearization', function() { describe('Linearization', function() {
it('should not find a linearization dictionary', function() { it('should not find a linearization dictionary', function() {