linux-container: Do not add %CONTAINER-FILE-SYSTEMS to Docker image OSes.
[guix.git] / tests / channels.scm
blob8540aef4351744f055490a56b6d87a7be816327c
1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2018 Ricardo Wurmus <rekado@elephly.net>
3 ;;;
4 ;;; This file is part of GNU Guix.
5 ;;;
6 ;;; GNU Guix is free software; you can redistribute it and/or modify it
7 ;;; under the terms of the GNU General Public License as published by
8 ;;; the Free Software Foundation; either version 3 of the License, or (at
9 ;;; your option) any later version.
10 ;;;
11 ;;; GNU Guix is distributed in the hope that it will be useful, but
12 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ;;; GNU General Public License for more details.
15 ;;;
16 ;;; You should have received a copy of the GNU General Public License
17 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
19 (define-module (test-channels)
20   #:use-module (guix channels)
21   #:use-module (guix profiles)
22   #:use-module ((guix build syscalls) #:select (mkdtemp!))
23   #:use-module (guix tests)
24   #:use-module (guix store)
25   #:use-module ((guix grafts) #:select (%graft?))
26   #:use-module (guix derivations)
27   #:use-module (guix sets)
28   #:use-module (guix gexp)
29   #:use-module (srfi srfi-1)
30   #:use-module (srfi srfi-26)
31   #:use-module (srfi srfi-64)
32   #:use-module (ice-9 match))
34 (test-begin "channels")
36 (define* (make-instance #:key
37                         (name 'fake)
38                         (commit "cafebabe")
39                         (spec #f))
40   (define instance-dir (mkdtemp! "/tmp/checkout.XXXXXX"))
41   (and spec
42        (with-output-to-file (string-append instance-dir "/.guix-channel")
43          (lambda _ (format #t "~a" spec))))
44   (checkout->channel-instance instance-dir
45                               #:commit commit
46                               #:name name))
48 (define instance--boring (make-instance))
49 (define instance--no-deps
50   (make-instance #:spec
51                  '(channel
52                    (version 0)
53                    (dependencies
54                     (channel
55                      (name test-channel)
56                      (url "https://example.com/test-channel"))))))
57 (define instance--simple
58   (make-instance #:spec
59                  '(channel
60                    (version 0)
61                    (dependencies
62                     (channel
63                      (name test-channel)
64                      (url "https://example.com/test-channel"))))))
65 (define instance--with-dupes
66   (make-instance #:spec
67                  '(channel
68                    (version 0)
69                    (dependencies
70                     (channel
71                      (name test-channel)
72                      (url "https://example.com/test-channel"))
73                     (channel
74                      (name test-channel)
75                      (url "https://example.com/test-channel")
76                      (commit "abc1234"))
77                     (channel
78                      (name test-channel)
79                      (url "https://example.com/test-channel-elsewhere"))))))
81 (define read-channel-metadata
82   (@@ (guix channels) read-channel-metadata))
85 (test-equal "read-channel-metadata returns #f if .guix-channel does not exist"
86   #f
87   (read-channel-metadata instance--boring))
89 (test-assert "read-channel-metadata returns <channel-metadata>"
90   (every (@@ (guix channels) channel-metadata?)
91          (map read-channel-metadata
92               (list instance--no-deps
93                     instance--simple
94                     instance--with-dupes))))
96 (test-assert "read-channel-metadata dependencies are channels"
97   (let ((deps ((@@ (guix channels) channel-metadata-dependencies)
98                (read-channel-metadata instance--simple))))
99     (match deps
100       (((? channel? dep)) #t)
101       (_ #f))))
103 (test-assert "latest-channel-instances includes channel dependencies"
104   (let* ((channel (channel
105                    (name 'test)
106                    (url "test")))
107          (test-dir (channel-instance-checkout instance--simple)))
108     (mock ((guix git) latest-repository-commit
109            (lambda* (store url #:key ref)
110              (match url
111                ("test" (values test-dir 'whatever))
112                (_ (values "/not-important" 'not-important)))))
113           (let ((instances (latest-channel-instances #f (list channel))))
114             (and (eq? 2 (length instances))
115                  (lset= eq?
116                         '(test test-channel)
117                         (map (compose channel-name channel-instance-channel)
118                              instances)))))))
120 (test-assert "latest-channel-instances excludes duplicate channel dependencies"
121   (let* ((channel (channel
122                    (name 'test)
123                    (url "test")))
124          (test-dir (channel-instance-checkout instance--with-dupes)))
125     (mock ((guix git) latest-repository-commit
126            (lambda* (store url #:key ref)
127              (match url
128                ("test" (values test-dir 'whatever))
129                (_ (values "/not-important" 'not-important)))))
130           (let ((instances (latest-channel-instances #f (list channel))))
131             (and (eq? 2 (length instances))
132                  (lset= eq?
133                         '(test test-channel)
134                         (map (compose channel-name channel-instance-channel)
135                              instances))
136                  ;; only the most specific channel dependency should remain,
137                  ;; i.e. the one with a specified commit.
138                  (find (lambda (instance)
139                          (and (eq? (channel-name
140                                     (channel-instance-channel instance))
141                                    'test-channel)
142                               (eq? (channel-commit
143                                     (channel-instance-channel instance))
144                                    'abc1234)))
145                        instances))))))
147 (test-assert "channel-instances->manifest"
148   ;; Compute the manifest for a graph of instances and make sure we get a
149   ;; derivation graph that mirrors the instance graph.  This test also ensures
150   ;; we don't try to access Git repositores at all at this stage.
151   (let* ((spec      (lambda deps
152                       `(channel (version 0)
153                                 (dependencies
154                                  ,@(map (lambda (dep)
155                                           `(channel
156                                             (name ,dep)
157                                             (url "http://example.org")))
158                                         deps)))))
159          (guix      (make-instance #:name 'guix))
160          (instance0 (make-instance #:name 'a))
161          (instance1 (make-instance #:name 'b #:spec (spec 'a)))
162          (instance2 (make-instance #:name 'c #:spec (spec 'b)))
163          (instance3 (make-instance #:name 'd #:spec (spec 'c 'a))))
164     (%graft? #f)                                    ;don't try to build stuff
166     ;; Create 'build-self.scm' so that GUIX is recognized as the 'guix' channel.
167     (let ((source (channel-instance-checkout guix)))
168       (mkdir (string-append source "/build-aux"))
169       (call-with-output-file (string-append source
170                                             "/build-aux/build-self.scm")
171         (lambda (port)
172           (write '(begin
173                     (use-modules (guix) (gnu packages bootstrap))
175                     (lambda _
176                       (package->derivation %bootstrap-guile)))
177                  port))))
179     (with-store store
180       (let ()
181         (define manifest
182           (run-with-store store
183             (channel-instances->manifest (list guix
184                                                instance0 instance1
185                                                instance2 instance3))))
187         (define entries
188           (manifest-entries manifest))
190         (define (depends? drv in out)
191           ;; Return true if DRV depends (directly or indirectly) on all of IN
192           ;; and none of OUT.
193           (let ((set (list->set
194                       (requisites store
195                                   (list (derivation-file-name drv)))))
196                 (in  (map derivation-file-name in))
197                 (out (map derivation-file-name out)))
198             (and (every (cut set-contains? set <>) in)
199                  (not (any (cut set-contains? set <>) out)))))
201         (define (lookup name)
202           (run-with-store store
203             (lower-object
204              (manifest-entry-item
205               (manifest-lookup manifest
206                                (manifest-pattern (name name)))))))
208         (let ((drv-guix (lookup "guix"))
209               (drv0     (lookup "a"))
210               (drv1     (lookup "b"))
211               (drv2     (lookup "c"))
212               (drv3     (lookup "d")))
213           (and (depends? drv-guix '() (list drv0 drv1 drv2 drv3))
214                (depends? drv0
215                          (list) (list drv1 drv2 drv3))
216                (depends? drv1
217                          (list drv0) (list drv2 drv3))
218                (depends? drv2
219                          (list drv1) (list drv3))
220                (depends? drv3
221                          (list drv2 drv0) (list))))))))
223 (test-end "channels")