mirror of
https://github.com/topjohnwu/cxx.git
synced 2025-02-24 01:52:27 +00:00
Merge pull request #38 from dtolnay/suite
Add test suite covering various permutations of signatures
This commit is contained in:
commit
d1010bdb39
@ -29,8 +29,9 @@ thiserror = "1.0"
|
||||
cc = "1.0.49"
|
||||
|
||||
[dev-dependencies]
|
||||
cxx-test-suite = { version = "0", path = "tests/ffi" }
|
||||
rustversion = "1.0"
|
||||
trybuild = "1.0"
|
||||
trybuild = "1.0.21"
|
||||
|
||||
[workspace]
|
||||
members = ["cmd", "demo-rs", "macro"]
|
||||
members = ["cmd", "demo-rs", "macro", "tests/ffi"]
|
||||
|
14
tests/ffi/Cargo.toml
Normal file
14
tests/ffi/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "cxx-test-suite"
|
||||
version = "0.0.0"
|
||||
edition = "2018"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
cxx = { path = "../.." }
|
||||
|
||||
[build-dependencies]
|
||||
cxx = { path = "../.." }
|
11
tests/ffi/build.rs
Normal file
11
tests/ffi/build.rs
Normal file
@ -0,0 +1,11 @@
|
||||
fn main() {
|
||||
if cfg!(trybuild) {
|
||||
return;
|
||||
}
|
||||
|
||||
cxx::Build::new()
|
||||
.bridge("lib.rs")
|
||||
.file("tests.cc")
|
||||
.flag("-std=c++11")
|
||||
.compile("cxx-test-suite");
|
||||
}
|
115
tests/ffi/lib.rs
Normal file
115
tests/ffi/lib.rs
Normal file
@ -0,0 +1,115 @@
|
||||
use cxx::{CxxString, UniquePtr};
|
||||
|
||||
#[cxx::bridge(namespace = tests)]
|
||||
pub mod ffi {
|
||||
struct Shared {
|
||||
z: usize,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
include!("tests/ffi/tests.h");
|
||||
|
||||
type C;
|
||||
|
||||
fn c_return_primitive() -> usize;
|
||||
fn c_return_shared() -> Shared;
|
||||
//TODO fn c_return_box() -> Box<R>;
|
||||
fn c_return_unique_ptr() -> UniquePtr<C>;
|
||||
fn c_return_ref(shared: &Shared) -> &usize;
|
||||
fn c_return_str(shared: &Shared) -> &str;
|
||||
fn c_return_rust_string() -> String;
|
||||
fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
|
||||
|
||||
fn c_take_primitive(n: usize);
|
||||
fn c_take_shared(shared: Shared);
|
||||
fn c_take_box(r: Box<R>);
|
||||
fn c_take_unique_ptr(c: UniquePtr<C>);
|
||||
//TODO fn c_take_ref_r(r: &R);
|
||||
fn c_take_ref_c(c: &C);
|
||||
fn c_take_str(s: &str);
|
||||
fn c_take_rust_string(s: String);
|
||||
fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
type R;
|
||||
|
||||
fn r_return_primitive() -> usize;
|
||||
fn r_return_shared() -> Shared;
|
||||
//TODO fn r_return_box() -> Box<R>;
|
||||
//TODO fn r_return_unique_ptr() -> UniquePtr<C>;
|
||||
fn r_return_ref(shared: &Shared) -> &usize;
|
||||
fn r_return_str(shared: &Shared) -> &str;
|
||||
fn r_return_rust_string() -> String;
|
||||
//TODO fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
|
||||
|
||||
fn r_take_primitive(n: usize);
|
||||
fn r_take_shared(shared: Shared);
|
||||
fn r_take_box(r: Box<R>);
|
||||
fn r_take_unique_ptr(c: UniquePtr<C>);
|
||||
fn r_take_ref_r(r: &R);
|
||||
fn r_take_ref_c(c: &C);
|
||||
fn r_take_str(s: &str);
|
||||
fn r_take_rust_string(s: String);
|
||||
fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
|
||||
}
|
||||
}
|
||||
|
||||
type R = ();
|
||||
|
||||
fn r_return_primitive() -> usize {
|
||||
2020
|
||||
}
|
||||
|
||||
fn r_return_shared() -> ffi::Shared {
|
||||
ffi::Shared { z: 2020 }
|
||||
}
|
||||
|
||||
fn r_return_ref(shared: &ffi::Shared) -> &usize {
|
||||
&shared.z
|
||||
}
|
||||
|
||||
fn r_return_str(shared: &ffi::Shared) -> &str {
|
||||
let _ = shared;
|
||||
"2020"
|
||||
}
|
||||
|
||||
fn r_return_rust_string() -> String {
|
||||
"2020".to_owned()
|
||||
}
|
||||
|
||||
fn r_take_primitive(n: usize) {
|
||||
assert_eq!(n, 2020);
|
||||
}
|
||||
|
||||
fn r_take_shared(shared: ffi::Shared) {
|
||||
assert_eq!(shared.z, 2020);
|
||||
}
|
||||
|
||||
fn r_take_box(r: Box<R>) {
|
||||
let _ = r;
|
||||
}
|
||||
|
||||
fn r_take_unique_ptr(c: UniquePtr<ffi::C>) {
|
||||
let _ = c;
|
||||
}
|
||||
|
||||
fn r_take_ref_r(r: &R) {
|
||||
let _ = r;
|
||||
}
|
||||
|
||||
fn r_take_ref_c(c: &ffi::C) {
|
||||
let _ = c;
|
||||
}
|
||||
|
||||
fn r_take_str(s: &str) {
|
||||
assert_eq!(s, "2020");
|
||||
}
|
||||
|
||||
fn r_take_rust_string(s: String) {
|
||||
assert_eq!(s, "2020");
|
||||
}
|
||||
|
||||
fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
|
||||
assert_eq!(s.as_ref().unwrap().to_str().unwrap(), "2020");
|
||||
}
|
111
tests/ffi/tests.cc
Normal file
111
tests/ffi/tests.cc
Normal file
@ -0,0 +1,111 @@
|
||||
#include "tests/ffi/tests.h"
|
||||
#include "tests/ffi/lib.rs"
|
||||
|
||||
extern "C" void cxx_test_suite_set_correct();
|
||||
|
||||
namespace tests {
|
||||
|
||||
C::C(size_t n) : n(n) {}
|
||||
|
||||
size_t C::get() const { return this->n; }
|
||||
|
||||
size_t c_return_primitive() { return 2020; }
|
||||
|
||||
Shared c_return_shared() { return Shared{2020}; }
|
||||
|
||||
std::unique_ptr<C> c_return_unique_ptr() {
|
||||
return std::unique_ptr<C>(new C{2020});
|
||||
}
|
||||
|
||||
const size_t &c_return_ref(const Shared &shared) { return shared.z; }
|
||||
|
||||
cxxbridge::RustStr c_return_str(const Shared &shared) {
|
||||
(void)shared;
|
||||
return "2020";
|
||||
}
|
||||
|
||||
cxxbridge::RustString c_return_rust_string() { return "2020"; }
|
||||
|
||||
std::unique_ptr<std::string> c_return_unique_ptr_string() {
|
||||
return std::unique_ptr<std::string>(new std::string("2020"));
|
||||
}
|
||||
|
||||
void c_take_primitive(size_t n) {
|
||||
if (n == 2020) {
|
||||
cxx_test_suite_set_correct();
|
||||
}
|
||||
}
|
||||
|
||||
void c_take_shared(Shared shared) {
|
||||
if (shared.z == 2020) {
|
||||
cxx_test_suite_set_correct();
|
||||
}
|
||||
}
|
||||
|
||||
void c_take_box(cxxbridge::RustBox<R> r) {
|
||||
(void)r;
|
||||
cxx_test_suite_set_correct();
|
||||
}
|
||||
|
||||
void c_take_unique_ptr(std::unique_ptr<C> c) {
|
||||
if (c->get() == 2020) {
|
||||
cxx_test_suite_set_correct();
|
||||
}
|
||||
}
|
||||
|
||||
void c_take_ref_r(const R &r) { (void)r; }
|
||||
|
||||
void c_take_ref_c(const C &c) {
|
||||
if (c.get() == 2020) {
|
||||
cxx_test_suite_set_correct();
|
||||
}
|
||||
}
|
||||
|
||||
void c_take_str(cxxbridge::RustStr s) {
|
||||
if (std::string(s) == "2020") {
|
||||
cxx_test_suite_set_correct();
|
||||
}
|
||||
}
|
||||
|
||||
void c_take_rust_string(cxxbridge::RustString s) {
|
||||
if (std::string(s) == "2020") {
|
||||
cxx_test_suite_set_correct();
|
||||
}
|
||||
}
|
||||
|
||||
void c_take_unique_ptr_string(std::unique_ptr<std::string> s) {
|
||||
if (*s == "2020") {
|
||||
cxx_test_suite_set_correct();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" const char *cxx_run_test() noexcept {
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
#define ASSERT(x) \
|
||||
do { \
|
||||
if (!(x)) { \
|
||||
return "Assertion failed: `" #x "`, " __FILE__ ":" TOSTRING(__LINE__); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
ASSERT(r_return_primitive() == 2020);
|
||||
ASSERT(r_return_shared().z == 2020);
|
||||
ASSERT(r_return_ref(Shared{2020}) == 2020);
|
||||
ASSERT(std::string(r_return_str(Shared{2020})) == "2020");
|
||||
ASSERT(std::string(r_return_rust_string()) == "2020");
|
||||
|
||||
r_take_primitive(2020);
|
||||
r_take_shared(Shared{2020});
|
||||
r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
|
||||
r_take_ref_c(C{2020});
|
||||
r_take_str(cxxbridge::RustStr("2020"));
|
||||
// TODO r_take_rust_string(cxxbridge::RustString("2020"));
|
||||
r_take_unique_ptr_string(
|
||||
std::unique_ptr<std::string>(new std::string("2020")));
|
||||
|
||||
cxx_test_suite_set_correct();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace tests
|
39
tests/ffi/tests.h
Normal file
39
tests/ffi/tests.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#include "include/cxxbridge.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace tests {
|
||||
|
||||
struct R;
|
||||
struct Shared;
|
||||
|
||||
class C {
|
||||
public:
|
||||
C(size_t n);
|
||||
size_t get() const;
|
||||
|
||||
private:
|
||||
size_t n;
|
||||
};
|
||||
|
||||
size_t c_return_primitive();
|
||||
Shared c_return_shared();
|
||||
cxxbridge::RustBox<R> c_return_box();
|
||||
std::unique_ptr<C> c_return_unique_ptr();
|
||||
const size_t &c_return_ref(const Shared &shared);
|
||||
cxxbridge::RustStr c_return_str(const Shared &shared);
|
||||
cxxbridge::RustString c_return_rust_string();
|
||||
std::unique_ptr<std::string> c_return_unique_ptr_string();
|
||||
|
||||
void c_take_primitive(size_t n);
|
||||
void c_take_shared(Shared shared);
|
||||
void c_take_box(cxxbridge::RustBox<R> r);
|
||||
void c_take_unique_ptr(std::unique_ptr<C> c);
|
||||
void c_take_ref_r(const R &r);
|
||||
void c_take_ref_c(const C &c);
|
||||
void c_take_str(cxxbridge::RustStr s);
|
||||
void c_take_rust_string(cxxbridge::RustString s);
|
||||
void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
|
||||
|
||||
} // namespace tests
|
71
tests/test.rs
Normal file
71
tests/test.rs
Normal file
@ -0,0 +1,71 @@
|
||||
use cxx_test_suite::ffi;
|
||||
use std::cell::Cell;
|
||||
use std::ffi::CStr;
|
||||
|
||||
thread_local! {
|
||||
static CORRECT: Cell<bool> = Cell::new(false);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn cxx_test_suite_set_correct() {
|
||||
CORRECT.with(|correct| correct.set(true));
|
||||
}
|
||||
|
||||
macro_rules! check {
|
||||
($run:expr) => {{
|
||||
CORRECT.with(|correct| correct.set(false));
|
||||
$run;
|
||||
assert!(CORRECT.with(|correct| correct.get()), stringify!($run));
|
||||
}};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_c_return() {
|
||||
let shared = ffi::Shared { z: 2020 };
|
||||
|
||||
assert_eq!(2020, ffi::c_return_primitive());
|
||||
assert_eq!(2020, ffi::c_return_shared().z);
|
||||
ffi::c_return_unique_ptr();
|
||||
assert_eq!(2020, *ffi::c_return_ref(&shared));
|
||||
assert_eq!("2020", ffi::c_return_str(&shared));
|
||||
assert_eq!("2020", ffi::c_return_rust_string());
|
||||
assert_eq!(
|
||||
"2020",
|
||||
ffi::c_return_unique_ptr_string()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_c_take() {
|
||||
let unique_ptr = ffi::c_return_unique_ptr();
|
||||
|
||||
check!(ffi::c_take_primitive(2020));
|
||||
check!(ffi::c_take_shared(ffi::Shared { z: 2020 }));
|
||||
check!(ffi::c_take_box(Box::new(())));
|
||||
check!(ffi::c_take_ref_c(unique_ptr.as_ref().unwrap()));
|
||||
check!(ffi::c_take_unique_ptr(unique_ptr));
|
||||
check!(ffi::c_take_str("2020"));
|
||||
check!(ffi::c_take_rust_string("2020".to_owned()));
|
||||
check!(ffi::c_take_unique_ptr_string(
|
||||
ffi::c_return_unique_ptr_string()
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_c_call_r() {
|
||||
fn cxx_run_test() {
|
||||
extern "C" {
|
||||
fn cxx_run_test() -> *const i8;
|
||||
}
|
||||
let failure = unsafe { cxx_run_test() };
|
||||
if !failure.is_null() {
|
||||
let msg = unsafe { CStr::from_ptr(failure) };
|
||||
eprintln!("{}", msg.to_string_lossy());
|
||||
}
|
||||
}
|
||||
check!(cxx_run_test());
|
||||
}
|
8
third-party/Cargo.lock
generated
vendored
8
third-party/Cargo.lock
generated
vendored
@ -81,6 +81,7 @@ dependencies = [
|
||||
"cc",
|
||||
"codespan",
|
||||
"codespan-reporting",
|
||||
"cxx-test-suite",
|
||||
"cxxbridge-macro",
|
||||
"link-cplusplus",
|
||||
"proc-macro2",
|
||||
@ -91,6 +92,13 @@ dependencies = [
|
||||
"trybuild",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx-test-suite"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cxx",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-cmd"
|
||||
version = "0.1.2"
|
||||
|
Loading…
x
Reference in New Issue
Block a user