summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/build-utils.scm24
-rw-r--r--tests/builders.scm121
-rw-r--r--tests/gremlin.scm66
-rw-r--r--tests/packages.scm85
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)))