" head -c 8 "$lib"
fi
# Flatten the archive to printable text once, the formulation 74-libtinyxml2 and
# 76-libmxml use: GNU grep suppresses matches inside binary data, and busybox tr
# does not handle [:print:] under -c, so the octal range is what both agree on.
flat=${TMPDIR:-/tmp}/bst-cmark.$$
( tr -c '\40-\176\n' ' ' < "$lib" > "$flat" 2>/dev/null )
# Nineteen members, one per upstream translation unit. Named rather than counted,
# so a dropped or renamed member is identified by the failure.
for m in blocks buffer cmark cmark_ctype commonmark houdini_href_e \
houdini_html_e houdini_html_u html inlines iterator latex man node \
references render scanners utf8 xml; do
check "cmark/member-$m" grep -q "$m\.c\.o" "$flat"
done
# The whole public API: every one of the 69 cmark_* functions cmark.h declares.
# The header/archive cross-check is exact -- there is no declared-but-undefined
# name -- so a consumer that compiles against this header links against this
# archive, which is the deliverable.
for s in cmark_consolidate_text_nodes cmark_get_default_mem_allocator \
cmark_iter_free cmark_iter_get_event_type cmark_iter_get_node \
cmark_iter_get_root cmark_iter_new cmark_iter_next cmark_iter_reset \
cmark_markdown_to_html cmark_node_append_child cmark_node_first_child \
cmark_node_free cmark_node_get_end_column cmark_node_get_end_line \
cmark_node_get_fence_info cmark_node_get_heading_level \
cmark_node_get_list_delim cmark_node_get_list_start \
cmark_node_get_list_tight cmark_node_get_list_type \
cmark_node_get_literal cmark_node_get_on_enter cmark_node_get_on_exit \
cmark_node_get_start_column cmark_node_get_start_line \
cmark_node_get_title cmark_node_get_type cmark_node_get_type_string \
cmark_node_get_url cmark_node_get_user_data cmark_node_insert_after \
cmark_node_insert_before cmark_node_last_child cmark_node_new \
cmark_node_new_with_mem cmark_node_next cmark_node_parent \
cmark_node_prepend_child cmark_node_previous cmark_node_replace \
cmark_node_set_fence_info cmark_node_set_heading_level \
cmark_node_set_list_delim cmark_node_set_list_start \
cmark_node_set_list_tight cmark_node_set_list_type \
cmark_node_set_literal cmark_node_set_on_enter cmark_node_set_on_exit \
cmark_node_set_title cmark_node_set_url cmark_node_set_user_data \
cmark_node_unlink cmark_parse_document cmark_parse_file \
cmark_parser_feed cmark_parser_finish cmark_parser_free \
cmark_parser_new cmark_parser_new_with_mem \
cmark_parser_new_with_mem_into_root cmark_render_commonmark \
cmark_render_html cmark_render_latex cmark_render_man \
cmark_render_xml cmark_version cmark_version_string; do
check "cmark/sym-$s" grep -q "$s" "$flat"
done
# The six houdini_* escapers. They are the HTML/URL escaping layer, exported but
# undeclared in the public header -- present because html.c and xml.c call them
# across translation units, and asserted so a visibility change that dropped them
# shows up here rather than as a link error in a consumer.
for s in houdini_escape_href houdini_escape_html houdini_escape_html0 \
houdini_unescape_ent houdini_unescape_html houdini_unescape_html_f; do
check "cmark/houdini-$s" grep -q "$s" "$flat"
done
# The re2c-generated scanners. These are the lexer and the only generated C in the
# build: scanners.c is checked in upstream, so re2c is NOT a build dependency here
# -- which is why this recipe needed no native tool and no DEPENDS.
for s in _scan_atx_heading_start _scan_setext_heading_line _scan_open_code_fence \
_scan_close_code_fence _scan_entity _scan_autolink_uri \
_scan_autolink_email _scan_html_tag _scan_dangerous_url _scan_scheme; do
check "cmark/scanner-$s" grep -q "$s" "$flat"
done
# The allocator indirection every node goes through.
check cmark/mem-default-allocator grep -q 'DEFAULT_MEM_ALLOCATOR' "$flat"
# utf8proc is vendored inside cmark rather than linked, so these are the proof
# UTF-8 handling is self-contained -- no libunistring, no ICU.
for s in cmark_utf8proc_iterate cmark_utf8proc_encode_char cmark_utf8proc_check \
cmark_utf8proc_case_fold; do
check "cmark/utf8proc-$s" grep -q "$s" "$flat"
done
# The wasm32 arm witness: the archive members are not host ELF.
check cmark/arm-not-elf sh -c '! head -c 512 "$1" | grep -q "ELF"' _ "$lib"
# Size window. libcmark.a is ~1.6 MB here, dominated by the entity table in
# houdini_html_u.c and the re2c scanners.
# The window is a measurement of the ARCHIVE, so it is asserted only where the
# archive is what shipped; a shared object's size is a different number nobody
# has measured, and inventing a window for it would assert a guess.
if [ "${lib%.a}" != "$lib" ]; then
sz=$(wc -c < "$lib")
check cmark/lib-size-window sh -c '[ "$1" -gt 900000 ] && [ "$1" -lt 3000000 ]' _ "$sz"
else
bst_skip cmark/lib-size-window "window measured on libcmark.a; this image ships $lib"
fi
rm -f "$flat"
# ------------------------------------------------------- packaging policy -----
# The library's shape rather than its absence. Asserting no .so encoded the
# distro-wide static premise BRINTOS-1740 retires one recipe at a time, and it
# fails on the recipe that converted correctly -- BRINTOS-893's class, and the
# same reasoning as the .pc cases above. What survives conversion is that whatever
# shipped is usable.
bst_lib_shape cmark/no-so "$root/usr/lib/libcmark.so" "$root/usr/lib/libcmark.so.*"
check cmark/no-la sh -c '! ls "$1"/libcmark.la >/dev/null 2>&1' _ "$root/usr/lib"
# BUILD_TESTING=OFF: neither test binary is built, so neither can be installed.
check cmark/no-api-test sh -c '! test -e "$1/usr/bin/api_test"' _ "$root"
check cmark/no-spec-test sh -c '! test -e "$1/usr/bin/spec_tests"' _ "$root"
# cmark-doc is deliberately not in the image, like every other port's -doc.
check cmark/no-man1 sh -c '! test -e "$1/usr/share/man/man1/cmark.1"' _ "$root"
check cmark/no-man3 sh -c '! test -e "$1/usr/share/man/man3/cmark.3"' _ "$root"
# ------------------------------------------------------------- pkgconf --------
if command -v pkgconf >/dev/null 2>&1; then
pcdir=$root/usr/lib/pkgconfig
check_eq cmark/pkgconf-modversion "0.31.0" \
"$(PKG_CONFIG_LIBDIR=$pcdir pkgconf --modversion libcmark 2>&1)"
# Note 2. The filtered pair, then the restoring pair -- it is the SECOND of each
# that carries the information, because empty filtered output alone is equally
# consistent with a field that was never populated (which is what 76-libmxml
# actually has).
check_eq cmark/pkgconf-libs "-lcmark" \
"$(PKG_CONFIG_LIBDIR=$pcdir pkgconf --libs libcmark 2>&1)"
check_eq cmark/pkgconf-libs-keep "-L/usr/lib -lcmark" \
"$(PKG_CONFIG_LIBDIR=$pcdir pkgconf --keep-system-libs --libs libcmark 2>&1)"
check_eq cmark/pkgconf-cflags "" \
"$(PKG_CONFIG_LIBDIR=$pcdir pkgconf --cflags libcmark 2>&1)"
check_eq cmark/pkgconf-cflags-keep "-I/usr/include" \
"$(PKG_CONFIG_LIBDIR=$pcdir pkgconf --keep-system-cflags --cflags libcmark 2>&1)"
check_eq cmark/pkgconf-var-prefix "/usr" \
"$(PKG_CONFIG_LIBDIR=$pcdir pkgconf --variable=prefix libcmark 2>&1)"
check_eq cmark/pkgconf-var-libdir "/usr/lib" \
"$(PKG_CONFIG_LIBDIR=$pcdir pkgconf --variable=libdir libcmark 2>&1)"
check_eq cmark/pkgconf-var-includedir "/usr/include" \
"$(PKG_CONFIG_LIBDIR=$pcdir pkgconf --variable=includedir libcmark 2>&1)"
check cmark/pkgconf-exists env PKG_CONFIG_LIBDIR=$pcdir pkgconf --exists libcmark
check cmark/pkgconf-atleast env PKG_CONFIG_LIBDIR=$pcdir pkgconf --atleast-version=0.31.0 libcmark
check_rc cmark/pkgconf-max 1 env PKG_CONFIG_LIBDIR=$pcdir pkgconf --max-version=0.30.0 libcmark
# The module is libcmark, not cmark -- the .pc is named for the library, not the
# recipe, and a consumer that guesses the recipe name gets nothing.
check_rc cmark/pkgconf-not-cmark 1 env PKG_CONFIG_LIBDIR=$pcdir pkgconf --exists cmark
else
bst_skip cmark/pkgconf-present "pkgconf not on this image"
fi
# ------------------------------------------------------------- runtime --------
# Everything above this line is true of a payload that never ran. Below, the
# parser runs. Expectations are the output of a native build of this same source
# at this same SRCREV, so a difference here is a difference between this arm and
# an ordinary host -- which is exactly what the suite is for.
if command -v cmark >/dev/null 2>&1; then
# %b so multi-line documents can be written inline; cmark reads stdin with no
# arguments, which is the invocation every case below uses except file-arg.
cm() { _md=$1; shift; printf '%b' "$_md" | cmark "$@"; }
check_out cmark/run-version "cmark 0.31.0 - CommonMark converter" cmark --version
check_out cmark/run-version-c "(C) 2014-2016 John MacFarlane" cmark --version
check_out cmark/run-help "Usage: cmark [FILE*]" cmark --help
check_out cmark/run-help-formats "html, xml, man, commonmark, latex" cmark --help
# Leaf blocks.
check_out cmark/run-atx-heading "Hello
" cm '# Hello'
check_out cmark/run-h2 "Sub
" cm '## Sub'
check_out cmark/run-setext "Title
" cm 'Title\n====='
check_out cmark/run-thematic "
" cm '---'
check_out cmark/run-paragraph "plain
" cm 'plain'
check_out cmark/run-indented-code "code line" cm ' code line\n'
check_out cmark/run-fenced-lang 'int x;' cm '```c\nint x;\n```'
# Inlines.
check_out cmark/run-emphasis "em" cm '*em*'
check_out cmark/run-strong "strong" cm '**strong**'
check_out cmark/run-nested-em "both" cm '***both***'
check_out cmark/run-codespan "code" cm 'a `code` b'
check_out cmark/run-link 'text' cm '[text](http://example.com)'
check_out cmark/run-image '
' cm ''
check_out cmark/run-autolink 'http://example.com' \
cm ''
# A backslash escape suppresses the emphasis and leaves the literal asterisks.
check_out cmark/run-backslash "*not em*
" cm '\\*not em\\*'
# Containers.
check_out cmark/run-blockquote "" cm '> quoted'
check_out cmark/run-ul "one" cm '- one\n- two'
check_out cmark/run-ol "first" cm '1. first\n2. second'
# A list that does not start at 1 carries the start attribute.
check_out cmark/run-ol-start '' cm '5. five\n6. six\n'
# A blank line between items makes the list loose, which wraps each item in .
check_out cmark/run-loose-list "$(printf '
- \n
a
')" cm '- a\n\n- b\n'
# Entities and escaping. & stays an entity; © is decoded to the
# character. Both directions matter -- the first is escaping, the second is the
# 2125-entry entity table in houdini_html_u.c doing its job.
check_out cmark/run-entity-amp "AT&T" cm 'AT&T'
check_out cmark/run-entity-copy "©" cm '©'
# Note 1: raw HTML is filtered unless --unsafe.
check_out cmark/run-html-filtered "" cm 'raw
'
check_out cmark/run-html-unsafe "raw
" cm 'raw
' --unsafe
# Line-break handling, all three modes. A soft break survives as a real newline
# inside the paragraph, so that needle has to be a real newline too.
check_out cmark/run-softbreak "$(printf 'a\nb
')" cm 'a\nb'
check_out cmark/run-hardbreak "a
" cm 'a \nb'
check_out cmark/run-hardbreaks "a
" cm 'a\nb' --hardbreaks
check_out cmark/run-nobreaks "a b
" cm 'a\nb' --nobreaks
# --smart: straight quotes to curly, -- to en dash, ... to ellipsis.
check_out cmark/run-smart-quote "“quoted”" cm '"quoted"' --smart
check_out cmark/run-smart-dash "–" cm 'a -- b' --smart
check_out cmark/run-smart-ellips "…" cm 'x...' --smart
# UTF-8 passes through byte-identically; cmark is byte-oriented and vendors its
# own utf8proc, so this exercises that vendored code rather than the locale.
check_out cmark/run-utf8-latin1 "héllo" cm 'héllo'
check_out cmark/run-utf8-emdash "—" cm '—'
# --sourcepos annotates with 1-based line:col spans.
check_out cmark/run-sourcepos 'data-sourcepos="1:1-1:4"' cm '# Hi' --sourcepos
# The other four renderers. Each is a separate translation unit in the archive,
# so these four cases are also the runtime counterpart of the member checks.
check_out cmark/run-t-html "Hi
" cm '# Hi' -t html
check_out cmark/run-t-xml-doctype '' cm '# Hi' -t xml
check_out cmark/run-t-xml-heading '' cm '# Hi' -t xml
check_out cmark/run-t-latex '\section{Hi}' cm '# Hi' -t latex
check_out cmark/run-t-man ".SH" cm '# Hi' -t man
# commonmark out normalises the input rather than echoing it: three spaces after
# the # collapse to one.
check_out cmark/run-t-commonmark "# Hi" cm '# Hi' -t commonmark
# Note 4: pipe tables are GFM, not CommonMark, so they stay a paragraph.
check_out cmark/run-no-tables "| a | b |" cm '| a | b |\n| --- | --- |\n| 1 | 2 |'
# File input, the one path that is not stdin -- and the one that touches the
# target VFS rather than a pipe.
doc=${TMPDIR:-/tmp}/bst-cmark-doc.$$
printf '# From a file\n\nBody *text*.\n' > "$doc"
check_out cmark/run-file-heading "
From a file
" cmark "$doc"
check_out cmark/run-file-body "Body text." cmark "$doc"
rm -f "$doc"
# Error paths: a missing file and an unknown option both exit 1, and the missing
# file reports errno rather than failing silently.
check_rc cmark/run-missing-file-rc 1 cmark "${TMPDIR:-/tmp}/bst-cmark-absent.$$"
# The trailing `; true` is load-bearing: check_out requires rc 0, and this
# command deliberately exits 1. The exit status is already asserted above, so
# here only the diagnostic text is under test.
check_out cmark/run-missing-file-msg "Error opening file" \
sh -c 'cmark "$1" 2>&1 >/dev/null; true' _ "${TMPDIR:-/tmp}/bst-cmark-absent.$$"
check_out cmark/run-missing-file-errno "No such file or directory" \
sh -c 'cmark "$1" 2>&1 >/dev/null; true' _ "${TMPDIR:-/tmp}/bst-cmark-absent.$$"
check_rc cmark/run-bad-option 1 sh -c 'printf x | cmark --nosuchopt'
# Empty input is empty output and still a success -- the degenerate document.
check_eq cmark/run-empty "" "$(printf '' | cmark 2>&1)"
check_rc cmark/run-empty-rc 0 sh -c 'printf "" | cmark'
else
bst_skip cmark/run-present "cmark not on this image"
fi