From e613bd8a8c931546fd10ef50338b5a5affa1b3c2 Mon Sep 17 00:00:00 2001 From: Joseph Frazer Date: Wed, 4 Mar 2020 15:31:20 -0500 Subject: [PATCH] [DEV-7081] Add options to tameld We want to add an option to set the output file to the linker so we do not need to redirect output to awk any longer. This also adds integration tests for tameld. --- build-aux/Makefile.am | 2 +- tamer/Cargo.lock | 238 ++++++++++++++++++++++++++++++++++ tamer/Cargo.toml | 7 + tamer/src/bin/tameld.rs | 215 +++++++++++++++++++++++++++++- tamer/src/ld/poc.rs | 15 +-- tamer/tests/data/empty.xmlo | 0 tamer/tests/data/invalid.xmlo | 1 + tamer/tests/tameld.rs | 89 +++++++++++++ 8 files changed, 554 insertions(+), 13 deletions(-) create mode 100644 tamer/tests/data/empty.xmlo create mode 100644 tamer/tests/data/invalid.xmlo create mode 100644 tamer/tests/tameld.rs 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(()) +}