Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1#!/usr/bin/env -S sbcl --script 2 3(require :uiop) 4 5;; prevent glibc hell 6(setf (uiop:getenv "LD_LIBRARY_PATH") "") 7 8(defparameter packages (uiop:read-file-lines "./lispPackagesToTest.txt")) 9 10(defparameter lisp (or (cadr sb-ext:*posix-argv*) "sbcl")) 11 12(defparameter nix-build "nix-build -E 'with import ../../../../default.nix {}; lispPackages_new.~aPackages.~a'") 13 14(defparameter cpu-count 15 (length 16 (remove-if-not 17 (lambda (line) 18 (uiop:string-prefix-p "processor" line)) 19 (uiop:read-file-lines "/proc/cpuinfo")))) 20 21(defparameter sem (sb-thread:make-semaphore :count cpu-count)) 22 23(defparameter statuses (make-hash-table :synchronized t)) 24 25(defparameter log-lock (sb-thread:make-mutex)) 26 27(format *error-output* "Testing ~a on ~a cores~%" lisp cpu-count) 28 29(defun clear-line () 30 (write-char #\Return *error-output*) 31 (write-char #\Escape *error-output*) 32 (write-char #\[ *error-output*) 33 (write-char #\K *error-output*)) 34 35(declaim (type fixnum errors)) 36(defglobal errors 0) 37 38(defmacro when-let (bindings &rest body) 39 (reduce 40 (lambda (expansion form) 41 (destructuring-bind (var test) form 42 (let ((testsym (gensym (symbol-name var)))) 43 `(let ((,testsym ,test)) 44 (when ,testsym 45 (let ((,var ,testsym)) 46 ,expansion)))))) 47 (reverse bindings) 48 :initial-value `(progn ,@body))) 49 50(dolist (pkg packages) 51 (sb-thread:wait-on-semaphore sem) 52 (sb-thread:make-thread 53 (lambda () 54 (handler-case 55 (unwind-protect 56 (multiple-value-bind (out err code) 57 (uiop:run-program 58 (format nil nix-build lisp pkg) 59 :error-output '(:string :stripped t) 60 :ignore-error-status t) 61 (declare (ignorable err)) 62 (setf (gethash pkg statuses) code) 63 (when-let ((pos (search "LOAD-FOREIGN-LIBRARY-ERROR" err :test #'string=)) 64 (lines (uiop:split-string (subseq err pos) :separator '(#\Newline)))) 65 (setf (gethash pkg statuses) 66 (fourth lines))) 67 (sb-thread:with-mutex (log-lock) 68 (clear-line) 69 (format *error-output* "[~a/~a] ~[OK~:;ERROR~] ~a~[~:;~%~]" 70 (hash-table-count statuses) 71 (length packages) 72 code 73 pkg 74 code) 75 (force-output *error-output*)) 76 (unless (zerop code) 77 (sb-ext:atomic-incf errors))) 78 (sb-thread:signal-semaphore sem)) 79 (error (e) 80 (format t "~a~%" e) 81 (sb-ext:quit :recklessly-p t :unix-status 1)))))) 82 83(sb-thread:wait-on-semaphore sem :n cpu-count) 84 85(format t "~%Done (~a/~a)." 86 (- (length packages) errors) 87 (length packages)) 88 89(when (plusp errors) 90 (format t "~%~%~a Errors: " errors) 91 (maphash (lambda (k v) 92 (unless (and (numberp v) (zerop v)) 93 (format t "~% ~a: ~a" k v))) 94 statuses))