diff options
| author | Ludovic Courtès <ludo@gnu.org> | 2023-04-21 15:38:06 +0200 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2023-04-21 16:16:38 +0200 |
| commit | a09c7da8f8d8e732f969cf0a09aaa78f87032ab1 (patch) | |
| tree | e4b41bde7ae01c29722f0265a3b44ef6a8933898 /gnu/tests.scm | |
| parent | fb32e226ce3d3cd9bf12989850b2dd719266d583 (diff) | |
tests: Fork and exec a new Guile for the marionette REPL.
By merely forking PID 1, details from PID 1 (shepherd) would leak into
the marionette process, such as the set of modules in scope and state
inherited from the shepherd process (<service> instances, fibers,
etc.). Running a fresh Guile instance avoids that.
* gnu/tests.scm (marionette-program): New procedure.
(marionette-shepherd-service): Change 'start' to use
'make-forkexec-constructor', and run the result of 'marionette-program'.
Diffstat (limited to 'gnu/tests.scm')
| -rw-r--r-- | gnu/tests.scm | 112 |
1 files changed, 60 insertions, 52 deletions
diff --git a/gnu/tests.scm b/gnu/tests.scm index ca677d315b5..96ecb40ea23 100644 --- a/gnu/tests.scm +++ b/gnu/tests.scm | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | 1 | ;;; GNU Guix --- Functional package management for GNU |
| 2 | ;;; Copyright © 2016-2020, 2022 Ludovic Courtès <ludo@gnu.org> | 2 | ;;; Copyright © 2016-2020, 2022-2023 Ludovic Courtès <ludo@gnu.org> |
| 3 | ;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com> | 3 | ;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com> |
| 4 | ;;; Copyright © 2017 Tobias Geerinckx-Rice <me@tobias.gr> | 4 | ;;; Copyright © 2017 Tobias Geerinckx-Rice <me@tobias.gr> |
| 5 | ;;; Copyright © 2021 Maxime Devos <maximedevos@telenet.be> | 5 | ;;; Copyright © 2021 Maxime Devos <maximedevos@telenet.be> |
| @@ -88,6 +88,61 @@ | |||
| 88 | (with-extensions extensions | 88 | (with-extensions extensions |
| 89 | gexp))) | 89 | gexp))) |
| 90 | 90 | ||
| 91 | (define (marionette-program device imported-modules extensions) | ||
| 92 | "Return the program that runs the marionette REPL on DEVICE. Ensure | ||
| 93 | IMPORTED-MODULES and EXTENSIONS are accessible from the REPL." | ||
| 94 | (define code | ||
| 95 | (with-imported-modules-and-extensions | ||
| 96 | `((guix build utils) | ||
| 97 | (guix build syscalls) | ||
| 98 | ,@imported-modules) | ||
| 99 | extensions | ||
| 100 | #~(begin | ||
| 101 | (use-modules (ice-9 match) | ||
| 102 | (ice-9 binary-ports)) | ||
| 103 | |||
| 104 | (define (self-quoting? x) | ||
| 105 | (letrec-syntax ((one-of (syntax-rules () | ||
| 106 | ((_) #f) | ||
| 107 | ((_ pred rest ...) | ||
| 108 | (or (pred x) | ||
| 109 | (one-of rest ...)))))) | ||
| 110 | (one-of symbol? string? keyword? pair? null? array? | ||
| 111 | number? boolean? char?))) | ||
| 112 | |||
| 113 | (let ((repl (open-file #$device "r+0")) | ||
| 114 | (console (open-file "/dev/console" "r+0"))) | ||
| 115 | ;; Redirect output to the console. | ||
| 116 | (close-fdes 1) | ||
| 117 | (close-fdes 2) | ||
| 118 | (dup2 (fileno console) 1) | ||
| 119 | (dup2 (fileno console) 2) | ||
| 120 | (close-port console) | ||
| 121 | |||
| 122 | (display 'ready repl) | ||
| 123 | (let loop () | ||
| 124 | (newline repl) | ||
| 125 | |||
| 126 | (match (read repl) | ||
| 127 | ((? eof-object?) | ||
| 128 | (primitive-exit 0)) | ||
| 129 | (expr | ||
| 130 | (catch #t | ||
| 131 | (lambda () | ||
| 132 | (let ((result (primitive-eval expr))) | ||
| 133 | (write (if (self-quoting? result) | ||
| 134 | result | ||
| 135 | (object->string result)) | ||
| 136 | repl))) | ||
| 137 | (lambda (key . args) | ||
| 138 | (print-exception (current-error-port) | ||
| 139 | (stack-ref (make-stack #t) 1) | ||
| 140 | key args) | ||
| 141 | (write #f repl))))) | ||
| 142 | (loop)))))) | ||
| 143 | |||
| 144 | (program-file "marionette-repl.scm" code)) | ||
| 145 | |||
| 91 | (define (marionette-shepherd-service config) | 146 | (define (marionette-shepherd-service config) |
| 92 | "Return the Shepherd service for the marionette REPL" | 147 | "Return the Shepherd service for the marionette REPL" |
| 93 | (match config | 148 | (match config |
| @@ -101,57 +156,10 @@ | |||
| 101 | 156 | ||
| 102 | (modules '((ice-9 match) | 157 | (modules '((ice-9 match) |
| 103 | (srfi srfi-9 gnu))) | 158 | (srfi srfi-9 gnu))) |
| 104 | (start | 159 | (start #~(make-forkexec-constructor |
| 105 | (with-imported-modules-and-extensions imported-modules extensions | 160 | (list #$(marionette-program device |
| 106 | #~(lambda () | 161 | imported-modules |
| 107 | (define (self-quoting? x) | 162 | extensions)))) |
| 108 | (letrec-syntax ((one-of (syntax-rules () | ||
| 109 | ((_) #f) | ||
| 110 | ((_ pred rest ...) | ||
| 111 | (or (pred x) | ||
| 112 | (one-of rest ...)))))) | ||
| 113 | (one-of symbol? string? keyword? pair? null? array? | ||
| 114 | number? boolean? char?))) | ||
| 115 | |||
| 116 | (match (primitive-fork) | ||
| 117 | (0 | ||
| 118 | (dynamic-wind | ||
| 119 | (const #t) | ||
| 120 | (lambda () | ||
| 121 | (let ((repl (open-file #$device "r+0")) | ||
| 122 | (console (open-file "/dev/console" "r+0"))) | ||
| 123 | ;; Redirect output to the console. | ||
| 124 | (close-fdes 1) | ||
| 125 | (close-fdes 2) | ||
| 126 | (dup2 (fileno console) 1) | ||
| 127 | (dup2 (fileno console) 2) | ||
| 128 | (close-port console) | ||
| 129 | |||
| 130 | (display 'ready repl) | ||
| 131 | (let loop () | ||
| 132 | (newline repl) | ||
| 133 | |||
| 134 | (match (read repl) | ||
| 135 | ((? eof-object?) | ||
| 136 | (primitive-exit 0)) | ||
| 137 | (expr | ||
| 138 | (catch #t | ||
| 139 | (lambda () | ||
| 140 | (let ((result (primitive-eval expr))) | ||
| 141 | (write (if (self-quoting? result) | ||
| 142 | result | ||
| 143 | (object->string result)) | ||
| 144 | repl))) | ||
| 145 | (lambda (key . args) | ||
| 146 | (print-exception (current-error-port) | ||
| 147 | (stack-ref (make-stack #t) 1) | ||
| 148 | key args) | ||
| 149 | (write #f repl))))) | ||
| 150 | (loop)))) | ||
| 151 | (lambda () | ||
| 152 | (primitive-exit 1)))) | ||
| 153 | (pid | ||
| 154 | pid))))) | ||
| 155 | (stop #~(make-kill-destructor))))))) | 163 | (stop #~(make-kill-destructor))))))) |
| 156 | 164 | ||
| 157 | (define marionette-service-type | 165 | (define marionette-service-type |
