summaryrefslogtreecommitdiff
path: root/gnu/tests.scm
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2023-04-21 15:38:06 +0200
committerLudovic Courtès <ludo@gnu.org>2023-04-21 16:16:38 +0200
commita09c7da8f8d8e732f969cf0a09aaa78f87032ab1 (patch)
treee4b41bde7ae01c29722f0265a3b44ef6a8933898 /gnu/tests.scm
parentfb32e226ce3d3cd9bf12989850b2dd719266d583 (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.scm112
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
93IMPORTED-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