Skip to content

Commit e9e084f

Browse files
committed
test: Add basic test for VaList
1 parent 0814087 commit e9e084f

File tree

3 files changed

+243
-0
lines changed

3 files changed

+243
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
-include ../tools.mk
2+
3+
all:
4+
$(RUSTC) checkrust.rs
5+
$(CC) test.c $(call STATICLIB,checkrust) $(call OUT_EXE,test) $(EXTRACFLAGS)
6+
$(call RUN,test)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_type = "staticlib"]
12+
#![feature(c_variadic)]
13+
#![feature(libc)]
14+
15+
extern crate libc;
16+
17+
use libc::{c_char, c_double, c_int, c_long, c_longlong};
18+
use std::ffi::VaList;
19+
use std::slice;
20+
use std::ffi::CStr;
21+
22+
#[repr(C)]
23+
#[derive(Clone, Copy, Debug)]
24+
pub enum AnswerType {
25+
Double,
26+
Long,
27+
LongLong,
28+
Int,
29+
Byte,
30+
CStr,
31+
Skip,
32+
}
33+
34+
#[repr(C)]
35+
pub union AnswerData {
36+
pub double: c_double,
37+
pub long: c_long,
38+
pub longlong: c_longlong,
39+
pub int: c_int,
40+
pub byte: c_char,
41+
pub cstr: *const c_char,
42+
pub skip_ty: AnswerType,
43+
}
44+
45+
#[repr(C)]
46+
pub struct Answer {
47+
tag: AnswerType,
48+
data: AnswerData,
49+
}
50+
51+
#[no_mangle]
52+
pub unsafe fn compare_answers(answers: &[Answer], mut ap: VaList) -> usize {
53+
for (i, answer) in answers.iter().enumerate() {
54+
match answer {
55+
Answer { tag: AnswerType::Double, data: AnswerData { double: d } } => {
56+
let tmp = ap.arg::<c_double>();
57+
if d.floor() != tmp.floor() {
58+
println!("Double: {} != {}", d, tmp);
59+
return i + 1;
60+
}
61+
}
62+
Answer { tag: AnswerType::Long, data: AnswerData { long: l } } => {
63+
let tmp = ap.arg::<c_long>();
64+
if *l != tmp {
65+
println!("Long: {} != {}", l, tmp);
66+
return i + 1;
67+
}
68+
}
69+
Answer { tag: AnswerType::LongLong, data: AnswerData { longlong: l } } => {
70+
let tmp = ap.arg::<c_longlong>();
71+
if *l != tmp {
72+
println!("Long Long: {} != {}", l, tmp);
73+
return i + 1;
74+
}
75+
}
76+
Answer { tag: AnswerType::Int, data: AnswerData { int: n } } => {
77+
let tmp = ap.arg::<c_int>();
78+
if *n != tmp {
79+
println!("Int: {} != {}", n, tmp);
80+
return i + 1;
81+
}
82+
}
83+
Answer { tag: AnswerType::Byte, data: AnswerData { byte: b } } => {
84+
let tmp = ap.arg::<c_char>();
85+
if *b != tmp {
86+
println!("Byte: {} != {}", b, tmp);
87+
return i + 1;
88+
}
89+
}
90+
Answer { tag: AnswerType::CStr, data: AnswerData { cstr: c0 } } => {
91+
let c1 = ap.arg::<*const c_char>();
92+
let cstr0 = CStr::from_ptr(*c0);
93+
let cstr1 = CStr::from_ptr(c1);
94+
if cstr0 != cstr1 {
95+
println!("C String: {:?} != {:?}", cstr0, cstr1);
96+
return i + 1;
97+
}
98+
}
99+
_ => {
100+
println!("Unknown type!");
101+
return i + 1;
102+
}
103+
}
104+
}
105+
return 0;
106+
}
107+
108+
#[no_mangle]
109+
pub unsafe extern "C" fn check_rust(argc: usize, answers: *const Answer, ap: VaList) -> usize {
110+
let slice = slice::from_raw_parts(answers, argc);
111+
compare_answers(slice, ap)
112+
}
113+
114+
#[no_mangle]
115+
pub unsafe extern "C" fn check_rust_copy(argc: usize, answers: *const Answer,
116+
mut ap: VaList) -> usize {
117+
let slice = slice::from_raw_parts(answers, argc);
118+
let mut skip_n = 0;
119+
for (i, answer) in slice.iter().enumerate() {
120+
match answer {
121+
Answer { tag: AnswerType::Skip, data: AnswerData { skip_ty } } => {
122+
match skip_ty {
123+
AnswerType::Double => { ap.arg::<c_double>(); }
124+
AnswerType::Long => { ap.arg::<c_long>(); }
125+
AnswerType::LongLong => { ap.arg::<c_longlong>(); }
126+
AnswerType::Int => { ap.arg::<c_int>(); }
127+
AnswerType::Byte => { ap.arg::<c_char>(); }
128+
AnswerType::CStr => { ap.arg::<*const c_char>(); }
129+
_ => { return i; }
130+
};
131+
}
132+
_ => {
133+
skip_n = i;
134+
break;
135+
}
136+
}
137+
}
138+
139+
ap.copy(|ap| {
140+
compare_answers(&slice[skip_n..], ap)
141+
})
142+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#include <stdarg.h>
12+
#include <assert.h>
13+
#include <stdint.h>
14+
#include <stdlib.h>
15+
16+
typedef enum {
17+
TAG_DOUBLE,
18+
TAG_LONG,
19+
TAG_LONGLONG,
20+
TAG_INT,
21+
TAG_BYTE,
22+
TAG_CSTR,
23+
TAG_SKIP,
24+
} tag;
25+
26+
typedef struct {
27+
tag answer_type;
28+
union {
29+
double double_precision;
30+
long num_long;
31+
long long num_longlong;
32+
int num_int;
33+
int8_t byte;
34+
char* cstr;
35+
tag skip_ty;
36+
} answer_data;
37+
} answer;
38+
39+
#define MK_DOUBLE(n) \
40+
{ TAG_DOUBLE, { .double_precision = n } }
41+
#define MK_LONG(n) \
42+
{ TAG_LONG, { .num_long = n } }
43+
#define MK_LONGLONG(n) \
44+
{ TAG_LONGLONG, { .num_longlong = n } }
45+
#define MK_INT(n) \
46+
{ TAG_INT, { .num_int = n } }
47+
#define MK_BYTE(b) \
48+
{ TAG_BYTE, { .byte = b } }
49+
#define MK_CSTR(s) \
50+
{ TAG_CSTR, { .cstr = s } }
51+
#define MK_SKIP(ty) \
52+
{ TAG_SKIP, { .skip_ty = TAG_ ## ty } }
53+
54+
extern size_t check_rust(size_t argc, const answer* answers, va_list ap);
55+
extern size_t check_rust_copy(size_t argc, const answer* answers, va_list ap);
56+
57+
size_t test_check_rust(size_t argc, const answer* answers, ...) {
58+
size_t ret = 0;
59+
va_list ap;
60+
va_start(ap, answers);
61+
ret = check_rust(argc, answers, ap);
62+
va_end(ap);
63+
return ret;
64+
}
65+
66+
size_t test_check_rust_copy(size_t argc, const answer* answers, ...) {
67+
size_t ret = 0;
68+
va_list ap;
69+
va_start(ap, answers);
70+
ret = check_rust_copy(argc, answers, ap);
71+
va_end(ap);
72+
return ret;
73+
}
74+
75+
int main(int argc, char* argv[]) {
76+
answer test_alignment0[] = {MK_LONGLONG(0x01LL), MK_INT(0x02), MK_LONGLONG(0x03LL)};
77+
assert(test_check_rust(3, test_alignment0, 0x01LL, 0x02, 0x03LL) == 0);
78+
79+
answer test_alignment1[] = {MK_INT(-1), MK_BYTE('A'), MK_BYTE('4'), MK_BYTE(';'),
80+
MK_INT(0x32), MK_INT(0x10000001), MK_CSTR("Valid!")};
81+
assert(test_check_rust(7, test_alignment1, -1, 'A', '4', ';', 0x32, 0x10000001,
82+
"Valid!") == 0);
83+
84+
answer basic_answers[] = {MK_DOUBLE(3.14), MK_LONG(12l), MK_BYTE('a'),
85+
MK_DOUBLE(6.28), MK_CSTR("Hello"), MK_INT(42),
86+
MK_CSTR("World")};
87+
assert(test_check_rust(7, basic_answers, 3.14, 12l, 'a', 6.28, "Hello",
88+
42, "World") == 0);
89+
90+
answer copy_answers[] = { MK_SKIP(DOUBLE), MK_SKIP(INT), MK_SKIP(BYTE), MK_SKIP(CSTR),
91+
MK_CSTR("Correctly skipped and copied list") };
92+
assert(test_check_rust_copy(5, copy_answers, 6.28, 16, 'A', "Skip Me!",
93+
"Correctly skipped and copied list") == 0);
94+
return 0;
95+
}

0 commit comments

Comments
 (0)