]> git.lizzy.rs Git - rust.git/commitdiff
test: Add basic test for VaList
authorDan Robertson <danlrobertson89@gmail.com>
Tue, 23 Oct 2018 23:25:58 +0000 (23:25 +0000)
committerDan Robertson <dan@dlrobertson.com>
Mon, 26 Nov 2018 22:56:20 +0000 (22:56 +0000)
src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/Makefile [new file with mode: 0644]
src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs [new file with mode: 0644]
src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c [new file with mode: 0644]

diff --git a/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/Makefile b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/Makefile
new file mode 100644 (file)
index 0000000..f124ca2
--- /dev/null
@@ -0,0 +1,6 @@
+-include ../tools.mk
+
+all:
+       $(RUSTC) checkrust.rs
+       $(CC) test.c $(call STATICLIB,checkrust) $(call OUT_EXE,test) $(EXTRACFLAGS)
+       $(call RUN,test)
diff --git a/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs
new file mode 100644 (file)
index 0000000..d4cc4a0
--- /dev/null
@@ -0,0 +1,142 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "staticlib"]
+#![feature(c_variadic)]
+#![feature(libc)]
+
+extern crate libc;
+
+use libc::{c_char, c_double, c_int, c_long, c_longlong};
+use std::ffi::VaList;
+use std::slice;
+use std::ffi::CStr;
+
+#[repr(C)]
+#[derive(Clone, Copy, Debug)]
+pub enum AnswerType {
+    Double,
+    Long,
+    LongLong,
+    Int,
+    Byte,
+    CStr,
+    Skip,
+}
+
+#[repr(C)]
+pub union AnswerData {
+    pub double: c_double,
+    pub long: c_long,
+    pub longlong: c_longlong,
+    pub int: c_int,
+    pub byte: c_char,
+    pub cstr: *const c_char,
+    pub skip_ty: AnswerType,
+}
+
+#[repr(C)]
+pub struct Answer {
+    tag: AnswerType,
+    data: AnswerData,
+}
+
+#[no_mangle]
+pub unsafe fn compare_answers(answers: &[Answer], mut ap: VaList) -> usize {
+    for (i, answer) in answers.iter().enumerate() {
+        match answer {
+            Answer { tag: AnswerType::Double, data: AnswerData { double: d } } => {
+                let tmp = ap.arg::<c_double>();
+                if d.floor() != tmp.floor() {
+                    println!("Double: {} != {}", d, tmp);
+                    return i + 1;
+                }
+            }
+            Answer { tag: AnswerType::Long, data: AnswerData { long: l } } => {
+                let tmp =  ap.arg::<c_long>();
+                if *l != tmp {
+                    println!("Long: {} != {}", l, tmp);
+                    return i + 1;
+                }
+            }
+            Answer { tag: AnswerType::LongLong, data: AnswerData { longlong: l } } => {
+                let tmp =  ap.arg::<c_longlong>();
+                if *l != tmp {
+                    println!("Long Long: {} != {}", l, tmp);
+                    return i + 1;
+                }
+            }
+            Answer { tag: AnswerType::Int, data: AnswerData { int: n } } => {
+                let tmp = ap.arg::<c_int>();
+                if *n != tmp {
+                    println!("Int: {} != {}", n, tmp);
+                    return i + 1;
+                }
+            }
+            Answer { tag: AnswerType::Byte, data: AnswerData { byte: b } } => {
+                let tmp = ap.arg::<c_char>();
+                if *b != tmp {
+                    println!("Byte: {} != {}", b, tmp);
+                    return i + 1;
+                }
+            }
+            Answer { tag: AnswerType::CStr, data: AnswerData { cstr: c0 } } => {
+                let c1 = ap.arg::<*const c_char>();
+                let cstr0 = CStr::from_ptr(*c0);
+                let cstr1 = CStr::from_ptr(c1);
+                if cstr0 != cstr1 {
+                    println!("C String: {:?} != {:?}", cstr0, cstr1);
+                    return i + 1;
+                }
+            }
+            _ => {
+                println!("Unknown type!");
+                return i + 1;
+            }
+        }
+    }
+    return 0;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn check_rust(argc: usize, answers: *const Answer, ap: VaList) -> usize {
+    let slice = slice::from_raw_parts(answers, argc);
+    compare_answers(slice, ap)
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn check_rust_copy(argc: usize, answers: *const Answer,
+                                         mut ap: VaList) -> usize {
+    let slice = slice::from_raw_parts(answers, argc);
+    let mut skip_n = 0;
+    for (i, answer) in slice.iter().enumerate() {
+        match answer {
+            Answer { tag: AnswerType::Skip, data: AnswerData { skip_ty } } => {
+                match skip_ty {
+                    AnswerType::Double => { ap.arg::<c_double>(); }
+                    AnswerType::Long => { ap.arg::<c_long>(); }
+                    AnswerType::LongLong => { ap.arg::<c_longlong>(); }
+                    AnswerType::Int => { ap.arg::<c_int>(); }
+                    AnswerType::Byte => { ap.arg::<c_char>(); }
+                    AnswerType::CStr => { ap.arg::<*const c_char>(); }
+                    _ => { return i; }
+                };
+            }
+            _ => {
+                skip_n = i;
+                break;
+            }
+        }
+    }
+
+    ap.copy(|ap| {
+        compare_answers(&slice[skip_n..], ap)
+    })
+}
diff --git a/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c
new file mode 100644 (file)
index 0000000..80d9a48
--- /dev/null
@@ -0,0 +1,95 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#include <stdarg.h>
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+typedef enum {
+    TAG_DOUBLE,
+    TAG_LONG,
+    TAG_LONGLONG,
+    TAG_INT,
+    TAG_BYTE,
+    TAG_CSTR,
+    TAG_SKIP,
+} tag;
+
+typedef struct {
+    tag answer_type;
+    union {
+        double double_precision;
+        long num_long;
+        long long num_longlong;
+        int num_int;
+        int8_t byte;
+        char* cstr;
+        tag skip_ty;
+    } answer_data;
+} answer;
+
+#define MK_DOUBLE(n) \
+    { TAG_DOUBLE, { .double_precision = n } }
+#define MK_LONG(n) \
+    { TAG_LONG, { .num_long = n } }
+#define MK_LONGLONG(n) \
+    { TAG_LONGLONG, { .num_longlong = n } }
+#define MK_INT(n) \
+    { TAG_INT, { .num_int = n } }
+#define MK_BYTE(b) \
+    { TAG_BYTE, { .byte = b } }
+#define MK_CSTR(s) \
+    { TAG_CSTR, { .cstr = s } }
+#define MK_SKIP(ty) \
+    { TAG_SKIP, { .skip_ty = TAG_ ## ty } }
+
+extern size_t check_rust(size_t argc, const answer* answers, va_list ap);
+extern size_t check_rust_copy(size_t argc, const answer* answers, va_list ap);
+
+size_t test_check_rust(size_t argc, const answer* answers, ...) {
+    size_t ret = 0;
+    va_list ap;
+    va_start(ap, answers);
+    ret = check_rust(argc, answers, ap);
+    va_end(ap);
+    return ret;
+}
+
+size_t test_check_rust_copy(size_t argc, const answer* answers, ...) {
+    size_t ret = 0;
+    va_list ap;
+    va_start(ap, answers);
+    ret = check_rust_copy(argc, answers, ap);
+    va_end(ap);
+    return ret;
+}
+
+int main(int argc, char* argv[]) {
+    answer test_alignment0[] = {MK_LONGLONG(0x01LL), MK_INT(0x02), MK_LONGLONG(0x03LL)};
+    assert(test_check_rust(3, test_alignment0, 0x01LL, 0x02, 0x03LL) == 0);
+
+    answer test_alignment1[] = {MK_INT(-1), MK_BYTE('A'), MK_BYTE('4'), MK_BYTE(';'),
+                                MK_INT(0x32), MK_INT(0x10000001), MK_CSTR("Valid!")};
+    assert(test_check_rust(7, test_alignment1, -1, 'A', '4', ';', 0x32, 0x10000001,
+                           "Valid!") == 0);
+
+    answer basic_answers[] = {MK_DOUBLE(3.14), MK_LONG(12l), MK_BYTE('a'),
+                              MK_DOUBLE(6.28), MK_CSTR("Hello"), MK_INT(42),
+                              MK_CSTR("World")};
+    assert(test_check_rust(7, basic_answers, 3.14, 12l, 'a', 6.28, "Hello",
+                           42, "World") == 0);
+
+    answer copy_answers[] = { MK_SKIP(DOUBLE), MK_SKIP(INT), MK_SKIP(BYTE), MK_SKIP(CSTR),
+                              MK_CSTR("Correctly skipped and copied list") };
+    assert(test_check_rust_copy(5, copy_answers, 6.28, 16, 'A', "Skip Me!",
+                                "Correctly skipped and copied list") == 0);
+    return 0;
+}