mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-07-07 20:06:36 +02:00
improve output of C tests
This commit is contained in:
parent
41a578ab2b
commit
ca904d6288
5 changed files with 59 additions and 5 deletions
|
@ -18,6 +18,11 @@ fn build_libtaskchampion(suites: &[&'static str]) {
|
||||||
build.object(libtaskchampion);
|
build.object(libtaskchampion);
|
||||||
build.include("../lib");
|
build.include("../lib");
|
||||||
build.include("src/bindings_tests/unity");
|
build.include("src/bindings_tests/unity");
|
||||||
|
build.define("UNITY_OUTPUT_CHAR", "test_output");
|
||||||
|
build.define(
|
||||||
|
"UNITY_OUTPUT_CHAR_HEADER_DECLARATION",
|
||||||
|
"test_output(char c)",
|
||||||
|
);
|
||||||
build.file("src/bindings_tests/unity/unity.c");
|
build.file("src/bindings_tests/unity/unity.c");
|
||||||
|
|
||||||
let mut files = vec!["src/bindings_tests/test.c".to_string()];
|
let mut files = vec!["src/bindings_tests/test.c".to_string()];
|
||||||
|
|
|
@ -1,14 +1,28 @@
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
// set up to send test output to TEST-OUTPUT
|
||||||
|
fn setup_output();
|
||||||
|
// close the output file
|
||||||
|
fn finish_output();
|
||||||
|
}
|
||||||
|
|
||||||
// Each suite is represented by a <name>_tests C function in <name>.c.
|
// Each suite is represented by a <name>_tests C function in <name>.c.
|
||||||
// All of these C files are built into a library that is linked to the crate -- but not to test
|
// All of these C files are built into a library that is linked to the crate -- but not to test
|
||||||
// crates. So, this macro produces a "glue function" that calls the C function, and that can be
|
// crates. So, this macro produces a "glue function" that calls the C function, and that can be
|
||||||
// called from test crates.
|
// called from test crates.
|
||||||
macro_rules! suite(
|
macro_rules! suite(
|
||||||
{ $s:ident } => {
|
{ $s:ident } => {
|
||||||
pub fn $s() -> i32 {
|
pub fn $s() -> (i32, String) {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn $s() -> i32;
|
fn $s() -> i32;
|
||||||
}
|
}
|
||||||
unsafe { $s() }
|
unsafe { setup_output() };
|
||||||
|
let res = unsafe { $s() };
|
||||||
|
unsafe { finish_output() };
|
||||||
|
let output = fs::read_to_string("TEST-OUTPUT")
|
||||||
|
.unwrap_or_else(|e| format!("could not open TEST-OUTPUT: {}", e));
|
||||||
|
(res, output)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "unity.h"
|
|
||||||
#include "taskchampion.h"
|
#include "taskchampion.h"
|
||||||
|
#include "unity.h"
|
||||||
|
|
||||||
// creating an in-memory replica does not crash
|
// creating an in-memory replica does not crash
|
||||||
static void test_replica_creation(void) {
|
static void test_replica_creation(void) {
|
||||||
|
|
|
@ -1,6 +1,30 @@
|
||||||
|
#include <stdio.h>
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
|
|
||||||
// these functions are shared between all test "suites"
|
// these functions are shared between all test "suites"
|
||||||
// and cannot be customized per-suite.
|
// and cannot be customized per-suite.
|
||||||
void setUp(void) { }
|
void setUp(void) { }
|
||||||
void tearDown(void) { }
|
void tearDown(void) { }
|
||||||
|
|
||||||
|
static FILE *output = NULL;
|
||||||
|
|
||||||
|
// Set up for test_output, writing output to "TEST-OUTPUT" in the
|
||||||
|
// current directory. The Rust test harness reads this file to get
|
||||||
|
// the output and display it only on failure. This is called by
|
||||||
|
// the Rust test harness
|
||||||
|
void setup_output(void) {
|
||||||
|
output = fopen("TEST-OUTPUT", "w");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the output file. Called by the Rust test harness.
|
||||||
|
void finish_output(void) {
|
||||||
|
fclose(output);
|
||||||
|
output = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this replaces UNITY_OUTPUT_CHAR, and writes output to
|
||||||
|
// TEST-OUTPUT in the current directory; the Rust test harness
|
||||||
|
// will read this data if the test fails.
|
||||||
|
void test_output(char c) {
|
||||||
|
fputc(c, output);
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
use tempfile::TempDir;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
// the C library running the tests is not reentrant, so we use a mutex to ensure that only one
|
// the C library running the tests is not reentrant, so we use a mutex to ensure that only one
|
||||||
|
@ -11,8 +12,18 @@ macro_rules! suite(
|
||||||
{ $s:ident } => {
|
{ $s:ident } => {
|
||||||
#[test]
|
#[test]
|
||||||
fn $s() {
|
fn $s() {
|
||||||
let _guard = MUTEX.lock().unwrap();
|
let tmp_dir = TempDir::new().expect("TempDir failed");
|
||||||
assert_eq!(integration_tests::bindings_tests::$s(), 0);
|
let (res, output) = {
|
||||||
|
let _guard = MUTEX.lock().unwrap();
|
||||||
|
// run the tests in the temp dir (NOTE: this must be inside
|
||||||
|
// the mutex guard!)
|
||||||
|
std::env::set_current_dir(tmp_dir.as_ref()).unwrap();
|
||||||
|
integration_tests::bindings_tests::$s()
|
||||||
|
};
|
||||||
|
println!("{}", output);
|
||||||
|
if res != 0 {
|
||||||
|
assert!(false, "test failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue