Skip to content

Commit e3bdb4c

Browse files
committed
use rstest instead of test_case
1 parent 2f1f9f9 commit e3bdb4c

File tree

3 files changed

+117
-142
lines changed

3 files changed

+117
-142
lines changed

Cargo.lock

Lines changed: 1 addition & 34 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

clarity-serialization/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ thiserror = { workspace = true }
2020

2121
[dev-dependencies]
2222
mutants = "0.0.3"
23-
test-case = { version = "3.3.1", default-features = false }
23+
rstest = "0.17.0"
2424

2525
[features]
2626
default = []

clarity-serialization/src/tests/representations.rs

Lines changed: 115 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -12,62 +12,63 @@
1212
//
1313
// You should have received a copy of the GNU General Public License
1414
// along with this program. If not, see <http://www.gnu.org/licenses/>.
15-
use std::io::Read;
1615

17-
use test_case::test_case;
16+
use rstest::rstest;
1817

1918
use crate::errors::CodecError;
2019
use crate::representations::{
2120
CONTRACT_MAX_NAME_LENGTH, CONTRACT_MIN_NAME_LENGTH, ClarityName, ContractName, MAX_STRING_LEN,
2221
};
2322
use crate::stacks_common::codec::StacksMessageCodec;
2423

25-
#[test_case("hello"; "valid_name")]
26-
#[test_case("hello-dash"; "dash")]
27-
#[test_case("hello_underscore"; "underscore")]
28-
#[test_case("test123"; "numbers")]
29-
#[test_case("a"; "single_letter")]
30-
#[test_case("set-token-uri!"; "exclamation_mark")]
31-
#[test_case("is-owner?"; "question_mark")]
32-
#[test_case("math+"; "plus")]
33-
#[test_case("greater-than<"; "less_than")]
34-
#[test_case("less-than>"; "greater_than")]
35-
#[test_case("<="; "less_than_or_equal_to")]
36-
#[test_case(">="; "greater_than_or_equal_to")]
37-
#[test_case("*"; "asterisk")]
38-
#[test_case("/"; "slash")]
39-
#[test_case("-"; "dash-only")]
40-
#[test_case("="; "equals")]
41-
fn test_clarity_name_valid(name: &str) {
24+
#[rstest]
25+
#[case::valid_name("hello")]
26+
#[case::dash("hello-dash")]
27+
#[case::underscore("hello_underscore")]
28+
#[case::numbers("test123")]
29+
#[case::single_letter("a")]
30+
#[case::exclamation_mark("set-token-uri!")]
31+
#[case::question_mark("is-owner?")]
32+
#[case::plus("math+")]
33+
#[case::less_than("greater-than<")]
34+
#[case::greater_than("less-than>")]
35+
#[case::less_than_or_equal_to("<=")]
36+
#[case::greater_than_or_equal_to(">=")]
37+
#[case::asterisk("*")]
38+
#[case::slash("/")]
39+
#[case::dash_only("-")]
40+
#[case::equals("=")]
41+
fn test_clarity_name_valid(#[case] name: &str) {
4242
let clarity_name = ClarityName::try_from(name.to_string())
4343
.unwrap_or_else(|_| panic!("Should parse valid clarity name: {name}"));
4444
assert_eq!(clarity_name.as_str(), name);
4545
}
4646

47-
#[test_case(""; "empty")]
48-
#[test_case("123abc"; "starts_with_number")]
49-
#[test_case("hello world"; "contains_space")]
50-
#[test_case("hello@world"; "contains_at")]
51-
#[test_case("hello#world"; "contains_hash")]
52-
#[test_case("hello$world"; "contains_dollar")]
53-
#[test_case("hello%world"; "contains_percent")]
54-
#[test_case("hello&world"; "contains_ampersand")]
55-
#[test_case("hello.world"; "contains_dot")]
56-
#[test_case("hello,world"; "contains_comma")]
57-
#[test_case("hello;world"; "contains_semicolon")]
58-
#[test_case("hello:world"; "contains_colon")]
59-
#[test_case("hello|world"; "contains_pipe")]
60-
#[test_case("hello\\world"; "contains_backslash")]
61-
#[test_case("hello\"world"; "contains_quote")]
62-
#[test_case("hello'world"; "contains_apostrophe")]
63-
#[test_case("hello[world"; "contains_bracket_open")]
64-
#[test_case("hello]world"; "contains_bracket_close")]
65-
#[test_case("hello{world"; "contains_curly_open")]
66-
#[test_case("hello}world"; "contains_curly_close")]
67-
#[test_case("hello(world"; "contains_parenthesis_open")]
68-
#[test_case("hello)world"; "contains_parenthesis_close")]
69-
#[test_case(&"a".repeat(MAX_STRING_LEN as usize + 1); "too_long")]
70-
fn test_clarity_name_invalid(name: &str) {
47+
#[rstest]
48+
#[case::empty("")]
49+
#[case::starts_with_number("123abc")]
50+
#[case::contains_space("hello world")]
51+
#[case::contains_at("hello@world")]
52+
#[case::contains_hash("hello#world")]
53+
#[case::contains_dollar("hello$world")]
54+
#[case::contains_percent("hello%world")]
55+
#[case::contains_ampersand("hello&world")]
56+
#[case::contains_dot("hello.world")]
57+
#[case::contains_comma("hello,world")]
58+
#[case::contains_semicolon("hello;world")]
59+
#[case::contains_colon("hello:world")]
60+
#[case::contains_pipe("hello|world")]
61+
#[case::contains_backslash("hello\\world")]
62+
#[case::contains_quote("hello\"world")]
63+
#[case::contains_apostrophe("hello'world")]
64+
#[case::contains_bracket_open("hello[world")]
65+
#[case::contains_bracket_close("hello]world")]
66+
#[case::contains_curly_open("hello{world")]
67+
#[case::contains_curly_close("hello}world")]
68+
#[case::contains_parenthesis_open("hello(world")]
69+
#[case::contains_parenthesis_close("hello)world")]
70+
#[case::too_long(&"a".repeat(MAX_STRING_LEN as usize + 1))]
71+
fn test_clarity_name_invalid(#[case] name: &str) {
7172
let result = ClarityName::try_from(name.to_string());
7273
assert!(result.is_err());
7374
assert!(matches!(
@@ -76,9 +77,10 @@ fn test_clarity_name_invalid(name: &str) {
7677
));
7778
}
7879

79-
#[test_case("test-name")]
80-
#[test_case(&"a".repeat(MAX_STRING_LEN as usize); "max-length")]
81-
fn test_clarity_name_serialization(name: &str) {
80+
#[rstest]
81+
#[case("test-name")]
82+
#[case::max_length(&"a".repeat(MAX_STRING_LEN as usize))]
83+
fn test_clarity_name_serialization(#[case] name: &str) {
8284
let name = ClarityName::try_from(name.to_string()).unwrap();
8385

8486
let mut buffer = Vec::new();
@@ -95,59 +97,62 @@ fn test_clarity_name_serialization(name: &str) {
9597
}
9698

9799
// the first byte is the length of the buffer.
98-
#[test_case(vec![4, 0xFF, 0xFE, 0xFD, 0xFC].as_slice(), "Failed to parse Clarity name: could not contruct from utf8"; "invalid_utf8")]
99-
#[test_case(vec![2, b'2', b'i'].as_slice(), "Failed to parse Clarity name: InvalidClarityName(\"ClarityName\", \"2i\")"; "invalid_name")] // starts with number
100-
#[test_case(vec![MAX_STRING_LEN + 1].as_slice(), "Failed to deserialize clarity name: too long"; "too_long")]
101-
#[test_case(vec![3, b'a'].as_slice(), "failed to fill whole buffer"; "wrong_length")]
102-
fn test_clarity_name_deserialization_errors<R: Read>(mut buffer: R, error_message: &str) {
103-
let result = ClarityName::consensus_deserialize(&mut buffer);
100+
#[rstest]
101+
#[case::invalid_utf8(vec![4, 0xFF, 0xFE, 0xFD, 0xFC], "Failed to parse Clarity name: could not contruct from utf8")]
102+
#[case::invalid_name(vec![2, b'2', b'i'], "Failed to parse Clarity name: InvalidClarityName(\"ClarityName\", \"2i\")")] // starts with number
103+
#[case::too_long(vec![MAX_STRING_LEN + 1], "Failed to deserialize clarity name: too long")]
104+
#[case::wrong_length(vec![3, b'a'], "failed to fill whole buffer")]
105+
fn test_clarity_name_deserialization_errors(#[case] buffer: Vec<u8>, #[case] error_message: &str) {
106+
let result = ClarityName::consensus_deserialize(&mut buffer.as_slice());
104107
assert!(result.is_err());
105108
assert_eq!(result.unwrap_err().to_string(), error_message);
106109
}
107110

108-
#[test_case("hello"; "valid_name")]
109-
#[test_case("contract-name"; "dash")]
110-
#[test_case("hello_world"; "underscore")]
111-
#[test_case("test123"; "numbers")]
112-
#[test_case("__transient"; "transient")]
113-
#[test_case("a"; "min_length")]
114-
#[test_case(&"a".repeat(CONTRACT_MAX_NAME_LENGTH); "max_length")]
115-
#[test_case(&"a".repeat(MAX_STRING_LEN as usize); "max_string_len")]
116-
fn test_contract_name_valid(name: &str) {
111+
#[rstest]
112+
#[case::valid_name("hello")]
113+
#[case::dash("contract-name")]
114+
#[case::underscore("hello_world")]
115+
#[case::numbers("test123")]
116+
#[case::transient("__transient")]
117+
#[case::min_length("a")]
118+
#[case::max_length(&"a".repeat(CONTRACT_MAX_NAME_LENGTH))]
119+
#[case::max_string_len(&"a".repeat(MAX_STRING_LEN as usize))]
120+
fn test_contract_name_valid(#[case] name: &str) {
117121
let contract_name = ContractName::try_from(name.to_string())
118122
.unwrap_or_else(|_| panic!("Should parse valid contract name: {name}"));
119123
assert_eq!(contract_name.as_str(), name);
120124
}
121125

122-
#[test_case(""; "emtpy")]
123-
#[test_case("123contract"; "starts_with_number")]
124-
#[test_case("hello world"; "contains_space")]
125-
#[test_case("hello@world"; "contains_at")]
126-
#[test_case("hello.world"; "contains_dot")]
127-
#[test_case("hello!world"; "contains_exclamation")]
128-
#[test_case("hello?world"; "contains_question")]
129-
#[test_case("hello+world"; "contains_plus")]
130-
#[test_case("hello*world"; "contains_asterisk")]
131-
#[test_case("hello=world"; "contains_equals")]
132-
#[test_case("hello/world"; "contains_slash")]
133-
#[test_case("hello<world"; "contains_less_than")]
134-
#[test_case("hello>world"; "contains_greater_than")]
135-
#[test_case("hello,world"; "contains_comma")]
136-
#[test_case("hello;world"; "contains_semicolon")]
137-
#[test_case("hello:world"; "contains_colon")]
138-
#[test_case("hello|world"; "contains_pipe")]
139-
#[test_case("hello\\world"; "contains_backslash")]
140-
#[test_case("hello\"world"; "contains_quote")]
141-
#[test_case("hello'world"; "contains_apostrophe")]
142-
#[test_case("hello[world"; "contains_bracket_open")]
143-
#[test_case("hello]world"; "contains_bracket_close")]
144-
#[test_case("hello{world"; "contains_curly_open")]
145-
#[test_case("hello}world"; "contains_curly_close")]
146-
#[test_case("hello(world"; "contains_parenthesis_open")]
147-
#[test_case("hello)world"; "contains_parenthesis_close")]
148-
#[test_case(&"a".repeat(CONTRACT_MIN_NAME_LENGTH - 1); "too_short")]
149-
#[test_case(&"a".repeat(MAX_STRING_LEN as usize + 1); "too_long")]
150-
fn test_contract_name_invalid(name: &str) {
126+
#[rstest]
127+
#[case::empty("")]
128+
#[case::starts_with_number("123contract")]
129+
#[case::contains_space("hello world")]
130+
#[case::contains_at("hello@world")]
131+
#[case::contains_dot("hello.world")]
132+
#[case::contains_exclamation("hello!world")]
133+
#[case::contains_question("hello?world")]
134+
#[case::contains_plus("hello+world")]
135+
#[case::contains_asterisk("hello*world")]
136+
#[case::contains_equals("hello=world")]
137+
#[case::contains_slash("hello/world")]
138+
#[case::contains_less_than("hello<world")]
139+
#[case::contains_greater_than("hello>world")]
140+
#[case::contains_comma("hello,world")]
141+
#[case::contains_semicolon("hello;world")]
142+
#[case::contains_colon("hello:world")]
143+
#[case::contains_pipe("hello|world")]
144+
#[case::contains_backslash("hello\\world")]
145+
#[case::contains_quote("hello\"world")]
146+
#[case::contains_apostrophe("hello'world")]
147+
#[case::contains_bracket_open("hello[world")]
148+
#[case::contains_bracket_close("hello]world")]
149+
#[case::contains_curly_open("hello{world")]
150+
#[case::contains_curly_close("hello}world")]
151+
#[case::contains_parenthesis_open("hello(world")]
152+
#[case::contains_parenthesis_close("hello)world")]
153+
#[case::too_short(&"a".repeat(CONTRACT_MIN_NAME_LENGTH - 1))]
154+
#[case::too_long(&"a".repeat(MAX_STRING_LEN as usize + 1))]
155+
fn test_contract_name_invalid(#[case] name: &str) {
151156
let result = ContractName::try_from(name.to_string());
152157
assert!(result.is_err());
153158
assert!(matches!(
@@ -156,14 +161,15 @@ fn test_contract_name_invalid(name: &str) {
156161
));
157162
}
158163

159-
#[test_case("test-contract"; "valid_name")]
160-
#[test_case("contract-name"; "dash")]
161-
#[test_case("hello_world"; "underscore")]
162-
#[test_case("test123"; "numbers")]
163-
#[test_case("__transient"; "transient")]
164-
#[test_case("a"; "min_length")]
165-
#[test_case(&"a".repeat(CONTRACT_MAX_NAME_LENGTH); "max_length")]
166-
fn test_contract_name_serialization(name: &str) {
164+
#[rstest]
165+
#[case::valid_name("test-contract")]
166+
#[case::dash("contract-name")]
167+
#[case::underscore("hello_world")]
168+
#[case::numbers("test123")]
169+
#[case::transient("__transient")]
170+
#[case::min_length("a")]
171+
#[case::max_length(&"a".repeat(CONTRACT_MAX_NAME_LENGTH))]
172+
fn test_contract_name_serialization(#[case] name: &str) {
167173
let name = ContractName::try_from(name.to_string()).unwrap();
168174
let mut buffer = Vec::with_capacity((name.len() + 1) as usize);
169175
name.consensus_serialize(&mut buffer)
@@ -176,9 +182,10 @@ fn test_contract_name_serialization(name: &str) {
176182
assert_eq!(deserialized, name);
177183
}
178184

179-
#[test_case(&"a".repeat(CONTRACT_MAX_NAME_LENGTH + 1); "too_long")]
180-
fn test_contract_name_serialization_too_long_or_short(name: &str) {
181-
let name = ContractName::try_from(name.to_string()).expect("should parse");
185+
#[test]
186+
fn test_contract_name_serialization_too_long() {
187+
let name =
188+
ContractName::try_from("a".repeat(CONTRACT_MAX_NAME_LENGTH + 1)).expect("should parse");
182189
let mut buffer = Vec::with_capacity((name.len() + 1) as usize);
183190
let result = name.consensus_serialize(&mut buffer);
184191
assert!(result.is_err());
@@ -192,12 +199,13 @@ fn test_contract_name_serialization_too_long_or_short(name: &str) {
192199
}
193200

194201
// the first byte is the length of the buffer.
195-
#[test_case(vec![4, 0xFF, 0xFE, 0xFD, 0xFC].as_slice(), "Failed to parse Contract name: could not construct from utf8"; "invalid_utf8")]
196-
#[test_case(vec![2, b'2', b'i'].as_slice(), "Failed to parse Contract name: InvalidContractName(\"ContractName\", \"2i\")"; "invalid_name")] // starts with number
197-
#[test_case(vec![MAX_STRING_LEN + 1].as_slice(), &format!("Failed to deserialize contract name: too short or too long: {}", MAX_STRING_LEN + 1); "too_long")]
198-
#[test_case(vec![3, b'a'].as_slice(), "failed to fill whole buffer"; "wrong_length")]
199-
fn test_contract_name_deserialization_errors<R: Read>(mut buffer: R, error_message: &str) {
200-
let result = ContractName::consensus_deserialize(&mut buffer);
202+
#[rstest]
203+
#[case::invalid_utf8(vec![4, 0xFF, 0xFE, 0xFD, 0xFC], "Failed to parse Contract name: could not construct from utf8")]
204+
#[case::invalid_name(vec![2, b'2', b'i'], "Failed to parse Contract name: InvalidContractName(\"ContractName\", \"2i\")")] // starts with number
205+
#[case::too_long(vec![MAX_STRING_LEN + 1], &format!("Failed to deserialize contract name: too short or too long: {}", MAX_STRING_LEN + 1))]
206+
#[case::wrong_length(vec![3, b'a'], "failed to fill whole buffer")]
207+
fn test_contract_name_deserialization_errors(#[case] buffer: Vec<u8>, #[case] error_message: &str) {
208+
let result = ContractName::consensus_deserialize(&mut buffer.as_slice());
201209
assert!(result.is_err());
202210
assert_eq!(result.unwrap_err().to_string(), error_message);
203211
}

0 commit comments

Comments
 (0)