Skip to content

Commit f1d7bda

Browse files
authored
tests: Add tests for public interface of DecodeError (#1120)
1 parent 258231d commit f1d7bda

File tree

2 files changed

+177
-0
lines changed

2 files changed

+177
-0
lines changed

tests/src/decode_error.rs

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
#![cfg(test)]
2+
3+
use alloc::{boxed::Box, string::ToString, vec::Vec};
4+
use prost::Message;
5+
use protobuf::test_messages::proto3::TestAllTypesProto3;
6+
7+
#[test]
8+
fn test_decode_error_invalid_wire_type() {
9+
let msg = [0x36].as_slice();
10+
assert_eq!(
11+
TestAllTypesProto3::decode(msg).unwrap_err().to_string(),
12+
"failed to decode Protobuf message: invalid wire type value: 6"
13+
);
14+
}
15+
16+
#[test]
17+
fn test_decode_error_invalid_varint() {
18+
let msg = [0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF].as_slice();
19+
assert_eq!(
20+
TestAllTypesProto3::decode(msg).unwrap_err().to_string(),
21+
"failed to decode Protobuf message: TestAllTypesProto3.optional_int32: invalid varint"
22+
);
23+
}
24+
25+
#[test]
26+
fn test_decode_error_multiple_levels() {
27+
use protobuf::test_messages::proto3::ForeignMessage;
28+
let msg = TestAllTypesProto3 {
29+
recursive_message: Some(Box::new(TestAllTypesProto3 {
30+
optional_foreign_message: Some(ForeignMessage { c: -1 }),
31+
..Default::default()
32+
})),
33+
..Default::default()
34+
};
35+
let mut buf = msg.encode_to_vec();
36+
37+
// Last byte is part of varint value `-1`. Set it to an invalid value.
38+
assert_eq!(buf.last().unwrap(), &0x01);
39+
*buf.last_mut().unwrap() = 0xFF;
40+
41+
assert_eq!(
42+
TestAllTypesProto3::decode(buf.as_slice()).unwrap_err().to_string(),
43+
"failed to decode Protobuf message: ForeignMessage.c: TestAllTypesProto3.optional_foreign_message: TestAllTypesProto3.recursive_message: invalid varint"
44+
);
45+
}
46+
47+
#[cfg(not(target_pointer_width = "64"))]
48+
#[test]
49+
fn test_decode_error_length_delimiter_too_large() {
50+
assert!((usize::MAX as u64) < u64::MAX);
51+
52+
let msg = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01].as_slice();
53+
assert_eq!(
54+
prost::decode_length_delimiter(msg).unwrap_err().to_string(),
55+
"failed to decode Protobuf message: length delimiter exceeds maximum usize value"
56+
);
57+
}
58+
59+
#[cfg(not(feature = "no-recursion-limit"))]
60+
#[test]
61+
fn test_decode_error_recursion_limit_reached() {
62+
let recursve_message = {
63+
let mut msg = TestAllTypesProto3::default();
64+
for _ in 0..101 {
65+
msg = TestAllTypesProto3 {
66+
recursive_message: Some(Box::new(msg)),
67+
..Default::default()
68+
};
69+
}
70+
msg
71+
};
72+
73+
let buf = recursve_message.encode_to_vec();
74+
assert_eq!(
75+
TestAllTypesProto3::decode(buf.as_slice()).unwrap_err().to_string(),
76+
"failed to decode Protobuf message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: TestAllTypesProto3.recursive_message: recursion limit reached"
77+
);
78+
}
79+
80+
#[test]
81+
fn test_decode_error_invalid_key_value() {
82+
let msg = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01].as_slice();
83+
assert_eq!(
84+
TestAllTypesProto3::decode(msg).unwrap_err().to_string(),
85+
"failed to decode Protobuf message: invalid key value: 1125899906842623"
86+
);
87+
}
88+
89+
#[test]
90+
fn test_decode_error_invalid_tag() {
91+
let msg = [0x00].as_slice();
92+
assert_eq!(
93+
TestAllTypesProto3::decode(msg).unwrap_err().to_string(),
94+
"failed to decode Protobuf message: invalid tag value: 0"
95+
);
96+
}
97+
98+
#[test]
99+
fn test_decode_error_unexpected_wire_type() {
100+
let mut buf = [0x00].as_slice();
101+
let mut msg = TestAllTypesProto3::default();
102+
let ctx = prost::encoding::DecodeContext::default();
103+
assert_eq!(
104+
msg.merge_field(1, prost::encoding::WireType::LengthDelimited, &mut buf, ctx).unwrap_err().to_string(),
105+
"failed to decode Protobuf message: TestAllTypesProto3.optional_int32: invalid wire type: LengthDelimited (expected Varint)"
106+
);
107+
}
108+
109+
#[test]
110+
fn test_decode_error_buffer_underflow() {
111+
let msg = [0x12].as_slice();
112+
assert_eq!(
113+
TestAllTypesProto3::decode_length_delimited(msg)
114+
.unwrap_err()
115+
.to_string(),
116+
"failed to decode Protobuf message: buffer underflow"
117+
);
118+
}
119+
120+
#[test]
121+
fn test_decode_error_invalid_string() {
122+
let msg = TestAllTypesProto3 {
123+
optional_string: "Hello".to_string(),
124+
..Default::default()
125+
};
126+
let mut buf = msg.encode_to_vec();
127+
128+
// Last byte is part of string value `o`. Set it to an invalid value.
129+
assert_eq!(buf.last().unwrap(), &b'o');
130+
*buf.last_mut().unwrap() = 0xA0;
131+
132+
assert_eq!(
133+
TestAllTypesProto3::decode(buf.as_slice()).unwrap_err().to_string(),
134+
"failed to decode Protobuf message: TestAllTypesProto3.optional_string: invalid string value: data is not UTF-8 encoded"
135+
);
136+
}
137+
138+
#[test]
139+
fn test_decode_error_any() {
140+
use prost_types::{Any, Timestamp};
141+
142+
let msg = Any {
143+
type_url: "non-existing-url".to_string(),
144+
value: Vec::new(),
145+
};
146+
147+
assert_eq!(
148+
msg.to_msg::<Timestamp>().unwrap_err().to_string(),
149+
"failed to decode Protobuf message: unexpected type URL.type_url: expected type URL: \"type.googleapis.com/google.protobuf.Timestamp\" (got: \"non-existing-url\")"
150+
);
151+
}
152+
153+
#[test]
154+
fn test_push() {
155+
let mut decode_error = prost::DecodeError::new("something failed");
156+
decode_error.push("Foo bad", "bar.foo");
157+
decode_error.push("Baz bad", "bar.baz");
158+
159+
assert_eq!(
160+
decode_error.to_string(),
161+
"failed to decode Protobuf message: Foo bad.bar.foo: Baz bad.bar.baz: something failed"
162+
);
163+
}
164+
165+
#[cfg(feature = "std")]
166+
#[test]
167+
fn test_into_std_io_error() {
168+
let decode_error = prost::DecodeError::new("something failed");
169+
let std_io_error = std::io::Error::from(decode_error);
170+
171+
assert_eq!(std_io_error.kind(), std::io::ErrorKind::InvalidData);
172+
assert_eq!(
173+
std_io_error.to_string(),
174+
"failed to decode Protobuf message: something failed"
175+
);
176+
}

tests/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ cfg_if! {
2424
}
2525
}
2626

27+
pub mod decode_error;
2728
pub mod extern_paths;
2829
pub mod no_root_packages;
2930
pub mod packages;

0 commit comments

Comments
 (0)