From: Dan Robertson Date: Tue, 23 Oct 2018 23:25:58 +0000 (+0000) Subject: test: Add basic test for VaList X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=e9e084f5fa8820aca67e5cf0ec301e52bbae1028;p=rust.git test: Add basic test for VaList --- 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 index 00000000000..f124ca2ab61 --- /dev/null +++ b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/Makefile @@ -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 index 00000000000..d4cc4a0ed5e --- /dev/null +++ b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs @@ -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 or the MIT license +// , 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::(); + if d.floor() != tmp.floor() { + println!("Double: {} != {}", d, tmp); + return i + 1; + } + } + Answer { tag: AnswerType::Long, data: AnswerData { long: l } } => { + let tmp = ap.arg::(); + if *l != tmp { + println!("Long: {} != {}", l, tmp); + return i + 1; + } + } + Answer { tag: AnswerType::LongLong, data: AnswerData { longlong: l } } => { + let tmp = ap.arg::(); + if *l != tmp { + println!("Long Long: {} != {}", l, tmp); + return i + 1; + } + } + Answer { tag: AnswerType::Int, data: AnswerData { int: n } } => { + let tmp = ap.arg::(); + if *n != tmp { + println!("Int: {} != {}", n, tmp); + return i + 1; + } + } + Answer { tag: AnswerType::Byte, data: AnswerData { byte: b } } => { + let tmp = ap.arg::(); + 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::(); } + AnswerType::Long => { ap.arg::(); } + AnswerType::LongLong => { ap.arg::(); } + AnswerType::Int => { ap.arg::(); } + AnswerType::Byte => { ap.arg::(); } + 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 index 00000000000..80d9a480142 --- /dev/null +++ b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#include +#include +#include +#include + +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; +}