test-ffi.scm 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. ;;; Copyright (C) 2023, 2024 David Thompson <dave@spritely.institute>
  2. ;;;
  3. ;;; Licensed under the Apache License, Version 2.0 (the "License");
  4. ;;; you may not use this file except in compliance with the License.
  5. ;;; You may obtain a copy of the License at
  6. ;;;
  7. ;;; http://www.apache.org/licenses/LICENSE-2.0
  8. ;;;
  9. ;;; Unless required by applicable law or agreed to in writing, software
  10. ;;; distributed under the License is distributed on an "AS IS" BASIS,
  11. ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. ;;; See the License for the specific language governing permissions and
  13. ;;; limitations under the License.
  14. ;;; Commentary:
  15. ;;;
  16. ;;; FFI tests.
  17. ;;;
  18. ;;; Code:
  19. (use-modules (ice-9 binary-ports)
  20. (ice-9 exceptions)
  21. (ice-9 popen)
  22. (ice-9 textual-ports)
  23. (srfi srfi-64)
  24. (test utils)
  25. (hoot compile)
  26. (hoot reflect)
  27. (wasm parse))
  28. (test-begin "test-ffi")
  29. (define-syntax-rule (test-ffi name expected source imports)
  30. (test-equal name
  31. expected
  32. (compile-value 'source
  33. #:imports (cons '(hoot ffi) %default-program-imports)
  34. #:wasm-imports imports)))
  35. (test-ffi
  36. "i32 param and result"
  37. 16
  38. (let ()
  39. (define-foreign fsquare
  40. "math" "square"
  41. i32 -> i32)
  42. (square 4))
  43. `(("math" . (("square" . ,(lambda (x) (* x x)))))))
  44. (test-ffi
  45. "i64 param and result"
  46. 16
  47. (let ()
  48. (define-foreign fsquare
  49. "math" "square"
  50. i64 -> i64)
  51. (square 4))
  52. `(("math" . (("square" . ,(lambda (x) (* x x)))))))
  53. (test-ffi
  54. "f32 param and result"
  55. 16.0
  56. (let ()
  57. (define-foreign fsquare
  58. "math" "fsquare"
  59. f32 -> f32)
  60. (fsquare 4.0))
  61. `(("math" . (("fsquare" . ,(lambda (x) (* x x)))))))
  62. (test-ffi
  63. "f64 param and result"
  64. 16.0
  65. (let ()
  66. (define-foreign fsquare
  67. "math" "fsquare"
  68. f64 -> f64)
  69. (fsquare 4.0))
  70. `(("math" . (("fsquare" . ,(lambda (x) (* x x)))))))
  71. (test-ffi
  72. "string param and result"
  73. "Hello, owl!"
  74. (let ()
  75. (define-foreign hello
  76. "host" "hello"
  77. (ref string) -> (ref string))
  78. (hello "owl"))
  79. `(("host" .
  80. (("hello" . ,(lambda (name) (string-append "Hello, " name "!")))))))
  81. (test-ffi
  82. "eq param and result"
  83. "hello"
  84. (let ()
  85. (define-foreign echo
  86. "host" "echo"
  87. (ref eq) -> (ref eq))
  88. (echo "hello"))
  89. `(("host" .
  90. (("echo" . ,(lambda (x) x))))))
  91. (test-ffi
  92. "extern param"
  93. #t
  94. (begin
  95. (define-foreign special-value
  96. "host" "getSpecialValue"
  97. -> (ref extern))
  98. (define-foreign %special-value?
  99. "host" "isSpecialValue"
  100. (ref extern) -> i32)
  101. (define (special-value? x)
  102. (= (%special-value? x) 1))
  103. (special-value? (special-value)))
  104. (let ((special '(special value)))
  105. `(("host" . (("getSpecialValue" . ,(lambda () special))
  106. ("isSpecialValue" . ,(lambda (x) (eq? x special))))))))
  107. (test-ffi
  108. "external?"
  109. #t
  110. (let ()
  111. (define-foreign get-extern
  112. "host" "getExtern"
  113. -> (ref null extern))
  114. (external? (get-extern)))
  115. `(("host" . (("getExtern" . ,(lambda () '(external value)))))))
  116. (test-ffi
  117. "external-null?"
  118. #t
  119. (let ()
  120. (define-foreign get-null
  121. "host" "getNull"
  122. -> (ref null extern))
  123. (external-null? (get-null)))
  124. `(("host" . (("getNull" . ,(lambda () #f))))))
  125. (test-ffi
  126. "external-non-null?"
  127. #t
  128. (let ()
  129. (define-foreign get-non-null
  130. "host" "getNonNull"
  131. -> (ref extern))
  132. (external-non-null? (get-non-null)))
  133. `(("host" . (("getNonNull" . ,(lambda () #t))))))
  134. (test-ffi
  135. "procedure->extern"
  136. 1
  137. (let ((counter 0))
  138. (define-foreign callback
  139. "host" "callback"
  140. (ref null extern) -> none)
  141. (callback
  142. (procedure->external
  143. (lambda () (set! counter (+ counter 1)))))
  144. counter)
  145. `(("host" .
  146. (("callback" . ,(lambda (f) (f) *unspecified*))))))
  147. (test-end* "test-ffi")