diff --git a/build-aux/Makefile.am b/build-aux/Makefile.am index e8ab2664..0cd1de71 100644 --- a/build-aux/Makefile.am +++ b/build-aux/Makefile.am @@ -133,7 +133,7 @@ strip: $(dest_standalone_strip) ui/package.strip.js %.xmle: %.xmlo $(path_tame)/.rev-xmle $(TAME_TS) @echo "WARNING: using WIP proof-of-concept linker!" - set -o pipefail; $(path_tame)/tamer/target/release/tameld $< | awk '/^ $@ + $(path_tame)/tamer/target/release/tameld -o $@ $< %.js: %.xmle $(TAME_TS) $(TAME) standalone $< $@ diff --git a/tamer/Cargo.lock b/tamer/Cargo.lock index 44b4f190..4b705f87 100644 --- a/tamer/Cargo.lock +++ b/tamer/Cargo.lock @@ -1,5 +1,29 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "assert_cmd" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "escargot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "predicates 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "predicates-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "predicates-tree 1.0.0 (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" + [[package]] name = "bumpalo" version = "2.6.0" @@ -10,11 +34,38 @@ name = "byteorder" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "difference" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "escargot" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "exitcode" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fixedbitset" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "float-cmp" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fxhash" version = "0.2.1" @@ -23,11 +74,42 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "getopts" +version = "0.2.21" +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 = "itoa" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memchr" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num-traits" +version = "0.2.11" +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 = "ordermap" version = "0.3.5" @@ -42,6 +124,40 @@ dependencies = [ "ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "predicates" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "float-cmp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "normalize-line-endings 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "predicates-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "predicates-core" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "predicates-tree" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "predicates-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "treeline 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quick-xml" version = "0.17.0" @@ -50,23 +166,145 @@ dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quote" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.16" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ryu" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tamer" version = "0.0.0" dependencies = [ + "assert_cmd 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "exitcode 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "predicates 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "quick-xml 0.17.0 (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" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "treeline" +version = "0.1.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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [metadata] +"checksum aho-corasick 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e63fd144e18ba274ae7095c0197a870a7b9468abc801dd62f190d80817d2ec" +"checksum assert_cmd 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7ac5c260f75e4e4ba87b7342be6edcecbcb3eb6741a0507fda7ad115845cc65" +"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" "checksum bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" +"checksum escargot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "19db1f7e74438642a5018cdf263bb1325b2e792f02dd0a3ca6d6c0f0d7b1d5a5" +"checksum exitcode 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193" "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" +"checksum float-cmp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da62c4f1b81918835a8c6a484a397775fff5953fe83529afd51b05f5c6a6617d" "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +"checksum getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +"checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +"checksum normalize-line-endings 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" +"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" "checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" +"checksum predicates 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "347a1b6f0b21e636bc9872fb60b83b8e185f6f5516298b8238699f7f9a531030" +"checksum predicates-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06075c3a3e92559ff8929e7a280684489ea27fe44805174c3ebd9328dcb37178" +"checksum predicates-tree 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e63c4859013b38a76eca2414c64911fba30def9e3202ac461a2d22831220124" +"checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" "checksum quick-xml 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcdba8c8d71275493d966ef052a88726ac8590c15a09968b32158205c672ef" +"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +"checksum regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" +"checksum regex-syntax 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "1132f845907680735a84409c3bebc64d1364a5683ffbce899550cd09d5eaefc1" +"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" +"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" +"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" +"checksum serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" +"checksum syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" +"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +"checksum treeline 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" +"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" diff --git a/tamer/Cargo.toml b/tamer/Cargo.toml index 64519f9c..7d27fd77 100644 --- a/tamer/Cargo.toml +++ b/tamer/Cargo.toml @@ -22,6 +22,10 @@ lto = true # in a release. lto = true +[dev-dependencies] +assert_cmd = "0.10" +predicates = "1" + [dependencies] bumpalo = ">= 2.6.0" # used by petgraph @@ -29,3 +33,6 @@ fixedbitset = ">= 0.1" fxhash = ">= 0.2.1" petgraph = ">= 0.4.13" quick-xml = ">= 0.17.0" +getopts = "0.2" +exitcode = "1.1.2" + diff --git a/tamer/src/bin/tameld.rs b/tamer/src/bin/tameld.rs index 40f51bcd..c06aa1ce 100644 --- a/tamer/src/bin/tameld.rs +++ b/tamer/src/bin/tameld.rs @@ -24,9 +24,220 @@ extern crate tamer; +use getopts::{Fail, Options}; +use std::env; use std::error::Error; use tamer::ld::poc; -pub fn main() -> Result<(), Box> { - poc::main() +/// Types of commands +enum Command { + Link(String, String), + Usage, +} + +/// Entrypoint for the linker +pub fn main() -> Result<(), Box> { + let args: Vec = env::args().collect(); + let program = &args[0]; + let opts = get_opts(); + let usage = opts.usage(&format!("Usage: {} -o OUTPUT FILE", program)); + + match parse_options(opts, args) { + Ok(Command::Link(input, output)) => poc::main(&input, &output), + Ok(Command::Usage) => { + println!("{}", usage); + std::process::exit(exitcode::OK); + } + Err(e) => { + eprintln!("{}", e); + println!("{}", usage); + std::process::exit(exitcode::USAGE); + } + } +} + +/// Get 'Options' +/// +/// ``` +/// use getopts::Options; +/// +/// let opts = get_opts(); +/// ``` +fn get_opts() -> Options { + let mut opts = Options::new(); + opts.optopt("o", "output", "set output file name", "NAME"); + opts.optflag("h", "help", "print this help menu"); + + opts +} + +/// Option parser +fn parse_options(opts: Options, args: Vec) -> Result { + let matches = match opts.parse(&args[1..]) { + Ok(m) => m, + Err(f) => { + return Err(f); + } + }; + + if matches.opt_present("h") { + return Ok(Command::Usage); + } + + let input = match matches.free.len() { + 0 => return Err(Fail::OptionMissing(String::from("FILE"))), + 1 => matches.free[0].clone(), + _ => return Err(Fail::UnrecognizedOption(matches.free[1].clone())), + }; + + let output = match matches.opt_str("o") { + Some(m) => m, + None => { + return Err(Fail::OptionMissing(String::from("-o OUTPUT"))); + } + }; + + Ok(Command::Link(input, output)) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn parse_options_help() { + let opts = get_opts(); + let result = parse_options( + opts, + vec![String::from("program"), String::from("-h")], + ); + + match result { + Ok(Command::Usage) => {} + _ => panic!("Long help option did not parse"), + } + } + + #[test] + fn parse_options_help_long() { + let opts = get_opts(); + let result = parse_options( + opts, + vec![String::from("program"), String::from("--help")], + ); + + match result { + Ok(Command::Usage) => {} + _ => panic!("Help option did not parse"), + } + } + + #[test] + fn parse_options_invalid() { + let opts = get_opts(); + let result = parse_options( + opts, + vec![String::from("program"), String::from("-q")], + ); + + match result { + Err(Fail::UnrecognizedOption(_)) => {} + _ => panic!("Invalid option not caught"), + } + } + + #[test] + fn parse_options_missing_input() { + let opts = get_opts(); + let result = parse_options(opts, vec![String::from("program")]); + + match result { + Err(Fail::OptionMissing(message)) => { + assert_eq!("FILE", message); + } + _ => panic!("Missing input not caught"), + } + } + + #[test] + fn parse_options_missing_output() { + let opts = get_opts(); + let result = parse_options( + opts, + vec![String::from("program"), String::from("foo")], + ); + + match result { + Err(Fail::OptionMissing(message)) => { + assert_eq!("-o OUTPUT", message); + } + _ => panic!("Missing output not caught"), + } + } + + #[test] + fn parse_options_too_many_args() { + let opts = get_opts(); + let result = parse_options( + opts, + vec![ + String::from("program"), + String::from("foo"), + String::from("-o"), + String::from("bar"), + String::from("baz"), + ], + ); + + match result { + Err(Fail::UnrecognizedOption(message)) => { + assert_eq!("baz", message); + } + _ => panic!("Extra option not caught"), + } + } + + #[test] + fn parse_options_valid() { + let opts = get_opts(); + let result = parse_options( + opts, + vec![ + String::from("program"), + String::from("foo"), + String::from("-o"), + String::from("bar"), + ], + ); + + match result { + Ok(Command::Link(infile, outfile)) => { + assert_eq!("foo", infile); + assert_eq!("bar", outfile); + } + _ => panic!("Unexpected result"), + } + } + + #[test] + fn parse_options_valid_long() { + let opts = get_opts(); + let result = parse_options( + opts, + vec![ + String::from("program"), + String::from("foo"), + String::from("--output"), + String::from("bar"), + ], + ); + + match result { + Ok(Command::Link(infile, outfile)) => { + assert_eq!("foo", infile); + assert_eq!("bar", outfile); + } + _ => panic!("Unexpected result"), + } + } } diff --git a/tamer/src/ld/poc.rs b/tamer/src/ld/poc.rs index 53f9f7bb..645a0988 100644 --- a/tamer/src/ld/poc.rs +++ b/tamer/src/ld/poc.rs @@ -30,19 +30,17 @@ use std::convert::TryInto; use std::error::Error; use std::fs; use std::io::BufReader; -use std::io::Cursor; type LinkerAsg<'i> = DefaultAsg<'i, global::ProgIdentSize>; type LinkerObjectRef = ObjectRef; -pub fn main() -> Result<(), Box> { +pub fn main(package_path: &str, output: &str) -> Result<(), Box> { let mut pkgs_seen: FxHashSet = Default::default(); let mut fragments: FxHashMap<&str, String> = Default::default(); let mut depgraph = LinkerAsg::with_capacity(65536, 65536); let mut roots = Vec::new(); let interner = DefaultInterner::new(); - let package_path = std::env::args().nth(1).expect("Missing argument"); let abs_path = fs::canonicalize(package_path).unwrap(); println!("WARNING: This is proof-of-concept; do not use!"); @@ -84,6 +82,7 @@ pub fn main() -> Result<(), Box> { &mut sorted, name.expect("missing root package name"), relroot.expect("missing root package relroot"), + output, )?; Ok(()) @@ -305,6 +304,7 @@ fn output_xmle<'a, 'i, I: Interner<'i>>( sorted: &mut Sections<'a, 'i>, name: &'i Symbol<'i>, relroot: String, + output: &str, ) -> Result<(), Box> { if !sorted.map.is_empty() { sorted.map.push_head(get_interner_value( @@ -332,17 +332,12 @@ fn output_xmle<'a, 'i, I: Interner<'i>>( )); } - let writer = Cursor::new(Vec::new()); - let mut xmle_writer = XmleWriter::new(writer); + let file = fs::File::create(output)?; + let mut xmle_writer = XmleWriter::new(file); xmle_writer .write(&sorted, name, &relroot) .expect("Could not write xmle output"); - print!( - "{}", - String::from_utf8(xmle_writer.into_inner().into_inner())? - ); - Ok(()) } diff --git a/tamer/tests/data/empty.xmlo b/tamer/tests/data/empty.xmlo new file mode 100644 index 00000000..e69de29b diff --git a/tamer/tests/data/invalid.xmlo b/tamer/tests/data/invalid.xmlo new file mode 100644 index 00000000..dd52bf93 --- /dev/null +++ b/tamer/tests/data/invalid.xmlo @@ -0,0 +1 @@ +This is not valid XML! diff --git a/tamer/tests/tameld.rs b/tamer/tests/tameld.rs new file mode 100644 index 00000000..585d25fe --- /dev/null +++ b/tamer/tests/tameld.rs @@ -0,0 +1,89 @@ +// Copyright (C) 2014-2019 Ryan Specialty Group, LLC. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use assert_cmd::prelude::*; +use predicates::prelude::*; +use std::process::Command; + +#[test] +fn link_invalid_argument() -> Result<(), Box> { + let mut cmd = Command::cargo_bin("tameld")?; + cmd.arg("-q"); + cmd.assert() + .failure() + .code(exitcode::USAGE) + .stderr(predicate::str::contains("Unrecognized option:")); + + Ok(()) +} + +#[test] +fn link_missing_input_file() -> Result<(), Box> { + let mut cmd = Command::cargo_bin("tameld")?; + cmd.assert() + .failure() + .code(exitcode::USAGE) + .stderr(predicate::str::contains("FILE")); + + Ok(()) +} + +#[test] +fn link_missing_output_file() -> Result<(), Box> { + let mut cmd = Command::cargo_bin("tameld")?; + cmd.arg("foobar"); + cmd.assert() + .failure() + .code(exitcode::USAGE) + .stderr(predicate::str::contains("-o OUTPUT")); + + Ok(()) +} + +#[test] +fn link_input_file_does_not_exist() -> Result<(), Box> { + let mut cmd = Command::cargo_bin("tameld")?; + cmd.arg("foobar"); + cmd.arg("-o").arg("tests/data/test-output.xmle"); + cmd.assert() + .failure() + .stderr(predicate::str::contains("No such file or directory")); + + Ok(()) +} + +#[test] +fn link_empty_input_file() -> Result<(), Box> { + let mut cmd = Command::cargo_bin("tameld")?; + cmd.arg("tests/data/empty.xmlo"); + cmd.arg("-o").arg("tests/data/test-output.xmle"); + cmd.assert() + .failure() + .stderr(predicate::str::contains("stack overflow")); // uh oh + + Ok(()) +} + +#[test] +fn link_invalid_input_file() -> Result<(), Box> { + let mut cmd = Command::cargo_bin("tameld")?; + cmd.arg("tests/data/invalid.xmlo"); + cmd.arg("-o").arg("tests/data/test-output.xmle"); + cmd.assert() + .failure() + .stderr(predicate::str::contains("stack overflow")); // uh oh + + Ok(()) +}