Skip to content

Commit 7f5b41f

Browse files
committed
Add tests for error_enum_use_lower_camel_case
1 parent 5489486 commit 7f5b41f

File tree

10 files changed

+445
-0
lines changed

10 files changed

+445
-0
lines changed

Cargo.lock

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ members = [
2828
"fixtures/coverall",
2929
"fixtures/callbacks",
3030
"fixtures/error-types",
31+
"fixtures/error-types-swift",
3132

3233
"fixtures/ext-types/custom-types",
3334
"fixtures/ext-types/http-headermap",

fixtures/error-types-swift/Cargo.toml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[package]
2+
name = "uniffi-fixture-error-types-swift"
3+
version = "0.22.0"
4+
edition = "2021"
5+
license = "MPL-2.0"
6+
publish = false
7+
8+
[lib]
9+
crate-type = ["lib", "cdylib"]
10+
name = "uniffi_error_types"
11+
12+
[dependencies]
13+
uniffi = {path = "../../uniffi"}
14+
anyhow = "1"
15+
thiserror = "1.0"
16+
17+
[build-dependencies]
18+
uniffi = {path = "../../uniffi", features = ["build"] }
19+
20+
[dev-dependencies]
21+
uniffi = {path = "../../uniffi", features = ["bindgen-tests"] }
22+
23+
[features]
24+
ffi-trace = ["uniffi/ffi-trace"]

fixtures/error-types-swift/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Tests for the `error_enum_use_lower_camel_case` uniffi configuration.

fixtures/error-types-swift/build.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
fn main() {
6+
uniffi::generate_scaffolding("./src/error_types.udl").unwrap();
7+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
namespace error_types {
2+
[Throws=ErrorInterface]
3+
void oops();
4+
5+
[Throws=ErrorInterface]
6+
void oops_nowrap();
7+
8+
ErrorInterface get_error(string message);
9+
10+
[Throws=RichError]
11+
void throw_rich(string message);
12+
};
13+
14+
interface TestInterface {
15+
constructor();
16+
17+
[Throws=ErrorInterface, Name="fallible_new"]
18+
constructor();
19+
20+
[Throws=ErrorInterface]
21+
void oops();
22+
};
23+
24+
[Traits=(Debug, Display)]
25+
interface ErrorInterface {
26+
sequence<string> chain();
27+
string? link(u64 index);
28+
};
29+
30+
// Kotlin replaces a trailing "Error" with "Exception"
31+
// for enums, so we should check it does for objects too.
32+
[Traits=(Debug, Display)]
33+
interface RichError {
34+
};

fixtures/error-types-swift/src/lib.rs

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
use std::sync::Arc;
6+
7+
#[derive(Debug, thiserror::Error)]
8+
#[error("{e:?}")]
9+
pub struct ErrorInterface {
10+
e: anyhow::Error,
11+
}
12+
13+
impl ErrorInterface {
14+
fn chain(&self) -> Vec<String> {
15+
self.e.chain().map(ToString::to_string).collect()
16+
}
17+
fn link(&self, ndx: u64) -> Option<String> {
18+
self.e.chain().nth(ndx as usize).map(ToString::to_string)
19+
}
20+
}
21+
22+
// A conversion into our ErrorInterface from anyhow::Error.
23+
// We can't use this implicitly yet, but it still helps.
24+
impl From<anyhow::Error> for ErrorInterface {
25+
fn from(e: anyhow::Error) -> Self {
26+
Self { e }
27+
}
28+
}
29+
30+
// Test an interface as the error type
31+
fn oops() -> Result<(), Arc<ErrorInterface>> {
32+
// must do explicit conversion to convert anyhow::Error into ErrorInterface
33+
Err(Arc::new(
34+
anyhow::Error::msg("oops")
35+
.context("because uniffi told me so")
36+
.into(),
37+
))
38+
}
39+
40+
// Like `oops`, but let UniFFI handle wrapping the interface with an arc
41+
fn oops_nowrap() -> Result<(), ErrorInterface> {
42+
// must do explicit conversion to convert anyhow::Error into ErrorInterface
43+
Err(anyhow::Error::msg("oops")
44+
.context("because uniffi told me so")
45+
.into())
46+
}
47+
48+
#[uniffi::export]
49+
fn toops() -> Result<(), Arc<dyn ErrorTrait>> {
50+
Err(Arc::new(ErrorTraitImpl {
51+
m: "trait-oops".to_string(),
52+
}))
53+
}
54+
55+
#[uniffi::export]
56+
async fn aoops() -> Result<(), Arc<ErrorInterface>> {
57+
Err(Arc::new(anyhow::Error::msg("async-oops").into()))
58+
}
59+
60+
fn get_error(message: String) -> std::sync::Arc<ErrorInterface> {
61+
Arc::new(anyhow::Error::msg(message).into())
62+
}
63+
64+
#[uniffi::export]
65+
pub trait ErrorTrait: Send + Sync + std::fmt::Debug + std::error::Error {
66+
fn msg(&self) -> String;
67+
}
68+
69+
#[derive(Debug, thiserror::Error)]
70+
#[error("{m:?}")]
71+
struct ErrorTraitImpl {
72+
m: String,
73+
}
74+
75+
impl ErrorTrait for ErrorTraitImpl {
76+
fn msg(&self) -> String {
77+
self.m.clone()
78+
}
79+
}
80+
81+
fn throw_rich(e: String) -> Result<(), RichError> {
82+
Err(RichError { e })
83+
}
84+
85+
// Exists to test trailing "Error" mapping in bindings
86+
#[derive(Debug, thiserror::Error)]
87+
#[error("RichError: {e:?}")]
88+
pub struct RichError {
89+
e: String,
90+
}
91+
92+
impl RichError {}
93+
94+
pub struct TestInterface {}
95+
96+
impl TestInterface {
97+
fn new() -> Self {
98+
TestInterface {}
99+
}
100+
101+
fn fallible_new() -> Result<Self, Arc<ErrorInterface>> {
102+
Err(Arc::new(anyhow::Error::msg("fallible_new").into()))
103+
}
104+
105+
fn oops(&self) -> Result<(), Arc<ErrorInterface>> {
106+
Err(Arc::new(
107+
anyhow::Error::msg("oops")
108+
.context("because the interface told me so")
109+
.into(),
110+
))
111+
}
112+
}
113+
114+
#[uniffi::export]
115+
impl TestInterface {
116+
// can't define this in UDL due to #1915
117+
async fn aoops(&self) -> Result<(), Arc<ErrorInterface>> {
118+
Err(Arc::new(anyhow::Error::msg("async-oops").into()))
119+
}
120+
}
121+
122+
// A procmacro as an error
123+
#[derive(Debug, uniffi::Object, thiserror::Error)]
124+
#[uniffi::export(Debug, Display)]
125+
pub struct ProcErrorInterface {
126+
e: String,
127+
}
128+
129+
#[uniffi::export]
130+
impl ProcErrorInterface {
131+
fn message(&self) -> String {
132+
self.e.clone()
133+
}
134+
}
135+
136+
impl std::fmt::Display for ProcErrorInterface {
137+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138+
write!(f, "ProcErrorInterface({})", self.e)
139+
}
140+
}
141+
142+
#[uniffi::export]
143+
fn throw_proc_error(e: String) -> Result<(), Arc<ProcErrorInterface>> {
144+
Err(Arc::new(ProcErrorInterface { e }))
145+
}
146+
147+
#[uniffi::export]
148+
fn return_proc_error(e: String) -> Arc<ProcErrorInterface> {
149+
Arc::new(ProcErrorInterface { e })
150+
}
151+
152+
#[derive(thiserror::Error, Debug)]
153+
#[error("NonUniffiTypeValue: {v}")]
154+
pub struct NonUniffiType {
155+
v: String,
156+
}
157+
158+
// Note: It's important for this test that this error
159+
// *not* be used directly as the `Err` for any functions etc.
160+
#[derive(thiserror::Error, uniffi::Error, Debug)]
161+
pub enum Inner {
162+
#[error("{0}")]
163+
CaseA(String),
164+
}
165+
166+
// Note: It's important for this test that this error
167+
// *not* be used directly as the `Err` for any functions etc.
168+
#[derive(thiserror::Error, uniffi::Error, Debug)]
169+
#[uniffi(flat_error)]
170+
pub enum FlatInner {
171+
#[error("{0}")]
172+
CaseA(String),
173+
#[error("{0}")]
174+
CaseB(NonUniffiType),
175+
}
176+
177+
// Enums have good coverage elsewhere, but simple coverage here is good.
178+
#[derive(thiserror::Error, uniffi::Error, Debug)]
179+
pub enum Error {
180+
#[error("Oops")]
181+
Oops,
182+
#[error("Value: {value}")]
183+
Value { value: String },
184+
#[error("IntValue: {value}")]
185+
IntValue { value: u16 },
186+
#[error(transparent)]
187+
FlatInnerError {
188+
#[from]
189+
error: FlatInner,
190+
},
191+
#[error(transparent)]
192+
InnerError { error: Inner },
193+
}
194+
195+
#[uniffi::export]
196+
fn oops_enum(i: u16) -> Result<(), Error> {
197+
if i == 0 {
198+
Err(Error::Oops)
199+
} else if i == 1 {
200+
Err(Error::Value {
201+
value: "value".to_string(),
202+
})
203+
} else if i == 2 {
204+
Err(Error::IntValue { value: i })
205+
} else if i == 3 {
206+
Err(Error::FlatInnerError {
207+
error: FlatInner::CaseA("inner".to_string()),
208+
})
209+
} else if i == 4 {
210+
Err(Error::FlatInnerError {
211+
error: FlatInner::CaseB(NonUniffiType {
212+
v: "value".to_string(),
213+
}),
214+
})
215+
} else if i == 5 {
216+
Err(Error::InnerError {
217+
error: Inner::CaseA("inner".to_string()),
218+
})
219+
} else {
220+
panic!("unknown variant {i}")
221+
}
222+
}
223+
224+
// tuple enum as an error.
225+
#[derive(thiserror::Error, uniffi::Error, Debug)]
226+
pub enum TupleError {
227+
#[error("Oops")]
228+
Oops(String),
229+
#[error("Value {0}")]
230+
Value(u16),
231+
}
232+
233+
#[uniffi::export]
234+
fn oops_tuple(i: u16) -> Result<(), TupleError> {
235+
if i == 0 {
236+
Err(TupleError::Oops("oops".to_string()))
237+
} else if i == 1 {
238+
Err(TupleError::Value(i))
239+
} else {
240+
panic!("unknown variant {i}")
241+
}
242+
}
243+
244+
#[uniffi::export(default(t = None))]
245+
fn get_tuple(t: Option<TupleError>) -> TupleError {
246+
t.unwrap_or_else(|| TupleError::Oops("oops".to_string()))
247+
}
248+
249+
uniffi::include_scaffolding!("error_types");

0 commit comments

Comments
 (0)