Mike Gerwitz

Activist for User Freedom

aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoseph Frazer <joseph.frazer@ryansg.com>2020-03-04 15:31:20 -0500
committerJoseph Frazer <joseph.frazer@ryansg.com>2020-03-06 09:41:55 -0500
commite613bd8a8c931546fd10ef50338b5a5affa1b3c2 (patch)
tree0a81c9d7406830068fa4273762897c5c9353191a
parent777494a6026e6eabff9ca9f05f00aa92e2f58c3d (diff)
downloadtame-e613bd8a8c931546fd10ef50338b5a5affa1b3c2.tar.gz
tame-e613bd8a8c931546fd10ef50338b5a5affa1b3c2.tar.bz2
tame-e613bd8a8c931546fd10ef50338b5a5affa1b3c2.zip
[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.
-rw-r--r--build-aux/Makefile.am2
-rw-r--r--tamer/Cargo.lock238
-rw-r--r--tamer/Cargo.toml7
-rw-r--r--tamer/src/bin/tameld.rs213
-rw-r--r--tamer/src/ld/poc.rs15
-rw-r--r--tamer/tests/data/empty.xmlo0
-rw-r--r--tamer/tests/data/invalid.xmlo1
-rw-r--r--tamer/tests/tameld.rs89
8 files changed, 553 insertions, 12 deletions
diff --git a/build-aux/Makefile.am b/build-aux/Makefile.am
index e8ab266..0cd1de7 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 '/^<package/{p=1};p' > $@
+ $(path_tame)/tamer/target/release/tameld -o $@ $<
%.js: %.xmle
$(TAME_TS)
$(TAME) standalone $< $@
diff --git a/tamer/Cargo.lock b/tamer/Cargo.lock
index 44b4f19..4b705f8 100644
--- a/tamer/Cargo.lock
+++ b/tamer/Cargo.lock
@@ -1,6 +1,30 @@
# 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -11,11 +35,38 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -24,11 +75,42 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -43,6 +125,40 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -51,22 +167,144 @@ dependencies = [
]
[[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 64519f9..7d27fd7 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 40f51bc..c06aa1c 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;
+/// Types of commands
+enum Command {
+ Link(String, String),
+ Usage,
+}
+
+/// Entrypoint for the linker
pub fn main() -> Result<(), Box<dyn Error>> {
- poc::main()
+ let args: Vec<String> = 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<String>) -> Result<Command, Fail> {
+ 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 53f9f7b..645a098 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<global::ProgIdentSize>;
-pub fn main() -> Result<(), Box<dyn Error>> {
+pub fn main(package_path: &str, output: &str) -> Result<(), Box<dyn Error>> {
let mut pkgs_seen: FxHashSet<String> = 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<dyn Error>> {
&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<dyn Error>> {
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 0000000..e69de29
--- /dev/null
+++ b/tamer/tests/data/empty.xmlo
diff --git a/tamer/tests/data/invalid.xmlo b/tamer/tests/data/invalid.xmlo
new file mode 100644
index 0000000..dd52bf9
--- /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 0000000..585d25f
--- /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 <http://www.gnu.org/licenses/>.
+
+use assert_cmd::prelude::*;
+use predicates::prelude::*;
+use std::process::Command;
+
+#[test]
+fn link_invalid_argument() -> Result<(), Box<dyn std::error::Error>> {
+ 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<dyn std::error::Error>> {
+ 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<dyn std::error::Error>> {
+ 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<dyn std::error::Error>> {
+ 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<dyn std::error::Error>> {
+ 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<dyn std::error::Error>> {
+ 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(())
+}