mv suite{_bench} to test-html-{ut,ref} crates

- allow compiling/running html tests without compiling main crate tests
  (useful when e.g. making type changes to events but html unaffected)
- avoid need for future flags in main crate
This commit is contained in:
Noah Hellman 2023-04-28 20:58:08 +02:00
parent d2a46663f1
commit 3cea79a122
18 changed files with 182 additions and 55 deletions

12
tests/html-ut/Cargo.toml Normal file
View file

@ -0,0 +1,12 @@
[package]
name = "test-html-ut"
description = "HTML output unit tests."
version = "0.1.0"
edition = "2021"
[dependencies]
jotdown = { path = "../.." }
[lib]
name = "test_html_ut"
path = "lib.rs"

24
tests/html-ut/Makefile Normal file
View file

@ -0,0 +1,24 @@
.POSIX:
.SUFFIXES: .test .rs
TEST=$(shell find ut -name '*.test' | sort)
TEST_RS=${TEST:.test=.rs}
BLACKLIST += djot_js_filters # lua filters not implemented
BLACKLIST += djot_js_symb # uses ast
BLACKLIST += djot_js_sourcepos # not parsable
ut/mod.rs: ${TEST_RS}
mkdir -p ut
rm -f $@
for f in ${TEST}; do \
name=$$(basename -s .test $$f); \
echo ${BLACKLIST} | tr ' ' '\n' | grep -q $$name || echo "mod $$name;" >> $@; \
done
.test.rs:
gawk -fgen.awk $< | head -n-1 > $@
clean:
rm -f ut/*.rs

6
tests/html-ut/build.rs Normal file
View file

@ -0,0 +1,6 @@
fn main() {
let status = std::process::Command::new("make")
.status()
.expect("failed to execute make");
assert!(status.success());
}

47
tests/html-ut/cmp.rs Normal file
View file

@ -0,0 +1,47 @@
#[macro_export]
macro_rules! compare {
($src:expr, $expected:expr) => {
use jotdown::Render;
let src = $src;
let expected = $expected;
let p = jotdown::Parser::new(src);
let mut actual = String::new();
jotdown::html::Renderer::default()
.push(p, &mut actual)
.unwrap();
assert_eq!(
actual.trim(),
expected.trim(),
concat!(
"\n",
"\x1b[0;1m========================= INPUT ============================\x1b[0m\n",
"\x1b[2m{}",
"\x1b[0;1m=================== ACTUAL vs EXPECTED =====================\x1b[0m\n",
"{}",
"\x1b[0;1m============================================================\x1b[0m\n",
),
$src,
{
let a = actual.trim().split('\n');
let b = expected.trim().split('\n');
let max = a.clone().count().max(b.clone().count());
let a_width = a.clone().map(|a| a.len()).max().unwrap_or(0);
a.chain(std::iter::repeat(""))
.zip(b.chain(std::iter::repeat("")))
.take(max)
.map(|(a, b)| {
format!(
"\x1b[{}m{:a_width$}\x1b[0m {}= \x1b[{}m{}\x1b[0m\n",
if a == b { "2" } else { "31" },
a,
if a == b { '=' } else { '!' },
if a == b { "2" } else { "32" },
b,
a_width = a_width,
)
})
.collect::<String>()
},
);
};
}

62
tests/html-ut/gen.awk Normal file
View file

@ -0,0 +1,62 @@
BEGIN {
FS=":"
while (getline < "skip") skips[$1]=$2
print "use crate::compare;"
print ""
}
$0 ~ "^`{3,}$" {
l=length($0)
if (fence == 0) { # enter fence
print "#[test]"
fence=l
} else if (fence == l) { # exit fence
if (ignore) {
ignore=0
} else {
printf " let expected = r##\""
close("src")
while (getline l < "src") print l
close("src")
system("rm -f src")
print "\"##;"
print " compare!(src, expected);"
print "}"
print ""
}
fence=0
} else {
print $0 > "src" # md/html
}
next
}
fence == 0 && $0 ~ "^`{3,} .*$" {
ignore=1
fence=match($0, "[^`]")-1
next
}
$0 ~ "^\\.$" && !ignore { # enter html
close("src")
cmd="cat src | md5sum | cut -c-7"
cmd | getline hash
close(cmd)
if (hash in skips) printf "#[ignore = \"%s\"]\n", skips[hash]
printf "fn test_%s() {\n", hash
printf " let src = r##\""
while (getline l < "src") print l
close("src")
system("rm -f src")
print "\"##;"
next
}
!ignore {
if (fence) {
# write to file so content can be piped to md5sum (without having to shell escape)
print $0 > "src" # md/html
} else if ($0 != "") {
printf "// %s\n", $0 # comment
}
}

50
tests/html-ut/lib.rs Normal file
View file

@ -0,0 +1,50 @@
#[cfg(test)]
mod ut;
#[macro_export]
macro_rules! compare {
($src:expr, $expected:expr) => {
use jotdown::Render;
let src = $src;
let expected = $expected;
let p = jotdown::Parser::new(src);
let mut actual = String::new();
jotdown::html::Renderer::default()
.push(p, &mut actual)
.unwrap();
assert_eq!(
actual.trim(),
expected.trim(),
concat!(
"\n",
"\x1b[0;1m========================= INPUT ============================\x1b[0m\n",
"\x1b[2m{}",
"\x1b[0;1m=================== ACTUAL vs EXPECTED =====================\x1b[0m\n",
"{}",
"\x1b[0;1m============================================================\x1b[0m\n",
),
$src,
{
let a = actual.trim().split('\n');
let b = expected.trim().split('\n');
let max = a.clone().count().max(b.clone().count());
let a_width = a.clone().map(|a| a.len()).max().unwrap_or(0);
a.chain(std::iter::repeat(""))
.zip(b.chain(std::iter::repeat("")))
.take(max)
.map(|(a, b)| {
format!(
"\x1b[{}m{:a_width$}\x1b[0m {}= \x1b[{}m{}\x1b[0m\n",
if a == b { "2" } else { "31" },
a,
if a == b { '=' } else { '!' },
if a == b { "2" } else { "32" },
b,
a_width = a_width,
)
})
.collect::<String>()
},
);
};
}

14
tests/html-ut/skip Normal file
View file

@ -0,0 +1,14 @@
38d85f9:multi-line block attributes
6c14561:multi-line block attributes
f4f22fc:attribute key class order
ae6fc15:bugged left/right quote
168469a:bugged left/right quote
2056174:unicode whitespace emph
2e8fffa:unicode whitespace strong
e1f5b5e:untrimmed whitespace before linebreak
07888f3:div close within raw block
8423412:heading id conflict with existing id
c0a3dec:escape in url
61876cf:roman alpha ambiguity
f31b357:roman alpha ambiguity
642d380:table end in verbatim inline

View file

@ -0,0 +1,58 @@
Footnote references may appear within a footnote.
```
[^a]
[^a]: a[^b][^c]
[^b]: b
.
<p><a id="fnref1" href="#fn1" role="doc-noteref"><sup>1</sup></a></p>
<section role="doc-endnotes">
<hr>
<ol>
<li id="fn1">
<p>a<a id="fnref2" href="#fn2" role="doc-noteref"><sup>2</sup></a><a id="fnref3" href="#fn3" role="doc-noteref"><sup>3</sup></a><a href="#fnref1" role="doc-backlink">↩︎︎</a></p>
</li>
<li id="fn2">
<p>b<a href="#fnref2" role="doc-backlink">↩︎︎</a></p>
</li>
<li id="fn3">
<p><a href="#fnref3" role="doc-backlink">↩︎︎</a></p>
</li>
</ol>
</section>
```
Footnote references in unreferenced footnotes are ignored.
```
para
[^a]: a[^b][^c]
[^b]: b
.
<p>para</p>
```
Footnotes may appear within footnotes.
```
[^b]
[^a]
[^a]: [^b]: inner
.
<p><a id="fnref1" href="#fn1" role="doc-noteref"><sup>1</sup></a>
<a id="fnref2" href="#fn2" role="doc-noteref"><sup>2</sup></a></p>
<section role="doc-endnotes">
<hr>
<ol>
<li id="fn1">
<p>inner<a href="#fnref1" role="doc-backlink">↩︎︎</a></p>
</li>
<li id="fn2">
<p><a href="#fnref2" role="doc-backlink">↩︎︎</a></p>
</li>
</ol>
</section>
```