Skip to content
This repository was archived by the owner on Dec 29, 2021. It is now read-only.

Commit aa318ad

Browse files
committed
Merge #46
46: Add with_env helper r=killercup a=Freyskeyd Check the discussion in #27 Signed-off-by: Freyskeyd <[email protected]>
2 parents c17c1aa + 060a7c0 commit aa318ad

File tree

5 files changed

+221
-4
lines changed

5 files changed

+221
-4
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ matrix:
1111
env: CLIPPY_VERS="0.0.165"
1212
before_script: |
1313
[[ "$(cargo +nightly-2017-10-09 clippy --version)" != "$CLIPPY_VERS" ]] && \
14-
cargo +nightly-2017-10-09 install clippy --vers "$CLIPPY_VERS" --force
14+
cargo +nightly-2017-10-09 install clippy --vers "$CLIPPY_VERS" --force || true
1515
script: |
1616
cargo +nightly-2017-10-09 clippy -- -D warnings
1717
- rust: nightly-2017-10-09
1818
env: RUSTFMT_VERS="0.2.8"
1919
before_script: |
2020
[[ "$(cargo +nightly-2017-10-09 fmt -- --version)" != "$RUSTFMT_VERS"* ]] && \
21-
cargo +nightly-2017-10-09 install rustfmt-nightly --vers "$RUSTFMT_VERS" --force
21+
cargo +nightly-2017-10-09 install rustfmt-nightly --vers "$RUSTFMT_VERS" --force || true
2222
script: |
2323
cargo +nightly-2017-10-09 fmt --all -- --write-mode=diff
2424
before_script:

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ colored = "1.5"
1717
difference = "1.0"
1818
error-chain = "0.11"
1919
serde_json = "1.0"
20+
environment = "0.1"
2021

2122
[build-dependencies]
2223
skeptic = "0.13"

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ like this:
7676
if there are special characters, which the macro doesn't accept, e.g.
7777
`assert_cmd!(cat "foo.txt")`.
7878

79+
Assert Cli use [Environment][Environment] underneath to deal with environment variables.
80+
7981
More detailed information is available in the [documentation]. :-)
8082

8183
## License
@@ -95,3 +97,4 @@ license, shall be dual licensed as above, without any additional terms or
9597
conditions.
9698

9799
[Documentation]: https://docs.rs/assert_cli
100+
[Environment]: https://github.com/Freyskeyd/environment

src/assert.rs

