Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test code for returning Result<transparent struct, transparent struct> #212

Closed
NiwakaDev opened this issue Apr 19, 2023 · 2 comments
Closed
Labels
good first issue Good for newcomers

Comments

@NiwakaDev
Copy link
Collaborator

NiwakaDev commented Apr 19, 2023

Related to #168.

I found that returning Result<transparent struct, transparent struct> works correctly without needing any PRs.

But, I think that we need to add any tests for returning Result<transparent struct, transparent struct>.

I guess that the following test codes might be helpful as references.

Codegen Test:

/// Test code generation for Rust function that returns a Result<T, E> where T is a transparent enum type and
/// E is a opaque Rust type.
mod extern_rust_fn_return_result_transparent_enum_type_and_opaque_rust_type {
use super::*;
fn bridge_module_tokens() -> TokenStream {
quote! {
mod ffi {
enum SomeOkEnum {
Variant1,
Variant2(i32),
}
extern "Rust" {
type SomeErrType;
}
extern "Rust" {
fn some_function() -> Result<SomeOkEnum, SomeErrType>;
}
}
}
}
fn expected_rust_tokens() -> ExpectedRustTokens {
ExpectedRustTokens::Contains(quote! {
#[repr(C)]
pub enum ResultSomeOkEnumAndSomeErrType{
Ok(__swift_bridge__SomeOkEnum),
Err(*mut super::SomeErrType),
}
#[export_name = "__swift_bridge__$some_function"]
pub extern "C" fn __swift_bridge__some_function() -> ResultSomeOkEnumAndSomeErrType{
match super::some_function() {
Ok(ok) => ResultSomeOkEnumAndSomeErrType::Ok(ok.into_ffi_repr()),
Err(err) => ResultSomeOkEnumAndSomeErrType::Err(Box::into_raw(Box::new({
let val: super::SomeErrType = err;
val
})) as *mut super::SomeErrType),
}
}
})
}
fn expected_swift_code() -> ExpectedSwiftCode {
ExpectedSwiftCode::ContainsAfterTrim(
r#"
public func some_function() throws -> SomeOkEnum {
try { let val = __swift_bridge__$some_function(); switch val.tag { case __swift_bridge__$ResultSomeOkEnumAndSomeErrType$ResultOk: return val.payload.ok.intoSwiftRepr() case __swift_bridge__$ResultSomeOkEnumAndSomeErrType$ResultErr: throw SomeErrType(ptr: val.payload.err) default: fatalError() } }()
}
"#,
)
}
fn expected_c_header() -> ExpectedCHeader {
ExpectedCHeader::ContainsManyAfterTrim(vec![
r#"
typedef enum __swift_bridge__$ResultSomeOkEnumAndSomeErrType$Tag {__swift_bridge__$ResultSomeOkEnumAndSomeErrType$ResultOk, __swift_bridge__$ResultSomeOkEnumAndSomeErrType$ResultErr} __swift_bridge__$ResultSomeOkEnumAndSomeErrType$Tag;
union __swift_bridge__$ResultSomeOkEnumAndSomeErrType$Fields {struct __swift_bridge__$SomeOkEnum ok; void* err;};
typedef struct __swift_bridge__$ResultSomeOkEnumAndSomeErrType{__swift_bridge__$ResultSomeOkEnumAndSomeErrType$Tag tag; union __swift_bridge__$ResultSomeOkEnumAndSomeErrType$Fields payload;} __swift_bridge__$ResultSomeOkEnumAndSomeErrType;
"#,
r#"struct __swift_bridge__$ResultSomeOkEnumAndSomeErrType __swift_bridge__$some_function(void)"#,
])
}
#[test]
fn extern_rust_result_transparent_enum_type_and_opaque_rust_type() {
CodegenTest {
bridge_module: bridge_module_tokens().into(),
expected_rust_tokens: expected_rust_tokens(),
expected_swift_code: expected_swift_code(),
expected_c_header: expected_c_header(),
}
.test();
}
}

Integration Test:

/// Verify that we can receive a Result<TransparentEnum, OpaqueRust> from Rust
func testResultTransparentEnumOpaqueRust() throws {
XCTContext.runActivity(named: "Should return a ResultTestOpaqueRustType") {
_ in
do {
let resultTransparentEnum : ResultTransparentEnum = try rust_func_return_result_transparent_enum_opaque_rust(true)
switch resultTransparentEnum {
case .NamedField(let data):
XCTAssertEqual(data, 123)
case .UnnamedFields(_, _):
XCTFail()
case .NoFields:
XCTFail()
}
} catch {
XCTFail()
}
}
XCTContext.runActivity(named: "Should throw an error") {
_ in
do {
let _: ResultTransparentEnum = try rust_func_return_result_transparent_enum_opaque_rust(false)
XCTFail("The function should have returned an error.")
} catch _ as ResultTestOpaqueRustType {
} catch {
XCTFail()
}
}
}

And then we need to update examples/async-functions/src/lib.rs:

// TODO: Return a `Result<MyIpAddress, SomeErrorType>`
// Once we support returning Result from an async function.

@NiwakaDev NiwakaDev added the good first issue Good for newcomers label Apr 19, 2023
@NiwakaDev NiwakaDev changed the title Update examples/async-functions and add test code for Result<struct, struct> Update examples/async-functions and add test code for Result<transparent struct, transparent struct> Apr 19, 2023
@NiwakaDev NiwakaDev changed the title Update examples/async-functions and add test code for Result<transparent struct, transparent struct> Add test code for Result<transparent struct, transparent struct> Apr 19, 2023
@NiwakaDev NiwakaDev changed the title Add test code for Result<transparent struct, transparent struct> Add test code for returning Result<transparent struct, transparent struct> Apr 19, 2023
@NiwakaDev NiwakaDev changed the title Add test code for returning Result<transparent struct, transparent struct> Add test code for returning Result<transparent struct, transparent struct> Apr 19, 2023
@chinedufn
Copy link
Owner

chinedufn commented Apr 22, 2023

Thanks for adding a guide!

Should we close this and instead add your guide to #168 ?

As in, maybe move your comment from this PR to #168 ?

Then whenever someone adds a test / updates the example we can close #168 .

@NiwakaDev
Copy link
Collaborator Author

Sure. I move this comment to #168 and then close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

2 participants