Tests panic when HTTP server starts after old one is closed - testing

I have some tests written, each function starts iron's HTTP server and closes it after test is done:
extern crate iron;
use iron::prelude::*;
fn hello_world(_: &mut Request) -> IronResult<Response> {
Ok(Response::with((iron::status::Ok, "Hello World")))
}
#[test]
fn test1() {
let mut server = Iron::new(hello_world).http("localhost:3000").unwrap();
server.close().unwrap();
}
#[test]
fn test2() {
let mut server = Iron::new(hello_world).http("localhost:3000").unwrap();
server.close().unwrap();
}
Doing cargo test I'm having:
Running target/debug/lib-f236975fe924352b
running 2 tests
test test1 ... ok
test test2 ... FAILED
failures:
---- test2 stdout ----
thread 'test2' panicked at 'called `Result::unwrap()` on an `Err` value: Io(Error { repr: Os { code: 98, message: "Address already in use" } })', ../src/libcore/result.rs:736
failures:
test2
test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured
It seems like the port is still in use by the start of the second test.

Rust's test runner is parallel by default, so yes, I would expect that this would happen. I would pick a different port number for each test, at least to start, since it's so easy.

Related

How to split the code in modules in Rust? [duplicate]

This question already has an answer here:
Can't understand Rust module system
(1 answer)
Closed 3 years ago.
I am reading the Rust Book, I am in the chapter 7.2, but I must be missing something, because I cannot organize my code in modules, the compiler (rustc 1.32.0) keeps giving me errors.
What I have read
I read rustc --explain E0433, which is the advice of the compiler, but I still cannot solve it.
I checked Rust by examples, and it seems that my code is correct, (my/mod.rs is using module my/nested.rs in its own folder)
I found some info on Internet, but it is of 4 years ago, and include the use of use, which is not yet in the book.
I also checked this question, but I am not using folders, and again, it gets away from the book explanation.
Minimal example
This is a minimal example that tries to mimic the "sound" example of the book, there is only two files: /src/main.rs and /src/m.rs.
main.rs
mod m;
fn main() {
let st_0 = m::St::new();
}
m.rs
pub mod m {
pub struct St {
a:i32,
b:i32,
}
impl St {
pub fn new() -> St{
println!("New St!");
St {
a: 12,
b: 13,
}
}
}
}
And this is what cargo tells me:
Compiling min v0.1.0 (/home/user/min)
error[E0433]: failed to resolve: could not find `St` in `m`
--> src/main.rs:3:19
|
3 | let st_0 = m::St::new();
| ^^ could not find `St` in `m`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0433`.
error: Could not compile `min`.
To learn more, run the command again with --verbose.
When you have everything in one file, like this:
main.rs
pub mod m {
pub struct St {
a:i32,
b:i32,
}
impl St {
pub fn new() -> St{
println!("New St!");
St {
a: 12,
b: 13,
}
}
}
}
mod m;
fn main() {
let st_0 = m::St::new();
}
you wrap the module with the
pub mod mode_name {
//code...
}
Once you put the module in another file, that wrapping goes away. The Rust book, shows it, but if you don't look carefully or if you are programming drunk, you may get confused with the pub mod instrument {...} of the nested module.
So m.rs has to look like this:
pub struct St {
a:i32,
b:i32,
}
impl St {
pub fn new() -> St{
println!("New St!");
St {
a: 12,
b: 13,
}
}
}

Can Golang test scripts issue warnings rather than errors?

I have a set of tests that may not pass due to external 3rd party issues.
I don't want the test to fail when this condition occurs but would like to be made aware.
Issuing a t.Errorf() is not idea because it will stop all subsequent tests. Is there some kind of "Warning" I can trigger that the test script would post and then continue with the remainder of the tests?
The go test tool is like the compiler. To the compiler something either compiles or doesn't, there are no warnings. I think the closest thing you're going to get is to use t.Skip. It will stop execution of the current test but does not mark it as failed. You will not see anything in the output of go test however so you have to use go test -v.
Here's an example package that uses t.Skipf if the addExternal function fails.
package app
import "testing"
func add(a, b int) int {
return a + b
}
func addExternal(a, b int) int {
return 4
}
func divide(a, b int) int {
return a / b
}
func TestThing(t *testing.T) {
got := add(1, 2)
want := 3
if got != want {
t.Errorf("add(1, 2) = %d, want %d", got, want)
}
}
func TestExternalThing(t *testing.T) {
got := addExternal(3, 4)
want := 7
if got != want {
t.Skipf("addExternal(3, 4) = %d, want %d", got, want)
}
}
func TestAnotherThing(t *testing.T) {
got := divide(6, 3)
want := 2
if got != want {
t.Errorf("divide(6, 3) = %d, want %d", got, want)
}
}
And here's the output from running that. Note the return status is 0 and the package is considered to have passed
$ go test -v
=== RUN TestThing
--- PASS: TestThing (0.00s)
=== RUN TestExternalThing
--- SKIP: TestExternalThing (0.00s)
app_test.go:29: addExternal(3, 4) = 4, want 7
=== RUN TestAnotherThing
--- PASS: TestAnotherThing (0.00s)
PASS
ok github.com/jcbwlkr/app 0.006s
$ echo $?
0
Note though that if I change the t.Skipf to t.Errorf or t.Fatalf I get this output
$ go test -v
=== RUN TestThing
--- PASS: TestThing (0.00s)
=== RUN TestExternalThing
--- FAIL: TestExternalThing (0.00s)
app_test.go:29: addExternal(3, 4) = 4, want 7
=== RUN TestAnotherThing
--- PASS: TestAnotherThing (0.00s)
FAIL
exit status 1
FAIL github.com/jcbwlkr/app 0.005s
$ echo $?
1
The other tests in the package are still ran. If I was testing multiple packages such as with go test -v ./... I believe they would also still be ran.

Wrong number of arguments when using mget with redis-rs

I'm trying to access Redis using Rust with the following:
extern crate redis;
use redis::{Client, Commands, Connection, RedisResult};
fn main() {
let redis_client = Client::open("redis://127.0.0.1/").unwrap();
let redis_conn = redis_client.get_connection().unwrap();
let mut keys_to_get = vec![];
keys_to_get.push("random_key_1".to_string());
keys_to_get.push("random_key_2".to_string());
let redis_result: String = redis_conn.get(keys_to_get).unwrap();
}
When I run cargo run I get:
Running `target/debug/test_resdis`
thread '<main>' panicked at 'called `Result::unwrap()` on an `Err` value: An error was signalled by the server: wrong number of arguments for 'get' command', ../src/libcore/result.rs:746
note: Run with `RUST_BACKTRACE=1` for a backtrace.
error: Process didn't exit successfully: `target/debug/test_resdis` (exit code: 101)
Am I doing something wrong, or is it a bug?
Running your program against a netcat server shows the following requests made:
*3
$3
GET
$12
random_key_1
$12
random_key_2
The GET command should be an MGET.
I believe this to be a bug in the implementation:
impl<T: ToRedisArgs> ToRedisArgs for Vec<T> {
fn to_redis_args(&self) -> Vec<Vec<u8>> {
ToRedisArgs::make_arg_vec(self)
}
}
impl<'a, T: ToRedisArgs> ToRedisArgs for &'a [T] {
fn to_redis_args(&self) -> Vec<Vec<u8>> {
ToRedisArgs::make_arg_vec(*self)
}
fn is_single_arg(&self) -> bool {
ToRedisArgs::is_single_vec_arg(*self)
}
}
Under the hood, the library inspects the key type to know if it's multivalued or not, using ToRedisArgs::is_single_arg, which has a default implementation of true.
As you can see, a slice implements ToRedisArgs::is_single_arg, but a Vec does not. This also suggests a workaround: treat the vector like a slice:
redis_conn.get(&*keys_to_get)
This issue has now been filed with the library.

Working with UDP using mio and getting an error "MutBuf is not implemented for the type MutSliceBuf"

For learning purposes I am currently trying to write small program which will implement echo-server for UDP packets which will work on a certain set of ports (say 10000-60000). So as it wouldn't be so good to spam 50k threads for this I need to use asynchronous IO and mio is excellent match for this task. But I've got a problem right from the start with this code:
extern crate mio;
extern crate bytes;
use mio::udp::*;
use bytes::MutSliceBuf;
fn main() {
let addr = "127.0.0.1:10000".parse().unwrap();
let socket = UdpSocket::bound(&addr).unwrap();
let mut buf = [0; 128];
socket.recv_from(&mut MutSliceBuf::wrap(&mut buf));
}
It is almost full copypaste from of mio's test_udp_socket.rs.But while mio's tests successfully pass through, then I try to compile this code I am getting following error:
src/main.rs:12:12: 12:55 error: the trait `bytes::buf::MutBuf` is not implemented for the type `bytes::buf::slice::MutSliceBuf<'_>` [E0277]
src/main.rs:12 socket.recv_from(&mut MutSliceBuf::wrap(&mut buf));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:12:12: 12:55 help: run `rustc --explain E0277` to see a detailed explanation
But examining code of src/buf/slice.rs from bytes crate (local copy of it too) we can clearly see what this trait was implemented:
impl<'a> MutBuf for MutSliceBuf<'a> {
fn remaining(&self) -> usize {
self.bytes.len() - self.pos
}
fn advance(&mut self, mut cnt: usize) {
cnt = cmp::min(cnt, self.remaining());
self.pos += cnt;
}
unsafe fn mut_bytes<'b>(&'b mut self) -> &'b mut [u8] {
&mut self.bytes[self.pos..]
}
}
It's probably something trivial, but I can't find it... What could be a problem which causes this error?
I am using rustc 1.3.0 (9a92aaf19 2015-09-15), crates mio and bytes is gotten straight from github.
Using Cargo with
[dependencies]
mio = "*"
bytes = "*"
this runs for me. Using the Github dependency,
[dependencies.mio]
git = "https://github.com/carllerche/mio.git"
gives the error you mention.
Strangely, version 0.4 depends on
bytes = "0.2.11"
whereas master depends on
git = "https://github.com/carllerche/bytes"
rev = "7edb577d0a"
which is only version 0.2.10. Strange.
The problem is that you end up getting two bytes dependencies compiled, so the error is more like
the trait `mio::bytes::buf::MutBuf` is not implemented for the type `self::bytes::buf::slice::MutSliceBuf<'_>`
The simplest way I see to fix this is to just use both packages from crates.io.
[dependencies]
mio = "*"
bytes = "*"
Another way is to use
[dependencies.bytes]
git = "https://github.com/carllerche/bytes"
rev = "7edb577d0a"
in your own Cargo.toml, such that you share versions.

Is there an assertException in any of the Haskell test frameworks?

I'm writing some tests using HUnit and I would like to assert that a particular function throws an exception given a certain input. I can't find an assert function which provides the required functionality. Anyone know of a test framework that does?
Although HUnit doesn't come with any exception assertions, it's easy to write your own:
import Control.Exception
import Control.Monad
import Test.HUnit
assertException :: (Exception e, Eq e) => e -> IO a -> IO ()
assertException ex action =
handleJust isWanted (const $ return ()) $ do
action
assertFailure $ "Expected exception: " ++ show ex
where isWanted = guard . (== ex)
testPasses = TestCase $ assertException DivideByZero (evaluate $ 5 `div` 0)
testFails = TestCase $ assertException DivideByZero (evaluate $ 5 `div` 1)
main = runTestTT $ TestList [ testPasses, testFails ]
You can do something more fancy like using a predicate instead of explicit comparison if you like.
$ ./testex
### Failure in: 1
Expected exception: divide by zero
Cases: 2 Tried: 2 Errors: 0 Failures: 1
Note that evaluate here might get optimized away (see GHC ticket #5129), but for testing code in the IO monad this should work fine.
You can use assertRaises from testpack.
hspec (or more precisely hspec-expectations) has shouldThrow.