diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/build-utils.scm | 24 | ||||
-rw-r--r-- | tests/builders.scm | 121 | ||||
-rw-r--r-- | tests/gremlin.scm | 66 | ||||
-rw-r--r-- | tests/packages.scm | 85 |
4 files changed, 287 insertions, 9 deletions
diff --git a/tests/build-utils.scm b/tests/build-utils.scm index 654b480ed9..31be7ff80f 100644 --- a/tests/build-utils.scm +++ b/tests/build-utils.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2012, 2015, 2016, 2019, 2020 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2019 Ricardo Wurmus <rekado@elephly.net> +;;; Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com> ;;; ;;; This file is part of GNU Guix. ;;; @@ -18,7 +19,7 @@ ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. -(define-module (test-build-utils) +(define-module (test build-utils) #:use-module (guix tests) #:use-module (guix build utils) #:use-module ((guix utils) @@ -241,4 +242,25 @@ print('hello world')")) "/some/other/path"))) #f))))) +(test-equal "substitute*, text contains a NUL byte, UTF-8" + "c\0d" + (with-fluids ((%default-port-encoding "UTF-8") + (%default-port-conversion-strategy 'error)) + ;; The GNU libc is locale sensitive. Depending on the value of LANG, the + ;; test could fail with "string contains #\\nul character: ~S" or "cannot + ;; convert wide string to output locale". + (setlocale LC_ALL "en_US.UTF-8") + (call-with-temporary-output-file + (lambda (file port) + (format port "a\0b") + (flush-output-port port) + + (substitute* file + (("a") "c") + (("b") "d")) + + (with-input-from-file file + (lambda _ + (get-string-all (current-input-port)))))))) + (test-end) diff --git a/tests/builders.scm b/tests/builders.scm index fdcf38ded3..2143c0738b 100644 --- a/tests/builders.scm +++ b/tests/builders.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2012, 2013, 2014, 2015, 2019 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2021 Lars-Dominik Braun <lars@6xq.net> ;;; ;;; This file is part of GNU Guix. ;;; @@ -17,22 +18,26 @@ ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. -(define-module (test-builders) +(define-module (tests builders) #:use-module (guix download) #:use-module (guix build-system) #:use-module (guix build-system gnu) + #:use-module (guix build gnu-build-system) + #:use-module (guix build utils) + #:use-module (guix build-system python) #:use-module (guix store) + #:use-module (guix monads) #:use-module (guix utils) #:use-module (guix base32) #:use-module (guix derivations) #:use-module (gcrypt hash) #:use-module (guix tests) - #:use-module ((guix packages) - #:select (package? - package-derivation package-native-search-paths)) + #:use-module (guix packages) #:use-module (gnu packages bootstrap) #:use-module (ice-9 match) + #:use-module (ice-9 textual-ports) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) #:use-module (srfi srfi-64)) ;; Test the higher-level builders. @@ -78,4 +83,112 @@ (test-assert "gnu-build-system" (build-system? gnu-build-system)) +(define unpack (assoc-ref %standard-phases 'unpack)) + +(define compressors '(("gzip" . "gz") + ("xz" . "xz") + ("bzip2" . "bz2") + (#f . #f))) + +(for-each + (match-lambda + ((comp . ext) + + (unless (network-reachable?) (test-skip 1)) ;for bootstrap binaries + (test-equal (string-append "gnu-build-system unpack phase, " + "single file (compression: " + (if comp comp "None") ")") + "expected text" + (let*-values + (((name) "test") + ((compressed-name) (if ext + (string-append name "." ext) + name)) + ((file hash) (test-file %store compressed-name "expected text"))) + (call-with-temporary-directory + (lambda (dir) + (with-directory-excursion dir + (unpack #:source file) + (call-with-input-file name get-string-all)))))))) + compressors) + + +;;; +;;; Test the sanity-check phase of the Python build system. +;;; + +(define* (make-python-dummy name #:key (setup-py-extra "") + (init-py "") (use-setuptools? #t)) + (dummy-package (string-append "python-dummy-" name) + (version "0.1") + (build-system python-build-system) + (arguments + `(#:tests? #f + #:use-setuptools? ,use-setuptools? + #:phases + (modify-phases %standard-phases + (replace 'unpack + (lambda _ + (mkdir-p "dummy") + (with-output-to-file "dummy/__init__.py" + (lambda _ + (display ,init-py))) + (with-output-to-file "setup.py" + (lambda _ + (format #t "\ +~a +setup( + name='dummy-~a', + version='0.1', + packages=['dummy'], + ~a + )" + (if ,use-setuptools? + "from setuptools import setup" + "from distutils.core import setup") + ,name ,setup-py-extra)))))))))) + +(define python-dummy-ok + (make-python-dummy "ok")) + +;; distutil won't install any metadata, so make sure our script does not fail +;; on a otherwise fine package. +(define python-dummy-no-setuptools + (make-python-dummy + "no-setuptools" #:use-setuptools? #f)) + +(define python-dummy-fail-requirements + (make-python-dummy "fail-requirements" + #:setup-py-extra "install_requires=['nonexistent'],")) + +(define python-dummy-fail-import + (make-python-dummy "fail-import" #:init-py "import nonexistent")) + +(define python-dummy-fail-console-script + (make-python-dummy "fail-console-script" + #:setup-py-extra (string-append "entry_points={'console_scripts': " + "['broken = dummy:nonexistent']},"))) + +(define (check-build-success store p) + (unless store (test-skip 1)) + (test-assert (string-append "python-build-system: " (package-name p)) + (let* ((drv (package-derivation store p))) + (build-derivations store (list drv))))) + +(define (check-build-failure store p) + (unless store (test-skip 1)) + (test-assert (string-append "python-build-system: " (package-name p)) + (not (false-if-exception (package-derivation store python-dummy-fail-requirements))))) + +(with-external-store store + (for-each (lambda (p) (check-build-success store p)) + (list + python-dummy-ok + python-dummy-no-setuptools)) + (for-each (lambda (p) (check-build-failure store p)) + (list + python-dummy-fail-requirements + python-dummy-fail-import + python-dummy-fail-console-script))) + (test-end "builders") diff --git a/tests/gremlin.scm b/tests/gremlin.scm index b0bb7a8e49..9ddac14265 100644 --- a/tests/gremlin.scm +++ b/tests/gremlin.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2015, 2018 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2015, 2018, 2020 Ludovic Courtès <ludo@gnu.org> ;;; ;;; This file is part of GNU Guix. ;;; @@ -23,9 +23,12 @@ #:use-module (guix build gremlin) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) + #:use-module (srfi srfi-34) #:use-module (srfi srfi-64) #:use-module (rnrs io ports) #:use-module (ice-9 popen) + #:use-module (ice-9 rdelim) + #:use-module (ice-9 regex) #:use-module (ice-9 match)) (define %guile-executable @@ -57,6 +60,40 @@ (string-take lib (string-contains lib ".so"))) (elf-dynamic-info-needed dyninfo)))))) +(unless (and %guile-executable (not (getenv "LD_LIBRARY_PATH")) + (file-needed %guile-executable)) ;statically linked? + (test-skip 1)) +(test-assert "file-needed/recursive" + (let* ((needed (file-needed/recursive %guile-executable)) + (pipe (dynamic-wind + (lambda () + ;; Tell ld.so to list loaded objects, like 'ldd' does. + (setenv "LD_TRACE_LOADED_OBJECTS" "yup")) + (lambda () + (open-pipe* OPEN_READ %guile-executable)) + (lambda () + (unsetenv "LD_TRACE_LOADED_OBJECTS"))))) + (define ldd-rx + (make-regexp "^[[:blank:]]+([[:graph:]]+ => )?([[:graph:]]+) .*$")) + + (define (read-ldd-output port) + ;; Read from PORT output in GNU ldd format. + (let loop ((result '())) + (match (read-line port) + ((? eof-object?) + (reverse result)) + ((= (cut regexp-exec ldd-rx <>) m) + (if m + (loop (cons (match:substring m 2) result)) + (loop result)))))) + + (define ground-truth + (remove (cut string-prefix? "linux-vdso.so" <>) + (read-ldd-output pipe))) + + (and (zero? (close-pipe pipe)) + (lset= string=? (pk 'truth ground-truth) (pk 'needed needed))))) + (test-equal "expand-origin" '("OOO/../lib" "OOO" @@ -96,4 +133,31 @@ (close-pipe pipe) str))))))) +(unless c-compiler + (test-skip 1)) +(test-equal "set-file-runpath + file-runpath" + "hello\n" + (call-with-temporary-directory + (lambda (directory) + (with-directory-excursion directory + (call-with-output-file "t.c" + (lambda (port) + (display "int main () { puts(\"hello\"); }" port))) + + (invoke c-compiler "t.c" + "-Wl,--enable-new-dtags" "-Wl,-rpath=/xxxxxxxxx") + + (let ((original-runpath (file-runpath "a.out"))) + (and (member "/xxxxxxxxx" original-runpath) + (guard (c ((runpath-too-long-error? c) + (string=? "a.out" (runpath-too-long-error-file c)))) + (set-file-runpath "a.out" (list (make-string 777 #\y)))) + (let ((runpath (delete "/xxxxxxxxx" original-runpath))) + (set-file-runpath "a.out" runpath) + (equal? runpath (file-runpath "a.out"))) + (let* ((pipe (open-input-pipe "./a.out")) + (str (get-string-all pipe))) + (close-pipe pipe) + str))))))) + (test-end "gremlin") diff --git a/tests/packages.scm b/tests/packages.scm index 2a290bc353..ff756c6001 100644 --- a/tests/packages.scm +++ b/tests/packages.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org> -;;; Copyright © Jan (janneke) Nieuwenhuizen <janneke@gnu.org> +;;; Copyright © 2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org> +;;; Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com> ;;; ;;; This file is part of GNU Guix. ;;; @@ -17,13 +18,14 @@ ;;; You should have received a copy of the GNU General Public License ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. -(define-module (test-packages) +(define-module (tests packages) #:use-module (guix tests) #:use-module (guix store) #:use-module (guix monads) #:use-module (guix grafts) - #:use-module ((guix gexp) #:select (local-file local-file-file)) + #:use-module (guix gexp) #:use-module (guix utils) + #:use-module ((guix build utils) #:select (tarball?)) #:use-module ((guix diagnostics) ;; Rename the 'location' binding to allow proper syntax ;; matching when setting the 'location' field of a package. @@ -32,6 +34,7 @@ (else name)))) #:use-module ((gcrypt hash) #:prefix gcrypt:) #:use-module (guix derivations) + #:use-module (guix download) #:use-module (guix packages) #:use-module (guix grafts) #:use-module (guix search-paths) @@ -51,6 +54,7 @@ #:use-module (gnu packages version-control) #:use-module (gnu packages xml) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) #:use-module (srfi srfi-26) #:use-module (srfi srfi-34) #:use-module (srfi srfi-35) @@ -578,6 +582,11 @@ (build-derivations %store (list drv)) (call-with-input-file output get-string-all))) + +;;; +;;; Source derivation with snippets. +;;; + (unless (network-reachable?) (test-skip 1)) (test-equal "package-source-derivation, snippet" "OK" @@ -633,11 +642,81 @@ (and (build-derivations %store (list (pk 'snippet-drv drv))) (call-with-input-file out get-string-all)))) +;; Note: lzip is not part of bootstrap-coreutils&co, so is not included to +;; avoid having to rebuild the world. +(define compressors '(("gzip" . "gz") + ("xz" . "xz") + ("bzip2" . "bz2") + (#f . #f))) + +(for-each + (match-lambda + ((comp . ext) + (unless (network-reachable?) (test-skip 1)) + (test-equal (string-append "origin->derivation, single file with snippet " + "(compression: " (if comp comp "None") ")") + "2 + 2 = 4" + (let*-values + (((name) "maths") + ((compressed-name) (if comp + (string-append name "." ext) + name)) + ((file hash) (test-file %store compressed-name "2 + 2 = 5")) + ;; Create an origin using the above computed file and its hash. + ((source) (origin + (method url-fetch) + (uri (string-append "file://" file)) + (file-name compressed-name) + (patch-inputs `(("tar" ,%bootstrap-coreutils&co) + ("xz" ,%bootstrap-coreutils&co) + ("bzip2" ,%bootstrap-coreutils&co) + ("gzip" ,%bootstrap-coreutils&co))) + (patch-guile %bootstrap-guile) + (modules '((guix build utils))) + (snippet `(substitute* ,name + (("5") "4"))) + (hash (content-hash hash)))) + ;; Build origin. + ((drv) (run-with-store %store (origin->derivation source))) + ((out) (derivation->output-path drv))) + ;; Decompress the resulting tar.xz and return its content. + (and (build-derivations %store (list drv)) + (if (tarball? out) + (let* ((bin #~(string-append #+%bootstrap-coreutils&co + "/bin")) + (f (computed-file + name + (with-imported-modules '((guix build utils)) + #~(begin + (use-modules (guix build utils)) + (setenv "PATH" #+bin) + (invoke "tar" "xvf" #+out) + (copy-file #+name #$output))))) + (drv (run-with-store %store (lower-object f))) + (_ (build-derivations %store (list drv)))) + (call-with-input-file (derivation->output-path drv) + get-string-all)) + (call-with-input-file out get-string-all))))))) + compressors) + (test-assert "return value" (let ((drv (package-derivation %store (dummy-package "p")))) (and (derivation? drv) (file-exists? (derivation-file-name drv))))) +(test-assert "package-derivation, inputs deduplicated" + (let* ((dep (dummy-package "dep")) + (p0 (dummy-package "p" (inputs `(("dep" ,dep))))) + (p1 (package (inherit p0) + (inputs `(("dep" ,(package (inherit dep))) + ,@(package-inputs p0)))))) + ;; Here P1 ends up with two non-eq? copies of DEP, under the same label. + ;; They should be deduplicated so that P0 and P1 lead to the same + ;; derivation rather than P1 ending up with duplicate entries in its + ;; '%build-inputs' variable. + (string=? (derivation-file-name (package-derivation %store p0)) + (derivation-file-name (package-derivation %store p1))))) + (test-assert "package-output" (let* ((package (dummy-package "p")) (drv (package-derivation %store package))) |