981 lines
28 KiB
Nix
981 lines
28 KiB
Nix
{
|
|
lib,
|
|
stdenv,
|
|
buildEnv,
|
|
runCommand,
|
|
fetchurl,
|
|
file,
|
|
texlive,
|
|
writeShellScript,
|
|
writeText,
|
|
texliveInfraOnly,
|
|
texliveConTeXt,
|
|
texliveSmall,
|
|
texliveMedium,
|
|
texliveFull,
|
|
}:
|
|
|
|
rec {
|
|
|
|
mkTeXTest = lib.makeOverridable (
|
|
{
|
|
name,
|
|
format,
|
|
text,
|
|
texLive ? texliveSmall,
|
|
options ? "-interaction=errorstopmode",
|
|
preTest ? "",
|
|
postTest ? "",
|
|
...
|
|
}@attrs:
|
|
runCommand "texlive-test-tex-${name}"
|
|
(
|
|
{
|
|
nativeBuildInputs = [ texLive ] ++ attrs.nativeBuildInputs or [ ];
|
|
text = builtins.toFile "${name}.tex" text;
|
|
}
|
|
// builtins.removeAttrs attrs [
|
|
"nativeBuildInputs"
|
|
"text"
|
|
"texLive"
|
|
]
|
|
)
|
|
''
|
|
export HOME="$(mktemp -d)"
|
|
mkdir "$out"
|
|
cd "$out"
|
|
cp "$text" "$name.tex"
|
|
${preTest}
|
|
$format $options "$name.tex"
|
|
${postTest}
|
|
''
|
|
);
|
|
|
|
tlpdbNix =
|
|
runCommand "texlive-test-tlpdb-nix"
|
|
{
|
|
nixpkgsTlpdbNix = ../../tools/typesetting/tex/texlive/tlpdb.nix;
|
|
tlpdbNix = texlive.tlpdb.nix;
|
|
}
|
|
''
|
|
mkdir -p "$out"
|
|
diff -u "''${nixpkgsTlpdbNix}" "''${tlpdbNix}" | tee "$out/tlpdb.nix.patch"
|
|
'';
|
|
|
|
# test two completely different font discovery mechanisms, both of which were once broken:
|
|
# - lualatex uses its own luaotfload script (#220228)
|
|
# - xelatex uses fontconfig (#228196)
|
|
opentype-fonts = lib.recurseIntoAttrs rec {
|
|
lualatex = mkTeXTest {
|
|
name = "opentype-fonts-lualatex";
|
|
format = "lualatex";
|
|
texLive = texliveSmall.withPackages (ps: [ ps.libertinus-fonts ]);
|
|
text = ''
|
|
\documentclass{article}
|
|
\usepackage{fontspec}
|
|
\setmainfont{Libertinus Serif}
|
|
\begin{document}
|
|
\LaTeX{} is great
|
|
\end{document}
|
|
'';
|
|
};
|
|
xelatex = lualatex.override {
|
|
name = "opentype-fonts-xelatex";
|
|
format = "xelatex";
|
|
};
|
|
};
|
|
|
|
chktex =
|
|
runCommand "texlive-test-chktex"
|
|
{
|
|
nativeBuildInputs = [
|
|
(texlive.withPackages (ps: [ ps.chktex ]))
|
|
];
|
|
input = builtins.toFile "chktex-sample.tex" ''
|
|
\documentclass{article}
|
|
\begin{document}
|
|
\LaTeX is great
|
|
\end{document}
|
|
'';
|
|
}
|
|
''
|
|
# chktex is supposed to return 2 when it (successfully) finds warnings, but no errors,
|
|
# see http://git.savannah.nongnu.org/cgit/chktex.git/commit/?id=ec0fb9b58f02a62ff0bfec98b997208e9d7a5998
|
|
(set +e; chktex -v -nall -w1 "$input" 2>&1; [ $? = 2 ] || exit 1; set -e) | tee "$out"
|
|
# also check that the output does indeed contain "One warning printed"
|
|
grep "One warning printed" "$out"
|
|
'';
|
|
|
|
context = mkTeXTest {
|
|
name = "texlive-test-context";
|
|
format = "context";
|
|
texLive = texliveConTeXt;
|
|
# check that the PDF has been created: we have hit cases of context
|
|
# failing with exit status 0 due to a misconfigured texlive
|
|
postTest = ''
|
|
if [[ ! -f "$name".pdf ]] ; then
|
|
echo "ConTeXt test failed: file '$name.pdf' not found"
|
|
exit 1
|
|
fi
|
|
'';
|
|
text = ''
|
|
\starttext
|
|
\startsection[title={ConTeXt test document}]
|
|
This is an {\em incredibly} simple ConTeXt document.
|
|
\stopsection
|
|
\stoptext
|
|
'';
|
|
};
|
|
|
|
dvipng = lib.recurseIntoAttrs {
|
|
# https://github.com/NixOS/nixpkgs/issues/75605
|
|
basic =
|
|
runCommand "texlive-test-dvipng-basic"
|
|
{
|
|
nativeBuildInputs = [
|
|
file
|
|
texliveMedium
|
|
];
|
|
input = fetchurl {
|
|
name = "test_dvipng.tex";
|
|
url = "http://git.savannah.nongnu.org/cgit/dvipng.git/plain/test_dvipng.tex?id=b872753590a18605260078f56cbd6f28d39dc035";
|
|
sha256 = "1pjpf1jvwj2pv5crzdgcrzvbmn7kfmgxa39pcvskl4pa0c9hl88n";
|
|
};
|
|
}
|
|
''
|
|
cp "$input" ./document.tex
|
|
|
|
latex document.tex
|
|
dvipng -T tight -strict -picky document.dvi
|
|
for f in document*.png; do
|
|
file "$f" | tee output
|
|
grep PNG output
|
|
done
|
|
|
|
mkdir "$out"
|
|
mv document*.png "$out"/
|
|
'';
|
|
|
|
# test dvipng's limited capability to render postscript specials via GS
|
|
ghostscript =
|
|
runCommand "texlive-test-ghostscript"
|
|
{
|
|
nativeBuildInputs = [
|
|
file
|
|
(texliveSmall.withPackages (ps: [ ps.dvipng ]))
|
|
];
|
|
input = builtins.toFile "postscript-sample.tex" ''
|
|
\documentclass{minimal}
|
|
\begin{document}
|
|
Ni
|
|
\special{ps:
|
|
newpath
|
|
0 0 moveto
|
|
7 7 rlineto
|
|
0 7 moveto
|
|
7 -7 rlineto
|
|
stroke
|
|
showpage
|
|
}
|
|
\end{document}
|
|
'';
|
|
gs_trap = writeShellScript "gs_trap.sh" ''
|
|
exit 1
|
|
'';
|
|
}
|
|
''
|
|
cp "$gs_trap" ./gs
|
|
export PATH=$PWD:$PATH
|
|
# check that the trap works
|
|
gs && exit 1
|
|
|
|
cp "$input" ./document.tex
|
|
|
|
latex document.tex
|
|
dvipng -T 1in,1in -strict -picky document.dvi
|
|
for f in document*.png; do
|
|
file "$f" | tee output
|
|
grep PNG output
|
|
done
|
|
|
|
mkdir "$out"
|
|
mv document*.png "$out"/
|
|
'';
|
|
};
|
|
|
|
# https://github.com/NixOS/nixpkgs/issues/75070
|
|
dvisvgm =
|
|
runCommand "texlive-test-dvisvgm"
|
|
{
|
|
nativeBuildInputs = [
|
|
file
|
|
texliveMedium
|
|
];
|
|
input = builtins.toFile "dvisvgm-sample.tex" ''
|
|
\documentclass{article}
|
|
\begin{document}
|
|
mwe
|
|
\end{document}
|
|
'';
|
|
}
|
|
''
|
|
cp "$input" ./document.tex
|
|
|
|
latex document.tex
|
|
dvisvgm document.dvi -n -o document_dvi.svg
|
|
cat document_dvi.svg
|
|
file document_dvi.svg | grep SVG
|
|
|
|
pdflatex document.tex
|
|
dvisvgm -P document.pdf -n -o document_pdf.svg
|
|
cat document_pdf.svg
|
|
file document_pdf.svg | grep SVG
|
|
|
|
mkdir "$out"
|
|
mv document*.svg "$out"/
|
|
'';
|
|
|
|
texdoc =
|
|
runCommand "texlive-test-texdoc"
|
|
{
|
|
nativeBuildInputs = [
|
|
(texlive.withPackages (ps: [
|
|
ps.luatex
|
|
ps.texdoc
|
|
ps.texdoc.texdoc
|
|
]))
|
|
];
|
|
}
|
|
''
|
|
texdoc --version
|
|
|
|
texdoc --debug --list texdoc | tee "$out"
|
|
grep texdoc.pdf "$out"
|
|
'';
|
|
|
|
# check that the default language is US English
|
|
defaultLanguage = lib.recurseIntoAttrs rec {
|
|
# language.def
|
|
etex = mkTeXTest {
|
|
name = "default-language-etex";
|
|
format = "etex";
|
|
text = ''
|
|
\catcode`\@=11
|
|
\ifnum\language=\lang@USenglish \message{[tests.texlive] Default language is US English.}
|
|
\else\errmessage{[tests.texlive] Error: default language is NOT US English.}\fi
|
|
\ifnum\language=0\message{[tests.texlive] Default language has id 0.}
|
|
\else\errmessage{[tests.texlive] Error: default language does NOT have id 0.}\fi
|
|
\bye
|
|
'';
|
|
};
|
|
# language.dat
|
|
latex = mkTeXTest {
|
|
name = "default-language-latex";
|
|
format = "latex";
|
|
text = ''
|
|
\makeatletter
|
|
\ifnum\language=\l@USenglish \GenericWarning{}{[tests.texlive] Default language is US English}
|
|
\else\GenericError{}{[tests.texlive] Error: default language is NOT US English}{}{}\fi
|
|
\ifnum\language=0\GenericWarning{}{[tests.texlive] Default language has id 0}
|
|
\else\GenericError{}{[tests.texlive] Error: default language does NOT have id 0}{}{}\fi
|
|
\stop
|
|
'';
|
|
};
|
|
# language.dat.lua
|
|
luatex = etex.override {
|
|
name = "default-language-luatex";
|
|
format = "luatex";
|
|
};
|
|
};
|
|
|
|
# check that all languages are available, including synonyms
|
|
allLanguages =
|
|
let
|
|
hyphenBase = texlive.pkgs.hyphen-base;
|
|
texLive = texliveFull;
|
|
in
|
|
lib.recurseIntoAttrs {
|
|
# language.def
|
|
etex = mkTeXTest {
|
|
name = "all-languages-etex";
|
|
format = "etex";
|
|
inherit hyphenBase texLive;
|
|
text = ''
|
|
\catcode`\@=11
|
|
\input kvsetkeys.sty
|
|
\def\CheckLang#1{
|
|
\ifcsname lang@#1\endcsname\message{[tests.texlive] Found language #1}
|
|
\else\errmessage{[tests.texlive] Error: missing language #1}\fi
|
|
}
|
|
\comma@parse{@texLanguages@}\CheckLang
|
|
\bye
|
|
'';
|
|
preTest = ''
|
|
texLanguages="$(sed -n -E 's/^\\addlanguage\s*\{([^}]+)\}.*$/\1/p' < "$hyphenBase"/tex/generic/config/language.def)"
|
|
texLanguages="''${texLanguages//$'\n'/,}"
|
|
substituteInPlace "$name.tex" --subst-var texLanguages
|
|
'';
|
|
};
|
|
# language.dat
|
|
latex = mkTeXTest {
|
|
name = "all-languages-latex";
|
|
format = "latex";
|
|
inherit hyphenBase texLive;
|
|
text = ''
|
|
\makeatletter
|
|
\@for\Lang:=italian,@texLanguages@\do{
|
|
\ifcsname l@\Lang\endcsname
|
|
\GenericWarning{}{[tests.texlive] Found language \Lang}
|
|
\else
|
|
\GenericError{}{[tests.texlive] Error: missing language \Lang}{}{}
|
|
\fi
|
|
}
|
|
\stop
|
|
'';
|
|
preTest = ''
|
|
texLanguages="$(sed -n -E 's/^([^%= \t]+).*$/\1/p' < "$hyphenBase"/tex/generic/config/language.dat)"
|
|
texLanguages="''${texLanguages//$'\n'/,}"
|
|
substituteInPlace "$name.tex" --subst-var texLanguages
|
|
'';
|
|
};
|
|
# language.dat.lua
|
|
luatex = mkTeXTest {
|
|
name = "all-languages-luatex";
|
|
format = "luatex";
|
|
inherit hyphenBase texLive;
|
|
text = ''
|
|
\directlua{
|
|
require('luatex-hyphen.lua')
|
|
langs = '@texLanguages@,'
|
|
texio.write('\string\n')
|
|
for l in langs:gmatch('([^,]+),') do
|
|
if luatexhyphen.lookupname(l) \string~= nil then
|
|
texio.write('[tests.texlive] Found language '..l..'.\string\n')
|
|
else
|
|
error('[tests.texlive] Error: missing language '..l..'.', 2)
|
|
end
|
|
end
|
|
}
|
|
\bye
|
|
'';
|
|
preTest = ''
|
|
texLanguages="$(sed -n -E 's/^.*\[("|'\''')(.*)("|'\''')].*$/\2/p' < "$hyphenBase"/tex/generic/config/language.dat.lua)"
|
|
texLanguages="''${texLanguages//$'\n'/,}"
|
|
substituteInPlace "$name.tex" --subst-var texLanguages
|
|
'';
|
|
};
|
|
};
|
|
|
|
# test that language files are generated as expected
|
|
hyphen-base =
|
|
runCommand "texlive-test-hyphen-base"
|
|
{
|
|
hyphenBase = texlive.pkgs.hyphen-base;
|
|
schemeFull = texliveFull;
|
|
schemeInfraOnly = texliveInfraOnly;
|
|
}
|
|
''
|
|
mkdir -p "$out"/{scheme-infraonly,scheme-full}
|
|
|
|
# create language files with no hyphenation patterns
|
|
cat "$hyphenBase"/tex/generic/config/language.us >language.dat
|
|
cat "$hyphenBase"/tex/generic/config/language.us.def >language.def
|
|
cat "$hyphenBase"/tex/generic/config/language.us.lua >language.dat.lua
|
|
|
|
cat >>language.dat.lua <<EOF
|
|
}
|
|
EOF
|
|
|
|
cat >>language.def <<EOF
|
|
%%% No changes may be made beyond this point.
|
|
|
|
\uselanguage {USenglish} %%% This MUST be the last line of the file.
|
|
EOF
|
|
|
|
for fname in language.{dat,def,dat.lua} ; do
|
|
diff --ignore-matching-lines='^\(%\|--\) Generated by ' -u \
|
|
{"$hyphenBase","$schemeFull"/share/texmf-var}/tex/generic/config/"$fname" \
|
|
| tee "$out/scheme-full/$fname.patch"
|
|
diff --ignore-matching-lines='^\(%\|--\) Generated by ' -u \
|
|
{,"$schemeInfraOnly"/share/texmf-var/tex/generic/config/}"$fname" \
|
|
| tee "$out/scheme-infraonly/$fname.patch"
|
|
done
|
|
'';
|
|
|
|
# verify that the restricted mode gets enabled when
|
|
# needed (detected by checking if it disallows --gscmd)
|
|
repstopdf =
|
|
runCommand "texlive-test-repstopdf"
|
|
{
|
|
nativeBuildInputs = [ (texlive.withPackages (ps: [ ps.epstopdf ])) ];
|
|
}
|
|
''
|
|
! (epstopdf --gscmd echo /dev/null 2>&1 || true) | grep forbidden >/dev/null
|
|
(repstopdf --gscmd echo /dev/null 2>&1 || true) | grep forbidden >/dev/null
|
|
mkdir "$out"
|
|
'';
|
|
|
|
# verify that the restricted mode gets enabled when
|
|
# needed (detected by checking if it disallows --gscmd)
|
|
rpdfcrop =
|
|
runCommand "texlive-test-rpdfcrop"
|
|
{
|
|
nativeBuildInputs = [ (texlive.withPackages (ps: [ ps.pdfcrop ])) ];
|
|
}
|
|
''
|
|
! (pdfcrop --gscmd echo $(command -v pdfcrop) 2>&1 || true) | grep 'restricted mode' >/dev/null
|
|
(rpdfcrop --gscmd echo $(command -v pdfcrop) 2>&1 || true) | grep 'restricted mode' >/dev/null
|
|
mkdir "$out"
|
|
'';
|
|
|
|
# check that all binaries run successfully, in the following sense:
|
|
# (1) run --version, -v, --help, -h successfully; or
|
|
# (2) run --help, -h, or no argument with error code but show help text; or
|
|
# (3) run successfully on a test.tex or similar file
|
|
# we ignore the binaries that cannot be tested as above, and are either
|
|
# compiled binaries or trivial shell wrappers
|
|
binaries =
|
|
let
|
|
# TODO known broken binaries
|
|
broken = [
|
|
# *.inc files in source container rather than run
|
|
"texaccents"
|
|
|
|
# 'Error initialising QuantumRenderer: no suitable pipeline found'
|
|
"tlcockpit"
|
|
] ++ lib.optional stdenv.hostPlatform.isDarwin "epspdftk"; # wish shebang is a script, not a binary!
|
|
|
|
# (1) binaries requiring -v
|
|
shortVersion = [
|
|
"devnag"
|
|
"diadia"
|
|
"pmxchords"
|
|
"ptex2pdf"
|
|
"simpdftex"
|
|
"ttf2afm"
|
|
];
|
|
# (1) binaries requiring --help or -h
|
|
help = [
|
|
"arlatex"
|
|
"bundledoc"
|
|
"cachepic"
|
|
"checklistings"
|
|
"dvipos"
|
|
"extractres"
|
|
"fig4latex"
|
|
"fragmaster"
|
|
"kpsewhere"
|
|
"latex-git-log"
|
|
"ltxfileinfo"
|
|
"mendex"
|
|
"pdflatexpicscale"
|
|
"perltex"
|
|
"pn2pdf"
|
|
"psbook"
|
|
"psnup"
|
|
"psresize"
|
|
"purifyeps"
|
|
"simpdftex"
|
|
"tex2xindy"
|
|
"texluac"
|
|
"texluajitc"
|
|
"upmendex"
|
|
"urlbst"
|
|
"yplan"
|
|
];
|
|
shortHelp = [
|
|
"adhocfilelist"
|
|
"authorindex"
|
|
"bbl2bib"
|
|
"bibdoiadd"
|
|
"bibmradd"
|
|
"biburl2doi"
|
|
"bibzbladd"
|
|
"bookshelf-listallfonts"
|
|
"bookshelf-mkfontsel"
|
|
"ctanupload"
|
|
"disdvi"
|
|
"dvibook"
|
|
"dviconcat"
|
|
"getmapdl"
|
|
"latex2man"
|
|
"listings-ext.sh"
|
|
"pygmentex"
|
|
];
|
|
# (2) binaries that return non-zero exit code even if correctly asked for help
|
|
ignoreExitCode = [
|
|
"authorindex"
|
|
"bookshelf-listallfonts"
|
|
"bookshelf-mkfontsel"
|
|
"dvibook"
|
|
"dviconcat"
|
|
"dvipos"
|
|
"extractres"
|
|
"fig4latex"
|
|
"fragmaster"
|
|
"latex2man"
|
|
"latex-git-log"
|
|
"listings-ext.sh"
|
|
"psbook"
|
|
"psnup"
|
|
"psresize"
|
|
"purifyeps"
|
|
"tex2xindy"
|
|
"texluac"
|
|
"texluajitc"
|
|
];
|
|
# (2) binaries that print help on no argument, returning non-zero exit code
|
|
noArg = [
|
|
"a2ping"
|
|
"bg5+latex"
|
|
"bg5+pdflatex"
|
|
"bg5latex"
|
|
"bg5pdflatex"
|
|
"cef5latex"
|
|
"cef5pdflatex"
|
|
"ceflatex"
|
|
"cefpdflatex"
|
|
"cefslatex"
|
|
"cefspdflatex"
|
|
"chkdvifont"
|
|
"dvi2fax"
|
|
"dvired"
|
|
"dviselect"
|
|
"dvitodvi"
|
|
"epsffit"
|
|
"findhyph"
|
|
"gbklatex"
|
|
"gbkpdflatex"
|
|
"komkindex"
|
|
"kpsepath"
|
|
"listbib"
|
|
"listings-ext"
|
|
"mag"
|
|
"mathspic"
|
|
"mf2pt1"
|
|
"mk4ht"
|
|
"mkt1font"
|
|
"mkgrkindex"
|
|
"musixflx"
|
|
"pdf2ps"
|
|
"pdfclose"
|
|
"pdftosrc"
|
|
"pdfxup"
|
|
"pedigree"
|
|
"pfb2pfa"
|
|
"pk2bm"
|
|
"prepmx"
|
|
"ps2pk"
|
|
"psselect"
|
|
"pstops"
|
|
"rubibtex"
|
|
"rubikrotation"
|
|
"sjislatex"
|
|
"sjispdflatex"
|
|
"srcredact"
|
|
"t4ht"
|
|
"teckit_compile"
|
|
"tex4ht"
|
|
"texdiff"
|
|
"texdirflatten"
|
|
"texplate"
|
|
"tie"
|
|
"ttf2kotexfont"
|
|
"ttfdump"
|
|
"vlna"
|
|
"vpl2ovp"
|
|
"vpl2vpl"
|
|
"yplan"
|
|
];
|
|
# (3) binaries requiring a .tex file
|
|
contextTest = [ "htcontext" ];
|
|
latexTest = [
|
|
"de-macro"
|
|
"e2pall"
|
|
"htlatex"
|
|
"htxelatex"
|
|
"makeindex"
|
|
"pslatex"
|
|
"rumakeindex"
|
|
"tpic2pdftex"
|
|
"wordcount"
|
|
"xhlatex"
|
|
];
|
|
texTest = [
|
|
"fontinst"
|
|
"htmex"
|
|
"httex"
|
|
"httexi"
|
|
"htxetex"
|
|
];
|
|
# tricky binaries or scripts that are obviously working but are hard to test
|
|
# (e.g. because they expect user input no matter the arguments)
|
|
# (printafm comes from ghostscript, not texlive)
|
|
ignored = [
|
|
# compiled binaries
|
|
"dt2dv"
|
|
"dv2dt"
|
|
"dvi2tty"
|
|
"dvidvi"
|
|
"dvispc"
|
|
"otp2ocp"
|
|
"outocp"
|
|
"pmxab"
|
|
|
|
# GUI scripts that accept no argument or crash without a graphics server; please test manualy
|
|
"epspdftk"
|
|
"texdoctk"
|
|
"tlshell"
|
|
"xasy"
|
|
|
|
# requires Cinderella, not open source and not distributed via Nixpkgs
|
|
"ketcindy"
|
|
];
|
|
# binaries that need a combined scheme and cannot work standalone
|
|
needScheme = [
|
|
# pfarrei: require working kpse to find lua module
|
|
"a5toa4"
|
|
|
|
# bibexport: requires kpsewhich
|
|
"bibexport"
|
|
|
|
# crossrefware: require bibtexperllibs under TEXMFROOT
|
|
"bbl2bib"
|
|
"bibdoiadd"
|
|
"bibmradd"
|
|
"biburl2doi"
|
|
"bibzbladd"
|
|
"checkcites"
|
|
"ltx2crossrefxml"
|
|
|
|
# epstopdf: requires kpsewhich
|
|
"epstopdf"
|
|
"repstopdf"
|
|
|
|
# requires kpsewhich
|
|
"memoize-extract.pl"
|
|
"memoize-extract.py"
|
|
|
|
# require other texlive binaries in PATH
|
|
"allcm"
|
|
"allec"
|
|
"chkweb"
|
|
"fontinst"
|
|
"ht*"
|
|
"installfont-tl"
|
|
"kanji-config-updmap-sys"
|
|
"kanji-config-updmap-user"
|
|
"kpse*"
|
|
"latexfileversion"
|
|
"mkocp"
|
|
"mkofm"
|
|
"mtxrunjit"
|
|
"pdftex-quiet"
|
|
"pslatex"
|
|
"rumakeindex"
|
|
"texconfig"
|
|
"texconfig-sys"
|
|
"texexec"
|
|
"texlinks"
|
|
"texmfstart"
|
|
"typeoutfileinfo"
|
|
"wordcount"
|
|
"xdvi"
|
|
"xhlatex"
|
|
|
|
# misc luatex binaries searching for luatex in PATH
|
|
"citeproc-lua"
|
|
"context"
|
|
"contextjit"
|
|
"ctanbib"
|
|
"digestif"
|
|
"epspdf"
|
|
"l3build"
|
|
"luafindfont"
|
|
"luaotfload-tool"
|
|
"luatools"
|
|
"make4ht"
|
|
"pmxchords"
|
|
"tex4ebook"
|
|
"texblend"
|
|
"texdoc"
|
|
"texfindpkg"
|
|
"texlogsieve"
|
|
"xindex"
|
|
|
|
# requires full TEXMFROOT (e.g. for config)
|
|
"mktexfmt"
|
|
"mktexmf"
|
|
"mktexpk"
|
|
"mktextfm"
|
|
"psnup"
|
|
"psresize"
|
|
"pstops"
|
|
"tlmgr"
|
|
"updmap"
|
|
"webquiz"
|
|
|
|
# texlive-scripts: requires texlive.infra's TeXLive::TLUtils under TEXMFROOT
|
|
"fmtutil"
|
|
"fmtutil-sys"
|
|
"fmtutil-user"
|
|
|
|
# texlive-scripts: not used in nixpkgs, need updmap in PATH
|
|
"updmap-sys"
|
|
"updmap-user"
|
|
];
|
|
|
|
# simple test files
|
|
contextTestTex = writeText "context-test.tex" ''
|
|
\starttext
|
|
A simple test file.
|
|
\stoptext
|
|
'';
|
|
latexTestTex = writeText "latex-test.tex" ''
|
|
\documentclass{article}
|
|
\begin{document}
|
|
A simple test file.
|
|
\end{document}
|
|
'';
|
|
texTestTex = writeText "tex-test.tex" ''
|
|
Hello.
|
|
\bye
|
|
'';
|
|
|
|
# link all binaries in single derivation
|
|
binPackages = lib.catAttrs "out" (lib.attrValues texlive.pkgs);
|
|
binaries = buildEnv {
|
|
name = "texlive-binaries";
|
|
paths = binPackages;
|
|
};
|
|
in
|
|
runCommand "texlive-test-binaries"
|
|
{
|
|
inherit
|
|
binaries
|
|
contextTestTex
|
|
latexTestTex
|
|
texTestTex
|
|
;
|
|
texliveScheme = texliveFull;
|
|
}
|
|
''
|
|
loadables="$(command -v bash)"
|
|
loadables="''${loadables%/bin/bash}/lib/bash"
|
|
enable -f "$loadables/realpath" realpath
|
|
mkdir -p "$out"
|
|
export HOME="$(mktemp -d)"
|
|
declare -i binCount=0 ignoredCount=0 brokenCount=0 failedCount=0
|
|
cp "$contextTestTex" context-test.tex
|
|
cp "$latexTestTex" latex-test.tex
|
|
cp "$texTestTex" tex-test.tex
|
|
|
|
testBin () {
|
|
path="$(realpath "$bin")"
|
|
path="''${path##*/}"
|
|
if [[ -z "$ignoreExitCode" ]] ; then
|
|
PATH="$path" "$bin" $args >"$out/$base.log" 2>&1
|
|
ret=$?
|
|
if [[ $ret == 0 ]] && grep -i 'command not found' "$out/$base.log" >/dev/null ; then
|
|
echo "command not found when running '$base''${args:+ $args}'"
|
|
return 1
|
|
fi
|
|
return $ret
|
|
else
|
|
PATH="$path" "$bin" $args >"$out/$base.log" 2>&1
|
|
ret=$?
|
|
if [[ $ret == 0 ]] && grep -i 'command not found' "$out/$base.log" >/dev/null ; then
|
|
echo "command not found when running '$base''${args:+ $args}'"
|
|
return 1
|
|
fi
|
|
if ! grep -Ei '(Example:|Options:|Syntax:|Usage:|improper command|SYNOPSIS)' "$out/$base.log" >/dev/null ; then
|
|
echo "did not find usage info when running '$base''${args:+ $args}'"
|
|
return $ret
|
|
fi
|
|
fi
|
|
}
|
|
|
|
for bin in "$binaries"/bin/* ; do
|
|
base="''${bin##*/}"
|
|
args=
|
|
ignoreExitCode=
|
|
binCount=$((binCount + 1))
|
|
|
|
# ignore non-executable files (such as context.lua)
|
|
if [[ ! -x "$bin" ]] ; then
|
|
ignoredCount=$((ignoredCount + 1))
|
|
continue
|
|
fi
|
|
|
|
case "$base" in
|
|
${lib.concatStringsSep "|" ignored})
|
|
ignoredCount=$((ignoredCount + 1))
|
|
continue ;;
|
|
${lib.concatStringsSep "|" broken})
|
|
brokenCount=$((brokenCount + 1))
|
|
continue ;;
|
|
${lib.concatStringsSep "|" help})
|
|
args=--help ;;
|
|
${lib.concatStringsSep "|" shortHelp})
|
|
args=-h ;;
|
|
${lib.concatStringsSep "|" noArg})
|
|
;;
|
|
${lib.concatStringsSep "|" contextTest})
|
|
args=context-test.tex ;;
|
|
${lib.concatStringsSep "|" latexTest})
|
|
args=latex-test.tex ;;
|
|
${lib.concatStringsSep "|" texTest})
|
|
args=tex-test.tex ;;
|
|
${lib.concatStringsSep "|" shortVersion})
|
|
args=-v ;;
|
|
ebong)
|
|
touch empty
|
|
args=empty ;;
|
|
ht)
|
|
args='latex latex-test.tex' ;;
|
|
pdf2dsc)
|
|
args='--help --help --help' ;;
|
|
typeoutfileinfo)
|
|
args=/dev/null ;;
|
|
*)
|
|
args=--version ;;
|
|
esac
|
|
|
|
case "$base" in
|
|
${lib.concatStringsSep "|" (ignoreExitCode ++ noArg)})
|
|
ignoreExitCode=1 ;;
|
|
esac
|
|
|
|
case "$base" in
|
|
${lib.concatStringsSep "|" needScheme})
|
|
bin="$texliveScheme/bin/$base"
|
|
if [[ ! -f "$bin" ]] ; then
|
|
ignoredCount=$((ignoredCount + 1))
|
|
continue
|
|
fi ;;
|
|
esac
|
|
|
|
if testBin ; then : ; else # preserve exit code
|
|
echo "failed '$base''${args:+ $args}' (exit code: $?)"
|
|
sed 's/^/ > /' < "$out/$base.log"
|
|
failedCount=$((failedCount + 1))
|
|
fi
|
|
done
|
|
|
|
echo "tested $binCount binaries: $ignoredCount ignored, $brokenCount broken, $failedCount failed"
|
|
[[ $failedCount = 0 ]]
|
|
'';
|
|
|
|
# check that all scripts have a Nix shebang
|
|
shebangs =
|
|
let
|
|
binPackages = lib.catAttrs "out" (lib.attrValues texlive.pkgs);
|
|
in
|
|
runCommand "texlive-test-shebangs" { } (
|
|
''
|
|
echo "checking that all texlive scripts shebangs are in '$NIX_STORE'"
|
|
declare -i scriptCount=0 invalidCount=0
|
|
''
|
|
+ (lib.concatMapStrings (pkg: ''
|
|
for bin in '${pkg.outPath}'/bin/* ; do
|
|
grep -I -q . "$bin" || continue # ignore binary files
|
|
[[ -x "$bin" ]] || continue # ignore non-executable files (such as context.lua)
|
|
scriptCount=$((scriptCount + 1))
|
|
read -r cmdline < "$bin"
|
|
read -r interp <<< "$cmdline"
|
|
if [[ "$interp" != "#!$NIX_STORE"/* && "$interp" != "#! $NIX_STORE"/* ]] ; then
|
|
echo "error: non-nix shebang '$interp' in script '$bin'"
|
|
invalidCount=$((invalidCount + 1))
|
|
fi
|
|
done
|
|
'') binPackages)
|
|
+ ''
|
|
echo "checked $scriptCount scripts, found $invalidCount non-nix shebangs"
|
|
[[ $invalidCount -gt 0 ]] && exit 1
|
|
mkdir -p "$out"
|
|
''
|
|
);
|
|
|
|
# verify that the precomputed licensing information in default.nix
|
|
# does indeed match the metadata of the individual packages.
|
|
#
|
|
# This is part of the test suite (and not the normal evaluation) to save
|
|
# time for "normal" evaluations. To be more in line with the other tests, this
|
|
# also builds a derivation, even though it is essentially an eval-time assertion.
|
|
licenses =
|
|
let
|
|
concatLicenses = builtins.foldl' (acc: el: if builtins.elem el acc then acc else acc ++ [ el ]);
|
|
# converts a license to its attribute name in lib.licenses
|
|
licenseToAttrName =
|
|
license: builtins.head (builtins.attrNames (lib.filterAttrs (n: v: license == v) lib.licenses));
|
|
lt = (a: b: a < b);
|
|
|
|
savedLicenses = scheme: scheme.meta.license;
|
|
savedLicensesAttrNames = scheme: map licenseToAttrName (savedLicenses scheme);
|
|
|
|
correctLicenses =
|
|
scheme:
|
|
builtins.foldl' (
|
|
acc: pkg: concatLicenses acc (lib.toList (pkg.meta.license or [ ]))
|
|
) [ ] scheme.passthru.requiredTeXPackages;
|
|
correctLicensesAttrNames = scheme: lib.sort lt (map licenseToAttrName (correctLicenses scheme));
|
|
|
|
hasLicenseMismatch =
|
|
scheme:
|
|
(lib.isDerivation scheme) && (savedLicensesAttrNames scheme) != (correctLicensesAttrNames scheme);
|
|
incorrectSchemes = lib.filterAttrs (n: hasLicenseMismatch) (texlive.combined // texlive.schemes);
|
|
prettyPrint = name: scheme: ''
|
|
license info for ${name} is incorrect! Note that order is enforced.
|
|
saved: [ ${lib.concatStringsSep " " (savedLicensesAttrNames scheme)} ]
|
|
correct: [ ${lib.concatStringsSep " " (correctLicensesAttrNames scheme)} ]
|
|
'';
|
|
errorText = lib.concatStringsSep "\n\n" (lib.mapAttrsToList prettyPrint incorrectSchemes);
|
|
in
|
|
runCommand "texlive-test-license"
|
|
{
|
|
inherit errorText;
|
|
}
|
|
(
|
|
if (incorrectSchemes == { }) then
|
|
"echo everything is fine! > $out"
|
|
else
|
|
''
|
|
echo "$errorText"
|
|
false
|
|
''
|
|
);
|
|
|
|
# verify that all fixed hashes are present
|
|
# this is effectively an eval-time assertion, converted into a derivation for
|
|
# ease of testing
|
|
fixedHashes =
|
|
let
|
|
fods = lib.concatMap (
|
|
p:
|
|
lib.optional (p ? tex && lib.isDerivation p.tex) p.tex
|
|
++ lib.optional (p ? texdoc) p.texdoc
|
|
++ lib.optional (p ? texsource) p.texsource
|
|
++ lib.optional (p ? tlpkg) p.tlpkg
|
|
) (lib.attrValues texlive.pkgs);
|
|
errorText = lib.concatMapStrings (
|
|
p:
|
|
lib.optionalString (
|
|
!p ? outputHash
|
|
) "${p.pname}-${p.tlOutputName} does not have a fixed output hash\n"
|
|
) fods;
|
|
in
|
|
runCommand "texlive-test-fixed-hashes"
|
|
{
|
|
inherit errorText;
|
|
passAsFile = [ "errorText" ];
|
|
}
|
|
''
|
|
if [[ -s "$errorTextPath" ]] ; then
|
|
cat "$errorTextPath"
|
|
echo Failed: some TeX Live packages do not have fixed output hashes. Please read UPGRADING.md for how to generate a new fixed-hashes.nix.
|
|
exit 1
|
|
else
|
|
touch "$out"
|
|
fi
|
|
'';
|
|
}
|