ffi tests

This commit is contained in:
dzaima 2022-05-27 23:53:01 +03:00
parent 662b23d808
commit 12631cb142
7 changed files with 230 additions and 2 deletions

3
.gitignore vendored
View File

@ -10,3 +10,6 @@ perf.*
/Singeli
/local/
CBQNHeapDump
/test/ffi/ffiTest.o
/test/ffi/test.got
/test/ffi/lib.so

View File

@ -22,7 +22,7 @@ static BQNV makeX(B x) {
void bqn_free(BQNV v) {
dec(getB(v));
}
static void freeTagged (BQNV v) { }
static void freeTagged(BQNV v) { }
#define DIRECT_BQNV 1
double bqn_toF64 (BQNV v) { double r = o2fu(getB(v)); freeTagged(v); return r; }
@ -444,7 +444,7 @@ usz genObj(BQNFFIEnt ent, B c, bool anyMut) {
if (!isArr(c)) thrF("FFI: Expected array corresponding to \"*%S\"", sty_names[o2cu(e)]);
usz ia = a(c)->ia;
bool mut = t->a[0].mutPtr;
switch(o2cu(e)) { default: thrF("FFI: Unimplemented pointer to \"%S\"", sty_names[o2cu(e)]);
switch(o2cu(e)) { default: thrF("FFI: \"*%S\" argument type NYI", sty_names[o2cu(e)]);
case sty_i8: cG = mut? taga(cpyI8Arr (c)) : toI8Any (c); break;
case sty_i16: cG = mut? taga(cpyI16Arr(c)) : toI16Any(c); break;
case sty_i32: cG = mut? taga(cpyI32Arr(c)) : toI32Any(c); break;

View File

@ -12,4 +12,5 @@ test/moreCfgs.sh path/to/mlochbaum/BQN // run "2+2" in a bunch of configurations
./BQN test/bitcpy.bqn // fuzz-test bit_cpy; requires a CBQN build with -DTEST_BITCPY
./BQN test/squeeze.bqn // fuzz-test squeezing; requires a CBQN build with -DEEQUAL_NEGZERO
./BQN test/random.bqn // various random tests
make -C test/ffi // test FFI functionality
```

85
test/ffi/ffiTest.c Normal file
View File

@ -0,0 +1,85 @@
#include <stdlib.h>
#include <stdio.h>
#include "../../src/ffi.h"
void do_nothing() { }
BQNV timesTen(BQNV v) {
size_t len = bqn_bound(v);
int32_t* buf = malloc(len*4);
bqn_readI32Arr(v, buf);
for (int i = 0; i < len; i++) buf[i] = buf[i] * 10;
BQNV res = bqn_makeI32Vec(len, buf);
free(buf);
bqn_free(v);
return res;
}
BQNV add_args(BQNV t, BQNV x) {
return bqn_makeF64(bqn_toF64(t) + bqn_toF64(x));
}
BQNV bind_add(BQNV x) {
BQNV r = bqn_makeBoundFn1(add_args, x);
bqn_free(x);
return r;
}
void printArgs(int8_t i8, int16_t i16, int32_t i32, uint8_t u8, uint16_t u16, uint32_t u32, float f, double d) {
printf("args: %d %d %d %u %u %u %.18f %.18f\n", i8, i16, i32, u8, u16, u32, f, d);
}
void noopArgs(int8_t i8, int16_t i16, int32_t i32, uint8_t u8, uint16_t u16, uint32_t u32, float f, double d) { }
void printPtrArgs(int8_t* i8, int16_t* i16, int32_t* i32, uint8_t* u8, uint16_t* u16, uint32_t* u32, float* f, double* d) {
printf("args: %d %d %d %u %u %u %.18f %.18f\n", *i8, *i16, *i32, *u8, *u16, *u32, *f, *d);
}
float printU64s(uint64_t a, uint64_t* b) {
printf("%llx %llx %llx %llx\n", (long long)a, (long long)b[0], (long long)b[1], (long long)b[2]);
return 12345678;
}
int32_t multiplyI32Ptrs(int32_t* a, int32_t* b, int32_t len) {
int32_t r = 0;
for (int i = 0; i < len; i++) {
r+= a[i]*b[i];
}
return r;
}
float sumF32Arr(float* f, int len) {
float r = 0;
for (int i = 0; i < len; i++) r+= f[i];
return r;
}
void incI32s(int32_t* a, int32_t len) {
for (int i = 0; i < len; i++) a[i]++;
}
void incInts(int32_t* a, int16_t* b, int8_t* c) {
printf("%d %d %d\n", *a, *b, *c);
(*a)++;
(*b)++;
(*c)++;
}
uint64_t ident_u64(uint64_t x) { return x; }
double ident_f64(double a) { return a; }
void* pick_ptr(void** arr, int idx) {
return arr[idx];
}
uint64_t pick_u64(uint64_t* arr, int idx) {
return arr[idx];
}
int plusone(int x) {
return x + 1;
}

7
test/ffi/makefile Normal file
View File

@ -0,0 +1,7 @@
test: build
@../../BQN test.bqn > test.got
@diff --color -su test.expected test.got
build:
$(CC) -O3 -g -c -fpic ffiTest.c -o ffiTest.o
$(CC) -shared -olib.so ffiTest.o

71
test/ffi/test.bqn Normal file
View File

@ -0,0 +1,71 @@
f@
Section {•Out 𝕩˜@+10}
f "lib.so" •FFI """do_nothing" •Show F
Section "# ""a"""
f "lib.so" •FFI "a""timesTen""a" •Show F 10
bind "lib.so" •FFI "a""bind_add"">a" g Bind 4 •Show G 123
Section "# print args"
f "lib.so" •FFI """printArgs""i8""i16""i32""u8""u16""u32""f32""f64" •Show F ¯123¯12323¯212312312250500003123456789π1
f "lib.so" •FFI "" "noopArgs""i8""i16""i32""u8""u16""u32""f32""f64" •Show F ¯123¯12323¯212312312250500003123456789π1
f "lib.so" •FFI """printPtrArgs""*i8""*i16""*i32""*u8""*u16""*u32""*f32""*f64" •Show F ¨¯123¯12323¯212312312250500003123456789π1
f "lib.so" •FFI """printPtrArgs""&i8""&i16""&i32""&u8""&u16""&u32""&f32""&f64" •Show F ¨¯123¯12323¯212312312250500003123456789π1
f "lib.so" •FFI "f32""printU64s""u64:c8""*u64:c8" •Show F "hellowor", "aaaaaaaa12345678texttext"
f "lib.so" •FFI "f32""printU64s""u64:u1""*u64:u1" •Show F 64ר12, 192ר21
! 3 •Type "lib.so" •FFI """printArgs""i8""i16:c8""i32""u8""u16""u32""f32""f64"
! 3 •Type "lib.so" •FFI """printArgs""i8""i16:c16""i32""u8""u16""u32""f32""f64"
! 3 •Type "lib.so" •FFI """printArgs""i8:c8""i16""i32""u8""u16""u32""f32""f64"
Section "# read pointers"
f "lib.so" •FFI "i32""multiplyI32Ptrs""*i32""*i32""i32" •Show F 10 •Show 10 •Show 10
f "lib.so" •FFI "f32""sumF32Arr""*f32:i32""i32" •Show F 1065353216107374182410779361281082130432108422758410863247361088421888109051904010915676161092616192,10
Section "# mutate i32*"
f "lib.so" •FFI "","incI32s","&u32", "i32" •Show F 1e8×20+10 10
f "lib.so" •FFI "","incI32s","&i32:u1", "i32" •Show F 1010101001010011011000010101001000100010001110111111001100100100, 2
f "lib.so" •FFI "","incI32s","&i32:c8", "i32" •Show F "helloworld", 2
f "lib.so" •FFI "","incI32s",">𝕨&i32:c8",">i32" •Show "helloworld" F 2
f "lib.so" •FFI "", "incI32s", "&i32:c8", "i32" •Show F "helloworld", 2
f "lib.so" •FFI "", "incI32s", "&i32:c8", "𝕨i32" •Show 2 F "helloworld"
f "lib.so" •FFI "", "incI32s", "&i32:c8",">𝕨i32" •Show 2 F "helloworld"
f "lib.so" •FFI "", "incI32s", ">&i32:c8",">𝕨i32" •Show 2 F "helloworld"
f "lib.so" •FFI "", "incI32s",">𝕨&i32:c8", ">i32" •Show "helloworld" F 2
f "lib.so" •FFI "", "incI32s", "&i32:c8", "i32" •Show F "helloworld", 2
f "lib.so" •FFI "&","incI32s", "&i32:c8", "i32" •Show F "helloworld", 2
Section "# mutate i32*, i16*, i8*"
f "lib.so" •FFI "","incInts","&i32", "&i16","&i8" •Show F ¨ 102030
f "lib.so" •FFI "","incInts","&i32", "𝕨&i16","&i8" •Show 20 F ¨ 1030
f "lib.so" •FFI "","incInts","&i32",">𝕨&i16","&i8" •Show 20 F ¨ 1030
Section "# u64 tests"
f "lib.so" •FFI "u64", "ident_u64",">u64:i32" •Show F 123412
f "lib.so" •FFI "u64", "ident_u64",">u64" •Show F +´25220
f "lib.so" •FFI "u64:i32","ident_u64",">u64" •Show F 123456789123456
f "lib.so" •FFI "u64:u1", "ident_u64",">u64:c8" •Show F "hellowor"
Section "# malloc test"
f "lib.so" •FFI "*:i32""malloc"">u64" •Show (•internal.Info) malloc F 123
f "lib.so" •FFI """free"">*:i32" F malloc
Section "# pick item"
f "lib.so" •FFI "*:i8""pick_ptr"">**:i8"">𝕨i32" •Show @+0 F "helloworfoobarba"-@
f "lib.so" •FFI "*:c8""pick_ptr"">**:c8"">𝕨i32" •Show 0 F "helloworfoobarba"
f "lib.so" •FFI "u64:i8","pick_u64",">*u64:i8",">𝕨i32" •Show @+2 F "000000001234560011122100abacabad"-@
f "lib.so" •FFI "u64:i8","pick_u64",">*u64:i8",">𝕨i32" •Show @+3 F "000000001234560011122100abacabad"-@
f "lib.so" •FFI "u64", "pick_u64",">*u64:i8",">𝕨i32" •Show 1 F "000000001234560011122100"-'0'
# erroring:
# "local/lib.so" •FFI ""‿"printArgs"‿"i8"‿"i16:c32"‿"i32"‿"u8"‿"u16"‿"u32"‿"f32"‿"f64"
# "local/lib.so" •FFI ""‿"testArgs"‿"i8:c16"‿"i16"‿"i32"‿"u8"‿"u16"‿"u32"‿"f32"‿"f64"
# "local/lib.so" •FFI ""‿"testArgs"‿"i8:c32"‿"i16"‿"i32"‿"u8"‿"u16"‿"u32"‿"f32"‿"f64"
# f ↩ "local/lib.so" •FFI "u64"‿"ident_u64"‿">u64:i32" ⋄ •Show F 1234‿12344444
# f ↩ "local/lib.so" •FFI "u64"‿"ident_u64"‿">u64" ⋄ •Show F +´2⋆53‿20

61
test/ffi/test.expected Normal file
View File

@ -0,0 +1,61 @@
@
# "a"
⟨ 0 10 20 30 40 50 60 70 80 90 ⟩
127
# print args
args: -123 -12323 -212312312 250 50000 3123456789 3.141592741012573242 2.718281828459045091
@
@
args: -123 -12323 -212312312 250 50000 3123456789 3.141592741012573242 2.718281828459045091
@
args: -123 -12323 -212312312 250 50000 3123456789 3.141592741012573242 2.718281828459045091
⟨ ⟨ ¯123 ⟩ ⟨ ¯12323 ⟩ ⟨ ¯212312312 ⟩ ⟨ 250 ⟩ ⟨ 50000 ⟩ ⟨ 3123456789 ⟩ ⟨ 3.141592741012573 ⟩ ⟨ 2.718281828459045 ⟩ ⟩
726f776f6c6c6568 6161616161616161 3837363534333231 7478657474786574
12345678
ff7fdfefefdf7bb4 ff7fdfefefdf7bb4 fefffdfff7ffbffb bffff7fffdfffeff
12345678
# read pointers
⟨ 9 8 7 6 5 4 3 2 1 0 ⟩
10
120
55
# mutate i32*
⟨ ⟨ 2000000001 2100000001 2200000001 2300000001 2400000001 2500000001 2600000001 2700000001 2800000001 2900000001 ⟩ ⟩
⟨ 0 1 1 0 1 0 1 0 0 1 0 1 0 0 1 1 0 1 1 0 0 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 1 0 0 1 1 0 0 1 0 0 1 0 0 ⟩
"iellpworld"
"iellpworld"
"iellpworld"
"iellpworld"
"iellpworld"
"iellpworld"
"iellpworld"
⟨ "iellpworld" ⟩
"iellpworld"
# mutate i32*, i16*, i8*
10 20 30
⟨ ⟨ 11 ⟩ ⟨ 21 ⟩ ⟨ 31 ⟩ ⟩
10 20 30
⟨ ⟨ 11 ⟩ ⟨ 21 ⟩ ⟨ 31 ⟩ ⟩
10 20 30
⟨ ⟨ 11 ⟩ ⟨ 21 ⟩ ⟨ 31 ⟩ ⟩
# u64 tests
51539608786
4503599628419072
⟨ ¯2045800064 28744 ⟩
⟨ 0 0 0 1 0 1 1 0 1 0 1 0 0 1 1 0 0 0 1 1 0 1 1 0 0 0 1 1 0 1 1 0 1 1 1 1 0 1 1 0 1 1 1 0 1 1 1 0 1 1 1 1 0 1 1 0 0 1 0 0 1 1 1 0 ⟩
# malloc test
⟨ "fff7: refc:2 type:26=i32arr alloc:128" 2 ⟩
# pick item
"hellowor"
"hellowor"
"11122100"
"abacabad"
6618611909121