Lines changed: 210 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use environment::Environment;
12
use errors::*;
23
use output::{OutputAssertion, OutputKind};
34
use std::default;
@@ -10,6 +11,7 @@ use std::vec::Vec;
1011
#[derive(Debug)]
1112
pub struct Assert {
1213
cmd: Vec<String>,
14+
env: Environment,
1315
current_dir: Option<PathBuf>,
1416
expect_success: Option<bool>,
1517
expect_exit_code: Option<i32>,
@@ -27,6 +29,7 @@ impl default::Default for Assert {
2729
.into_iter()
2830
.map(String::from)
2931
.collect(),
32+
env: Environment::inherit(),
3033
current_dir: None,
3134
expect_success: Some(true),
3235
expect_exit_code: None,
@@ -87,6 +90,7 @@ impl Assert {
8790
/// .with_args(&["42"])
8891
/// .stdout().contains("42")
8992
/// .unwrap();
93+
///
9094
/// ```
9195
pub fn with_args(mut self, args: &[&str]) -> Self {
9296
self.cmd.extend(args.into_iter().cloned().map(String::from));
@@ -128,6 +132,41 @@ impl Assert {
128132
self
129133
}
130134

135+
/// Sets environments variables for the command.
136+
///
137+
/// # Examples
138+
///
139+
/// ```rust
140+
/// extern crate assert_cli;
141+
///
142+
/// assert_cli::Assert::command(&["printenv"])
143+
/// .with_env(&[("TEST_ENV", "OK")])
144+
/// .stdout().contains("TEST_ENV=OK")
145+
/// .execute()
146+
/// .unwrap();
147+
///
148+
/// let env = assert_cli::Environment::empty()
149+
/// .insert("FOO", "BAR");
150+
///
151+
/// assert_cli::Assert::command(&["printenv"])
152+
/// .with_env(&env)
153+
/// .stdout().is("FOO=BAR")
154+
/// .execute()
155+
/// .unwrap();
156+
///
157+
/// ::std::env::set_var("BAZ", "BAR");
158+
///
159+
/// assert_cli::Assert::command(&["printenv"])
160+
/// .stdout().contains("BAZ=BAR")
161+
/// .execute()
162+
/// .unwrap();
163+
/// ```
164+
pub fn with_env<E: Into<Environment>>(mut self, env: E) -> Self {
165+
self.env = env.into();
166+
167+
self
168+
}
169+
131170
/// Small helper to make chains more readable.
132171
///
133172
/// # Examples
@@ -253,13 +292,17 @@ impl Assert {
253292
/// ```
254293
pub fn execute(self) -> Result<()> {
255294
let cmd = &self.cmd[0];
295+
256296
let args: Vec<_> = self.cmd.iter().skip(1).collect();
257297
let mut command = Command::new(cmd);
258298
let command = command
259299
.stdin(Stdio::piped())
260300
.stdout(Stdio::piped())
261-
.stderr(Stdio::piped());
262-
let command = command.args(&args);
301+
.stderr(Stdio::piped())
302+
.env_clear()
303+
.envs(self.env.clone().compile())
304+
.args(&args);
305+
263306
let command = match self.current_dir {
264307
Some(ref dir) => command.current_dir(dir),
265308
None => command,
@@ -426,3 +469,168 @@ impl OutputAssertionBuilder {
426469
self.not().is(output)
427470
}
428471
}
472+
473+
#[cfg(test)]
474+
mod test {
475+
use super::*;
476+
use std::ffi::OsString;
477+
478+
fn command() -> Assert {
479+
Assert::command(&["printenv"])
480+
}
481+
482+
#[test]
483+
fn take_ownership() {
484+
let x = Environment::inherit();
485+
486+
command().with_env(x.clone()).with_env(&x).with_env(x);
487+
}
488+
489+
#[test]
490+
fn in_place_mod() {
491+
let y = Environment::empty();
492+
493+
let y = y.insert("key", "value");
494+
495+
assert_eq!(
496+
y.compile(),
497+
vec![(OsString::from("key"), OsString::from("value"))]
498+
);
499+
}
500+
501+
#[test]
502+
fn in_place_mod2() {
503+
let x = Environment::inherit();
504+
505+
command()
506+
.with_env(&x.insert("key", "value").insert("key", "vv"))
507+
.stdout()
508+
.contains("key=vv")
509+
.execute()
510+
.unwrap();
511+
// Granted, `insert` moved `x`, so we can no longer reference it, even
512+
// though only a reference was passed to `with_env`
513+
}
514+
515+
#[test]
516+
fn in_place_mod3() {
517+
// In-place modification while allowing later accesses to the `Environment`
518+
let y = Environment::empty();
519+
520+
assert_eq!(
521+
y.clone().insert("key", "value").compile(),
522+
vec![(OsString::from("key"), OsString::from("value"))]
523+
);
524+
525+
command()
526+
.with_env(y)
527+
.stdout()
528+
.not()
529+
.contains("key=value")
530+
.execute()
531+
.unwrap();
532+
}
533+
534+
#[test]
535+
fn empty_env() {
536+
// In-place modification while allowing later accesses to the `Environment`
537+
let y = Environment::empty();
538+
539+
assert!(command().with_env(y).stdout().is("").execute().is_ok());
540+
}
541+
#[test]
542+
fn take_vec() {
543+
let v = vec![("bar".to_string(), "baz".to_string())];
544+
545+
command()
546+
.with_env(&vec![("bar", "baz")])
547+
.stdout()
548+
.contains("bar=baz")
549+
.execute()
550+
.unwrap();
551+
552+
command()
553+
.with_env(&v)
554+
.stdout()
555+
.contains("bar=baz")
556+
.execute()
557+
.unwrap();
558+
559+
command()
560+
.with_env(&vec![("bar", "baz")])
561+
.stdout()
562+
.isnt("")
563+
.execute()
564+
.unwrap();
565+
}
566+
567+
#[test]
568+
fn take_slice_of_strs() {
569+
command()
570+
.with_env(&[("bar", "BAZ")])
571+
.stdout()
572+
.contains("bar=BAZ")
573+
.execute()
574+
.unwrap();
575+
576+
command()
577+
.with_env(&[("bar", "BAZ")][..])
578+
.stdout()
579+
.contains("bar=BAZ")
580+
.execute()
581+
.unwrap();
582+
583+
command()
584+
.with_env([("bar", "BAZ")].as_ref())
585+
.stdout()
586+
.contains("bar=BAZ")
587+
.execute()
588+
.unwrap();
589+
}
590+
591+
#[test]
592+
fn take_slice_of_strings() {
593+
// same deal as above
594+
595+
command()
596+
.with_env(&[("bar".to_string(), "BAZ".to_string())])
597+
.stdout()
598+
.contains("bar=BAZ")
599+
.execute()
600+
.unwrap();
601+
602+
command()
603+
.with_env(&[("bar".to_string(), "BAZ".to_string())][..])
604+
.stdout()
605+
.contains("bar=BAZ")
606+
.execute()
607+
.unwrap();
608+
}
609+
610+
#[test]
611+
fn take_slice() {
612+
command()
613+
.with_env(&[("hey", "ho")])
614+
.stdout()
615+
.contains("hey=ho")
616+
.execute()
617+
.unwrap();
618+
619+
command()
620+
.with_env(&[("hey", "ho".to_string())])
621+
.stdout()
622+
.contains("hey=ho")
623+
.execute()
624+
.unwrap();
625+
}
626+
627+
#[test]
628+
fn take_string_i32() {
629+
command()
630+
.with_env(&[("bar", 3 as i32)])
631+
.stdout()
632+
.contains("bar=3")
633+
.execute()
634+
.unwrap();
635+
}
636+
}

src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
#![deny(missing_docs)]
119119

120120
extern crate difference;
121+
extern crate environment;
121122
#[macro_use]
122123
extern crate error_chain;
123124
extern crate serde_json;
@@ -135,3 +136,7 @@ mod diff;
135136
mod assert;
136137
pub use assert::Assert;
137138
pub use assert::OutputAssertionBuilder;
139+
/// Environment is a re-export of the Environment crate
140+
///
141+
/// It allow you to define/override environment variables for one or more assertions.
142+
pub use environment::Environment;

0 commit comments

Comments
 (0)