Skip to content

Commit 5bd9984

Browse files
committed
Make itests use expect and expect_err for fallible conversion testing
Add some tests to ensure conversion works as expected Document things
1 parent 5bd5f24 commit 5bd9984

File tree

9 files changed

+313
-65
lines changed

9 files changed

+313
-65
lines changed

godot-codegen/src/central_generator.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -596,17 +596,6 @@ fn make_sys_code(central_items: &CentralItems) -> TokenStream {
596596
}
597597
}
598598

599-
impl std::fmt::Display for VariantType {
600-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
601-
match self {
602-
Self::Nil => f.write_str("Nil"),
603-
#(
604-
Self::#variant_ty_enumerators_pascal => f.write_str(stringify!(#variant_ty_enumerators_pascal)),
605-
)*
606-
}
607-
}
608-
}
609-
610599
// ----------------------------------------------------------------------------------------------------------------------------------------------
611600

612601
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]

godot-core/src/builtin/meta/godot_convert/convert_error.rs

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@
44
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
55
*/
66

7-
use std::error::Error as StdError;
7+
use std::error::Error;
88
use std::fmt;
99

1010
use godot_ffi::VariantType;
1111

1212
use crate::builtin::{array_inner, meta::ClassName};
1313

14-
type Cause = Box<dyn StdError + Send + Sync + 'static>;
14+
type Cause = Box<dyn Error + Send + Sync>;
1515

