Rust panic unit test - specifics of matching the error message [duplicate] - testing

This question already has answers here:
How do I write a Rust unit test that ensures that a panic has occurred?
(8 answers)
Closed 3 years ago.
I'm looking for a way to assert that a piece of code panics, and that the panic message contains a particular string. I came up with the following which appears to work:
let actual = std::panic::catch_unwind(|| decode(notation.to_string()));
assert!(actual.is_err());
let err = *(actual.unwrap_err().downcast::<String>().unwrap());
assert!(err.contains("Invalid"));
I know that I can use #[should_panic] and that it lets me specify a message to check for, but I only want to partially match the exact error message.

Use #[should_panic(expected = "substring of panic message")]
Example
fn some_panic_function() {
panic!("abc substring of panic message abc");
}
#[test]
#[should_panic(expected = "substring of panic message")]
fn test_some_panic_function() {
some_panic_function();
}
From this https://doc.rust-lang.org/book/ch11-01-writing-tests.html

Related

Why do I get “Lexical with name '$x' does not exist in this frame” when using “will leave”?

I have the following Raku code:
class Thing {
method close {
say "closed";
}
};
for 1..1000 {
my $x will leave { .close } = Thing.new;
}
Running it, I get the error:
Lexical with name '$x' does not exist in this frame
in block <unit> at c.raku line 7
Interestingly, this only happens if the number of iterations is high enough (with 500 or 100, I do not get any error messages).
If I change the body of the cycle to
my $x = Thing.new;
LEAVE $x.close;
then everything works without errors as well.
What is happening here? Did I misunderstand the will leave construct? (It seems to me the two versions should be equivalent.)
EDIT: Further observation – when running the code multiple times, the error appears nondeterministically. This suggests that the problem is somehow connected to garbage collection, but I am still confused as to what actually happens here.
I am using Rakudo v2021.03.
This is a bug. Have made an issue for it: https://github.com/rakudo/rakudo/issues/4403
I suggest using the workaround in the meantime.

How can I capture whether an error occurred in Rust's swap_with_slice() vec method?

The documentation tells me that the swap_with_slice() method can potentially panic if the slices are of two different lengths. I am writing a parser which deals with data coming across TCP. My encoding scheme is such that the following should never panic, unless it is a malformed request. In this case, I don't want my programme to crash, but instead handle the error. How do I capture whether swap_with_slice panics or not? Since it itself does not return a Result?
let mut bytes_id = [0; 16];
bytes_id.swap_with_slice(&mut self.raw_bytes[Headers::MessageLength as usize..Headers::Data as usize]);
This should work
let result = std::panic::catch_unwind(|| <expected_to_panic_operation_here>);

How can I improve this code? Prompt user input [Rust]

I am learning Rust by just coding right after the first 4 chapters of The Book. Getting started I am still getting used to how borrowing and sharing work and how we can take advantage of them in code.
This snippet of code is supposed to prompt user for an IP address, and if enter is pressed, then to return the loopback address. It works fine, but I am curious to know how this could be improved in any ways, because I definitely know it can. Thank you!
fn prompt_host() -> String {
let mut input_text = String::new();
println!(" input host IP, press enter for loopback:");
io::stdin()
.read_line(&mut input_text)
.expect(" ERROR: failed to read from stdin");
let len = input_text.len();
input_text.truncate(len - 1);
if input_text == "" {
return String::from("127.0.0.1");
}
return input_text as String;
}
Just some hints:
I think I would return something related to std::net::IpAddr instead of String (if there's a type for your needs, I would use it).
std::net::IpAddr implements FromStr, so you can use input_text.parse() and obtain a Result<IpAddr, Err> (since the conversion from string may fail).
I would use trim to get rid of spaces.
I would use is_empty to test if the string is empty. - Or even cover this case by just using parse.
There are (at least) two places that may fail: read_line and parse, so I would think about returning an Option<IpAddr> or even Result<IpAddr, ErrorType> for an appropriate ErrorType.

Reading part of a line [duplicate]

This question already has answers here:
How to read a string from keyboard on the same line with output? [duplicate]
(2 answers)
Closed 7 years ago.
I'm totally new to Rust, and in fact just started today. (For those who saw my previous deleted question, you have my most sincere apology.)
I'm just trying to build a simple application to sharpen my skills, but I meet a problem. I like to create something where you can just type stuff, and for those who know dunnet, start each line with two larger than signs.
But I haven't really found out how to read the bits after the two signs. I searched on Google and StackOverflow, but this is the best I got:
//Starting a line
fn start(){print!(">>");}
//Seeking input and saving input
fn line_init() -> String
{
use std::io;
use std::io::BufRead;
start();
let mut input = String::new();
let stdin = io::stdin();
stdin.lock().read_line(&mut input).unwrap();
input
}
//Main function
fn main() {
loop
{
print!("{}", line_init());
}
}
But of course, the user input line lands on a new line, which isn't exactly what I want. This is the C++ version of the thing I want (in fact, I'm just duplicating my C++ project in Rust):
cout << ">>";
string input;
getline(cin, input);
Sorry that this post is getting a bit long!
Do you mean that the user sees something like the following on the console?
hello
>>
instead of
>> hello
?
In that case, the problem is that Rust stdout is line-buffered by default, so unless you write a newline, nothing will be printed to the console.
You need to flush the stdout after you write the line prefix:
fn start(){
print!(">>");
io::stdout().flush().unwrap();
}

Objective-C macro giving a parse error: Expected identifier [duplicate]

This question already has answers here:
Macro compiler error: "Parse Issue" when an argument name appears elsewhere
(2 answers)
Closed 9 years ago.
The following macro is giving me a parse error. Can't see what's wrong here.
#define adjust(tag, x, y) if (self.tag==tag) { origin.x += x; origin.y += y; return origin; }
....
adjust(20, 28, 265)
EDIT:
Look at the attached screenshot. I want to use macro expansion just to improve the code readability. It's a very local usage, hence no risk or reuse etc.
Your macro refers to an undefined attribute origin, which if it doesn't exist in the scope of the replacement, will cause a compiler error after the macro has been expanded. Actually, as a whole, your macro isn't very modular. For example, you have references to tag and self, which are attributes that
Would be very contextual
Would cause compilation to fail if they do not occur and have specific meaning after macro expansion has been completed