utils.scm 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. ;;; Copyright (C) 2023, 2024 Igalia, S.L.
  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. ;;; Test utilities.
  17. ;;;
  18. ;;; Code:
  19. (define-module (test utils)
  20. #:use-module (wasm assemble)
  21. #:use-module (wasm parse)
  22. #:use-module (hoot compile)
  23. #:use-module (hoot reflect)
  24. #:use-module (ice-9 binary-ports)
  25. #:use-module (ice-9 match)
  26. #:use-module (ice-9 popen)
  27. #:use-module (ice-9 textual-ports)
  28. #:use-module (srfi srfi-64)
  29. #:export (d8
  30. srcdir
  31. builddir
  32. use-d8?
  33. use-hoot-vm?
  34. unwind-protect
  35. scope-file
  36. call-with-compiled-wasm-file
  37. compile-call*
  38. test-compilation
  39. test-call
  40. test-call/hoot-vm
  41. test-end*
  42. with-imports
  43. with-additional-imports))
  44. (define d8 (or (getenv "D8") "d8"))
  45. (define srcdir (or (getenv "SRCDIR") (getcwd)))
  46. (define builddir (or (getenv "BUILDDIR") (getcwd)))
  47. (define test-hosts (string-split (or (getenv "WASM_HOST") "d8,hoot") #\,))
  48. (define use-d8? (member "d8" test-hosts))
  49. (define use-hoot-vm? (member "hoot" test-hosts))
  50. (define (scope-file file-name)
  51. (string-append srcdir "/" file-name))
  52. (define (unwind-protect body unwind)
  53. (call-with-values
  54. (lambda ()
  55. (with-exception-handler
  56. (lambda (exn)
  57. (unwind)
  58. (raise-exception exn))
  59. body))
  60. (lambda vals
  61. (unwind)
  62. (apply values vals))))
  63. (define (call-with-compiled-wasm-file wasm f)
  64. (let* ((wasm-port (mkstemp "/tmp/tmp-wasm-XXXXXX"))
  65. (wasm-file-name (port-filename wasm-port)))
  66. (put-bytevector wasm-port (assemble-wasm wasm))
  67. (close-port wasm-port)
  68. (unwind-protect
  69. (lambda () (f wasm-file-name))
  70. (lambda () (delete-file wasm-file-name)))))
  71. (define (run-d8 . args)
  72. (let* ((args (cons* "--experimental-wasm-stringref" args))
  73. (port (apply open-pipe* OPEN_READ d8 args))
  74. (output (get-string-all port)))
  75. (close-port port)
  76. (string-trim-both output)))
  77. (define (compile-value/d8 wasm)
  78. (call-with-compiled-wasm-file
  79. wasm
  80. (lambda (wasm-file-name)
  81. (run-d8 (scope-file "test/load-wasm-and-print.js") "--" srcdir builddir wasm-file-name))))
  82. (define (compile-call/d8 proc . args)
  83. (let lp ((modules (cons proc args)) (files '()) (first? #t))
  84. (match modules
  85. (()
  86. (apply run-d8 (scope-file "test/test-call.js") "--" srcdir builddir (reverse files)))
  87. ((module . rest)
  88. (call-with-compiled-wasm-file
  89. module
  90. (lambda (file)
  91. (lp rest (cons file files) #f)))))))
  92. (define (call-with-printed-values thunk)
  93. (string-trim-both
  94. (with-output-to-string
  95. (lambda ()
  96. (call-with-values thunk
  97. (lambda vals
  98. (for-each (lambda (x)
  99. ((@@ (hoot reflect) %hoot-print) x (current-output-port))
  100. (newline))
  101. vals)))))))
  102. (define (compile-value/hoot wasm)
  103. (call-with-printed-values
  104. (lambda ()
  105. (hoot-load (hoot-instantiate wasm)))))
  106. (define (compile-call/hoot proc . args)
  107. (call-with-printed-values
  108. (lambda ()
  109. (let* ((proc-module (hoot-instantiate proc))
  110. (proc* (hoot-load proc-module))
  111. (reflector (hoot-module-reflector proc-module))
  112. (args* (map (lambda (arg)
  113. (hoot-load
  114. (hoot-instantiate arg '() reflector)))
  115. args)))
  116. (apply proc* args*)))))
  117. (define (compare-results hoot-result d8-result)
  118. (cond
  119. ((and use-hoot-vm? use-d8?)
  120. (unless (equal? hoot-result d8-result)
  121. (error "our result differs from d8" hoot-result d8-result))
  122. hoot-result)
  123. (use-d8? d8-result)
  124. (else hoot-result)))
  125. (define %imports (make-parameter %default-program-imports))
  126. (define cache (make-hash-table))
  127. (define (compile/cache expr . args)
  128. (cond
  129. ((hash-ref cache (cons expr args)))
  130. (else
  131. (let ((result (apply compile expr #:imports (%imports) args)))
  132. (hash-set! cache (cons expr args) result)
  133. result))))
  134. (define (compile-value* expr)
  135. (let ((wasm (compile/cache expr)))
  136. (compare-results (and use-hoot-vm? (compile-value/hoot wasm))
  137. (and use-d8? (compile-value/d8 wasm)))))
  138. (define (compile-call* proc . args)
  139. (let ((proc* (compile/cache proc))
  140. (args* (map (lambda (exp)
  141. (compile/cache exp #:import-abi? #t #:export-abi? #f))
  142. args)))
  143. (compare-results (and use-hoot-vm? (apply compile-call/hoot proc* args*))
  144. (and use-d8? (apply compile-call/d8 proc* args*)))))
  145. (define (compile-call*/hoot-vm proc . args)
  146. (apply compile-call/hoot
  147. (compile/cache proc)
  148. (map (lambda (exp)
  149. (compile/cache exp #:import-abi? #t #:export-abi? #f))
  150. args)))
  151. (define-syntax-rule (test-compilation expr repr)
  152. (test-equal repr repr (compile-value* 'expr)))
  153. (define-syntax-rule (test-call repr proc arg ...)
  154. (test-equal repr repr (compile-call* 'proc 'arg ...)))
  155. (define-syntax-rule (test-call/hoot-vm repr proc arg ...)
  156. (test-equal repr repr (compile-call*/hoot-vm `proc `arg ...)))
  157. (define-syntax-rule (test-end* name)
  158. (begin
  159. (when (and (batch-mode?)
  160. (or (not (zero? (test-runner-fail-count (test-runner-get))))
  161. (not (zero? (test-runner-xpass-count (test-runner-get))))))
  162. (force-output)
  163. (exit 1))
  164. (test-end name)))
  165. (define-syntax-rule (with-imports (ispec ...) . body)
  166. (parameterize ((%imports '(ispec ...)))
  167. . body))
  168. (define-syntax-rule (with-additional-imports (ispec ...) . body)
  169. (parameterize ((%imports (cons* 'ispec ... (%imports))))
  170. . body))