diff options
-rw-r--r-- | Cargo.lock | 255 | ||||
-rw-r--r-- | dhall/Cargo.toml | 9 | ||||
-rw-r--r-- | dhall/src/tests.rs | 2 | ||||
-rw-r--r-- | dhall/tests/spec.rs | 686 |
4 files changed, 950 insertions, 2 deletions
@@ -45,6 +45,16 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hermit-abi 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "autocfg" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -123,6 +133,20 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "clap" +version = "2.33.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "console_error_panic_hook" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -146,6 +170,59 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "crossbeam-channel" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-queue" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "ctor" version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -163,6 +240,7 @@ dependencies = [ "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libtest-mimic 0.2.0 (git+https://github.com/LukasKalbertodt/libtest-mimic)", "once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -379,6 +457,14 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "hermit-abi" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -529,6 +615,17 @@ version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "libtest-mimic" +version = "0.2.0" +source = "git+https://github.com/LukasKalbertodt/libtest-mimic#bbdd404e13e10f1fae0a2ea6a9fbcc02201bef01" +dependencies = [ + "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "log" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -557,11 +654,24 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "memchr" version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "memoffset" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "mime" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -822,6 +932,30 @@ dependencies = [ ] [[package]] +name = "proc-macro-error" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-error-attr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "proc-macro-hack" version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -890,6 +1024,29 @@ dependencies = [ ] [[package]] +name = "rayon" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "redox_syscall" version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -992,6 +1149,11 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "security-framework" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1136,6 +1298,33 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "structopt" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "structopt-derive" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "syn" version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1146,6 +1335,16 @@ dependencies = [ ] [[package]] +name = "syn-mid" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "tempfile" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1159,6 +1358,22 @@ dependencies = [ ] [[package]] +name = "termcolor" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "thread_local" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1277,6 +1492,16 @@ dependencies = [ ] [[package]] +name = "unicode-segmentation" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "unicode-xid" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1297,6 +1522,11 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "version-sync" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1493,6 +1723,7 @@ dependencies = [ "checksum annotate-snippets 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aba2d96b8c8b5e656ad7ffb0d09f57772f10a1db74c8d23fca0ec695b38a4047" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" +"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" "checksum base64 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e223af0dc48c96d4f8342ec01a4974f139df863896b316681efd36742f22cc67" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" @@ -1505,9 +1736,15 @@ dependencies = [ "checksum bytes 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "118cf036fbb97d0816e3c34b2d7a1e8cfc60f68fcf63d550ddbe9bd5f59c213b" "checksum cc 1.0.54 (registry+https://github.com/rust-lang/crates.io-index)" = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129" "checksum console_error_panic_hook 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211" "checksum core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" "checksum core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" +"checksum crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" +"checksum crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" +"checksum crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +"checksum crossbeam-queue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" +"checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" "checksum ctor 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "39858aa5bac06462d4dd4b9164848eb81ffc4aa5c479746393598fd193afa227" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" @@ -1534,6 +1771,7 @@ dependencies = [ "checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" "checksum h2 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "79b7246d7e4b979c03fa093da39cfb3617a96bbeee6310af63991668d7e843ff" "checksum half 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d36fab90f82edc3c747f9d438e06cf0a491055896f2a279638bb5beed6c40177" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hermit-abi 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909" "checksum hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" "checksum http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" @@ -1551,11 +1789,14 @@ dependencies = [ "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lexical-core 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616" "checksum libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)" = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" +"checksum libtest-mimic 0.2.0 (git+https://github.com/LukasKalbertodt/libtest-mimic)" = "<none>" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum loom 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecc775857611e1df29abba5c41355cdf540e7e9d4acfdf0f355eefee82330b7" "checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" "checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" +"checksum memoffset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" "checksum mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" "checksum mime_guess 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" "checksum mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)" = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" @@ -1585,6 +1826,8 @@ dependencies = [ "checksum ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" "checksum pretty 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f60c0d9f6fc88ecdd245d90c1920ff76a430ab34303fc778d33b1d0a4c3bf6d3" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" +"checksum proc-macro-error 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678" +"checksum proc-macro-error-attr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53" "checksum proc-macro-hack 0.5.16 (registry+https://github.com/rust-lang/crates.io-index)" = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4" "checksum proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa" "checksum pulldown-cmark 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3e142c3b8f49d2200605ee6ba0b1d757310e9e7a72afe78c36ee2ef67300ee00" @@ -1593,6 +1836,8 @@ dependencies = [ "checksum rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" "checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +"checksum rayon 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "62f02856753d04e03e26929f820d0a0a337ebe71f849801eea335d464b349080" +"checksum rayon-core 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e92e15d89083484e11353891f1af602cc661426deb9564c298b270c726973280" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" "checksum regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" "checksum regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" @@ -1604,6 +1849,7 @@ dependencies = [ "checksum schannel 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" "checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" +"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" "checksum security-framework 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535" "checksum security-framework-sys 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" @@ -1619,8 +1865,14 @@ dependencies = [ "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum socket2 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" "checksum static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum structopt 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "de2f5e239ee807089b62adce73e48c625e0ed80df02c7ab3f068f5db5281065c" +"checksum structopt-derive 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "510413f9de616762a4fbeab62509bf15c729603b72d7cd71280fbca431b1c118" "checksum syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "e8d5d96e8cbb005d6959f119f773bfaebb5684296108fb32600c00cde305b2cd" +"checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" "checksum time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" "checksum tinyvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "53953d2d3a5ad81d9f844a32f14ebb121f50b650cd59d0ee2a07cf13c617efed" @@ -1636,9 +1888,12 @@ dependencies = [ "checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977" +"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" +"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" "checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" "checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" "checksum vcpkg 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" +"checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" "checksum version-sync 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382f6877399646e1b88f4b89813b4577147fa924464317378eb39c280d1e9e4c" "checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" "checksum walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" diff --git a/dhall/Cargo.toml b/dhall/Cargo.toml index 9a30d24..ecb68eb 100644 --- a/dhall/Cargo.toml +++ b/dhall/Cargo.toml @@ -11,6 +11,10 @@ edition = "2018" build = "build.rs" include = ["src/**/*", "README.md", "build.rs"] +[[test]] +name = "spec" +harness = false + [dependencies] annotate-snippets = "0.7.0" hex = "0.4.2" @@ -31,9 +35,12 @@ url = "2.1" reqwest = { version = "0.10", features = ["blocking"] } [dev-dependencies] +# Latest master allows tests to be run in parallel. +libtest-mimic = { version = "0.2.0", git = "https://github.com/LukasKalbertodt/libtest-mimic" } pretty_assertions = "0.6.1" -version-sync = "0.9" rand = "0.7" +version-sync = "0.9" +walkdir = "2" [build-dependencies] walkdir = "2" diff --git a/dhall/src/tests.rs b/dhall/src/tests.rs index 08a4a4a..c9ba377 100644 --- a/dhall/src/tests.rs +++ b/dhall/src/tests.rs @@ -356,5 +356,5 @@ mod spec { } // See build.rs - include!(concat!(env!("OUT_DIR"), "/spec_tests.rs")); + // include!(concat!(env!("OUT_DIR"), "/spec_tests.rs")); } diff --git a/dhall/tests/spec.rs b/dhall/tests/spec.rs new file mode 100644 index 0000000..3521f6a --- /dev/null +++ b/dhall/tests/spec.rs @@ -0,0 +1,686 @@ +use std::env; +use std::ffi::OsString; +use std::fs::{create_dir_all, read_to_string, File}; +use std::io::{Read, BufRead, BufReader, Write}; +use std::path::{Path, PathBuf}; +use std::rc::Rc; +use std::fmt::Display; + +use walkdir::WalkDir; +use libtest_mimic::{Arguments, Outcome, Test, run_tests}; +#[cfg(not(test))] +use assert_eq as assert_eq_pretty; +#[cfg(test)] +use pretty_assertions::assert_eq as assert_eq_pretty; + +use dhall::error::{ErrorKind, Result}; +use dhall::syntax::{binary, Expr}; +use dhall::{Normalized, Parsed, Resolved, Typed}; + +macro_rules! assert_eq_display { + ($left:expr, $right:expr) => {{ + match (&$left, &$right) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + panic!( + r#"assertion failed: `(left == right)` + left: `{}`, +right: `{}`"#, + left_val, right_val + ) + } + } + } + }}; +} + +/// Wrapper around string slice that makes debug output `{:?}` to print string same way as `{}`. +/// Used in different `assert*!` macros in combination with `pretty_assertions` crate to make +/// test failures to show nice diffs. +#[derive(PartialEq, Eq)] +#[doc(hidden)] +pub struct PrettyString(String); + +/// Make diff to display string as multi-line string +impl std::fmt::Debug for PrettyString { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str(&self.0) + } +} + +macro_rules! assert_eq_pretty_str { + ($left:expr, $right:expr) => { + assert_eq_pretty!( + PrettyString($left.to_string()), + PrettyString($right.to_string()) + ); + }; +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum FileType { + /// Dhall source file + Text, + /// Dhall binary file + Binary, + /// Text file with hash + Hash, + /// Text file with expected text output + UI, +} + +#[derive(Clone)] +enum TestFile { + Source(String), + Binary(String), + UI(String), +} + +impl FileType { + fn to_ext(self) -> &'static str { + match self { + FileType::Text => "dhall", + FileType::Binary => "dhallb", + FileType::Hash => "hash", + FileType::UI => "txt", + } + } + fn constructor(self) -> &'static str { + match self { + FileType::Text => "TestFile::Source", + FileType::Binary => "TestFile::Binary", + FileType::Hash => "TestFile::Binary", + FileType::UI => "TestFile::UI", + } + } + fn construct(self, path: &str) -> TestFile { + match self { + FileType::Text => TestFile::Source(format!("{}.{}", path, self.to_ext())), + FileType::Binary => TestFile::Binary(format!("{}.{}", path, self.to_ext())), + FileType::Hash => TestFile::Binary(format!("{}.{}", path, self.to_ext())), + FileType::UI => TestFile::UI(format!("{}.{}", path, self.to_ext())), + } + } +} + +impl TestFile { + pub fn path(&self) -> PathBuf { + match self { + TestFile::Source(path) + | TestFile::Binary(path) + | TestFile::UI(path) => PathBuf::from("dhall").join(path), + } + } + + /// Parse the target file + pub fn parse(&self) -> Result<Parsed> { + match self { + TestFile::Source(_) => Parsed::parse_file(&self.path()), + TestFile::Binary(_) => Parsed::parse_binary_file(&self.path()), + TestFile::UI(_) => panic!("Can't parse a UI test file"), + } + } + /// Parse and resolve the target file + pub fn resolve(&self) -> Result<Resolved> { + Ok(self.parse()?.resolve()?) + } + /// Parse, resolve and tck the target file + pub fn typecheck(&self) -> Result<Typed> { + Ok(self.resolve()?.typecheck()?) + } + /// Parse, resolve, tck and normalize the target file + pub fn normalize(&self) -> Result<Normalized> { + Ok(self.typecheck()?.normalize()) + } + + /// If UPDATE_TEST_FILES=1, we overwrite the output files with our own output. + fn force_update() -> bool { + env::var("UPDATE_TEST_FILES") == Ok("1".to_string()) + } + /// Write the provided expression to the pointed file. + fn write_expr(&self, expr: impl Into<Expr>) -> Result<()> { + let expr = expr.into(); + let path = self.path(); + create_dir_all(path.parent().unwrap())?; + let mut file = File::create(path)?; + match self { + TestFile::Source(_) => { + writeln!(file, "{}", expr)?; + } + TestFile::Binary(_) => { + let expr_data = binary::encode(&expr)?; + file.write_all(&expr_data)?; + } + TestFile::UI(_) => panic!("Can't write an expression to a UI file"), + } + Ok(()) + } + /// Write the provided string to the pointed file. + fn write_ui(&self, x: impl Display) -> Result<()> { + match self { + TestFile::UI(_) => {} + _ => panic!("Can't write a ui string to a dhall file"), + } + let path = self.path(); + create_dir_all(path.parent().unwrap())?; + let mut file = File::create(path)?; + writeln!(file, "{}", x)?; + Ok(()) + } + + /// Check that the provided expression matches the file contents. + pub fn compare(&self, expr: impl Into<Expr>) -> Result<()> { + let expr = expr.into(); + if !self.path().is_file() { + return self.write_expr(expr); + } + + let expected = self.parse()?.to_expr(); + if expr != expected { + if Self::force_update() { + self.write_expr(expr)?; + } else { + assert_eq_display!(expr, expected); + } + } + Ok(()) + } + /// Check that the provided expression matches the file contents. + pub fn compare_debug(&self, expr: impl Into<Expr>) -> Result<()> { + let expr = expr.into(); + if !self.path().is_file() { + return self.write_expr(expr); + } + + let expected = self.parse()?.to_expr(); + if expr != expected { + if Self::force_update() { + self.write_expr(expr)?; + } else { + assert_eq_pretty!(expr, expected); + } + } + Ok(()) + } + /// Check that the provided expression matches the file contents. + pub fn compare_binary(&self, expr: impl Into<Expr>) -> Result<()> { + let expr = expr.into(); + match self { + TestFile::Binary(_) => {} + _ => panic!("This is not a binary file"), + } + if !self.path().is_file() { + return self.write_expr(expr); + } + + let expr_data = binary::encode(&expr)?; + let expected_data = { + let mut data = Vec::new(); + File::open(&self.path())?.read_to_end(&mut data)?; + data + }; + + // Compare bit-by-bit + if expr_data != expected_data { + if Self::force_update() { + self.write_expr(expr)?; + } else { + use serde_cbor::de::from_slice; + use serde_cbor::value::Value; + // Pretty-print difference + assert_eq_pretty!( + from_slice::<Value>(&expr_data).unwrap(), + from_slice::<Value>(&expected_data).unwrap() + ); + // If difference was not visible in the cbor::Nir, compare normally. + assert_eq!(expr_data, expected_data); + } + } + Ok(()) + } + /// Check that the provided string matches the file contents. Writes to the corresponding file + /// if it is missing. + pub fn compare_ui(&self, x: impl Display) -> Result<()> { + if !self.path().is_file() { + return self.write_ui(x); + } + + let expected = read_to_string(self.path())?; + let msg = format!("{}\n", x); + if msg != expected { + if Self::force_update() { + self.write_ui(x)?; + } else { + assert_eq_pretty_str!(expected, msg); + } + } + Ok(()) + } +} + +#[derive(Clone)] +struct TestFeature { + /// Name of the module, used in the output of `cargo test` + module_name: &'static str, + /// Directory containing the tests files, relative to the base tests directory + directory: &'static str, + /// Relevant variant of `dhall::tests::Test` + variant: Rc<dyn Fn(TestFile, TestFile) -> SpecTest>, + /// Given a file name, whether to only include it in release tests + too_slow_path: Rc<dyn Fn(&str) -> bool>, + /// Given a file name, whether to exclude it + exclude_path: Rc<dyn Fn(&str) -> bool>, + /// Type of the input file + input_type: FileType, + /// Type of the output file, if any + output_type: Option<FileType>, +} + +#[derive(Clone)] +enum SpecTest { + ParserSuccess(TestFile, TestFile), + ParserFailure(TestFile, TestFile), + Printer(TestFile, TestFile), + BinaryEncoding(TestFile, TestFile), + BinaryDecodingSuccess(TestFile, TestFile), + BinaryDecodingFailure(TestFile, TestFile), + ImportSuccess(TestFile, TestFile), + ImportFailure(TestFile, TestFile), + SemanticHash(TestFile, TestFile), + TypeInferenceSuccess(TestFile, TestFile), + TypeInferenceFailure(TestFile, TestFile), + Normalization(TestFile, TestFile), + AlphaNormalization(TestFile, TestFile), +} + +fn define_features() -> Vec<TestFeature> { + let default_feature = TestFeature { + module_name: "", + directory: "", + variant: Rc::new(|_, _| panic!()), + too_slow_path: Rc::new(|_path: &str| false), + exclude_path: Rc::new(|_path: &str| false), + input_type: FileType::Text, + output_type: None, + }; + + #[allow(clippy::nonminimal_bool)] + vec![ + TestFeature { + module_name: "parser_success", + directory: "parser/success/", + variant: Rc::new(SpecTest::ParserSuccess), + too_slow_path: Rc::new(|path: &str| path == "largeExpression"), + exclude_path: Rc::new(|path: &str| { + false + // Pretty sure the test is incorrect + || path == "unit/import/urls/quotedPathFakeUrlEncode" + }), + output_type: Some(FileType::Binary), + ..default_feature.clone() + }, + TestFeature { + module_name: "parser_failure", + directory: "parser/failure/", + variant: Rc::new(SpecTest::ParserFailure), + output_type: Some(FileType::UI), + ..default_feature.clone() + }, + TestFeature { + module_name: "printer", + directory: "parser/success/", + variant: Rc::new(SpecTest::Printer), + too_slow_path: Rc::new(|path: &str| path == "largeExpression"), + output_type: Some(FileType::UI), + ..default_feature.clone() + }, + TestFeature { + module_name: "binary_encoding", + directory: "parser/success/", + variant: Rc::new(SpecTest::BinaryEncoding), + too_slow_path: Rc::new(|path: &str| path == "largeExpression"), + exclude_path: Rc::new(|path: &str| { + false + // Pretty sure the test is incorrect + || path == "unit/import/urls/quotedPathFakeUrlEncode" + // See https://github.com/pyfisch/cbor/issues/109 + || path == "double" + || path == "unit/DoubleLitExponentNoDot" + || path == "unit/DoubleLitSecretelyInt" + }), + output_type: Some(FileType::Binary), + ..default_feature.clone() + }, + TestFeature { + module_name: "binary_decoding_success", + directory: "binary-decode/success/", + variant: Rc::new(SpecTest::BinaryDecodingSuccess), + exclude_path: Rc::new(|path: &str| { + false + // We don't support bignums + || path == "unit/IntegerBigNegative" + || path == "unit/IntegerBigPositive" + || path == "unit/NaturalBig" + }), + input_type: FileType::Binary, + output_type: Some(FileType::Text), + ..default_feature.clone() + }, + TestFeature { + module_name: "binary_decoding_failure", + directory: "binary-decode/failure/", + variant: Rc::new(SpecTest::BinaryDecodingFailure), + input_type: FileType::Binary, + output_type: Some(FileType::UI), + ..default_feature.clone() + }, + TestFeature { + module_name: "import_success", + directory: "import/success/", + variant: Rc::new(SpecTest::ImportSuccess), + exclude_path: Rc::new(|path: &str| { + false + // TODO: import hash + || path == "hashFromCache" + // TODO: the standard does not respect https://tools.ietf.org/html/rfc3986#section-5.2 + || path == "unit/asLocation/RemoteCanonicalize4" + // TODO: import headers + || path == "customHeaders" + || path == "headerForwarding" + || path == "noHeaderForwarding" + }), + output_type: Some(FileType::Text), + ..default_feature.clone() + }, + TestFeature { + module_name: "import_failure", + directory: "import/failure/", + variant: Rc::new(SpecTest::ImportFailure), + exclude_path: Rc::new(|path: &str| { + false + // TODO: import headers + || path == "customHeadersUsingBoundVariable" + }), + output_type: Some(FileType::UI), + ..default_feature.clone() + }, + TestFeature { + module_name: "semantic_hash", + directory: "semantic-hash/success/", + variant: Rc::new(SpecTest::SemanticHash), + exclude_path: Rc::new(|path: &str| { + false + // We don't support bignums + || path == "simple/integerToDouble" + // See https://github.com/pyfisch/cbor/issues/109 + || path == "prelude/Integer/toDouble/0" + || path == "prelude/Integer/toDouble/1" + || path == "prelude/Natural/toDouble/0" + }), + output_type: Some(FileType::Hash), + ..default_feature.clone() + }, + TestFeature { + module_name: "beta_normalize", + directory: "normalization/success/", + variant: Rc::new(SpecTest::Normalization), + too_slow_path: Rc::new(|path: &str| path == "remoteSystems"), + exclude_path: Rc::new(|path: &str| { + false + // Cannot typecheck + || path == "unit/Sort" + // We don't support bignums + || path == "simple/integerToDouble" + // TODO: fix Double/show + || path == "prelude/JSON/number/1" + }), + output_type: Some(FileType::Text), + ..default_feature.clone() + }, + TestFeature { + module_name: "alpha_normalize", + directory: "alpha-normalization/success/", + variant: Rc::new(SpecTest::AlphaNormalization), + exclude_path: Rc::new(|path: &str| { + // This test is designed to not typecheck + path == "unit/FunctionNestedBindingXXFree" + }), + output_type: Some(FileType::Text), + ..default_feature.clone() + }, + TestFeature { + module_name: "type_inference_success", + directory: "type-inference/success/", + variant: Rc::new(SpecTest::TypeInferenceSuccess), + too_slow_path: Rc::new(|path: &str| path == "prelude"), + output_type: Some(FileType::Text), + ..default_feature.clone() + }, + TestFeature { + module_name: "type_inference_failure", + directory: "type-inference/failure/", + variant: Rc::new(SpecTest::TypeInferenceFailure), + exclude_path: Rc::new(|path: &str| { + false + // TODO: enable free variable checking + || path == "unit/MergeHandlerFreeVar" + }), + output_type: Some(FileType::UI), + ..default_feature + }, + ] +} + +fn run_test_or_panic(test: &SpecTest) { + let res = if env::var("CI_GRCOV").is_ok() { + let test: SpecTest = test.clone(); + // Augment stack size when running with 0 inlining to avoid overflows + std::thread::Builder::new() + .stack_size(128 * 1024 * 1024) + .spawn(move || run_test(&test)) + .unwrap() + .join() + .unwrap() + } else { + run_test(test) + }; + match res { + Ok(_) => {} + Err(e) => panic!(e.to_string()), + } +} + +fn run_test(test: &SpecTest) -> Result<()> { + use self::SpecTest::*; + // Setup current directory to the root of the repository. Important for `as Location` tests. + env::set_current_dir( + PathBuf::from(env!("CARGO_MANIFEST_DIR")).parent().unwrap(), + )?; + // Set environment variable for import tests. + env::set_var("DHALL_TEST_VAR", "6 * 7"); + + match test { + ParserSuccess(expr, expected) => { + let expr = expr.parse()?; + // This exercices both parsing and binary decoding + expected.compare_debug(expr)?; + } + ParserFailure(expr, expected) => { + use std::io; + let err = expr.parse().unwrap_err(); + match err.kind() { + ErrorKind::Parse(_) => {} + ErrorKind::IO(e) if e.kind() == io::ErrorKind::InvalidData => {} + e => panic!("Expected parse error, got: {:?}", e), + } + expected.compare_ui(err)?; + } + BinaryEncoding(expr, expected) => { + let expr = expr.parse()?; + expected.compare_binary(expr)?; + } + BinaryDecodingSuccess(expr, expected) => { + let expr = expr.parse()?; + expected.compare_debug(expr)?; + } + BinaryDecodingFailure(expr, expected) => { + let err = expr.parse().unwrap_err(); + expected.compare_ui(err)?; + } + Printer(expr, expected) => { + let parsed = expr.parse()?; + // Round-trip pretty-printer + let reparsed = Parsed::parse_str(&parsed.to_string())?; + assert_eq!(reparsed, parsed); + expected.compare_ui(parsed)?; + } + ImportSuccess(expr, expected) => { + let expr = expr.normalize()?; + expected.compare(expr)?; + } + ImportFailure(expr, expected) => { + let err = expr.resolve().unwrap_err(); + expected.compare_ui(err)?; + } + SemanticHash(expr, expected) => { + let expr = expr.normalize()?.to_expr_alpha(); + let hash = hex::encode(expr.hash()?); + expected.compare_ui(format!("sha256:{}", hash))?; + } + TypeInferenceSuccess(expr, expected) => { + let ty = expr.typecheck()?.get_type()?; + expected.compare(ty)?; + } + TypeInferenceFailure(expr, expected) => { + let err = expr.typecheck().unwrap_err(); + expected.compare_ui(err)?; + } + Normalization(expr, expected) => { + let expr = expr.normalize()?; + expected.compare(expr)?; + } + AlphaNormalization(expr, expected) => { + let expr = expr.normalize()?.to_expr_alpha(); + expected.compare(expr)?; + } + } + + Ok(()) +} + +fn dhall_files_in_dir<'a>( + dir: &'a Path, + take_ab_suffix: bool, + filetype: FileType, +) -> impl Iterator<Item = (String, String)> + 'a { + WalkDir::new(dir) + .into_iter() + .filter_map(|e| e.ok()) + .filter_map(move |path| { + let path = path.path().strip_prefix(dir).unwrap(); + let ext = path.extension()?; + if *ext != OsString::from(filetype.to_ext()) { + return None; + } + let path = path.to_string_lossy(); + let path = &path[..path.len() - 1 - ext.len()]; + let path = if take_ab_suffix && &path[path.len() - 1..] != "A" { + return None; + } else if take_ab_suffix { + path[..path.len() - 1].to_owned() + } else { + path.to_owned() + }; + // Transform path into a valid Rust identifier + let name = path.replace("/", "_").replace("-", "_"); + Some((name, path)) + }) +} + +fn make_test_module( + tests: &mut Vec<Test<SpecTest>>, + base_paths: &[&Path], + feature: TestFeature, +) -> std::io::Result<()> { + let take_ab_suffix = feature.output_type.is_some() + && (feature.output_type != Some(FileType::UI) + || feature.module_name == "printer"); + let input_suffix = if take_ab_suffix { "A" } else { "" }; + let output_suffix = if take_ab_suffix { "B" } else { "" }; + + for base_path in base_paths { + let tests_dir = base_path.join(feature.directory); + for (name, path) in + dhall_files_in_dir(&tests_dir, take_ab_suffix, feature.input_type) + { + if (feature.exclude_path)(&path) { + continue; + } + if (feature.too_slow_path)(&path) { + #[cfg(debug_assertions)] + continue; + } + let path = tests_dir.join(path); + let path = path.to_string_lossy(); + + let input = feature + .input_type + .construct(&format!("{}{}", path, input_suffix)); + let output = match feature.output_type { + None => None, + Some(output_type @ FileType::UI) => { + // All ui outputs are in the local `tests/` directory. + let path = PathBuf::from("tests/").join( + PathBuf::from(path.as_ref()) + .strip_prefix(base_path) + .unwrap(), + ); + let path = path.to_str().unwrap(); + let output = output_type + .construct(&format!("{}{}", path, output_suffix)); + Some(output) + } + Some(output_type) => { + let output = output_type + .construct(&format!("{}{}", path, output_suffix)); + Some(output) + } + }; + + let test = match output { + None => panic!(), + Some(output) => { + (feature.variant)(input, output) + } + }; + tests.push(Test { + name: format!("{}::{}", feature.module_name, name), + kind: "".into(), + is_ignored: false, + is_bench: false, + data: test, + }); + } + } + Ok(()) +} + +fn generate_tests() -> Vec<Test<SpecTest>> { + let spec_tests_dirs = + vec![Path::new("../dhall-lang/tests/"), Path::new("tests/")]; + + let features = define_features(); + + let mut tests = Vec::new(); + for feature in features { + make_test_module(&mut tests, &spec_tests_dirs, feature).unwrap(); + } + tests +} + +fn main() { + let tests = generate_tests(); + + let args = Arguments::from_args(); + run_tests(&args, tests, |test| { run_test_or_panic(&test.data); Outcome::Passed }).exit(); +} |