Skip to content

Commit

Permalink
external grammar tests
Browse files Browse the repository at this point in the history
at this point productions have hit 100%, but it is misleading ... there
are probably quite a few variations we still need to cover, though I
think I will do that via larger end to end tests instead of focused
grammar tests
  • Loading branch information
bathos committed Feb 12, 2017
1 parent ee80c01 commit 293b989
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 10 deletions.
9 changes: 5 additions & 4 deletions src/processor/index.js
Expand Up @@ -159,18 +159,19 @@ class Processor extends Decoder {
const possibleChaosIter = PARAMETER_REFERENCE(node, false);

possibleChaosIter.next();
possibleChaosIter.next(this.boundary());

const innerCP = yield;
const innerCP = injectedCPs.shift() || (yield);

// Special case: '%' may appear as part of one non-literal value: the
// symbol in parameter entity declarations themselves. Therefore we
// need to use the following CP to disambiguate.

if (!isWhitespaceChar(innerCP)) {
if (isWhitespaceChar(innerCP)) {
injectedCPs.unshift(innerCP);
} else {
chaosIter = possibleChaosIter;
cp = innerCP;
} else {
injectedCPs.unshift(innerCP);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/processor/productions/parameter-reference.js
Expand Up @@ -10,7 +10,7 @@ export default function * (nodes, inEntityValue) {

referenceBoundary()();

const entity = nodes.getEntity(name);
const entity = nodes.doctype.getEntity(name);

if (!entity) {
yield `parameter entity "${ name }" to have been defined`;
Expand Down
Expand Up @@ -59,6 +59,25 @@ tap.test('Conditional section in external DTD (INCLUDE, nested)', test => {
.then(test.end);
});

tap.test('Unmatched include section terminal', test => {
parseHalp({
input: `
<!DOCTYPE foo SYSTEM "foo">
<foo bar=""/>
`,
foo: `
<![INCLUDE[
<!ELEMENT foo EMPTY>
<![INCLUDE[
<!ATTLIST foo bar CDATA #IMPLIED>
]]>
`
}).catch(err => {
test.match(err.message, ']]>');
test.end();
});
});

tap.test('Conditional section in external DTD (IGNORE)', test => {
parseHalp({
input: `
Expand All @@ -67,11 +86,7 @@ tap.test('Conditional section in external DTD (IGNORE)', test => {
]>
<foo/>
`,
foo: `
<![IGNORE[
<!ELEMENT foo EMPTY>
]]>
`
foo: `<![IGNORE[<!ELEMENT foo EMPTY>]]>`
}).then(([ doctype ]) => {
test.equal(doctype.external.length, 0);
})
Expand Down Expand Up @@ -139,6 +154,33 @@ tap.test('Ignored section content does need to be valid chars', test => {
});
});

tap.test('Parameterization of conditional sections', test => {
parseHalp({
input: `
<!DOCTYPE foo SYSTEM "foo" [
<!ENTITY % nor "IGNORE">
<!ENTITY % lud "INCLUDE">
<!ENTITY % xxx "]]&#x3E;">
]>
<foo/>
`,
foo: `
<![ %nor; [
<!ELEMENT bar EMPTY>
%xxx;
]]>
<![ %lud; [
<!ELEMENT foo EMPTY>
]]>
`
}).then(([ { external } ]) => {
test.equal(external.length, 1);
test.equal(external[0].name, 'foo');
})
.catch(test.error)
.then(test.end);
});

tap.test('Conditional section in internal DTD is not recognized', test => {
parse(`
<!DOCTYPE foo [
Expand All @@ -152,3 +194,107 @@ tap.test('Conditional section in internal DTD is not recognized', test => {
test.end();
});
});

tap.test('External PE refs recognized in correct contexts', test => {
parseHalp({
input: `
<!DOCTYPE foo SYSTEM "foo">
<foo><foo/></foo>
`,
poo: `
foo
`,
foo: `
<!ENTITY % foo SYSTEM "poo">
<?bar %foo;?>
<!ELEMENT %foo; (%foo;)*>
<!--%foo;-->
`
}).then(([ { external: [ , pi, ed, cm ] } ]) => {
test.equal(pi.instruction, '%foo;');
test.equal(ed.name, 'foo');
test.equal(cm.content, '%foo;');
})
.catch(test.error)
.then(test.end);
});

tap.test('External PE ref padding behavior', test => {
parseHalp({
input: `
<!DOCTYPE foo SYSTEM "foo">
<foo><bar/></foo>
`,
foo: `
<!ENTITY % bar "bar">
<!ENTITY % baz "(%bar;|baz)">
<!ELEMENT bar EMPTY>
<!ELEMENT baz EMPTY>
<!ELEMENT foo%baz;>
`
}).then(([ { external: [ , { value } ] } ]) => {
test.equal(String.fromCodePoint(...value), '(bar|baz)');
})
.catch(test.error)
.then(test.end);
});

tap.test('PE must be defined', test => {
parse(`
<!DOCTYPE foo [
<!ELEMENT foo EMPTY>
%bar;
]>
<foo/>
`).catch(err => {
test.match(err.message, 'bar');
test.end();
});
});

tap.test('General entity may not be used as PE', test => {
parse(`
<!DOCTYPE foo [
<!ELEMENT foo EMPTY>
<!ENTITY bar "baz">
%bar;
]>
<foo/>
`).catch(err => {
test.match(err.message, 'parameter');
test.end();
});
});

tap.test('General entity may be externally defined', test => {
parseHalp({
input: `
<!DOCTYPE foo [
<!ELEMENT foo (bar)>
<!ELEMENT bar (#PCDATA)*>
<!ENTITY baz SYSTEM "baz" >
]>
<foo>&baz;</foo>
`,
baz: `
<bar>baz</bar>
`
}).then(([ , [ [ cdata ] ] ]) => {
test.equal(cdata.text, 'baz');
})
.catch(test.error)
.then(test.end);
});

tap.test('Unparsed entity notation must have been declared', test => {
parse(`
<!DOCTYPE foo [
<!ELEMENT foo EMPTY>
<!ENTITY bar SYSTEM "bar" NDATA baz>
]>
<foo/>
`).catch(err => {
test.match(err.message, 'baz');
test.end();
});
});
33 changes: 33 additions & 0 deletions test/processor/test-xml-and-text-decl.js
Expand Up @@ -130,3 +130,36 @@ tap.test('text declaration is recognized in external entity', test => {
.catch(test.error)
.then(test.end);
});

tap.test('external entity initial PI vs text decl', test => {
parseHalp({
input:`
<!DOCTYPE foo [
<!ELEMENT foo EMPTY>
<!ENTITY % bar SYSTEM "bar">
%bar;
]>
<foo/>
`,
bar:`<?xmlpoops?>`
}).then(([ [ , , pi ] ]) => {
test.equal(pi.target, 'xmlpoops');
})
.catch(test.error)
.then(test.end);
});

tap.test('external dtd initial PI vs text decl', test => {
parseHalp({
input:`
<!DOCTYPE foo SYSTEM 'foo'>
<foo/>
`,
foo:`<?doggo puppers?><!ELEMENT foo EMPTY>`
}).then(([ { external: [ pi ] } ]) => {
test.equal(pi.target, 'doggo');
})
.catch(test.error)
.then(test.end);
});

0 comments on commit 293b989

Please sign in to comment.