Added `bundles` directory

This commit is contained in:
rm-dr 2024-09-19 19:08:01 -07:00
parent bab45fc1eb
commit ed60761808
No known key found for this signature in database
GPG Key ID: B4DF96450FAAD9F2
25 changed files with 1859 additions and 0 deletions

58
bundles/README.md Normal file
View File

@ -0,0 +1,58 @@
# Tectonic Bundles
This repository contains tools for building bundles for [Tectonic](https://tectonic-typesetting.github.io).
You should only need this if you're producing your own bundles. If you're just using Tectonic to compile LaTeX,
you should use the pre-generated bundles we distribute.
## Prerequisites
To use these tools, you will need:
- GNU `patch`. Patch is called by `tectonic bundle create `.
- A [TeXlive tarball](https://tug.org/texlive/acquire-tar.html).
The following bundles are available:
- [`texlive2023`](./bundles/texlive2023): based on `texlive2023-20230313`.
## Build Process:
Before building any bundles, you'll need to download the prerequisite files.
Usually, this is a [TeXlive tarball](https://tug.org/texlive/acquire-tar.html) with a version that matches the bundle you want to build.
See `bundle.toml` in the bundle you want to build.
To build a bundle, run the following:
- `cd bundles`
- `tectonic -X bundle create --build-dir ./build texlive2023/bundle.toml v1`
This runs the following jobs, in order. Individual jobs may be run by specifying `--job <job name>`.
- `select`
- `pack`
The contents of `<build dir>/content` may be inspected and edited after running `select`. \
This should only be used to debug bundles.
## Extra Documentation
- Each directory in [`./bundles`](./bundles/) is a bundle specification, documented [here](./bundles/README.md).
- Only one bundle format is currently supported, it is described in [`./format-v1.md`](./format-v1.md).
- This repository includes legacy bundle [tests](./tests/README.md), which may be broken.
## Output files
The files that `tectonic bundle create` produces are listed below:
- `./build/output/<bundle>/content`: contains all bundle files. It is organized by source: files from the bundle's `include` dir will be under `./include`, texlive files will be under `./texlive`, and so on. See `builder/src/select.rs`.
This directory also contains some metadata:
- `content/FILELIST`: each line of this file is `<path> <hash>`, sorted by file name.\
Files with identical names are included.\
Files not in any search path are also included.\
`<hash>` is either a hex sha256 of that file's contents, or `nohash` for a few special files.
- `content/SHA256SUM`: The sha256sum of `content/FILES`. This string uniquely defines this bundle.
- `content/SEARCH`: File search order for this bundle. See bundle spec documentation.
- `search-report`: debug file. Lists all directories that will not be searched by the rules in `search-order`.\
The entries in this file are non-recursive: If `search-report` contains a line with `/texlive`, this means that direct children of `/texlive` (like `/texlive/file.tex`) will not be found, but files in *subdirectories* (like `/texlive/tex/file.tex`) may be.
**Final output files are listed below:**
- `<bundle>.ttb`: the bundle. Note that the ttb version is *not* included in the extension.
- Index location and length are printed once this job completes.
- You can extract files from this bundle by running `dd if=file.ttb ibs=1 skip=<start> count=<len> | gunzip`

3
bundles/bundles/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# Ignore build files & resources
/build
*.tar

166
bundles/bundles/README.md Normal file
View File

@ -0,0 +1,166 @@
# Bundle Specification
Every directory in this dir defines a Tectonic bundle.
The main configuration file is `bundle.toml`, its contents are documented below.
## Overview
```toml
[bundle]
# This bundle's name
name = "texlive2023"
# This bundle's expected final SHA256 hash. See the bundle specification to learn how it's generated.
# If this is left empty, the bundle hash will be printed once the bundle is built.
expected_hash = "c1bbb5f8498d2bb5471cc2b0790700ecb86fc992ec290f7eb718d8751f8ada2a"
# Bundle search order. This tells Tectonic how to search for files.
# The global `search_order` may have two kinds of values:
# - plain strings (which follow the usual search order rules)
# - `{ input = "" }` entries, which specify an input's search order.
# If an input is not listed here, it will NOT be searched!
# (unless one specifies "//", which is a bad idea.)
#
# This is used to generate SEARCH in the bundle.
search_order = ["/", { input = "include" }, { input = "texlive" }]
# Note the triple-quoted multiline strings:
# this is the best way to get raw strings in TOML.
ignore = [
# Files and extensions we want to ignore.
# These will be applied to ALL inputs.
# If a file's relative path matches any of these patterns,
# that file will be excluded from the bundle.
'''.*/LICENSE\.md''',
'''.*/Makefile''',
'''.*/README''',
'''.*/README.md''',
'''.*/readme\.txt'''
]
# A simple directory input, with `path` relative to this toml file.
[inputs."include"]
source.dir.path = "include"
# A tarball input, usually used to add TeXlive files.
#
# Note that this MUST be a .tar file.
# You'll likely download a compressed tar file. Extract it.
#
# It's a good idea to add a comment with the TeXlive version
# and url of this file, so that others may find it.
[inputs."texlive"]
# Patch directory for this input. Optional.
# This should be a directory of `.diff` files in unified format,
# the first line of which specifies the path (relative to `root_dir` below)
# of the file that diff should be applied to.
#
#
# To make a patch file, you should...
# - Copy the original file and apply your changes.
# - Run `diff "original-file" "modified-file" > file.diff`. ORDER MATTERS!
# - Add **one** new line to the top of `file.diff` containing a path to the file this diff should be applied to. This path should be relative to the bundle's content dir, as shown below.
# - Place `file.diff` anywhere in your bundle's include dir. The file selection script should find and apply it.
#
# The line at the top is essential and must be added manually.
# We can't do without it, since we may have many files with # the same name.
#
# Also note that the brace decorations used in `search_order` may also be used in this first line.
# For example, a patch marked `tex/{latex,latex-dev}/base/latex.ltx` will be applied to `latex.ltx` in both
# `texlive/tex/latex` and `texlive/tex/latex-dev`. This will only work if those files are identical.
patch_dir = "patches/texlive"
# Path to the tarball, relative to this toml file's parent directory.
source.tarball.path = "texlive-20230313-texmf.tar"
# Compute this hash by running `sha256 -b file.tar`
source.tarball.hash = "ac1683d4abeb7fd534851ad7ff0ec891da7da4729603506efd0245259dcdcc67"
# The directory inside this tarball to add. Optional.
# All paths below are relative to this.
source.tarball.root_dir = "texlive-20230313-texmf/texmf-dist"
# Regex ignore pattens. Any file whose path matches any of these patterns will not be added to the bundle.
# These are relative to `root_dir` and do NOT start with a slash.
ignore = [
'''tex/luatex/.*''',
'''tex/lualatex/.*'''
]
# Search order of this input.
# This is optional, ommitting `search_order` is equivalent
# to setting `search_order = [ "//" ]`
#
# As always, these paths are relative to `root_dir` and do NOT start with a slash.
#
#
# Lines may be decorated with braces: `/a/{b,c}/` will become `/a/b` and `a/c`, in that order.
# - Brace decorations may not be nested.
# - Paths may not contain braces. Escaping with `\{` will not work.
# - Multiple brace decorations in one line are allowed:
# `/{a,b}/{1,2}` expands to `/a/1`, `/a/2`, `/b/1`, `b/2`, in that order.
#
# Just like kpathsea search paths, each search pattern can end with one or two slashes.
# - If a line ends with two slashes (like `texlive/tex/latex//`), it will match all subdirectories of that path.
# - If a line ends with one slash (like `texlive/tex/latex/`), it will match only direct children of that path:
# `texlive/tex/latex/a.tex` will be searched, `texlive/tex/latex/base/a.tex` will not.
#
# - If a line does not end with a slash, we pretend it ends with one.
# - If a line ends with three or more slashes, it won't be searched at all. Don't do that.
#
# This scheme lets us override the default "alphabetic depth-first search" by adding seach paths as follows,
# which will look for direct children of `latex` before descending into subdirectories:
# ```
# texlive/tex/latex/
# texlive/tex/latex//
# ```
search_order = [
"tex/{xelatex,latex,xetex,plain,generic}//",
"bibtex/{bib,bst,csf}//",
"web2c//",
"fonts//",
"biber//",
"mft//",
"dvips//",
"makeindex//",
"{web,cweb}//",
"ttf2pk//",
"dvipdfmx/",
]
```
## Extra details: finding files
### Overview
Any TeX distribution needs a way to find files. This is necessary because files are usually included only by name: `\include{file}`, `\usepackage{package}`, etc. Where do we find `file.tex` and `package.sty`?
In a conventional TeXLive installation, kpathsea solves this problem. It defines an array of "search paths," and walks through them when you ask for a file. You can find an overview [here](https://www.overleaf.com/learn/latex/Articles/An_introduction_to_Kpathsea_and_how_TeX_engines_search_for_files) and more detailed information in the kpathsea docs.
Tectonic's supporting files are distributed in bundles, so we can't use the same approach.
Within tectonic's *bundles*[^1], we use FILELIST and SEARCH files to map a filename to an input path. Note that this logic is implemented in tectonic, not in the bundle build script.
[^1]: Tectonic searches for files on your disk seperately. The information in this file only applies to bundles. I won't document this fully here, you'll have to read the tectonic docs and source code.
- **Case 1:** tectonic looks for `file.tex` and finds one path in `FILELIST`\
Nothing fancy here, we just use the file we found.
- **Case 2:** tectonic looks for `partial/path/to/file.tex`\
This is an edge case caused by some packages (for example, `fithesis`). To handle this,
we first find `file.tex` in `FILELIST` and look at its path. If its path ends with `partial/path/to/file.tex`, we use it,
if it doesn't, we don't. If multiple files match, we print an error--that shouldn't ever happen.
- **Case 3:** tectonic looks for `file.tex` and finds multiple paths in `FILELIST`\
This where things get interesting. First, we match all paths against each line of the bundles's `SEARCH` file with a simple `starts_with`.
- If *exactly one* path matches a certain line, we immediately stop checking and use that path. Search lines are ordered by priority, so if only one path matches the first line, it *must* be the right path to use.
- If multiple paths match a certain line, we discard all others and resolve the conflict alphabetically.
- If we've checked all lines of `SEARCH` and found no matches, we didn't find the file. Return an error.
"Resolving the conflict alphabetically" means we sort the paths in alphabetical order and pick the first. This emulates an alphabetically-ordered depth-first search on the file tree, which is a reasonable default.
Any filename conflicts which would be resolved alphabetically are listed in `search-report` after the `select` build step. These aren't errors, but we should look over that file to make sure everything is working as expected.

View File

@ -0,0 +1,89 @@
[bundle]
name = "texlive2023"
expected_hash = "e2571849ee65f1c8cb6dc7e433a1ae6b97b47eb24d27074cd485ff2bb87a79ab"
search_order = ["/", { input = "include" }, { input = "texlive" }]
# Note the triple-quoted multiline strings:
# this is the best way to get raw strings in TOML.
ignore = [
# Files and extensions we usually want to ignore.
'''.*/00readme\.txt''',
'''.*/LICENSE\.md''',
'''.*/Makefile''',
'''.*/README''',
'''.*/README.md''',
'''.*/readme\.txt''',
'''.*/ls-R''',
'''.*\.fmt''',
'''.*\.log''',
'''.*\.lua''',
'''.*\.mf''',
'''.*\.pl''',
'''.*\.ps''',
]
[inputs."include"]
source.dir.path = "include"
# Requires texlive-20230313-texmf, which is available at
# https://ftp.math.utah.edu/pub/tex/historic/systems/texlive/2023/texlive-20230313-texmf.tar.xz
# download and extract this file as a .tar in this directory.
[inputs."texlive"]
source.tarball.path = "texlive-20230313-texmf.tar"
source.tarball.hash = "ac1683d4abeb7fd534851ad7ff0ec891da7da4729603506efd0245259dcdcc67"
source.tarball.root_dir = "texlive-20230313-texmf/texmf-dist"
patch_dir = "patches/texlive"
ignore = [
# I don't think tectonic has xindy support, ignore for now
'''xindy/.*''',
# We may need this, but exclude for now.
'''tex4ht/.*''',
# These require pLaTeX2e, tectonic uses XeTeX
'''tex/uplatex/.*''',
'''tex/uptex/.*''',
# Other odd tex formats & unnecessary files
'''tex/cslatex/.*''',
'''tex/csplain/.*''',
'''tex/ptex/.*''',
'''tex/platex/.*''',
'''tex/lollipop/.*''',
'''tex/context/.*''',
'''context/.*''',
'''texdoc/.*''',
'''texdoctk/.*''',
'''texconfig/.*''',
'''scripts/.*''',
'''dvips/.*''',
'''asymptote/.*''',
'''makeindex/.*''',
'''luatex-cache/.*''',
'''hb2gf/.*''',
'''chktex/.*''',
'''source/.*''',
'''doc/.*''',
'''tex/luatex/.*''',
'''tex/lualatex/.*''',
'''tex/lambda/.*''',
'''omega/.*''',
]
search_order = [
"tex/{xelatex,latex,xetex,plain,generic}//",
"bibtex/{bib,bst,csf}//",
"web2c//",
"fonts//",
"biber//",
"mft//",
"dvips//",
"makeindex//",
"{web,cweb}//",
"ttf2pk//",
"dvipdfmx/",
]

View File

@ -0,0 +1 @@
\input xelatex.ini

View File

@ -0,0 +1 @@
\input plain \dump

View File

@ -0,0 +1,24 @@
tex/latex/fithesis/style/mu/fithesis-mu-base.sty
131c131,138
< \setmainfont[Ligatures=TeX]{TeX Gyre Pagella}
---
> \setmainfont{texgyrepagella}[
> Ligatures = TeX,
> Extension = .otf,
> UprightFont = *-regular,
> ItalicFont = *-italic,
> BoldFont = *-bold,
> BoldItalicFont = *-bolditalic,
> ]
136c143,151
< \setsansfont[Ligatures=TeX,Scale=MatchLowercase]{TeX Gyre Heros}
---
> \setmainfont{texgyreheros}[
> Ligatures = TeX,
> Scale = MatchLowercase,
> Extension = .otf,
> UprightFont = *-regular,
> ItalicFont = *-italic,
> BoldFont = *-bold,
> BoldItalicFont = *-bolditalic,
> ]

View File

@ -0,0 +1,5 @@
tex/latex/fontawesome/fontawesome.sty
45c45
< \newfontfamily{\FA}{FontAwesome}
---
> \newfontfamily{\FA}{FontAwesome.otf}

View File

@ -0,0 +1,32 @@
tex/{latex,latex-dev}/base/latex.ltx
7211,7237c7211,7212
< \typeout{^^J! LaTeX Error: File `#1.#2' not found.^^J^^J%
< Type X to quit or <RETURN> to proceed,^^J%
< or enter new name. (Default extension: #2)^^J}%
< \message{Enter file name: }%
< {\endlinechar\m@ne
< \global\read\m@ne to\@gtempa}%
< \ifx\@gtempa\@empty
< \let\@missingfile@area\@empty
< \let\@missingfile@base\@empty
< \def\@missingfile@ext{tex}%
< \else
< \def\reserved@b{\batchmode\read-1 to \reserved@a}%
< \def\reserved@a{x}\ifx\reserved@a\@gtempa\reserved@b\fi
< \def\reserved@a{X}\ifx\reserved@a\@gtempa\reserved@b\fi
< \filename@parse\@gtempa
< \edef\filename@ext{%
< \ifx\filename@ext\relax#2\else\filename@ext\fi}%
< \edef\reserved@a{%
< \noexpand\IfFileExists
< {\filename@area\filename@base.\filename@ext}%
< {\def\noexpand\@missingfile@area{\filename@area}%
< \def\noexpand\@missingfile@base{\filename@base}%
< \def\noexpand\@missingfile@ext {\filename@ext}}%
< {\noexpand\@missingfileerror
< {\filename@area\filename@base}{\filename@ext}}}%
< \reserved@a
< \fi
---
> % Tectonic: no terminal input allowed, so this is always a fatal error.
> \errmessage{! LaTeX Error: File `#1.#2' not found.}%

View File

@ -0,0 +1,25 @@
tex/latex/listings/listings.sty
2057,2075c2057,2059
< \typeout{^^J! Package Listings Error: File `#1(.#2)' not found.^^J%
< ^^JType X to quit or <RETURN> to proceed,^^J%
< or enter new name. (Default extension: #2)^^J}%
< \message{Enter file name: }%
< {\endlinechar\m@ne \global\read\m@ne to\@gtempa}%
< \ifx\@gtempa\@empty \else
< \def\reserved@a{x}\ifx\reserved@a\@gtempa\batchmode\@@end\fi
< \def\reserved@a{X}\ifx\reserved@a\@gtempa\batchmode\@@end\fi
< \filename@parse\@gtempa
< \edef\filename@ext{%
< \ifx\filename@ext\relax#2\else\filename@ext\fi}%
< \edef\reserved@a{\noexpand\IfFileExists %
< {\filename@area\filename@base.\filename@ext}%
< {\noexpand\lst@InputListing %
< {\filename@area\filename@base.\filename@ext}}%
< {\noexpand\lst@MissingFileError
< {\filename@area\filename@base}{\filename@ext}}}%
< \expandafter\reserved@a %
< \fi}
---
> % Tectonic: no terminal input allowed, so this is always a fatal error.
> \errmessage{! Package Listings Error: File `#1(.#2)' not found.}%
> }

63
bundles/format-v1.md Normal file
View File

@ -0,0 +1,63 @@
# Tectonic Bundle Format V1 Specification
A single TTBv1 bundle may be used on the network or from a local filesystem. This bundle format contains two parts:
- A 66-byte header, documented below
- File data, a concatenated blob of gzipped files. One of these blobs is the bundle index.
Note that the extension for a tectonic bundle is `ttb`, regardless of its version. Also note that a bundle's hash depends on it's content. If we generate two bundles in different formats from one specification, the the resulting bundle hashes should be identical..
### Header format
A TTBv1 header consists of the following fields, in order.
All numbers are stored with little-endian byte ordering.
- `14 bytes`: magic bytes. Always `tectonicbundle`, in any ttb version.
- ` 4 bytes`: bundle version, a `u32`. In this case, always 1.
- ` 8 bytes`: index location, a `u64`. This is the first byte of the bundle index file.
- ` 4 bytes`: gzipped index length, a `u32`. This is the length the bundle index file.
- ` 4 bytes`: true index length, a `u32`. This is the decompressed length of the bundle index file.
- `32 bytes`: this bundle's hash.
### Index
Bundle contents are stored as a concatenated `gzip` blobs after the header. These are found using a special file called the Index, the location of which location is stored in the header. The index is generated from the "meta-files" that the file selector produces, namely `FILELIST` and `SEARCH`. These are included in the bundle for consistency, but shouldn't ever be used.
The index may be retrieved from a bundle by running `dd if=file.ttb ibs=1 skip=<start> count=<len> | gunzip`.
The Index file comes in sections, each of which starts on a line marked with square braces. The following sections are currently used, all others are ignored.
- `[DEFAULTSEARCH]`: the default search order.
- `[SEARCH:<name>]`: a search specification. Tectonic will search these paths for files, in this order. See the [bundle spec documentation](../../bundles/README.md).
- `[FILELIST]`: a list of files in this bundle.
- Each line contains the following: `<start_byte> <gzip_len> <real_len> <hash> <path>`
- `<hash>` is either a sha256 hash, or `nohash` for certain special files.
- `<start_byte>` and `<gzip_len>` are the location and length of files in the bundle.
- `<real_len>` is the decompressed length of each file, used for efficient memory allocation.
- `<path>` is the file's path. This is relative, and doesn't start with a slash. Also, this is intentionally last: paths may contain spaces (but not newlines!).
This index is generated by a script, so *very little error-checking is done inside Tectonic*. Keep the following in mind:
- Empty lines should not exist
- Any lines before a section specification are ignored
- Invalid sections are ignored
- Only the last line of `[DEFAULTSEARCH]` has any effect
- We assume that the default `[SEARCH:<name>]` exists.
An example index is below.
```
[DEFAULTSEARCH]
MAIN
[SEARCH:MAIN]
/
/include//
/texlive/tex/xelatex//
/texlive/tex/latex//
/texlive/tex/xetex//
/texlive/tex/plain//
[FILELIST]
70 6065990 17331559 nohash FILELIST
6066060 133 360 589b5c09a33c2655c76f9a6b9bbb6060674c896fbc5b4555af0e20c86f32ac13 SEARCH
6066193 72 65 nohash SHA256SUM
6066265 39 19 86d8d12cfdfbe74a81b9df7c5b38a766303a772d57e7cb0d228e1e7b9294cf34 include/tectonic/tectonic-format-latex.tex
... many more lines ...
```

29
bundles/tests/README.md Normal file
View File

@ -0,0 +1,29 @@
# Testing Bundles
These are a work in progress, and may be broken.
All tests are run through `test.sh` as follows: `./test.sh <path-to-ttb> <test set>`.
Tests require the following:
- a `ttb` bundle (local or remote)
- a recent installation of Tectonic
## Test Sets
The following test sets are avaiable:
- `files`, which tries to compile all files under `tests/files` and `tests/formats`
- `classes`, which tries to compile a simple document using `tests/classes.list`
Note that most test files contain comments explaining the reason and expected outcome of the test.
## Test Output
All test output ends up under `tests/build`
**Output for `files`:**
- `files/logs`: log files for all builds (passed or failed)
- `files/*.{pdf,fmt,etc}`: output files for each build
**Output for `classes`**
- `failed`: classes that failed to compile
- `passed`: classes that complied without error
- `logs`: log files for all compile jobs

628
bundles/tests/classes.list Normal file
View File

@ -0,0 +1,628 @@
BHCexam xfail
BMSTU-IU8 xfail
ConcProg ok
FUpowerdot xfail
IEEEconf ok
IEEEtran ok
IMTEKda xfail
ReadableCV xfail
RecipeBook ok
SPhdThesis ok
TOPletter xfail
URbeamer xfail
URletter xfail
UoWthesis ok
a0poster ok
aalok xfail
aastex ok
aastex61 ok
aastex62 ok
aastex63 ok
aastex631 ok
abntex2 ok
abstbook ok
achemso ok,titleauth
acmart ok
acmconf xfail
active-conf ok
adfathesis ok
afparticle ok,titleauth
afthesis ok
agecon ok
aguplus xfail
aiaa-tc ok
ajae ok
akklecture ok,titleauth
akkscript ok
akktecdoc ok
akletter ok
ametsoc ok
amsart ok
amsbook ok
amsdtx ok
amsldoc ok
amsproc ok
aomart ok
apa ok
apa6 xfail - looks unmaintained; uses known option to flushend package
apa6e xfail
apa7 ok
apecon ok
arabart ok
arabbook ok
arabic-book xfail
arabrep ok
arabrep1 xfail
argetabelle ok
article ok
articleingud ok
articoletteracdp ok
artikel1 ok
artikel2 ok
artikel3 ok
asaetr ok
ascelike ok
asmeconf xfail
asmejour xfail - typo breaks build on XeTeX
assignment ok
aucklandthesis ok
bangorcsthesis xfail
bangorexam xfail
bankstatement ok
barticle xfail
basque-book ok
bbook xfail
beamer ok
beamer-rl xfail
beamerswitch xfail
beaulivre ok
beilstein ok
beletter ok
bewerbung ok
bfhbeamer xfail
bfhpub xfail
bfhsciposter xfail
bfhthesis xfail
bgteubner xfail
bidimoderncv xfail
bidipresentation ok
biditufte-book ok
biditufte-handout ok
bitart xfail
bitbook xfail
bjfuthesis xfail
bletter ok
bmstu xfail
boek ok
boek3 ok
book ok
bookcover ok
bookest ok
bookshelf xfail
br-lex ok
brandeis-dissertation ok
brandeis-problemset xfail
brandeis-thesis xfail
brief ok
buctcover xfail
buctthesis xfail
businesscard-qrcode ok
bxjsarticle ok
bxjsbook ok
bxjsreport ok
bxjsslide ok
caesar_book ok
cas-dc xfail
cas-sc xfail
cascadilla xfail
cassete ok
cc xfail
cd ok
cd-cover ok
cesenaexam xfail
cheatsheet ok
chletter ok
cje xfail
cnbwp xfail
cnltx-doc xfail
codedoc ok
colorart ok
colorbook ok
combine xfail
confproc xfail
contracard ok
cours ok
courseoutline ok
coursepaper ok
cquthesis xfail
csbulletin ok
csbulobalka xfail
csbulv1 xfail
ctexart ok
ctexbeamer ok
ctexbook ok
ctexrep ok
ctxdoc ok
curve ok
cv4tw xfail
cweb xfail
dfgproposal xfail
dfgreporting xfail
dinbrief ok
disser xfail
dithesis xfail
document-structure xfail
droit-fr xfail
dtk ok
dvdcoll ok
easybook ok
ebsthesis ok
ecca ok
ecv xfail
einfart ok
ejpecp xfail
elbioimp ok
elegantbook ok
elegantnote ok
elegantpaper ok
elpres ok
elsarticle ok
elteikthesis ok
emisa xfail
emulateapj ok
erae ok
erdc xfail
eskd xfail
eskdgraph xfail
eskdtab xfail
eskdtext xfail
estcpmm ok
etiketka ok
euproposal xfail
eureporting xfail
europasscv xfail
europecv ok
europroc ok
exam ok
exam-n ok
examdesign xfail
exesheet ok
extarticle ok
extbook ok
extletter ok
extproc ok
extreport ok
facsimile ok
factura xfail
facture xfail
fancyhandout ok
fancyslides ok
fbithesis xfail
fcavtex ok
fdudoc xfail
fduthesis xfail
fduthesis-en xfail
fei xfail
ffslides xfail
fiche ok
fithesis ok
fithesis2 ok
fithesis3 ok
fithesis4 ok
flacards ok
flashcard xfail
flashcards xfail
frletter ok
fsbispit xfail
g-brief ok
g-brief2 ok
gaceta ok
gammas xfail
geradwp ok
gmdocc ok
gost732 xfail
gradstudentresume xfail
grant xfail
grant-afosr xfail
grant-aro xfail
grant-darpa xfail
grant-doe xfail
grant-nih xfail
grant-nrl xfail
grant-nsf xfail
grant-onr xfail
graphpaper ok
gridslides ok
gsemthesis ok
guitartabs ok
gzt xfail
gztarticle ok
h2020proposal ok
harnon-cv xfail
hausarbeit-jura xfail
hcart xfail
hcletter xfail
hcreport xfail
hcslides xfail
hecthese ok
hepthesis ok
hgbarticle xfail
hgbreport xfail
hgbthesis xfail
hitec ok,titleauth
hithesis xfail
hitreport ok
hitszthesis xfail
hletter ok
hpsdiss xfail
hu-berlin-letter xfail
huawei ok
hustthesis xfail
hwexam xfail
iagproc ok
icsv ok
idcc xfail
ijdc-v14 xfail
ijdc-v9 ok
ijmart ok
ijsra xfail
image-gallery ok
imsproc ok
inkpaper xfail
invoice-class ok
iodhbwm ok
iscram ok
isodoc xfail
isov2 ok
itaxpf ok
iwhdp xfail
jacow xfail
jarticle xfail
jbook xfail
jlreq xfail
jltxdoc xfail
jmlr ok
jmlrbook xfail
jnuexam ok
journal ok
jpsj2 ok
jreport xfail
jrurstud ok
jsarticle xfail
jsbook xfail
jspf xfail
jsreport xfail
jura ok
jurabook ok
juraovw ok
juraurtl ok
kdgcoursetext ok,titleauth
kdgmasterthesis ok,titleauth
kdpcover ok
kerntest xfail
kiyou xfail
kluwer ok
knittingpattern ok
komacv ok
ksp-thesis xfail
l3doc ok
labbook ok
langscibook xfail
leadsheet ok
leaflet ok
lebhart ok
lectures xfail
legislation xfail
letgut xfail
letter ok
letteracdp ok
lettre ok
limap ok
limecv xfail
lion-msc xfail
llncs ok
lni ok,titleauth
lps ok
lt3graph-packagedoc xfail
ltjarticle xfail
ltjbook xfail
ltjltxdoc xfail
ltjreport xfail
ltjsarticle xfail
ltjsbook xfail
ltjskiyou xfail
ltjspf xfail
ltjsreport xfail
ltjtarticle xfail
ltjtbook xfail
ltjtreport xfail
ltnews ok
ltugboat ok
ltugproc ok
ltxdoc ok
ltxdockit ok
ltxguide ok
ltxguidex ok
ltxmdf xfail
matapli xfail
matc3mem ok
mcmthesis ok
medstarbeamer xfail
meetingmins ok
memoir ok
mensa-tex ok
mentis xfail
metanorma ok
milog ok
minimal ok
minimart ok
minimbook ok
mla ok
mluexercise xfail
mnras ok
moderncv xfail
modernposter ok
movie ok
msu-thesis ok
mucproc xfail
mugsthesis ok
muling ok
musuos ok
muthesis ok
mwart ok
mwbk ok
mwrep ok
my-thesis ok
mycv ok
myletter ok
mynsfc ok
nanicolle xfail
nature ok
ncc ok
nccproc ok
nddiss2e xfail
ndsu-thesis ok
newlfm xfail
nih ok
nihbiosketch xfail
njf ok
njurepo xfail
njustthesis xfail
njuthesis ok
nlctdoc ok
nostarch xfail
notesslides ok
novel xfail
nrc1 xfail
nrc2 xfail
nwafuthesis xfail
nwejm xfail
nwejmart xfail - assumes font "Latin Modern Mono" is available
oblivoir ok
oblivoir-utf xfail
oblivoir-xl xfail
octavo ok
oegatb xfail
onrannual ok
oup-authoring-template ok
paper ok
papertex xfail
pbsheet xfail
pdfArticle xfail
pecha xfail
petiteannonce ok
phfextendedabstract ok
philosophersimprint ok
pittetd ok
pkuthss xfail
plari ok
play ok
plnews xfail
pocoec ok
postcards xfail
powerdot xfail
powersem xfail
ppr-prv xfail
pracjourn ok
pressrelease ok
proc ok
proposal xfail
prosper xfail
protocol ok
prtec ok
ptptex ok
qcm ok
quantumarticle xfail
qyxf-book xfail
rapport1 ok
rapport3 ok
rbt-mathnotes xfail
rbt-mathnotes-formula-sheet xfail
rbt-mathnotes-hw xfail
recipe ok
recipecard xfail
refart ok
refrep ok
regstud ok
report ok
reporting xfail
resphilosophica ok
resumecls ok
revtex4 ok
revtex4-1 ok
revtex4-2 ok
rtklage xfail
ryersonSGSThesis xfail
ryethesis xfail
sageep ok
sapthesis ok
schuleab ok
schulein ok
schuleit ok
schulekl ok
schuleub xfail
schuleue ok
schullsg ok
schullzk ok
schulma-ab ok
schulma-gutachten ok
schulma-klausur xfail
schulma-komp ok
schulma-mdlprf ok
schulma-praes ok
sciposter ok
scrartcl ok
scrarticle ok
scrbook ok
scrdoc ok
screenplay ok
scrguide xfail
scrjrnl xfail
scrletter ok
scrlttr2 ok
scrreport ok
scrreprt ok
sdapsclassic xfail
sduthesis ok
seminar xfail
semproc ok
sesamanuel xfail
seu-ml-assign xfail
seuthesix xfail
sffms ok,titleauth
shtthesis xfail
sibjnm xfail
sides ok
simplecv ok
simpleresumecv xfail
simplethesisdissertation xfail
simplivre ok
simurgh-doc xfail
skbarticle ok
skbbeamer ok
skbbook ok
skblncsbeamer xfail
skblncsppt ok
skbmoderncv xfail
skdoc xfail
skeyval-testclass xfail
skrapport xfail
slides ok
smfart ok
smfbook ok
source2edoc ok
spie ok
sr-vorl ok
sslides ok
stage ok
standalone ok
stex xfail
subfiles xfail
suftesi xfail
sugconf titleauth,xfail - uses inputenc
tabriz-thesis ok
talk ok
tarticle xfail
tbook xfail
tcldoc ok
tclldoc ok
technionThesis xfail
thesis-ekf ok
thesis-gwu xfail
thesis-qom xfail
third-rep xfail
thuthesis ok
tikz-kalender ok
tikzposter ok
tlc-article ok,titleauth
toptesi ok
treport xfail
tudabeamer xfail
tudaexercise ok
tudaleaflet ok
tudaletter xfail
tudaposter xfail
tudapub xfail
tudasciposter ok
tudscrartcl ok
tudscrbook ok
tudscrdoc ok
tudscrmanual xfail
tudscrposter ok
tudscrreprt ok
tufte-book ok
tufte-handout ok
tui xfail
turabian xfail
turabian-researchpaper ok
turabian-thesis ok
ua-thesis ok
uafthesis ok
uantwerpenbamathesis ok
uantwerpencoursetext ok
uantwerpenexam ok
uantwerpenletter ok
uantwerpenphdthesis ok
uantwerpenreport ok
ucalgmthesis ok
ucbthesis ok
ucdavisthesis ok
ucsmonograph ok
ucthesis ok
udesoftec xfail
uebungsblatt xfail
uestcthesis xfail
uhhassignment ok
uiucredborder ok
uiucthesis ok
ujarticle xfail
ujbook xfail
ujreport xfail
ulthese xfail
umich-thesis ok
umthesis ok
unam-thesis xfail
unbtex ok
unifith ok
unitn-bimrep xfail
univie-ling-expose ok
univie-ling-paper ok
univie-ling-thesis ok
univie-ling-wlg xfail
unizgklasa ok
uothesis ok
upmethodology-document xfail
upmgr ok
uspatent ok
usthesis xfail
ut-thesis ok
utarticle xfail
utbook xfail
utexasthesis ok
utreport xfail
uwa-pcf xfail
uwa-pif xfail
uwmslide ok
uwthesis ok
verifica ok
wallcalendar xfail
webquiz ok
willowtreebook xfail
withargs-packagedoc xfail
wkmgr ok
worlddev ok
wsemclassic xfail
xduthesis xfail
xebaposter xfail
xepersian-magazine ok
xmuthesis xfail
xoblivoir ok
xsim-manual xfail
yaletter xfail
yathesis ok
yazd-thesis ok
yb-book xfail
ycbook ok
ydoc xfail
york-thesis ok
zbMATH ok

View File

@ -0,0 +1,94 @@
\documentclass[12pt]{article}
\usepackage[inline]{asymptote}
% This test compiles without error, but
% the output pdf is missing graphics.
\title{2D Graphics with Asymptote}
\author{The Asymptote Project}
\begin{document}
\maketitle
\begin{asydef}
//
// Global Asymptote definitions can be put here.
//
usepackage("bm");
texpreamble("\def\V#1{\bm{#1}}");
\end{asydef}
Here is a venn diagram produced with Asymptote, drawn to width 4cm:
\def\A{A}
\def\B{\V{B}}
\begin{center}
\begin{asy}
size(4cm,0);
pen colour1=red;
pen colour2=green;
pair z0=(0,0);
pair z1=(-1,0);
pair z2=(1,0);
real r=1.5;
path c1=circle(z1,r);
path c2=circle(z2,r);
fill(c1,colour1);
fill(c2,colour2);
picture intersection=new picture;
fill(intersection,c1,colour1+colour2);
clip(intersection,c2);
add(intersection);
draw(c1);
draw(c2);
//draw("$\A$",box,z1); // Requires [inline] package option.
//draw(Label("$\B$","$B$"),box,z2); // Requires [inline] package option.
draw("$A$",box,z1);
draw("$\V{B}$",box,z2);
pair z=(0,-2);
real m=3;
margin BigMargin=Margin(0,m*dot(unit(z1-z),unit(z0-z)));
draw(Label("$A\cap B$",0),conj(z)--z0,Arrow,BigMargin);
draw(Label("$A\cup B$",0),z--z0,Arrow,BigMargin);
draw(z--z1,Arrow,Margin(0,m));
draw(z--z2,Arrow,Margin(0,m));
shipout(bbox(0.25cm));
\end{asy}
\end{center}
Here are some graphs. The figure is scaled to line width.
\begin{center}
\begin{asy}[width=\the\linewidth,inline=true]
pair z0=(0,0);
pair z1=(2,0);
pair z2=(5,0);
pair zf=z1+0.75*(z2-z1);
draw(z1--z2);
dot(z1,red+0.15cm);
dot(z2,darkgreen+0.3cm);
label("$m$",z1,1.2N,red);
label("$M$",z2,1.5N,darkgreen);
label("$\hat{\ }$",zf,0.2*S,fontsize(24pt)+blue);
pair s=-0.2*I;
draw("$x$",z0+s--z1+s,N,red,Arrows,Bars,PenMargins);
s=-0.5*I;
draw("$\bar{x}$",z0+s--zf+s,blue,Arrows,Bars,PenMargins);
s=-0.95*I;
draw("$X$",z0+s--z2+s,darkgreen,Arrows,Bars,PenMargins);
\end{asy}
\end{center}
\end{document}

View File

@ -0,0 +1,14 @@
\documentclass{article}
\usepackage{chessfss}
\usepackage{chessboard}
\usepackage{xskak}
\begin{document}
\begin{center}
\newchessgame
\chessboard[normalboard, showmover=false]
\end{center}
\end{document}

View File

@ -0,0 +1,10 @@
\documentclass{article}
\usepackage{fontawesome}
% Fontawesome was patched to fix font path.
% It should now look for fonts in the bundle
% rather than system font dirs.
\begin{document}
\faStar
\end{document}

View File

@ -0,0 +1,44 @@
\documentclass[
digital,
twoside,
nolof,
nolot
]{fithesis4}
\usepackage[main=english]{babel}
% The fithesis document class uses tex paths in many odd ways:
% - it provides many files with the same name
% - it loads these files, depending on configuration, with a partial path
%
% This behavior makes fithesis a good test case for
% Tectonic's file search algorithm.
\thesissetup{
date = \the\year/\the\month/\the\day,
university = mu,
faculty = sci,
type = bc,
programme = NA,
field = Sport Management,
department = Department of Social Sciences and Sport Management,
author = Jane Doe,
gender = f,
advisor = {Prof. RNDr. John Smith, CSc.},
title = The use of LaTeX for the Typesetting
of Sports Tables,
TeXtitle = The use of \LaTeX\ for the Typesetting
of Sports Tables,
keywords = {keyword1, keywords2, ...},
TeXkeywords = {keyword1, keywords2, \ldots},
abstract = {%
This is the abstract of my thesis, which can
span multiple paragraphs.
}
}
\begin{document}
test
\end{document}

View File

@ -0,0 +1,19 @@
\documentclass{article}
\usepackage{fontspec}
\setmainfont{TeX Gyre Pagella}
% Try to load a font by name.
% At the moment, this searches the system font cache,
% and thus usually fails.
%
% Eventually we'll implement support for that in Tectonic:
% we should check the bundle for ALL fonts, even those loaded
% by name.
\begin{document}
\section*{Introduction}
This is Introduction
\end{document}

View File

@ -0,0 +1,20 @@
\documentclass{article}
\usepackage{markdown}
% The markdown package requires shell escapes,
% which are currently disabled.
% We expect this test to fail, for now.
\begin{document}
\begin{markdown}
# Grocery list
## Food
- baked beans
- spaghetti
## Stationery
- writing pad
- pencils
\end{markdown}
\end{document}

View File

@ -0,0 +1,11 @@
\documentclass{report}
\usepackage{pgfornament}
\begin{document}
\begin{center}
Below is a test ornament.\linebreak
\pgfornament[scale=0.125]{3}
\end{center}
\end{document}

View File

@ -0,0 +1,7 @@
\documentclass[a4paper,12pt]{article}
\usepackage{polyglossia}
\setmainlanguage[variant=brazilian]{portuguese}
\begin{document}
Test
\end{document}

View File

@ -0,0 +1 @@
\input xelatex.ini

View File

@ -0,0 +1 @@
\input plain \dump

302
bundles/tests/packages.py Executable file
View File

@ -0,0 +1,302 @@
#! /usr/bin/env python3
# -*- mode: python; coding: utf-8 -*-
# Copyright 2020-2021 the Tectonic Project.
# Licensed under the MIT License.
"""
Test builds using some of the LaTeX package (style) files provided in a bundle.
There are thousands of these (about 5000 as of TeXLive 2020), so we use a
reproducible-random scheme to skip most of them to keep the testing time
reasonable. In particular:
- I did an initial run over all of the packages on the TeXLive 2020 bundle when
setting this all up. All of the packages that failed were marked with a "skip"
tag. These are always skipped.
- All of the packages were assigned a randomly-generated number between 0 and 99
(inclusive), using a `rand=` key in the listing file. Of the remaining
non-"skip" packages, only a fraction of them are tested, using the random key
to select them. This program takes a `-S` option to specify the percentage of
packages to test, and a `-K` option to specify which random subset to
investigate. Packages where `(randkey + K) % 100 >= S` are skipped.
- Packages without a `rand=` setting are always tested.
- The default `-S` setting is 5%, which tests about 150 packages and takes about
7 minutes to run. The default `-K` setting is random.
"""
import argparse
import os.path
import random
import subprocess
import sys
from test_utils import *
# We use percent formatting since all the TeX braces would be super annoying to
# escape in str.format() formatting.
DOC_CLASS_TEMPLATE = r"\documentclass{%(class)s}"
PACKAGE_TEMPLATE = r"\usepackage{%(package)s}"
DOCUMENT_BODY = r"""\begin{document}
Hello, world.
\end{document}"""
def entrypoint(argv):
settings = make_arg_parser().parse_args(argv[1:])
bundle = Bundle.open_with_inferred_state(settings.bundle_dir)
packagedir = bundle.test_path("packages")
n_errors = 0
n_surprises = 0
n_tested = 0
n_skipped = 0
n_missing = 0
n_removed = 0
n_xfail = 0
# Random sampling setup
if settings.sample_key is None:
settings.sample_key = random.randint(0, 99)
if settings.update:
print("note: update mode engaged - will rewrite packages.txt")
print()
# Load the packages from the bundle
bundle_packages = set()
with open(bundle.listing_path()) as flist:
for line in flist:
base = line.strip()
if base.endswith(".sty"):
bundle_packages.add(base[:-4])
# Load the stored information
ref_packages = {}
packages_path = bundle.path("packages.txt")
with open(packages_path) as fref:
for line in fref:
bits = line.split()
classname = bits[0]
info = {}
info["tags"] = set(bits[1].split(","))
for bit in bits[2:]:
if bit.startswith("rand="):
info["randkey"] = int(bit[5:])
else:
die(f"unexpected metadata item {bit!r} in packages.txt")
ref_packages[classname] = info
# Cross-check the two lists
for p in bundle_packages:
if p not in ref_packages:
# `just_added` enables us to make sure to test new packages in
# update mode
print(f"MISSING {p} - not in packages.txt")
ref_packages[p] = {
"tags": set(["ok"]),
"randkey": random.randint(0, 99),
"just_added": settings.update,
}
if not settings.update:
n_missing += 1
n_errors += 1
refkeys = list(ref_packages.keys())
for p in refkeys:
if p not in bundle_packages:
print(f"REMOVED {p} - in packages.txt but not bundle")
del ref_packages[p]
if not settings.update:
n_removed += 1
n_errors += 1
if n_missing + n_removed > 0:
print("NOTE: use --update to rebuild packages.txt if needed")
# Sampling setup.
if settings.sample_percentage is None:
TARGET_N_PACKAGES = 100
settings.sample_percentage = max(
100 * TARGET_N_PACKAGES // len(ref_packages), 1
)
n_eff = settings.sample_percentage * len(ref_packages) // 100
print(
f"note: targeting about {n_eff} randomized test cases ({settings.sample_percentage}% of corpus; actual number will vary)"
)
else:
print(
f"note: sampling {settings.sample_percentage}% of the randomized test cases"
)
print(
f"note: sample key is {settings.sample_key}; use argument `-K {settings.sample_key}` to reproduce this run`"
)
# Run the tests
refkeys = sorted(ref_packages.keys())
for pkg in refkeys:
info = ref_packages[pkg]
tags = info["tags"]
if info.get("just_added", False):
random_skipped = False
elif "randkey" in info:
effkey = (info["randkey"] + settings.sample_key) % 100
random_skipped = effkey >= settings.sample_percentage
else:
random_skipped = False
if "skip" in tags or random_skipped:
n_skipped += 1
continue
print(pkg, "... ", end="")
sys.stdout.flush()
n_tested += 1
thisdir = os.path.join(packagedir, pkg)
os.makedirs(thisdir, exist_ok=True)
texpath = os.path.join(thisdir, "index.tex")
params = {
"class": "article",
"package": pkg,
}
with open(texpath, "wt") as f:
print(DOC_CLASS_TEMPLATE % params, file=f)
print(PACKAGE_TEMPLATE % params, file=f)
print(DOCUMENT_BODY, file=f)
with open(os.path.join(thisdir, "log.txt"), "wb") as log:
result = subprocess.call(
[TECTONIC_PROGRAM, "-p", "-b", bundle.zip_path(), texpath],
shell=False,
stdout=log,
stderr=subprocess.STDOUT,
)
if result == 0:
if "ok" in tags:
print("pass", flush=True)
else:
# This test succeeded even though we didn't expect it to.
# Not a bad thing, but worth noting!
print("pass (unexpected)", flush=True)
n_surprises += 1
try:
tags.remove("xfail")
except KeyError:
pass
tags.add("ok")
else:
if "xfail" in tags:
print("xfail", flush=True)
n_xfail += 1
else:
# This test failed unexpectedly :-(
print("FAIL", flush=True)
n_errors += 1
if settings.update:
try:
tags.remove("ok")
except KeyError:
pass
tags.add("xfail")
print()
print("Summary:")
print(f"- Tested {n_tested} packages")
if n_skipped:
print(f"- {n_skipped} cases skipped")
if n_missing:
print(f"- {n_missing} packages missing from packages.txt")
if n_removed:
print(f"- {n_removed} packages in packages.txt removed from bundle")
if n_xfail:
print(f"- {n_xfail} expected failures")
if n_surprises:
print(f"- {n_surprises} surprise passes")
if n_errors:
print(
f"- {n_errors} total errors: test failed (outputs stored in {packagedir})"
)
else:
print(f"- no errors: test passed (outputs stored in {packagedir})")
# Update listing if needed
if settings.update:
with open(packages_path, "wt") as f:
for pkg in refkeys:
info = ref_packages[pkg]
tag_text = ",".join(sorted(info["tags"]))
randkey = info.get("randkey")
if randkey is None:
rest = ""
else:
rest = f" rand={randkey}"
print(pkg, " ", tag_text, rest, sep="", file=f)
# All done!
return 1 if n_errors and not settings.update else 0
def make_arg_parser():
p = argparse.ArgumentParser()
p.add_argument(
"--update",
action="store_true",
help="Update mode: sync packages.txt to bundle; may wish to use `-S 100` too",
)
p.add_argument(
"-S",
"--samp-pct",
dest="sample_percentage",
type=int,
help="The percentage of test cases to sample",
)
p.add_argument(
"-K",
"--samp-key",
dest="sample_key",
type=int,
help='The "key" determining which random subset of cases are sampled',
)
p.add_argument(
"bundle_dir",
help="The directory of the bundle specification",
)
return p
if __name__ == "__main__":
sys.exit(entrypoint(sys.argv))

212
bundles/tests/test.sh Executable file
View File

@ -0,0 +1,212 @@
#!/usr/bin/env bash
this_dir="$(pwd)"
test_dir="${this_dir}"
bundle_path="$(realpath "${1}")"
output_dir="${test_dir}/build"
rm -drf "${output_dir}"
mkdir -p "${output_dir}"
function relative() {
echo "./$(realpath --relative-to="${this_dir}" "${1}")"
}
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'
function test_files() {
rm -drf "${output_dir}/files"
mkdir -p "${output_dir}/files"
mkdir -p "${output_dir}/files/logs"
for f in "${test_dir}/files"/*; do
echo -n "Testing file $(relative "${f}")..."
tectonic \
--chatter minimal \
--outdir "${output_dir}/files" \
--bundle "${bundle_path}" \
"${f}" \
&> "${output_dir}/files/logs/$(basename "${f}").log"
if [[ $? == 0 ]]; then
echo -en "\r${GREEN}PASS${NC}"
else
echo -en "\r${RED}FAIL${NC}"
fi
echo " Tested file $(relative "${f}")"
done
for f in "${test_dir}/formats"/*; do
echo -n "Testing format $(relative "${f}")..."
tectonic \
--chatter minimal \
--outdir "${output_dir}/files" \
-p --outfmt "fmt" \
--bundle "${bundle_path}" \
"${f}" \
&> "${output_dir}/files/logs/$(basename "${f}").log"
if [[ $? == 0 ]]; then
echo -en "\r${GREEN}PASS${NC}"
else
echo -en "\r${RED}FAIL${NC}"
fi
echo " Tested format $(relative "${f}")"
done
}
function test_class_single() {
local class="${1}"
local flags="${2}"
mkdir -p "${output_dir}/classes/logs/failed"
mkdir -p "${output_dir}/classes/logs/passed"
local target="$(mktemp --tmpdir="${output_dir}/classes" "tmp.XXXX")"
(
echo "\documentclass{${class}}"
echo ""
if [[ $flags =~ "titleauth" ]]; then
echo "title{Test Title}"
echo "\author{An Author}"
echo ""
fi
echo "\begin{document}"
echo "Hello, world"
echo "\end{document}"
) > "${target}"
tectonic \
--chatter minimal \
--outdir "${output_dir}/classes" \
--bundle "${bundle_path}" \
"${target}" \
&> "${output_dir}/classes/logs/${class}.log"
if [[ $? == 0 ]]; then
echo "$class" >> "${output_dir}/classes/passed"
mv "${output_dir}/classes/logs/${class}.log" "${output_dir}/classes/logs/passed"
echo 0
else
echo "$class" >> "${output_dir}/classes/failed"
mv "${output_dir}/classes/logs/${class}.log" "${output_dir}/classes/logs/failed"
echo 1
fi
rm "${target}"
}
function test_classes() {
rm -drf "${output_dir}/classes"
mkdir -p "${output_dir}/classes"
local fails=0
local passes=0
local skipped=0
local total=$(wc -l < "${test_dir}/classes.list")
cat "${test_dir}/classes.list" | while read class flags; do
if [[ $flags =~ "xfail" ]]; then
skipped=$(($skipped+1))
continue
fi
r=$(test_class_single "${class}" "${flags}")
if [[ $r == 0 ]]; then
passes=$(($passes+1))
else
fails=$(($fails+1))
fi
echo -en "\r"
echo -en "$(($passes + $fails + $skipped))/${total} "
echo -en "${GREEN}P:${passes}${NC} "
echo -en "${RED}F:${fails}${NC} "
echo -en "S:${skipped}${NC} "
echo -en " Tested class ${class}"
# Delete remnant of previous class name
# and move cursor back.
echo -en " "
echo -en "\033[22D"
done
echo ""
}
function test_class() {
class="$1"
flags="$2"
exists=false;
exists=$(
cat "${test_dir}/classes.list" | while read tclass flags; do
if [[ "${class}" == "${tclass}" ]]; then
echo "${class}"
break
fi
done
)
if [[ -z $exists ]]; then
echo "No such class "${class}""
exit 1
fi
echo -n "Testing class "${class}"..."
r=$(test_class_single "${class}" "${flags}")
if [[ $r == 0 ]]; then
echo -e " ${GREEN}Pass${NC}"
else
echo -e " ${RED}Fail${NC}"
fi
}
case "${2}" in
"all")
test_files
test_classes
;;
"files")
test_files
;;
"classes")
test_classes
;;
"class")
test_class "${3}" "${4}"
;;
*)
echo "Unknown test suite `${1}`"
echo "See README.md"
;;
esac