@@ -2,13 +2,7 @@ import assert from 'tjs:assert';
2
2
import FFI from 'tjs:ffi' ;
3
3
import initCParser from '../src/js/stdlib/ffi/ffiutils.js' ;
4
4
5
- const isMacArm = tjs . platform === 'darwin' && tjs . uname ( ) . machine === 'arm64' ;
6
- const isWindows = tjs . platform === 'windows' ;
7
-
8
5
( function ( ) {
9
- const libm = new FFI . Lib ( FFI . Lib . LIBM_NAME ) ;
10
- const libc = new FFI . Lib ( FFI . Lib . LIBC_NAME ) ;
11
-
12
6
let sopath = './build/libffi-test.so' ;
13
7
switch ( tjs . platform ) {
14
8
case 'linux' :
@@ -21,42 +15,37 @@ const isWindows = tjs.platform === 'windows';
21
15
sopath = './build/libffi-test.dll' ;
22
16
break ;
23
17
}
18
+ const testlib = new FFI . Lib ( sopath ) ;
24
19
25
20
function testSimpleCalls ( ) {
26
-
27
- const absF = new FFI . CFunction ( libm . symbol ( 'abs' ) , FFI . types . sint , [ FFI . types . sint ] ) ;
28
- assert . eq ( absF . call ( - 9 ) , 9 ) ;
21
+ const simple_func1 = new FFI . CFunction ( testlib . symbol ( 'simple_func1' ) , FFI . types . sint , [ FFI . types . sint ] ) ;
22
+ assert . eq ( simple_func1 . call ( - 9 ) , - 8 ) ;
29
23
30
- if ( ! isWindows ) { // for some reason, windows (mingw) does not find this function
31
- const fabsfF = new FFI . CFunction ( libm . symbol ( 'fabsf' ) , FFI . types . float , [ FFI . types . float ] ) ;
32
- assert . ok ( Math . abs ( fabsfF . call ( - 3.45 ) - 3.45 ) < 0.00001 ) ;
33
- assert . eq ( fabsfF . call ( - 4 ) , 4 ) ;
34
- }
24
+ const simple_func2 = new FFI . CFunction ( testlib . symbol ( 'simple_func2' ) , FFI . types . float , [ FFI . types . float ] ) ;
25
+ assert . ok ( Math . abs ( simple_func2 . call ( 98.9 ) - 99.9 ) < 0.00001 ) ;
35
26
36
- const atoiF = new FFI . CFunction ( libc . symbol ( 'atoi' ) , FFI . types . sint , [ FFI . types . string ] ) ;
27
+ const simple_func3 = new FFI . CFunction ( testlib . symbol ( 'simple_func3' ) , FFI . types . double , [ FFI . types . double ] ) ;
28
+ assert . ok ( Math . abs ( simple_func3 . call ( 98.9 ) - 99.9 ) < 0.00001 ) ;
29
+
30
+ const atoiF = new FFI . CFunction ( testlib . symbol ( 'parse_int' ) , FFI . types . sint , [ FFI . types . string ] ) ;
37
31
assert . eq ( atoiF . call ( "1234" ) , 1234 ) ;
38
32
39
- const strerrorF = new FFI . CFunction ( libc . symbol ( 'strerror ' ) , FFI . types . string , [ FFI . types . sint ] ) ;
40
- assert . eq ( strerrorF . call ( 1 /* EPERM */ ) , "Operation not permitted " ) ;
33
+ const strerrorF = new FFI . CFunction ( testlib . symbol ( 'int_to_string ' ) , FFI . types . string , [ FFI . types . sint ] ) ;
34
+ assert . eq ( strerrorF . call ( 345 ) , "345 " ) ;
41
35
42
- // Not sure what's wrong on macOS + arm64
43
- if ( ! isMacArm ) {
44
- const sprintfF3 = new FFI . CFunction ( libc . symbol ( 'sprintf' ) , FFI . types . sint , [ FFI . types . buffer , FFI . types . string , FFI . types . sint ] , 1 ) ;
45
- const strbuf = new Uint8Array ( 15 ) ; // 14 byte string + null byte
46
- assert . eq ( sprintfF3 . call ( strbuf , 'printf test %d\n' , 5 ) , 14 ) ;
47
- assert . eq ( FFI . bufferToString ( strbuf ) , 'printf test 5\n' ) ;
48
- }
36
+ const sprintfF3 = new FFI . CFunction ( testlib . symbol ( 'test_sprintf' ) , FFI . types . sint , [ FFI . types . buffer , FFI . types . string , FFI . types . sint ] , 2 ) ;
37
+ const strbuf = new Uint8Array ( 15 ) ; // 14 byte string + null byte
38
+ assert . eq ( sprintfF3 . call ( strbuf , 'printf test %d\n' , 5 ) , 14 ) ;
39
+ assert . eq ( FFI . bufferToString ( strbuf ) , 'printf test 5\n' ) ;
49
40
50
- const strcatF = new FFI . CFunction ( libc . symbol ( 'strcat ' ) , FFI . types . string , [ FFI . types . buffer , FFI . types . string ] ) ;
41
+ const strcatF = new FFI . CFunction ( testlib . symbol ( 'test_strcat ' ) , FFI . types . string , [ FFI . types . buffer , FFI . types . string ] ) ;
51
42
const strbuf2 = new Uint8Array ( 12 ) ;
52
43
strbuf2 . set ( ( new TextEncoder ( ) ) . encode ( 'part1:' ) ) ;
53
44
assert . eq ( strcatF . call ( strbuf2 , "part2" ) , "part1:part2" ) ;
54
45
assert . eq ( FFI . bufferToString ( strbuf2 ) , "part1:part2" ) ;
55
46
}
56
47
57
48
function testSimpleVariables ( ) {
58
- const testlib = new FFI . Lib ( sopath ) ;
59
-
60
49
const testIntSymbol = testlib . symbol ( 'test_int' ) ;
61
50
const testIntPointer = new FFI . Pointer ( testIntSymbol . addr , 1 , FFI . types . sint ) ;
62
51
assert . eq ( testIntPointer . deref ( ) , 123 ) ;
@@ -69,59 +58,36 @@ const isWindows = tjs.platform === 'windows';
69
58
}
70
59
71
60
function testStructs ( ) {
72
- const divT = new FFI . StructType ( [ [ 'quot ' , FFI . types . sint ] , [ 'rem ' , FFI . types . sint ] ] , 'div_t ' ) ;
73
- const divF = new FFI . CFunction ( libc . symbol ( 'div ' ) , divT , [ FFI . types . sint , FFI . types . sint ] ) ;
74
- assert . equal ( divF . call ( 10 , 3 ) , { quot : 3 , rem : 1 } ) ;
61
+ const test_t = new FFI . StructType ( [ [ 'a ' , FFI . types . sint ] , [ 'b ' , FFI . types . uchar ] , [ 'c' , FFI . types . uint64 ] ] , 'test_struct ' ) ;
62
+ const return_struct_test = new FFI . CFunction ( testlib . symbol ( 'return_struct_test ' ) , test_t , [ FFI . types . sint ] ) ;
63
+ assert . equal ( return_struct_test . call ( 10 ) , { a : 10 , b : "b" . charCodeAt ( 0 ) , c : 123 } ) ;
75
64
}
76
65
77
66
function testPointersAndStructsOpendir ( ) {
78
- // for some reason, windows (mingw) does not find this function
79
- // for some (other) reason, macOS on arm segfaults
80
- if ( isMacArm || isWindows ) {
81
- return ;
82
- }
83
- const opendirF = new FFI . CFunction ( libc . symbol ( 'opendir' ) , FFI . types . pointer , [ FFI . types . string ] ) ;
84
- let direntSt ;
85
- if ( tjs . platform == 'darwin' ) { // macos has another dirent definition
86
- direntSt = new FFI . StructType ( [
87
- [ 'fileno' , FFI . types . uint32 ] ,
88
- [ 'reclen' , FFI . types . uint16 ] ,
89
- [ 'type' , FFI . types . uint8 ] ,
90
- [ 'namelen' , FFI . types . uint8 ] ,
91
- [ 'name' , new FFI . StaticStringType ( 255 , 'char255' ) ] ,
92
- ] , 'dirent' ) ;
93
- } else {
94
- direntSt = new FFI . StructType ( [
95
- [ 'ino' , FFI . types . size ] ,
96
- [ 'type' , FFI . types . size ] ,
97
- [ 'reclen' , FFI . types . uint16 ] ,
98
- [ 'type' , FFI . types . uint8 ] ,
99
- [ 'name' , new FFI . StaticStringType ( 255 , 'char255' ) ] ,
100
- ] , 'dirent' ) ;
101
- }
102
- const direntPtrT = new FFI . PointerType ( direntSt , 1 ) ;
103
- const readdirF = new FFI . CFunction ( libc . symbol ( 'readdir' ) , direntPtrT , [ FFI . types . pointer ] ) ;
104
- const closedirF = new FFI . CFunction ( libc . symbol ( 'closedir' ) , FFI . types . sint , [ FFI . types . pointer ] ) ;
67
+ const open_test_handle = new FFI . CFunction ( testlib . symbol ( 'open_test_handle' ) , FFI . types . pointer , [ FFI . types . sint ] ) ;
68
+ const entry_t = new FFI . StructType ( [ [ 'a' , FFI . types . sint ] ] ) ;
69
+ const entry_ptr_t = new FFI . PointerType ( entry_t , 1 ) ;
70
+ const get_next_entry = new FFI . CFunction ( testlib . symbol ( 'get_next_entry' ) , entry_ptr_t , [ FFI . types . pointer ] ) ;
71
+ const close_test_handle = new FFI . CFunction ( testlib . symbol ( 'close_test_handle' ) , FFI . types . void , [ FFI . types . pointer ] ) ;
105
72
106
- const dirH = opendirF . call ( import . meta. dirname ) ;
107
- assert . ok ( dirH !== null ) ;
108
- const fileList = [ ] ;
109
- let direntPtr ;
73
+ const handle = open_test_handle . call ( 5 ) ;
74
+ let i = 0 ;
75
+ let entry ;
110
76
do {
111
- direntPtr = readdirF . call ( dirH ) ;
112
- if ( ! direntPtr . isNull ) {
113
- const obj = direntPtr . deref ( ) ;
77
+ entry = get_next_entry . call ( handle ) ;
78
+ if ( ! entry . isNull ) {
79
+ i ++ ;
80
+ const obj = entry . deref ( ) ;
114
81
assert . eq ( typeof obj , 'object' ) ;
115
- fileList . push ( obj ) ;
116
- } else {
117
- assert . eq ( direntPtr . addr , 0n ) ;
82
+ assert . eq ( obj . a , i ) ;
118
83
}
119
- } while ( ! direntPtr . isNull ) ;
120
- assert . ok ( fileList . some ( e => e . name == 'test-ffi.js' ) ) ;
121
- assert . eq ( closedirF . call ( dirH ) , 0 ) ;
84
+ } while ( ! entry . isNull ) ;
85
+ close_test_handle . call ( handle ) ;
86
+ assert . eq ( i , 5 ) ;
122
87
}
123
88
124
89
function testPointersAndStructsTime ( ) {
90
+ const libc = new FFI . Lib ( FFI . Lib . LIBC_NAME ) ;
125
91
const tmT = new FFI . StructType ( [
126
92
[ 'sec' , FFI . types . sint ] ,
127
93
[ 'min' , FFI . types . sint ] ,
@@ -618,51 +584,39 @@ const isWindows = tjs.platform === 'windows';
618
584
}
619
585
620
586
function testLibFromCProto ( ) {
621
- const libc = new FFI . Lib ( FFI . Lib . LIBC_NAME ) ;
622
- libc . parseCProto ( `
623
- typedef long int time_t;
624
- typedef long clock_t;
625
-
626
- struct tm
627
- {
628
- int sec;
629
- int min;
630
- int hour;
631
- int mday;
632
- int mon;
633
- int year;
634
- int wday;
635
- int yday;
636
- int isdst;
637
- long int gmtoff;
638
- const char *tm_zone;
587
+ const testlib = new FFI . Lib ( sopath ) ;
588
+ testlib . parseCProto ( `
589
+ char* test_strcat(char* a, char* b);
590
+ struct test{
591
+ int a;
592
+ char b;
593
+ uint64_t c;
639
594
};
640
-
641
- clock_t clock();
642
- time_t time (time_t *__timer);
643
- double difftime (time_t __time1, time_t __time0);
644
- char* asctime (struct tm *__tp);
595
+ typedef struct test s_test;
596
+ s_test return_struct_test(int a);
597
+ char* sprint_struct_test(s_test* t);
645
598
` ) ;
646
599
647
- const clockVal = libc . call ( 'clock' ) ;
648
- assert . ok ( typeof clockVal == 'number' && clockVal > 0 ) ;
649
- assert . ok ( libc . call ( 'time' , [ null ] ) - Date . now ( ) / 1000 + 1 < 2 ) ;
650
- assert . eq ( libc . call ( 'difftime' , 100 , 50 ) , 50 ) ;
651
- const structTmT = libc . getType ( 'struct tm' ) ;
652
- const tmData = {
653
- sec : 0 , min : 0 , hour : 0 ,
654
- year : 122 , mon : 6 , mday : 1 ,
655
- isdst : 0 , gmtoff : 0 , tm_zone : 'UTC'
600
+ const strcatF = new FFI . CFunction ( testlib . symbol ( 'test_strcat' ) , FFI . types . string , [ FFI . types . buffer , FFI . types . string ] ) ;
601
+ const strbuf2 = new Uint8Array ( 12 ) ;
602
+ strbuf2 . set ( ( new TextEncoder ( ) ) . encode ( 'part1:' ) ) ;
603
+ assert . eq ( strcatF . call ( strbuf2 , "part2" ) , "part1:part2" ) ;
604
+ assert . eq ( FFI . bufferToString ( strbuf2 ) , "part1:part2" ) ;
605
+
606
+ const structTest = testlib . getType ( 'struct test' ) ;
607
+ assert . eq ( structTest , testlib . getType ( 's_test' ) ) ;
608
+ const structData = {
609
+ a : 1 , b : 2 , c : 3
656
610
} ;
657
- const tmBuf = structTmT . toBuffer ( tmData ) ;
658
- const regex = / ^ S u n J u l [ 0 ] 1 0 0 : 0 0 : 0 0 2 0 2 2 \n $ / ;
659
- assert . truthy ( libc . call ( 'asctime ' , FFI . Pointer . createRefFromBuf ( structTmT , tmBuf ) ) . match ( regex ) ) ;
660
- assert . truthy ( libc . call ( 'asctime ' , FFI . Pointer . createRef ( structTmT , tmData ) ) . match ( regex ) ) ;
611
+ const tmBuf = structTest . toBuffer ( structData ) ;
612
+ const expect = 'a: 1, b: 2, c: 3' ;
613
+ assert . eq ( testlib . call ( 'sprint_struct_test ' , FFI . Pointer . createRefFromBuf ( structTest , tmBuf ) ) , expect ) ;
614
+ assert . eq ( testlib . call ( 'sprint_struct_test ' , FFI . Pointer . createRef ( structTest , structData ) ) , expect ) ;
661
615
}
662
616
663
617
function testCProtoPtrInStruct ( ) {
664
- const libc = new FFI . Lib ( FFI . Lib . LIBC_NAME ) ;
665
- libc . parseCProto ( `
618
+ const testlib = new FFI . Lib ( sopath ) ;
619
+ testlib . parseCProto ( `
666
620
struct a{
667
621
int a;
668
622
int b;
@@ -678,8 +632,8 @@ const isWindows = tjs.platform === 'windows';
678
632
int f;
679
633
}* asdasd2;
680
634
` ) ;
681
- assert . eq ( libc . getType ( 'asdasd' ) . size , 2 * FFI . types . pointer . size ) ;
682
- assert . eq ( libc . getType ( 'asdasd2' ) . size , FFI . types . pointer . size ) ;
635
+ assert . eq ( testlib . getType ( 'asdasd' ) . size , 2 * FFI . types . pointer . size ) ;
636
+ assert . eq ( testlib . getType ( 'asdasd2' ) . size , FFI . types . pointer . size ) ;
683
637
}
684
638
685
639
testSimpleCalls ( ) ;
@@ -691,5 +645,4 @@ const isWindows = tjs.platform === 'windows';
691
645
testCProtoParser ( ) ;
692
646
testLibFromCProto ( ) ;
693
647
testCProtoPtrInStruct ( ) ;
694
-
695
648
} ) ( ) ;
0 commit comments