linux-container: Add 'eval/container'.
[jackhill/guix/guix.git] / tests / channels.scm
CommitLineData
af12790b
RW
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/>.
18
19(define-module (test-channels)
20 #:use-module (guix channels)
ed75bdf3 21 #:use-module (guix profiles)
af12790b
RW
22 #:use-module ((guix build syscalls) #:select (mkdtemp!))
23 #:use-module (guix tests)
ed75bdf3
LC
24 #:use-module (guix store)
25 #:use-module ((guix grafts) #:select (%graft?))
26 #:use-module (guix derivations)
1fafc383 27 #:use-module (guix sets)
ed75bdf3 28 #:use-module (guix gexp)
af12790b 29 #:use-module (srfi srfi-1)
ed75bdf3 30 #:use-module (srfi srfi-26)
af12790b
RW
31 #:use-module (srfi srfi-64)
32 #:use-module (ice-9 match))
33
34(test-begin "channels")
35
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))))
ed75bdf3
LC
44 (checkout->channel-instance instance-dir
45 #:commit commit
46 #:name name))
af12790b
RW
47
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"))))))
80
81(define read-channel-metadata
82 (@@ (guix channels) read-channel-metadata))
83
84\f
85(test-equal "read-channel-metadata returns #f if .guix-channel does not exist"
86 #f
87 (read-channel-metadata instance--boring))
88
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))))
95
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))))
102
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)))))))
119
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))))))
146
ed75bdf3
LC
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
165
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))
174
175 (lambda _
176 (package->derivation %bootstrap-guile)))
177 port))))
178
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))))
186
187 (define entries
188 (manifest-entries manifest))
189
190 (define (depends? drv in out)
1fafc383
LC
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)))))
ed75bdf3
LC
196 (in (map derivation-file-name in))
197 (out (map derivation-file-name out)))
1fafc383
LC
198 (and (every (cut set-contains? set <>) in)
199 (not (any (cut set-contains? set <>) out)))))
ed75bdf3
LC
200
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)))))))
207
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
1fafc383 219 (list drv1) (list drv3))
ed75bdf3 220 (depends? drv3
1fafc383 221 (list drv2 drv0) (list))))))))
ed75bdf3 222
af12790b 223(test-end "channels")