-
Notifications
You must be signed in to change notification settings - Fork 256
Added integration tests, added back test_simple_workspace #607
Conversation
Nice! I think that's the best approach here, using cargotest, generating test data in the target/ directory and spawning separate rls processes. It fixes/does all the thing we wanted, good job! Integration tests are nice, but it's a shame we lose helper types and are back to unstructured JSON messages. At some point I believe it'd be good to split it into bin/lib, so we can at least the types here. Just wanted to chime in to thank you for working on this 👍 . At first glance this looks good for me, but I'll come back and do a more detailed review in the morning, if you don't mind. |
tests/support/harness.rs
Outdated
pub struct RlsHandle { | ||
child: Child, | ||
stdin: ChildStdin, | ||
stdout: BufReader<ChildStdout>, |
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 is this buffered? So we can easily only read a message when a whole message is ready to be read?
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.
So that I can search for a \n using read_line when reading the headers like Content-Length: XX
tests/support/mod.rs
Outdated
} | ||
|
||
let ProjectBuilder{ name: _, root, files: _, .. } = self; | ||
root |
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.
Aren't lines 92-93 just equivalent to returning self.root
here?
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.
Yeah you seem to be right. I'll simplify this when I get a chance tomorrow.
I simplified that one line of code.
Aren't the types in the crate BTW, my biggest concern with this PR is that I didn't spend much time thinking about the different environments/OSes the tests might be ran, and how exactly to launch the rls binary in each instance. For example, I didn't even worry about setting |
I agree. Just wanted to note that sometimes you want to focus the test on different parts than the input handling, where it's convenient to assume correct input, hence why reusing existing functionality, e.g. being able to pass structured input and analyze received structured output is convenient.
So what we're most concerned with here is how the tests are ran in the Rust CI environment. I did dig around and talked with @alexcrichton about that - it seems that we basically execute Also checked with a local Rust build and it seems to work, however with a small caveat. Because we don't implement a timeout here, my test harness just hung on a We need to ensure that the test suite doesn't hang in the Rust CI, so for this to land we also need to implement the timeout. I'll play around and see if we can easily bolt on some timeouts here. |
I implemented a timeout at the top of each test. I guess it's a good place for a timeout and it can cover any possible reason the test might take a while. I had previously tried to add a timeout to the read_message function and that wasn't working out very well. |
I've updated simple_workspace_test so that it passes when workspace mode is off by default. I've also included comments of how to change it if it's ever reenabled. |
I'm not sure about this. On one hand, yes, we kind of do to make it a proper integration test. On the other hand, the stdin/stdout layer is pretty trivial and unlikely to go wrong, so I'd rather make it more ergonomic to write tests for the common case, rather than be able to test 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.
Thanks for this PR! It looks good. I left a few comments inline, but I'll wait for Xanewok to re-review too. In particular, we need to be sure this will work inside the Rust repo.
tests/support/mod.rs
Outdated
|
||
use support::paths::TestPathExt; | ||
|
||
pub mod harness; |
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 are some things here and some things in harness
, istm they are all kind of related and should be in the same module, or maybe split in some other way.
tests/tests.rs
Outdated
mod support; | ||
use support::{basic_bin_manifest, project}; | ||
use support::harness::{ExpectedMessage, RlsHandle}; | ||
|
||
fn timeout<F>(dur: Duration, func: F) |
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 should probably be in one of the support
modules
tests/tests.rs
Outdated
mod support; | ||
use support::{basic_bin_manifest, project}; | ||
use support::harness::{ExpectedMessage, RlsHandle}; | ||
|
||
fn timeout<F>(dur: Duration, func: F) | ||
where F: FnOnce() + Send + 'static { | ||
let pair = Arc::new((Mutex::new(false), Condvar::new())); |
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.
Making this pair doesn't seem worthwhile to me, you could just clone the mutex and condvar separately in fewer lines of code.
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 not sure what you mean here. I don't actually want to clone the mutex and condvar and I don't see how I could do it in less lines. BTW, this code follows the rust stdlib example code for how to work with CondVar.
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 meant you could write:
let mutex = Arc::new(Mutex::new(...));
let condvar = Arc::new(Condvar::new());
(and clone the Arc
s, not the mutex/condvar). I guess having a pair saves an Arc
but it seems a bit convoluted to me.
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.
Either way is fine, though.
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.
Read the stdlib regarding Condvar
+ examples and additionally pthread API - this is surprisingly unergonomic to use! I tried to simplify it somehow, but couldn't. I'd expect it to be much easier to run a task in thread with a timeout, but it feels like one has to do the all the machinery by hand, just like in C.
tests/tests.rs
Outdated
]); | ||
|
||
rls.shutdown_exit(); | ||
timeout(Duration::from_secs(300), ||{ |
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.
Could you factor the timeout into a const please?
Sorry I took so long to review! |
Just as a note, with
on Ubuntu 17.10 x86_64 4.13.0-19-generic. I'll run |
@nrc workspace mode is on now by default, so this will need to change still. I'll open a second PR with this commit |
Add integration tests based on #607
This should be a path to fixing #524, and a fix for #455. I have borrowed some code from cargotest, and from the current test harness, and I've created a new test integration test harness.
println
would break rls, but the previous tests would not fail.