summary refs log tree commit diff
path: root/tests/utils.scm
diff options
context:
space:
mode:
Diffstat (limited to 'tests/utils.scm')
-rw-r--r--tests/utils.scm87
1 files changed, 72 insertions, 15 deletions
diff --git a/tests/utils.scm b/tests/utils.scm
index b5706aa792..adac5d4381 100644
--- a/tests/utils.scm
+++ b/tests/utils.scm
@@ -27,6 +27,9 @@
   #:use-module (rnrs io ports)
   #:use-module (ice-9 match))
 
+(define temp-file
+  (string-append "t-utils-" (number->string (getpid))))
+
 (test-begin "utils")
 
 (test-assert "bytevector->base16-string->bytevector"
@@ -139,36 +142,88 @@
                    (append pids1 pids2)))
            (equal? (get-bytevector-all decompressed) data)))))
 
-(test-equal "fcntl-flock"
-  0                                               ; the child's exit status
-  (let ((file (open-input-file (search-path %load-path "guix.scm"))))
-    (fcntl-flock file 'read-lock)
+(false-if-exception (delete-file temp-file))
+(test-equal "fcntl-flock wait"
+  42                                              ; the child's exit status
+  (let ((file (open-file temp-file "w0")))
+    ;; Acquire an exclusive lock.
+    (fcntl-flock file 'write-lock)
     (match (primitive-fork)
       (0
        (dynamic-wind
          (const #t)
          (lambda ()
-           ;; Taking a read lock should be OK.
-           (fcntl-flock file 'read-lock)
-           (fcntl-flock file 'unlock)
-
-           (catch 'flock-error
-             (lambda ()
-               ;; Taking an exclusive lock should raise an exception.
-               (fcntl-flock file 'write-lock))
-             (lambda args
-               (primitive-exit 0)))
+           ;; Reopen FILE read-only so we can have a read lock.
+           (let ((file (open-file temp-file "r")))
+             ;; Wait until we can acquire the lock.
+             (fcntl-flock file 'read-lock)
+             (primitive-exit (read file)))
            (primitive-exit 1))
          (lambda ()
            (primitive-exit 2))))
       (pid
+       ;; Write garbage and wait.
+       (display "hello, world!"  file)
+       (force-output file)
+       (sleep 1)
+
+       ;; Write the real answer.
+       (seek file 0 SEEK_SET)
+       (truncate-file file 0)
+       (write 42 file)
+       (force-output file)
+
+       ;; Unlock, which should let the child continue.
+       (fcntl-flock file 'unlock)
+
        (match (waitpid pid)
          ((_  . status)
           (let ((result (status:exit-val status)))
-            (fcntl-flock file 'unlock)
             (close-port file)
             result)))))))
 
+(test-equal "fcntl-flock non-blocking"
+  EAGAIN                                          ; the child's exit status
+  (match (pipe)
+    ((input . output)
+     (match (primitive-fork)
+       (0
+        (dynamic-wind
+          (const #t)
+          (lambda ()
+            (close-port output)
+
+            ;; Wait for the green light.
+            (read-char input)
+
+            ;; Open FILE read-only so we can have a read lock.
+            (let ((file (open-file temp-file "w")))
+              (catch 'flock-error
+                (lambda ()
+                  ;; This attempt should throw EAGAIN.
+                  (fcntl-flock file 'write-lock #:wait? #f))
+                (lambda (key errno)
+                  (primitive-exit errno))))
+            (primitive-exit -1))
+          (lambda ()
+            (primitive-exit -2))))
+       (pid
+        (close-port input)
+        (let ((file (open-file temp-file "w")))
+          ;; Acquire an exclusive lock.
+          (fcntl-flock file 'write-lock)
+
+          ;; Tell the child to continue.
+          (write 'green-light output)
+          (force-output output)
+
+          (match (waitpid pid)
+            ((_  . status)
+             (let ((result (status:exit-val status)))
+               (fcntl-flock file 'unlock)
+               (close-port file)
+               result)))))))))
+
 ;; This is actually in (guix store).
 (test-equal "store-path-package-name"
   "bash-4.2-p24"
@@ -178,5 +233,7 @@
 
 (test-end)
 
+(false-if-exception (delete-file temp-file))
+
 
 (exit (= (test-runner-fail-count (test-runner-current)) 0))