Testing your crate C-API
source link: https://dev.to/luzero/testing-your-crate-c-api-19nc
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Testing your crate C-API
Nov 22
・2 min read
I wrote previously about cargo-c.
It is a good solution if you want to use your rust crates from C: with minimal changes you get a set of libraries, header and pkg-config that downstream application won't feel any different than a normal C library.
But an itch was left. I wanted to have proper tests and make so they won't feel much different than what we have in the cargo ecosystem.
The long-term plan was to make cargo build the C code as a stand alone Unit and link everything together in the test runner. Getting it right requires lots of time and so far I hadn't had enough.
Inline-c
Recently I stumbled upon inline-c and it felt like a great shortcut.
It let you write tests by embedding C code and then have the procedural macro invoke the compiler with the parameters pass using the usual env variables: CC
, CFLAGS
, LDFLAGS
and so on.
#[test]
fn test_api_something() {
set_var("INLINE_C_RS_CFLAGS", "-Iinclude/something/")
set_var("INLINE_C_RS_LDFLAGS", "-Llib/path -lsomething")
(assert_c! {
#include <something.h>
int main() {
SomeThing *thing = NULL;
int ret = some_init(&thing);
if (ret != 0)
return -1;
...
some_destroy(&thing);
return 0;
}
})
.success()
}
It does work nicely but it requires to feed it the right include and library search path.
cargo ctest
cargo-c produces the header and library in known locations so it is fairly easy to set the env variables accordingly and makes the whole experience much nicer.
All you need to do is to add inline-c
to your [dev-dependencies].
[dev-dependencies]
inline-c = "0.1"
Write the test without having to care about where the header and the libraries are:
#[cfg(feature = "capi")]
mod capi {
use inline_c::assert_c;
#[test]
fn test_capi() {
(assert_c! {
#include <example_project.h>
#include <stdio.h>
int main() {
ExampleProjectOddCounter *counter = example_project_oddcounter_new(4);
if (counter) {
printf("Unexpected success\n");
return 1;
}
counter = example_project_oddcounter_new(5);
if (!counter) {
printf("Error creating ExampleProjectOddCounter\n");
return 1;
}
example_project_oddcounter_increment(counter);
uint32_t result = example_project_oddcounter_get_current(counter);
example_project_oddcounter_free(counter);
if (result == 7) {
return 0;
} else {
printf("Error: unexpected result: %d\n", result);
return 1;
}
}
})
.success();
}
}
And then run the tests through cargo-c:
$ cargo ctest
It is available since version 0.6.17
that I just released on crates.io.
Enjoy!
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK