]> gitweb.factorcode.org Git - factor.git/blob - basis/compiler/tests/alien.factor
retire mixed int/float fastcall tests because who cares
[factor.git] / basis / compiler / tests / alien.factor
1 USING: accessors alien alien.c-types alien.libraries
2 alien.syntax arrays classes.struct combinators
3 compiler continuations effects io io.backend io.pathnames
4 io.streams.string kernel math memory namespaces
5 namespaces.private parser quotations sequences
6 specialized-arrays stack-checker stack-checker.errors
7 system threads tools.test words alien.complex concurrency.promises ;
8 FROM: alien.c-types => float short ;
9 SPECIALIZED-ARRAY: float
10 SPECIALIZED-ARRAY: char
11 IN: compiler.tests.alien
12
13 <<
14 : libfactor-ffi-tests-path ( -- string )
15     "resource:" absolute-path
16     {
17         { [ os winnt? ]  [ "libfactor-ffi-test.dll" ] }
18         { [ os macosx? ] [ "libfactor-ffi-test.dylib" ] }
19         { [ os unix?  ]  [ "libfactor-ffi-test.so" ] }
20     } cond append-path ;
21
22 "f-cdecl" libfactor-ffi-tests-path cdecl add-library
23
24 "f-stdcall" libfactor-ffi-tests-path stdcall add-library
25
26 "f-fastcall" libfactor-ffi-tests-path fastcall add-library
27 >>
28
29 LIBRARY: f-cdecl
30
31 FUNCTION: void ffi_test_0 ;
32 [ ] [ ffi_test_0 ] unit-test
33
34 FUNCTION: int ffi_test_1 ;
35 [ 3 ] [ ffi_test_1 ] unit-test
36
37 FUNCTION: int ffi_test_2 int x int y ;
38 [ 5 ] [ 2 3 ffi_test_2 ] unit-test
39 [ "hi" 3 ffi_test_2 ] must-fail
40
41 FUNCTION: int ffi_test_3 int x int y int z int t ;
42 [ 25 ] [ 2 3 4 5 ffi_test_3 ] unit-test
43
44 FUNCTION: float ffi_test_4 ;
45 [ 1.5 ] [ ffi_test_4 ] unit-test
46
47 FUNCTION: double ffi_test_5 ;
48 [ 1.5 ] [ ffi_test_5 ] unit-test
49
50 FUNCTION: int ffi_test_9 int a int b int c int d int e int f int g ;
51 [ 28 ] [ 1 2 3 4 5 6 7 ffi_test_9 ] unit-test
52 [ "a" 2 3 4 5 6 7 ffi_test_9 ] must-fail
53 [ 1 2 3 4 5 6 "a" ffi_test_9 ] must-fail
54
55 STRUCT: FOO { x int } { y int } ;
56
57 : make-FOO ( x y -- FOO )
58     FOO <struct> swap >>y swap >>x ;
59
60 FUNCTION: int ffi_test_11 int a FOO b int c ;
61
62 [ 14 ] [ 1 2 3 make-FOO 4 ffi_test_11 ] unit-test
63
64 FUNCTION: int ffi_test_13 int a int b int c int d int e int f int g int h int i int j int k ;
65
66 [ 66 ] [ 1 2 3 4 5 6 7 8 9 10 11 ffi_test_13 ] unit-test
67
68 FUNCTION: FOO ffi_test_14 int x int y ;
69
70 [ 11 6 ] [ 11 6 ffi_test_14 [ x>> ] [ y>> ] bi ] unit-test
71
72 FUNCTION: c-string ffi_test_15 c-string x c-string y ;
73
74 [ "foo" ] [ "xy" "zt" ffi_test_15 ] unit-test
75 [ "bar" ] [ "xy" "xy" ffi_test_15 ] unit-test
76 [ 1 2 ffi_test_15 ] must-fail
77
78 STRUCT: BAR { x long } { y long } { z long } ;
79
80 FUNCTION: BAR ffi_test_16 long x long y long z ;
81
82 [ 11 6 -7 ] [
83     11 6 -7 ffi_test_16 [ x>> ] [ y>> ] [ z>> ] tri
84 ] unit-test
85
86 STRUCT: TINY { x int } ;
87
88 FUNCTION: TINY ffi_test_17 int x ;
89
90 [ 11 ] [ 11 ffi_test_17 x>> ] unit-test
91
92 [ [ alien-indirect ] infer ] [ inference-error? ] must-fail-with
93
94 : indirect-test-1 ( ptr -- result )
95     int { } cdecl alien-indirect ;
96
97 { 1 1 } [ indirect-test-1 ] must-infer-as
98
99 [ B{ } indirect-test-1 ] [ { "kernel-error" 3 6 B{ } } = ] must-fail-with
100
101 [ 3 ] [ &: ffi_test_1 indirect-test-1 ] unit-test
102
103 : indirect-test-1' ( ptr -- )
104     int { } cdecl alien-indirect drop ;
105
106 { 1 0 } [ indirect-test-1' ] must-infer-as
107
108 [ ] [ &: ffi_test_1 indirect-test-1' ] unit-test
109
110 [ -1 indirect-test-1 ] must-fail
111
112 : indirect-test-2 ( x y ptr -- result )
113     int { int int } cdecl alien-indirect gc ;
114
115 { 3 1 } [ indirect-test-2 ] must-infer-as
116
117 [ 5 ]
118 [ 2 3 &: ffi_test_2 indirect-test-2 ]
119 unit-test
120
121 : indirect-test-3 ( a b c d ptr -- result )
122     int { int int int int } stdcall alien-indirect
123     gc ;
124
125 [ f ] [ "f-stdcall" load-library f = ] unit-test
126 [ stdcall ] [ "f-stdcall" library abi>> ] unit-test
127
128 : ffi_test_18 ( w x y z -- int )
129     int "f-stdcall" "ffi_test_18" { int int int int }
130     alien-invoke gc ;
131
132 [ 25 ] [ 2 3 4 5 ffi_test_18 ] unit-test
133
134 : ffi_test_19 ( x y z -- BAR )
135     BAR "f-stdcall" "ffi_test_19" { long long long }
136     alien-invoke gc ;
137
138 [ 11 6 -7 ] [
139     11 6 -7 ffi_test_19 [ x>> ] [ y>> ] [ z>> ] tri
140 ] unit-test
141
142 FUNCTION: double ffi_test_6 float x float y ;
143 [ 6.0 ] [ 3.0 2.0 ffi_test_6 ] unit-test
144 [ "a" "b" ffi_test_6 ] must-fail
145
146 FUNCTION: double ffi_test_7 double x double y ;
147 [ 6.0 ] [ 3.0 2.0 ffi_test_7 ] unit-test
148
149 FUNCTION: double ffi_test_8 double x float y double z float t int w ;
150 [ 19.0 ] [ 3.0 2.0 1.0 6.0 7 ffi_test_8 ] unit-test
151
152 FUNCTION: int ffi_test_10 int a int b double c int d float e int f int g int h ;
153 [ -34 ] [ 1 2 3.0 4 5.0 6 7 8 ffi_test_10 ] unit-test
154
155 FUNCTION: void ffi_test_20 double x1, double x2, double x3,
156     double y1, double y2, double y3,
157     double z1, double z2, double z3 ;
158
159 [ ] [ 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 ffi_test_20 ] unit-test
160
161 ! Make sure XT doesn't get clobbered in stack frame
162
163 : ffi_test_31 ( a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a -- result y )
164     int
165     "f-cdecl" "ffi_test_31"
166     { int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int }
167     alien-invoke gc 3 ;
168
169 [ 861 3 ] [ 42 [ ] each-integer ffi_test_31 ] unit-test
170
171 : ffi_test_31_point_5 ( a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a -- result )
172     float
173     "f-cdecl" "ffi_test_31_point_5"
174     { float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float }
175     alien-invoke ;
176
177 [ 861.0 ] [ 42 [ >float ] each-integer ffi_test_31_point_5 ] unit-test
178
179 FUNCTION: longlong ffi_test_21 long x long y ;
180
181 [ 121932631112635269 ]
182 [ 123456789 987654321 ffi_test_21 ] unit-test
183
184 FUNCTION: long ffi_test_22 long x longlong y longlong z ;
185
186 [ 987655432 ]
187 [ 1111 121932631112635269 123456789 ffi_test_22 ] unit-test
188
189 [ 1111 f 123456789 ffi_test_22 ] must-fail
190
191 STRUCT: RECT
192     { x float } { y float }
193     { w float } { h float } ;
194
195 : <RECT> ( x y w h -- rect )
196     RECT <struct>
197         swap >>h
198         swap >>w
199         swap >>y
200         swap >>x ;
201
202 FUNCTION: int ffi_test_12 int a int b RECT c int d int e int f ;
203
204 [ 45 ] [ 1 2 3.0 4.0 5.0 6.0 <RECT> 7 8 9 ffi_test_12 ] unit-test
205
206 [ 1 2 { 1 2 3 } 7 8 9 ffi_test_12 ] must-fail
207
208 FUNCTION: float ffi_test_23 ( float[3] x, float[3] y ) ;
209
210 [ 32.0 ] [
211     { 1.0 2.0 3.0 } >float-array
212     { 4.0 5.0 6.0 } >float-array
213     ffi_test_23
214 ] unit-test
215
216 ! Test odd-size structs
217 STRUCT: test-struct-1 { x char[1] } ;
218
219 FUNCTION: test-struct-1 ffi_test_24 ;
220
221 [ S{ test-struct-1 { x char-array{ 1 } } } ] [ ffi_test_24 ] unit-test
222
223 STRUCT: test-struct-2 { x char[2] } ;
224
225 FUNCTION: test-struct-2 ffi_test_25 ;
226
227 [ S{ test-struct-2 { x char-array{ 1 2 } } } ] [ ffi_test_25 ] unit-test
228
229 STRUCT: test-struct-3 { x char[3] } ;
230
231 FUNCTION: test-struct-3 ffi_test_26 ;
232
233 [ S{ test-struct-3 { x char-array{ 1 2 3 } } } ] [ ffi_test_26 ] unit-test
234
235 STRUCT: test-struct-4 { x char[4] } ;
236
237 FUNCTION: test-struct-4 ffi_test_27 ;
238
239 [ S{ test-struct-4 { x char-array{ 1 2 3 4 } } } ] [ ffi_test_27 ] unit-test
240
241 STRUCT: test-struct-5 { x char[5] } ;
242
243 FUNCTION: test-struct-5 ffi_test_28 ;
244
245 [ S{ test-struct-5 { x char-array{ 1 2 3 4 5 } } } ] [ ffi_test_28 ] unit-test
246
247 STRUCT: test-struct-6 { x char[6] } ;
248
249 FUNCTION: test-struct-6 ffi_test_29 ;
250
251 [ S{ test-struct-6 { x char-array{ 1 2 3 4 5 6 } } } ] [ ffi_test_29 ] unit-test
252
253 STRUCT: test-struct-7 { x char[7] } ;
254
255 FUNCTION: test-struct-7 ffi_test_30 ;
256
257 [ S{ test-struct-7 { x char-array{ 1 2 3 4 5 6 7 } } } ] [ ffi_test_30 ] unit-test
258
259 STRUCT: test-struct-8 { x double } { y double } ;
260
261 FUNCTION: double ffi_test_32 test-struct-8 x int y ;
262
263 [ 9.0 ] [
264     test-struct-8 <struct>
265     1.0 >>x
266     2.0 >>y
267     3 ffi_test_32
268 ] unit-test
269
270 STRUCT: test-struct-9 { x float } { y float } ;
271
272 FUNCTION: double ffi_test_33 test-struct-9 x int y ;
273
274 [ 9.0 ] [
275     test-struct-9 <struct>
276     1.0 >>x
277     2.0 >>y
278     3 ffi_test_33
279 ] unit-test
280
281 STRUCT: test-struct-10 { x float } { y int } ;
282
283 FUNCTION: double ffi_test_34 test-struct-10 x int y ;
284
285 [ 9.0 ] [
286     test-struct-10 <struct>
287     1.0 >>x
288     2 >>y
289     3 ffi_test_34
290 ] unit-test
291
292 STRUCT: test-struct-11 { x int } { y int } ;
293
294 FUNCTION: double ffi_test_35 test-struct-11 x int y ;
295
296 [ 9.0 ] [
297     test-struct-11 <struct>
298     1 >>x
299     2 >>y
300     3 ffi_test_35
301 ] unit-test
302
303 STRUCT: test-struct-12 { a int } { x double } ;
304
305 : make-struct-12 ( x -- alien )
306     test-struct-12 <struct>
307         swap >>x ;
308
309 FUNCTION: double ffi_test_36 ( test-struct-12 x ) ;
310
311 [ 1.23456 ] [ 1.23456 make-struct-12 ffi_test_36 ] unit-test
312
313 FUNCTION: ulonglong ffi_test_38 ( ulonglong x, ulonglong y ) ;
314
315 [ t ] [ 31 2^ 32 2^ ffi_test_38 63 2^ = ] unit-test
316
317 ! Test callbacks
318
319 : callback-1 ( -- callback ) void { } cdecl [ ] alien-callback ;
320
321 [ 0 1 ] [ [ callback-1 ] infer [ in>> length ] [ out>> length ] bi ] unit-test
322
323 [ t ] [ callback-1 alien? ] unit-test
324
325 : callback_test_1 ( ptr -- ) void { } cdecl alien-indirect ;
326
327 [ ] [ callback-1 callback_test_1 ] unit-test
328
329 : callback-2 ( -- callback ) void { } cdecl [ [ 5 throw ] ignore-errors ] alien-callback ;
330
331 [ ] [ callback-2 callback_test_1 ] unit-test
332
333 : callback-3 ( -- callback ) void { } cdecl [ 5 "x" set ] alien-callback ;
334
335 [ t 3 5 ] [
336     [
337         namestack*
338         3 "x" set callback-3 callback_test_1
339         namestack* eq?
340         "x" get "x" get-global
341     ] with-scope
342 ] unit-test
343
344 : callback-5 ( -- callback )
345     void { } cdecl [ gc ] alien-callback ;
346
347 [ "testing" ] [
348     "testing" callback-5 callback_test_1
349 ] unit-test
350
351 : callback-5b ( -- callback )
352     void { } cdecl [ compact-gc ] alien-callback ;
353
354 [ "testing" ] [
355     "testing" callback-5b callback_test_1
356 ] unit-test
357
358 : callback-6 ( -- callback )
359     void { } cdecl [ [ continue ] callcc0 ] alien-callback ;
360
361 [ 1 2 3 ] [ callback-6 callback_test_1 1 2 3 ] unit-test
362
363 : callback-7 ( -- callback )
364     void { } cdecl [ 1000000 sleep ] alien-callback ;
365
366 [ 1 2 3 ] [ callback-7 callback_test_1 1 2 3 ] unit-test
367
368 [ f ] [ namespace global eq? ] unit-test
369
370 : callback-8 ( -- callback )
371     void { } cdecl [ [ ] in-thread yield ] alien-callback ;
372
373 [ ] [ callback-8 callback_test_1 ] unit-test
374
375 : callback-9 ( -- callback )
376     int { int int int } cdecl [
377         + + 1 +
378     ] alien-callback ;
379
380 FUNCTION: void ffi_test_36_point_5 ( ) ;
381
382 [ ] [ ffi_test_36_point_5 ] unit-test
383
384 FUNCTION: int ffi_test_37 ( void* func ) ;
385
386 [ 1 ] [ callback-9 ffi_test_37 ] unit-test
387
388 [ 7 ] [ callback-9 ffi_test_37 ] unit-test
389
390 STRUCT: test_struct_13
391 { x1 float }
392 { x2 float }
393 { x3 float }
394 { x4 float }
395 { x5 float }
396 { x6 float } ;
397
398 : make-test-struct-13 ( -- alien )
399     test_struct_13 <struct>
400         1.0 >>x1
401         2.0 >>x2
402         3.0 >>x3
403         4.0 >>x4
404         5.0 >>x5
405         6.0 >>x6 ;
406
407 FUNCTION: int ffi_test_39 ( long a, long b, test_struct_13 s ) ;
408
409 [ 21 ] [ 12347 12347 make-test-struct-13 ffi_test_39 ] unit-test
410
411 ! Joe Groff found this problem
412 STRUCT: double-rect
413 { a double }
414 { b double }
415 { c double }
416 { d double } ;
417
418 : <double-rect> ( a b c d -- foo )
419     double-rect <struct>
420         swap >>d
421         swap >>c
422         swap >>b
423         swap >>a ;
424
425 : >double-rect< ( foo -- a b c d )
426     {
427         [ a>> ]
428         [ b>> ]
429         [ c>> ]
430         [ d>> ]
431     } cleave ;
432
433 : double-rect-callback ( -- alien )
434     void { void* void* double-rect } cdecl
435     [ "example" set-global 2drop ] alien-callback ;
436
437 : double-rect-test ( arg -- arg' )
438     f f rot
439     double-rect-callback
440     void { void* void* double-rect } cdecl alien-indirect
441     "example" get-global ;
442
443 [ 1.0 2.0 3.0 4.0 ]
444 [ 1.0 2.0 3.0 4.0 <double-rect> double-rect-test >double-rect< ] unit-test
445
446 STRUCT: test_struct_14
447     { x1 double }
448     { x2 double } ;
449
450 FUNCTION: test_struct_14 ffi_test_40 ( double x1, double x2 ) ;
451
452 [ 1.0 2.0 ] [
453     1.0 2.0 ffi_test_40 [ x1>> ] [ x2>> ] bi
454 ] unit-test
455
456 : callback-10 ( -- callback )
457     test_struct_14 { double double } cdecl
458     [
459         test_struct_14 <struct>
460             swap >>x2
461             swap >>x1
462     ] alien-callback ;
463
464 : callback-10-test ( x1 x2 callback -- result )
465     test_struct_14 { double double } cdecl alien-indirect ;
466
467 [ 1.0 2.0 ] [
468     1.0 2.0 callback-10 callback-10-test
469     [ x1>> ] [ x2>> ] bi
470 ] unit-test
471
472 FUNCTION: test-struct-12 ffi_test_41 ( int a, double x ) ;
473
474 [ 1 2.0 ] [
475     1 2.0 ffi_test_41
476     [ a>> ] [ x>> ] bi
477 ] unit-test
478
479 : callback-11 ( -- callback )
480     test-struct-12 { int double } cdecl
481     [
482         test-struct-12 <struct>
483             swap >>x
484             swap >>a
485     ] alien-callback ;
486
487 : callback-11-test ( x1 x2 callback -- result )
488     test-struct-12 { int double } cdecl alien-indirect ;
489
490 [ 1 2.0 ] [
491     1 2.0 callback-11 callback-11-test
492     [ a>> ] [ x>> ] bi
493 ] unit-test
494
495 STRUCT: test_struct_15
496     { x float }
497     { y float } ;
498
499 FUNCTION: test_struct_15 ffi_test_42 ( float x, float y ) ;
500
501 [ 1.0 2.0 ] [ 1.0 2.0 ffi_test_42 [ x>> ] [ y>> ] bi ] unit-test
502
503 : callback-12 ( -- callback )
504     test_struct_15 { float float } cdecl
505     [
506         test_struct_15 <struct>
507             swap >>y
508             swap >>x
509     ] alien-callback ;
510
511 : callback-12-test ( x1 x2 callback -- result )
512     test_struct_15 { float float } cdecl alien-indirect ;
513
514 [ 1.0 2.0 ] [
515     1.0 2.0 callback-12 callback-12-test [ x>> ] [ y>> ] bi
516 ] unit-test
517
518 STRUCT: test_struct_16
519     { x float }
520     { a int } ;
521
522 FUNCTION: test_struct_16 ffi_test_43 ( float x, int a ) ;
523
524 [ 1.0 2 ] [ 1.0 2 ffi_test_43 [ x>> ] [ a>> ] bi ] unit-test
525
526 : callback-13 ( -- callback )
527     test_struct_16 { float int } cdecl
528     [
529         test_struct_16 <struct>
530             swap >>a
531             swap >>x
532     ] alien-callback ;
533
534 : callback-13-test ( x1 x2 callback -- result )
535     test_struct_16 { float int } cdecl alien-indirect ;
536
537 [ 1.0 2 ] [
538     1.0 2 callback-13 callback-13-test
539     [ x>> ] [ a>> ] bi
540 ] unit-test
541
542 FUNCTION: test_struct_14 ffi_test_44 ( ) ; inline
543
544 [ 1.0 2.0 ] [ ffi_test_44 [ x1>> ] [ x2>> ] bi ] unit-test
545
546 : stack-frame-bustage ( -- a b ) ffi_test_44 gc 3 ;
547
548 [ ] [ stack-frame-bustage 2drop ] unit-test
549
550 ! C99 tests
551 os windows? [
552
553 FUNCTION: complex-float ffi_test_45 ( int x ) ;
554
555 [ C{ 3.0 0.0 } ] [ 3 ffi_test_45 ] unit-test
556
557 FUNCTION: complex-double ffi_test_46 ( int x ) ;
558
559 [ C{ 3.0 0.0 } ] [ 3 ffi_test_46 ] unit-test
560
561 FUNCTION: complex-float ffi_test_47 ( complex-float x, complex-double y ) ;
562
563 [ C{ 4.0 4.0 } ] [
564     C{ 1.0 2.0 }
565     C{ 1.5 1.0 } ffi_test_47
566 ] unit-test
567
568 ! Reported by jedahu
569 STRUCT: bool-field-test
570     { name c-string }
571     { on bool }
572     { parents short } ;
573
574 FUNCTION: short ffi_test_48 ( bool-field-test x ) ;
575
576 [ 123 ] [
577     bool-field-test <struct>
578         123 >>parents
579     ffi_test_48
580 ] unit-test
581
582 ] unless
583
584 ! Test interaction between threads and callbacks
585 : thread-callback-1 ( -- callback )
586     int { } cdecl [ yield 100 ] alien-callback ;
587
588 : thread-callback-2 ( -- callback )
589     int { } cdecl [ yield 200 ] alien-callback ;
590
591 : thread-callback-invoker ( callback -- n )
592     int { } cdecl alien-indirect ;
593
594 <promise> "p" set
595 [ thread-callback-1 thread-callback-invoker "p" get fulfill ] in-thread
596 [ 200 ] [ thread-callback-2 thread-callback-invoker ] unit-test
597 [ 100 ] [ "p" get ?promise ] unit-test
598
599 ! Regression: calling an undefined function would raise a protection fault
600 FUNCTION: void this_does_not_exist ( ) ;
601
602 [ this_does_not_exist ] [ { "kernel-error" 9 f f } = ] must-fail-with
603
604 ! More alien-assembly tests are in cpu.* vocabs
605 : assembly-test-1 ( -- ) void { } cdecl [ ] alien-assembly ;
606
607 [ ] [ assembly-test-1 ] unit-test
608
609 [ f ] [ "f-fastcall" load-library f = ] unit-test
610 [ fastcall ] [ "f-fastcall" library abi>> ] unit-test
611
612 : ffi_test_49 ( x -- int )
613     int "f-fastcall" "ffi_test_49" { int }
614     alien-invoke gc ;
615 : ffi_test_50 ( x y -- int )
616     int "f-fastcall" "ffi_test_50" { int int }
617     alien-invoke gc ;
618 : ffi_test_51 ( x y z -- int )
619     int "f-fastcall" "ffi_test_51" { int int int }
620     alien-invoke gc ;
621     
622 [ 4 ] [ 3 ffi_test_49 ] unit-test
623 [ 8 ] [ 3 4 ffi_test_50 ] unit-test
624 [ 13 ] [ 3 4 5 ffi_test_51 ] unit-test