-
Notifications
You must be signed in to change notification settings - Fork 19
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very cool! Thank you so much for this!
I left some inline comments. Most importantly, please move the tests so they become unit tests.
Also, I saw you merged master into this. That's fine; please keep on adding commits to this branch without rebasing, but it'd be awesome if you could squash it once all reviews are done :)
src/assert.rs
Outdated
@@ -24,6 +26,7 @@ impl default::Default for Assert { | |||
Assert { | |||
cmd: vec!["cargo", "run", "--"] | |||
.into_iter().map(String::from).collect(), | |||
env: Environment::empty(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it should default to inherit
.
src/environment.rs
Outdated
pub vars: Vec<(String, String)>, | ||
/// Define if the structure must inherit | ||
pub inherit: bool, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fields should not be pub
. The compile
method's output is all we should ever test in integration tests.
src/environment.rs
Outdated
|
||
/// Compile Environment object | ||
pub fn compile(&self) -> Vec<(String, String)> { | ||
::std::env::vars().chain(self.vars.clone()).collect() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this have an if self.inherit
?
src/assert.rs
Outdated
let command = command.args(&args); | ||
let command = command | ||
.env_clear() | ||
.envs(::std::env::vars().chain(self.env.clone().vars)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure you want to call compile
here.
tests/environment.rs
Outdated
@@ -0,0 +1,72 @@ | |||
extern crate assert_cli; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you move all the tests into a #[cfg(test)] mod test
in environment.rs
and use the real with_env
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fact is, with_env doesn't allow to test the environment object after ...
src/environment.rs
Outdated
fn to_environment_tuple(&self) -> (String, String); | ||
} | ||
|
||
impl<'s, T: ToString, Z:ToString> EnvironmentItem for &'s (T, Z) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
space after Z:
src/assert.rs
Outdated
/// .stdout().contains("TEST_ENV=OK") | ||
/// .execute() | ||
/// .unwrap(); | ||
/// ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feel free to add some more examples here as they are the real integration tests :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm really liking this API!
.stderr(Stdio::piped()); | ||
let command = command.args(&args); | ||
.stderr(Stdio::piped()) | ||
.env_clear() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There a reason we unconditionally clear and then re-add the vars
we cleared via compile
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact we need the env_clear()
because .envs
doesn't clear it or replace the whole variables.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'm missing something. I had assumed we'd only call env_clear()
when inherit == false
. Its unclear to me why we need env_clear
when inherit == true
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By clearing the environment before adding our own environment, we don't have to check if inherit is true nor false in execute command. We just want to clear and add the appropriate environment. That's the environment role to know when to add the existing env or not.
If inherit is set to true, the compile
method will return a merge of actual environment (env::vars()
) and our customized variables. I think it's nicer to have a compile method returning what our environment will look like. But feel free to propose something else I'm ok with it :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tl;dr move along, these aren't the droids you're looking for.
I think it's nicer to have a compile method returning what our environment will look like.
That is nice. It helps with testing, etc.
I just assumed that Assert
would directly access the members of Environment
and there wouldn't be a need for a public .compile()
.
Recreating an inherited environment is more work but I'm assuming it doesn't matter in this case, despite it being against "you pay for what you use" (adds cost to people not using these new features).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@killercup how do you see this test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Set an env var to something that is not UTF-8. How would I get a byte slice like that? head -c 42 /dev/urandom | rcat --quote
(with this rcat) gives me:
b"\xf4\xa9\xd5\x8d\xc0\xe8\x00\xff\x1dqz\x86k\x83\xcb~\xc1\x18!\xfa\x01J\x1c\\:\x18)%\xd4\xa6^7\xb4\x93\x80.\x9a\x9c\xe1\xcf\xe2,"
which is not valid UTF-8.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but vars()
use UTF-8 variables, do we really want to support not valid UTF-8? I don't think..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's exactly what I'm saying: I'm fine with only allowing our users to add UTF-8 vars but we should not destroy valid, inherited env vars. So, calling vars
at all is probably not a good call, and vars_os
is the better option. Btw, you can find the impl of how std::process::Command
deals with env vars on Unix here (it uses a HashMap<OsString, (usize, CString)>
to store env vars).
How much work would it be to allow OsStr
instead of String
in our APIs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you still add a test with the non-UTF-8 env var value?
src/assert.rs
Outdated
let command = command.args(&args); | ||
.stderr(Stdio::piped()) | ||
.env_clear() | ||
.envs(self.env.clone().compile())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function consumes Asssert
so we should be able to avoid the .clone()
src/assert.rs
Outdated
@@ -26,6 +29,7 @@ impl default::Default for Assert { | |||
Assert { | |||
cmd: vec!["cargo", "run", "--"] | |||
.into_iter().map(String::from).collect(), | |||
env: Environment::empty(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the default be
empty
inherit
(I presume this isstd::process::Command
's default and the current behavior)None
(usestd::process::Command
's default which is the current behavior)
src/environment.rs
Outdated
/// Customized environment variables | ||
pub vars: Vec<(String, String)>, | ||
/// Define if the structure must inherit | ||
pub inherit: bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The members should probably not be pub
src/environment.rs
Outdated
} | ||
|
||
impl Environment { | ||
/// Create a new Environment object with inherit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like a little more context would be helpful
Create a new Environment that inherits this process' environment.
src/environment.rs
Outdated
} | ||
} | ||
|
||
/// Create a new Environment object without inheriting |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same about more context. Also, it can be confusing to describe something by what it is not.
So maybe Create a new Environment independent of the current process's Environment
?
src/assert.rs
Outdated
@@ -3,14 +3,17 @@ use std::process::{Command, Stdio}; | |||
use std::path::PathBuf; | |||
use std::vec::Vec; | |||
use std::io::Write; | |||
use std::convert::Into; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's in the prelude
src/environment.rs
Outdated
|
||
fn command() -> Assert { | ||
Assert::command(&["printenv"]) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's very clever 👍
Can you add an empty line below the fn?
src/environment.rs
Outdated
#[cfg(test)] | ||
mod test { | ||
use super::*; | ||
use super::super::Assert; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know it's a very good Assert, but use ::Assert;
should suffice ;)
f3b6e26
to
82288e6
Compare
src/environment.rs
Outdated
if self.inherit { | ||
::std::env::vars().chain(self.vars.clone()).collect() | ||
} else { | ||
self.vars.clone() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should Environment
be moved into this?
This would give the caller control on whether the .clone()
s are needed or not. In our case, we call compile
when consuming Assert
, so we wouldn't need to call any of these .clone()
s.
.travis.yml
Outdated
@@ -5,13 +5,6 @@ rust: | |||
- beta | |||
- stable | |||
- nightly | |||
matrix: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@killercup @epage I removed the nightly-2017-03-15, are you ok with this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The .envs
methods from Command
is stable since 1.10. But not for the 2017-03-15
build. I was wondering about why we are still testing this particular build.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason (which I like and want to copy to my other projects) is to pin the version of rust/clippy.
In my other projects, we are always running the latest clippy. Sometimes it is out of sync with rustc, so the build ignores clippy, losing coverage. Even when it succeeds, there might be new clippy warnings which will get turned into errors, sporadically breaking our build.
What I'd recommend is to lock us to a new version of clippy. This might be best as a separate PR so any clippy fixes don't get mixed in with your changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a sucker for lints, clippy needs to stay! Hell, I might even enforce rustfmt!
What I'd recommend is to lock us to a new version of clippy. This might be best as a separate PR so any clippy fixes don't get mixed in with your changes.
I'll just do that in minute, @Freyskeyd you can merge in master after this.
Update: #47
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@killercup I love having everything checked in the CI!
I'm unsure how stable rustfmt's output is from release to release. I've not yet submitted a rustfmt.toml to my other projects. I have played with a build optimization for rustfmt for locking to a specific version that you might find handy.
See https://github.com/cobalt-org/cobalt.rs/blob/master/.travis.yml#L29
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're using the old rustfmt, not rustfmt-nightly :) I opened #48 for getting our formatting in check.
@killercup can you check why the CI doesn't pass? |
Probably because I tried being too clever… can you append |
588998b
to
8cb7289
Compare
https://travis-ci.org/killercup/assert_cli/builds/285971508
I assume the |
@Freyskeyd, wow, thanks for the quick OsString update! @epage, yeah, it's a ternary: |
Would that cause the return value of |
@killercup I tried with About travis, what do you want to do? |
Maybe? Probably. We could also try to use a real
Yes, sorry, I meant OsString!
Eh, I want you to fix the valid error and the formatting? 😛 |
3a528a9
to
835a843
Compare
@killercup @epage I updated the code, can you check it please? :) |
I move it to another crate because I need it outside https://github.com/Freyskeyd/environment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome work. Having this as an external crate is pretty cool. Feel free to advertise that assert_cli uses it in its Readme ;)
Just a few more tiny nits and I will happily merge this :)
.stderr(Stdio::piped()); | ||
let command = command.args(&args); | ||
.stderr(Stdio::piped()) | ||
.env_clear() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you still add a test with the non-UTF-8 env var value?
src/lib.rs
Outdated
@@ -135,3 +137,4 @@ mod diff; | |||
mod assert; | |||
pub use assert::Assert; | |||
pub use assert::OutputAssertionBuilder; | |||
pub use environment::Environment; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to add some specific docs here mentioning this is a report from the external crate? I assume it inherits the docs from the item in the crate right now.
src/assert.rs
Outdated
fn in_place_mod2() { | ||
let x = Environment::inherit(); | ||
|
||
assert!( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the assert!(… .is_ok())
dance when you can just write .unwrap()
?
src/assert.rs
Outdated
/// .stdout().is("FOO=BAR") | ||
/// .execute() | ||
/// .unwrap(); | ||
/// ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great examples! Can you maybe add a third one that sets a var in the test's thread context and then shows that it's also available in the command output?
34fb40b
to
16aaa61
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates!
Use Environment crate to override and insert new environment variables. Signed-off-by: Freyskeyd <[email protected]>
bors r+ |
46: Add with_env helper r=killercup a=Freyskeyd Check the discussion in #27 Signed-off-by: Freyskeyd <[email protected]>
Build succeeded |
Check the discussion in #27
Signed-off-by: Freyskeyd [email protected]