|
|
|
|
|
|
|
|
|
# Coverage
|
|
|
|
|
|
|
|
|
|
This file is just a collection of unit tests not covered elsewhere.
|
|
|
|
|
|
|
|
|
|
Most notably regression tests, tests improving code coverage and other useful
|
|
|
|
|
things may drop here.
|
|
|
|
|
|
|
|
|
|
(However any tests requiring any additional command line option, like enabling
|
|
|
|
|
an extension, must be included in their respective files.)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## GitHub Issues
|
|
|
|
|
|
|
|
|
|
### [Issue 2](https://github.com/mity/md4c/issues/2)
|
|
|
|
|
|
|
|
|
|
Raw HTML block:
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
<gi att1=tok1 att2=tok2>
|
|
|
|
|
.
|
|
|
|
|
<gi att1=tok1 att2=tok2>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
Inline:
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
foo <gi att1=tok1 att2=tok2> bar
|
|
|
|
|
.
|
|
|
|
|
<p>foo <gi att1=tok1 att2=tok2> bar</p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
Inline with a line break:
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
foo <gi att1=tok1
|
|
|
|
|
att2=tok2> bar
|
|
|
|
|
.
|
|
|
|
|
<p>foo <gi att1=tok1
|
|
|
|
|
att2=tok2> bar</p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 4](https://github.com/mity/md4c/issues/4)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
![alt text with *entity* ©](img.png 'title')
|
|
|
|
|
.
|
|
|
|
|
<p><img src="img.png" alt="alt text with entity ©" title="title"></p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 9](https://github.com/mity/md4c/issues/9)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
> [foo
|
|
|
|
|
> bar]: /url
|
|
|
|
|
>
|
|
|
|
|
> [foo bar]
|
|
|
|
|
.
|
|
|
|
|
<blockquote>
|
|
|
|
|
<p><a href="/url">foo
|
|
|
|
|
bar</a></p>
|
|
|
|
|
</blockquote>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 10](https://github.com/mity/md4c/issues/10)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
[x]:
|
|
|
|
|
x
|
|
|
|
|
- <?
|
|
|
|
|
|
|
|
|
|
x
|
|
|
|
|
.
|
|
|
|
|
<ul>
|
|
|
|
|
<li><?
|
|
|
|
|
|
|
|
|
|
x
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 11](https://github.com/mity/md4c/issues/11)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
x [link](/url "foo – bar") x
|
|
|
|
|
.
|
|
|
|
|
<p>x <a href="/url" title="foo – bar">link</a> x</p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 14](https://github.com/mity/md4c/issues/14)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
a***b* c*
|
|
|
|
|
.
|
|
|
|
|
<p>a*<em><em>b</em> c</em></p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 15](https://github.com/mity/md4c/issues/15)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
***b* c*
|
|
|
|
|
.
|
|
|
|
|
<p>*<em><em>b</em> c</em></p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 21](https://github.com/mity/md4c/issues/21)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
a*b**c*
|
|
|
|
|
.
|
|
|
|
|
<p>a<em>b**c</em></p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 33](https://github.com/mity/md4c/issues/33)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
```&&&&&&&&
|
|
|
|
|
.
|
|
|
|
|
<pre><code class="language-&&&&&&&&"></code></pre>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 36](https://github.com/mity/md4c/issues/36)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
__x_ _x___
|
|
|
|
|
.
|
|
|
|
|
<p><em><em>x</em> <em>x</em></em>_</p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 39](https://github.com/mity/md4c/issues/39)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
[\\]: x
|
|
|
|
|
.
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 40](https://github.com/mity/md4c/issues/40)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
[x](url
|
|
|
|
|
'title'
|
|
|
|
|
)x
|
|
|
|
|
.
|
|
|
|
|
<p><a href="url" title="title">x</a>x</p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 65](https://github.com/mity/md4c/issues/65)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
`
|
|
|
|
|
.
|
|
|
|
|
<p>`</p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 74](https://github.com/mity/md4c/issues/74)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
[f]:
|
|
|
|
|
-
|
|
|
|
|
xx
|
|
|
|
|
-
|
|
|
|
|
.
|
|
|
|
|
<pre><code>xx
|
|
|
|
|
</code></pre>
|
|
|
|
|
<ul>
|
|
|
|
|
<li></li>
|
|
|
|
|
</ul>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 78](https://github.com/mity/md4c/issues/78)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
[SS ẞ]: /url
|
|
|
|
|
[ẞ SS]
|
|
|
|
|
.
|
|
|
|
|
<p><a href="/url">ẞ SS</a></p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 83](https://github.com/mity/md4c/issues/83)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
foo
|
|
|
|
|
>
|
|
|
|
|
.
|
|
|
|
|
<p>foo</p>
|
|
|
|
|
<blockquote>
|
|
|
|
|
</blockquote>
|
|
|
|
|
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 95](https://github.com/mity/md4c/issues/95)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
. foo
|
|
|
|
|
.
|
|
|
|
|
<p>. foo</p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 96](https://github.com/mity/md4c/issues/96)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
[ab]: /foo
|
|
|
|
|
[a] [ab] [abc]
|
|
|
|
|
.
|
|
|
|
|
<p>[a] <a href="/foo">ab</a> [abc]</p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
[a b]: /foo
|
|
|
|
|
[a b]
|
|
|
|
|
.
|
|
|
|
|
<p><a href="/foo">a b</a></p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 97](https://github.com/mity/md4c/issues/97)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
*a **b c* d**
|
|
|
|
|
.
|
|
|
|
|
<p><em>a <em><em>b c</em> d</em></em></p>
|
|
|
|
|
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 100](https://github.com/mity/md4c/issues/100)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
<foo@123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123>
|
|
|
|
|
.
|
|
|
|
|
<p><a href="mailto:foo@123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123">foo@123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123</a></p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
<foo@123456789012345678901234567890123456789012345678901234567890123x.123456789012345678901234567890123456789012345678901234567890123>
|
|
|
|
|
.
|
|
|
|
|
<p><foo@123456789012345678901234567890123456789012345678901234567890123x.123456789012345678901234567890123456789012345678901234567890123></p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
(Note the `x` here which turns it over the max. allowed length limit.)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 107](https://github.com/mity/md4c/issues/107)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
***foo *bar baz***
|
|
|
|
|
.
|
|
|
|
|
<p>*<strong>foo <em>bar baz</em></strong></p>
|
|
|
|
|
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 124](https://github.com/mity/md4c/issues/124)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
~~~
|
|
|
|
|
x
|
|
|
|
|
~~~
|
|
|
|
|
|
|
|
|
|
~~~
|
|
|
|
|
x
|
|
|
|
|
~~~
|
|
|
|
|
.
|
|
|
|
|
<pre><code> x
|
|
|
|
|
</code></pre>
|
|
|
|
|
<pre><code> x
|
|
|
|
|
</code></pre>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 131](https://github.com/mity/md4c/issues/131)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
[![alt][img]][link]
|
|
|
|
|
|
|
|
|
|
[img]: img_url
|
|
|
|
|
[link]: link_url
|
|
|
|
|
.
|
|
|
|
|
<p><a href="link_url"><img src="img_url" alt="alt"></a></p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 142](https://github.com/mity/md4c/issues/142)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
[fooﬗ]: /url
|
|
|
|
|
[fooﬕ]
|
|
|
|
|
.
|
|
|
|
|
<p>[fooﬕ]</p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### [Issue 149](https://github.com/mity/md4c/issues/149)
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
- <script>
|
|
|
|
|
- foo
|
|
|
|
|
bar
|
|
|
|
|
</script>
|
|
|
|
|
.
|
|
|
|
|
<ul>
|
|
|
|
|
<li><script>
|
|
|
|
|
</li>
|
|
|
|
|
<li>foo
|
|
|
|
|
bar
|
|
|
|
|
</script></li>
|
|
|
|
|
</ul>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Code coverage
|
|
|
|
|
|
|
|
|
|
### `md_is_unicode_whitespace__()`
|
|
|
|
|
|
|
|
|
|
Unicode whitespace (here U+2000) forms a word boundary so these cannot be
|
|
|
|
|
resolved as emphasis span because there is no closer mark.
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
*foo *bar
|
|
|
|
|
.
|
|
|
|
|
<p>*foo *bar</p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### `md_is_unicode_punct__()`
|
|
|
|
|
|
|
|
|
|
Ditto for Unicode punctuation (here U+00A1).
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
*foo¡*bar
|
|
|
|
|
.
|
|
|
|
|
<p>*foo¡*bar</p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### `md_get_unicode_fold_info()`
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
[Příliš žluťoučký kůň úpěl ďábelské ódy.]
|
|
|
|
|
|
|
|
|
|
[PŘÍLIŠ ŽLUŤOUČKÝ KŮŇ ÚPĚL ĎÁBELSKÉ ÓDY.]: /url
|
|
|
|
|
.
|
|
|
|
|
<p><a href="/url">Příliš žluťoučký kůň úpěl ďábelské ódy.</a></p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### `md_decode_utf8__()` and `md_decode_utf8_before__()`
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
á*Á (U+00E1, i.e. two byte UTF-8 sequence)
|
|
|
|
|
* (U+2000, i.e. three byte UTF-8 sequence)
|
|
|
|
|
.
|
|
|
|
|
<p>á*Á (U+00E1, i.e. two byte UTF-8 sequence)
|
|
|
|
|
* (U+2000, i.e. three byte UTF-8 sequence)</p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### `md_is_link_destination_A()`
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
[link](</url\.with\.escape>)
|
|
|
|
|
.
|
|
|
|
|
<p><a href="/url.with.escape">link</a></p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### `md_link_label_eq()`
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
[foo bar]
|
|
|
|
|
|
|
|
|
|
[foo bar]: /url
|
|
|
|
|
.
|
|
|
|
|
<p><a href="/url">foo bar</a></p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### `md_is_inline_link_spec()`
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
> [link](/url 'foo
|
|
|
|
|
> bar')
|
|
|
|
|
.
|
|
|
|
|
<blockquote>
|
|
|
|
|
<p><a href="/url" title="foo
|
|
|
|
|
bar">link</a></p>
|
|
|
|
|
</blockquote>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### `md_build_ref_def_hashtable()`
|
|
|
|
|
|
|
|
|
|
All link labels in the following example all have the same FNV1a hash (after
|
|
|
|
|
normalization of the label, which means after converting to a vector of Unicode
|
|
|
|
|
codepoints and lowercase folding).
|
|
|
|
|
|
|
|
|
|
So the example triggers quite complex code paths which are not otherwise easily
|
|
|
|
|
tested.
|
|
|
|
|
|
|
|
|
|
```````````````````````````````` example
|
|
|
|
|
[foo]: /foo
|
|
|
|
|
[qnptgbh]: /qnptgbh
|
|
|
|
|
[abgbrwcv]: /abgbrwcv
|
|
|
|
|
[abgbrwcv]: /abgbrwcv2
|
|
|
|
|
[abgbrwcv]: /abgbrwcv3
|
|
|
|
|
[abgbrwcv]: /abgbrwcv4
|
|
|
|
|
[alqadfgn]: /alqadfgn
|
|
|
|
|
|
|
|
|
|
[foo]
|
|
|
|
|
[qnptgbh]
|
|
|
|
|
[abgbrwcv]
|
|
|
|
|
[alqadfgn]
|
|
|
|
|
[axgydtdu]
|
|
|
|
|
.
|
|
|
|
|
<p><a href="/foo">foo</a>
|
|
|
|
|
<a href="/qnptgbh">qnptgbh</a>
|
|
|
|
|
<a href="/abgbrwcv">abgbrwcv</a>
|
|
|
|
|
<a href="/alqadfgn">alqadfgn</a>
|
|
|
|
|
[axgydtdu]</p>
|
|
|
|
|
````````````````````````````````
|
|
|
|
|
|
|
|
|
|
For the sake of completeness, the following C program was used to find the hash
|
|
|
|
|
collisions by brute force:
|
|
|
|
|
|
|
|
|
|
~~~
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static unsigned etalon;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define MD_FNV1A_BASE 2166136261
|
|
|
|
|
#define MD_FNV1A_PRIME 16777619
|
|
|
|
|
|
|
|
|
|
static inline unsigned
|
|
|
|
|
fnv1a(unsigned base, const void* data, size_t n)
|
|
|
|
|
{
|
|
|
|
|
const unsigned char* buf = (const unsigned char*) data;
|
|
|
|
|
unsigned hash = base;
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
for(i = 0; i < n; i++) {
|
|
|
|
|
hash ^= buf[i];
|
|
|
|
|
hash *= MD_FNV1A_PRIME;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return hash;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static unsigned
|
|
|
|
|
unicode_hash(const char* data, size_t n)
|
|
|
|
|
{
|
|
|
|
|
unsigned value;
|
|
|
|
|
unsigned hash = MD_FNV1A_BASE;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for(i = 0; i < n; i++) {
|
|
|
|
|
value = data[i];
|
|
|
|
|
hash = fnv1a(hash, &value, sizeof(unsigned));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return hash;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
recurse(char* buffer, size_t off, size_t len)
|
|
|
|
|
{
|
|
|
|
|
int ch;
|
|
|
|
|
|
|
|
|
|
if(off < len - 1) {
|
|
|
|
|
for(ch = 'a'; ch <= 'z'; ch++) {
|
|
|
|
|
buffer[off] = ch;
|
|
|
|
|
recurse(buffer, off+1, len);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for(ch = 'a'; ch <= 'z'; ch++) {
|
|
|
|
|
buffer[off] = ch;
|
|
|
|
|
if(unicode_hash(buffer, len) == etalon) {
|
|
|
|
|
printf("Dup: %.*s\n", (int)len, buffer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
main(int argc, char** argv)
|
|
|
|
|
{
|
|
|
|
|
char buffer[32];
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
|
|
if(argc < 2)
|
|
|
|
|
etalon = unicode_hash("foo", 3);
|
|
|
|
|
else
|
|
|
|
|
etalon = unicode_hash(argv[1], strlen(argv[1]));
|
|
|
|
|
|
|
|
|
|
for(len = 1; len <= sizeof(buffer); len++)
|
|
|
|
|
recurse(buffer, 0, len);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
~~~
|