16+
/// Represents errors that can occur when converting values from Godot.
1617
#[derive(Debug)]
1718
pub struct ConvertError {
1819
kind: ErrorKind,
@@ -21,7 +22,7 @@ pub struct ConvertError {
2122
}
2223

2324
impl ConvertError {
24-
/// Create a new error for conversion of type `T`.
25+
/// Create a new error for a conversion.
2526
fn new(kind: ErrorKind) -> Self {
2627
Self {
2728
kind,
@@ -30,8 +31,9 @@ impl ConvertError {
3031
}
3132
}
3233

33-
pub fn custom<C: Into<Cause>>(cause: C) -> Self {
34-
Self::new(ErrorKind::Custom).with_cause(cause)
34+
/// Create a new custom error for a conversion.
35+
pub fn custom() -> Self {
36+
Self::new(ErrorKind::Custom)
3537
}
3638

3739
/// Add a rust-error as an underlying cause for the conversion error.
@@ -40,12 +42,22 @@ impl ConvertError {
4042
self
4143
}
4244

45+
/// Returns the rust-error that caused this error, if one exists.
46+
pub fn cause(&self) -> Option<&(dyn Error + Send + Sync)> {
47+
self.cause.as_deref()
48+
}
49+
4350
/// Add the value that failed to be converted.
4451
pub fn with_value<V: fmt::Debug + 'static>(mut self, value: V) -> Self {
4552
self.value = Some(Box::new(value));
4653
self
4754
}
4855

56+
/// Returns the value that failed to convert, if one exists.
57+
pub fn value(&self) -> Option<&(dyn fmt::Debug)> {
58+
self.value.as_deref()
59+
}
60+
4961
fn description(&self) -> Option<String> {
5062
self.kind.description()
5163
}
@@ -68,11 +80,11 @@ impl fmt::Display for ConvertError {
6880
}
6981
}
7082

71-
impl StdError for ConvertError {
72-
fn source(&self) -> Option<&(dyn StdError + 'static)> {
83+
impl Error for ConvertError {
84+
fn source(&self) -> Option<&(dyn Error + 'static)> {
7385
self.cause
7486
.as_ref()
75-
.map(|cause| &**cause as &(dyn StdError + 'static))
87+
.map(|cause| &**cause as &(dyn Error + 'static))
7688
}
7789
}
7890

@@ -115,13 +127,13 @@ impl FromGodotError {
115127
if expected.variant_type() != got.variant_type() {
116128
if expected.is_typed() {
117129
return format!(
118-
"expected array of type {}, got array of type {}",
130+
"expected array of type {:?}, got array of type {:?}",
119131
expected.variant_type(),
120132
got.variant_type()
121133
);
122134
} else {
123135
return format!(
124-
"expected untyped array, got array of type {}",
136+
"expected untyped array, got array of type {:?}",
125137
got.variant_type()
126138
);
127139
}
@@ -209,7 +221,7 @@ impl FromVariantError {
209221
fn description(&self) -> String {
210222
match self {
211223
Self::BadType { expected, got } => {
212-
format!("expected Variant of type `{expected}` but got Variant of type `{got}`")
224+
format!("expected Variant of type `{expected:?}` but got Variant of type `{got:?}`")
213225
}
214226
Self::WrongClass { expected } => {
215227
format!("got variant of wrong class, expected class `{expected}`")

godot-core/src/builtin/variant/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use sys::{ffi_methods, interface_fn, GodotFfi};
1212

1313
mod impls;
1414

15-
pub use impls::*;
1615
pub use sys::{VariantOperator, VariantType};
1716

1817
use super::meta::{impl_godot_as_self, FromGodot, ToGodot};

godot-macros/src/derive/derive_from_variant.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub fn derive_from_godot(decl: Declaration) -> ParseResult<TokenStream> {
2525

2626
let mut body = quote! {
2727
let root = variant.try_to::<::godot::builtin::Dictionary>()?;
28-
let root = root.get(#name_string).ok_or(ConvertError::custom(concat!("missing expected value ", #name_string)).with_value(root.clone()))?;
28+
let root = root.get(#name_string).ok_or(ConvertError::custom().with_cause(concat!("missing expected value ", #name_string)).with_value(root.clone()))?;
2929
};
3030

3131
match decl {
@@ -94,7 +94,7 @@ pub fn derive_from_godot(decl: Declaration) -> ParseResult<TokenStream> {
9494
body = quote! {
9595
#body
9696
#matches
97-
Err(ConvertError::custom("unknown error"))
97+
Err(ConvertError::custom())
9898
};
9999
}
100100
}
@@ -131,7 +131,7 @@ fn make_named_struct(
131131
} else {
132132
(
133133
quote! {
134-
let #ident = root.get(#string_ident).ok_or(ConvertError::custom(concat!("missing expected value ", #string_ident)).with_value(root.clone()))?;
134+
let #ident = root.get(#string_ident).ok_or(ConvertError::custom().with_cause(concat!("missing expected value ", #string_ident)).with_value(root.clone()))?;
135135
},
136136
quote! { #ident: #ident.try_to()? },
137137
)
@@ -165,7 +165,7 @@ fn make_tuple_struct(
165165
} else {
166166
quote! {
167167
let #ident = root.pop_front()
168-
.ok_or(ConvertError::custom("missing expected value").with_value(root.clone()))?
168+
.ok_or(ConvertError::custom().with_cause("missing expected value").with_value(root.clone()))?
169169
.try_to::<#field_type>()?;
170170
}
171171
},
@@ -252,7 +252,7 @@ fn make_enum_tuple(
252252
} else {
253253
quote! {
254254
let #ident = variant.pop_front()
255-
.ok_or(ConvertError::custom("missing expected value").with_value(variant.clone()))?
255+
.ok_or(ConvertError::custom().with_cause("missing expected value").with_value(variant.clone()))?
256256
.try_to::<#field_type>()?;
257257
}
258258
};
@@ -287,7 +287,7 @@ fn make_enum_named(
287287
} else {
288288
quote! {
289289
let #field_name = variant.get(#field_name_string)
290-
.ok_or(ConvertError::custom(concat!("missing expected value ", #field_name_string)).with_value(variant.clone()))?
290+
.ok_or(ConvertError::custom().with_cause(concat!("missing expected value ", #field_name_string)).with_value(variant.clone()))?
291291
.try_to::<#field_type>()?;
292292
}
293293
};

itest/rust/src/builtin_tests/containers/array_test.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -418,8 +418,11 @@ fn typed_array_return_from_godot_func() {
418418
fn typed_array_try_from_untyped() {
419419
let node = Node::new_alloc();
420420
let array = VariantArray::from(&[node.clone().to_variant()]);
421-
let converted = array.to_variant().try_to::<Array<Option<Gd<Node>>>>();
422-
assert!(converted.is_err(), "converted = {converted:?}");
421+
422+
array
423+
.to_variant()
424+
.try_to::<Array<Option<Gd<Node>>>>()
425+
.expect_err("untyped array should not coerce to typed array");
423426

424427
node.free();
425428
}
@@ -428,8 +431,11 @@ fn typed_array_try_from_untyped() {
428431
fn untyped_array_try_from_typed() {
429432
let node = Node::new_alloc();
430433
let array = Array::<Option<Gd<Node>>>::from(&[Some(node.clone())]);
431-
let converted = array.to_variant().try_to::<VariantArray>();
432-
assert!(converted.is_err(), "converted = {converted:?}");
434+
435+
array
436+
.to_variant()
437+
.try_to::<VariantArray>()
438+
.expect_err("typed array should not coerce to untyped array");
433439

434440
node.free();
435441
}

itest/rust/src/builtin_tests/containers/variant_test.rs

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,11 @@ fn variant_call() {
120120
let result = variant.call("set_position", &[position.to_variant()]);
121121
assert!(result.is_nil());
122122

123-
let result = variant.call("get_position", &[]);
124-
assert_eq!(
125-
result
126-
.try_to::<Vector2>()
127-
.expect("`get_position` should return Vector2"),
128-
position
129-
);
123+
let result = variant
124+
.call("get_position", &[])
125+
.try_to::<Vector2>()
126+
.expect("`get_position` should return Vector2");
127+
assert_eq!(result, position);
130128

131129
let result = variant.call("to_string", &[]);
132130
assert_eq!(result.get_type(), VariantType::String);
@@ -300,19 +298,29 @@ fn variant_null_object_is_nil() {
300298

301299
#[itest]
302300
fn variant_conversion_fails() {
303-
assert!("hello".to_variant().try_to::<i64>().is_err(),);
304-
assert!(28.to_variant().try_to::<f32>().is_err());
305-
assert!(10.to_variant().try_to::<bool>().is_err());
306-
assert!(false.to_variant().try_to::<String>().is_err());
307-
assert!(VariantArray::default()
308-
.to_variant()
309-
.try_to::<StringName>()
310-
.is_err());
301+
fn assert_convert_err<T: ToGodot, U: FromGodot + std::fmt::Debug>(value: T) {
302+
use std::any::type_name;
303+
value.to_variant().try_to::<U>().expect_err(&format!(
304+
"`{}` should not convert to `{}`",
305+
type_name::<T>(),
306+
type_name::<U>()
307+
));
308+
}
309+
310+
assert_convert_err::<_, i64>("hello");
311+
assert_convert_err::<i32, f32>(28);
312+
assert_convert_err::<i32, bool>(10);
313+
assert_convert_err::<_, String>(false);
314+
assert_convert_err::<_, StringName>(VariantArray::default());
315+
311316
//assert_eq!(
312317
// Dictionary::default().to_variant().try_to::<Array>(),
313318
// Err(VariantConversionError)
314319
//);
315-
assert!(Variant::nil().to_variant().try_to::<Dictionary>().is_err());
320+
Variant::nil()
321+
.to_variant()
322+
.try_to::<Dictionary>()
323+
.expect_err("`nil` should not convert to `Dictionary`");
316324
}
317325

318326
#[itest]

0 commit comments

Comments
 (0)