gnu: crm114: Fix typo in description.
[jackhill/guix/guix.git] / tests / lint.scm
CommitLineData
b4f5e0e8
CR
1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2012, 2013 Cyril Roelandt <tipecaml@gmail.com>
83f18e06 3;;; Copyright © 2014, 2015, 2016 Eric Bavier <bavier@member.fsf.org>
bc4d81d2 4;;; Copyright © 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
052d53df 5;;; Copyright © 2015, 2016 Mathieu Lirzin <mthl@gnu.org>
891a843d 6;;; Copyright © 2016 Hartmut Goebel <h.goebel@crazy-compilers.com>
689db38e 7;;; Copyright © 2017 Alex Kost <alezost@gmail.com>
f4007b25 8;;; Copyright © 2017 Efraim Flashner <efraim@flashner.co.il>
40fa21c2 9;;; Copyright © 2018, 2019 Arun Isaac <arunisaac@systemreboot.net>
464b1fff 10;;; Copyright © 2020 Timothy Sample <samplet@ngyro.com>
eac82c0e 11;;; Copyright © 2020 Tobias Geerinckx-Rice <me@tobias.gr>
c68070e4 12;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
5532371a 13;;; Copyright © 2021 Maxime Devos <maximedevos@telenet.be>
b4f5e0e8
CR
14;;;
15;;; This file is part of GNU Guix.
16;;;
17;;; GNU Guix is free software; you can redistribute it and/or modify it
18;;; under the terms of the GNU General Public License as published by
19;;; the Free Software Foundation; either version 3 of the License, or (at
20;;; your option) any later version.
21;;;
22;;; GNU Guix is distributed in the hope that it will be useful, but
23;;; WITHOUT ANY WARRANTY; without even the implied warranty of
24;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25;;; GNU General Public License for more details.
26;;;
27;;; You should have received a copy of the GNU General Public License
28;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
29
c74f0cb2
LC
30;; Avoid interference.
31(unsetenv "http_proxy")
32
4e7b6b48 33(define-module (test-lint)
8b385969 34 #:use-module (guix tests)
17ab08bc 35 #:use-module (guix tests http)
754e5be2 36 #:use-module (guix download)
50f5c46d 37 #:use-module (guix git-download)
b4f5e0e8
CR
38 #:use-module (guix build-system gnu)
39 #:use-module (guix packages)
f363c836 40 #:use-module (guix lint)
b4f5e0e8 41 #:use-module (guix ui)
55549c7b 42 #:use-module (guix swh)
5532371a 43 #:use-module ((guix gexp) #:select (gexp local-file gexp?))
4f156c25 44 #:use-module ((guix utils) #:select (call-with-temporary-directory))
464b1fff
TS
45 #:use-module ((guix import hackage) #:select (%hackage-url))
46 #:use-module ((guix import stackage) #:select (%stackage-url))
b4f5e0e8 47 #:use-module (gnu packages)
99fe215c 48 #:use-module (gnu packages glib)
b4f5e0e8 49 #:use-module (gnu packages pkg-config)
3b98522b 50 #:use-module (gnu packages python-xyz)
eac82c0e 51 #:use-module ((gnu packages bash) #:select (bash bash-minimal))
61f28fe7 52 #:use-module (web uri)
907c98ac
LC
53 #:use-module (web server)
54 #:use-module (web server http)
55 #:use-module (web response)
9bee2bd1 56 #:use-module (ice-9 match)
50fc2384
CB
57 #:use-module (ice-9 regex)
58 #:use-module (ice-9 getopt-long)
59 #:use-module (ice-9 pretty-print)
55549c7b 60 #:use-module (rnrs bytevectors)
50fc2384 61 #:use-module (srfi srfi-1)
907c98ac 62 #:use-module (srfi srfi-9 gnu)
50fc2384 63 #:use-module (srfi srfi-26)
b4f5e0e8
CR
64 #:use-module (srfi srfi-64))
65
66;; Test the linter.
67
950d2ea4
LC
68(define %null-sha256
69 ;; SHA256 of the empty string.
70 (base32
71 "0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73"))
72
bfcb3d76
LC
73(define %long-string
74 (make-string 2000 #\a))
907c98ac 75
50fc2384
CB
76(define (string-match-or-error pattern str)
77 (or (string-match pattern str)
78 (error str "did not match" pattern)))
79
80(define single-lint-warning-message
81 (match-lambda
82 (((and (? lint-warning?) warning))
83 (lint-warning-message warning))))
84
37592014
LC
85(define (warning-contains? str warnings)
86 "Return true if WARNINGS is a singleton with a warning that contains STR."
87 (match warnings
88 (((? lint-warning? warning))
89 (string-contains (lint-warning-message warning) str))))
90
b4f5e0e8
CR
91\f
92(test-begin "lint")
93
50fc2384
CB
94(test-equal "description: not a string"
95 "invalid description: foobar"
96 (single-lint-warning-message
97 (check-description-style
98 (dummy-package "x" (description 'foobar)))))
99
100(test-equal "description: not empty"
101 "description should not be empty"
102 (single-lint-warning-message
103 (check-description-style
104 (dummy-package "x" (description "")))))
105
106(test-equal "description: invalid Texinfo markup"
107 "Texinfo markup in description is invalid"
108 (single-lint-warning-message
109 (check-description-style
110 (dummy-package "x" (description "f{oo}b@r")))))
111
112(test-equal "description: does not start with an upper-case letter"
113 "description should start with an upper-case letter or digit"
114 (single-lint-warning-message
115 (let ((pkg (dummy-package "x"
116 (description "bad description."))))
117 (check-description-style pkg))))
118
119(test-equal "description: may start with a digit"
120 '()
121 (let ((pkg (dummy-package "x"
122 (description "2-component library."))))
123 (check-description-style pkg)))
124
125(test-equal "description: may start with lower-case package name"
126 '()
127 (let ((pkg (dummy-package "x"
128 (description "x is a dummy package."))))
129 (check-description-style pkg)))
130
131(test-equal "description: two spaces after end of sentence"
132 "sentences in description should be followed by two spaces; possible infraction at 3"
133 (single-lint-warning-message
134 (let ((pkg (dummy-package "x"
135 (description "Bad. Quite bad."))))
136 (check-description-style pkg))))
137
138(test-equal "description: end-of-sentence detection with abbreviations"
139 '()
140 (let ((pkg (dummy-package "x"
141 (description
142 "E.g. Foo, i.e. Bar resp. Baz (a.k.a. DVD)."))))
143 (check-description-style pkg)))
144
145(test-equal "description: may not contain trademark signs: ™"
146 "description should not contain trademark sign '™' at 20"
147 (single-lint-warning-message
148 (let ((pkg (dummy-package "x"
149 (description "Does The Right Thing™"))))
150 (check-description-style pkg))))
151
152(test-equal "description: may not contain trademark signs: ®"
153 "description should not contain trademark sign '®' at 17"
154 (single-lint-warning-message
155 (let ((pkg (dummy-package "x"
156 (description "Works with Format®"))))
157 (check-description-style pkg))))
158
159(test-equal "description: suggest ornament instead of quotes"
160 "use @code or similar ornament instead of quotes"
161 (single-lint-warning-message
162 (let ((pkg (dummy-package "x"
163 (description "This is a 'quoted' thing."))))
164 (check-description-style pkg))))
165
edb328ad
BW
166(test-equal "description: leading whitespace"
167 "description contains leading whitespace"
168 (single-lint-warning-message
169 (let ((pkg (dummy-package "x"
170 (description " Whitespace."))))
171 (check-description-style pkg))))
172
93d85dea
XC
173(test-equal "description: trailing whitespace"
174 "description contains trailing whitespace"
175 (single-lint-warning-message
176 (let ((pkg (dummy-package "x"
177 (description "Whitespace. "))))
178 (check-description-style pkg))))
179
50fc2384
CB
180(test-equal "synopsis: not a string"
181 "invalid synopsis: #f"
182 (single-lint-warning-message
183 (let ((pkg (dummy-package "x"
184 (synopsis #f))))
185 (check-synopsis-style pkg))))
186
187(test-equal "synopsis: not empty"
188 "synopsis should not be empty"
189 (single-lint-warning-message
190 (let ((pkg (dummy-package "x"
191 (synopsis ""))))
192 (check-synopsis-style pkg))))
193
194(test-equal "synopsis: valid Texinfo markup"
195 "Texinfo markup in synopsis is invalid"
196 (single-lint-warning-message
197 (check-synopsis-style
198 (dummy-package "x" (synopsis "Bad $@ texinfo")))))
199
200(test-equal "synopsis: does not start with an upper-case letter"
201 "synopsis should start with an upper-case letter or digit"
202 (single-lint-warning-message
203 (let ((pkg (dummy-package "x"
204 (synopsis "bad synopsis"))))
205 (check-synopsis-style pkg))))
206
207(test-equal "synopsis: may start with a digit"
208 '()
209 (let ((pkg (dummy-package "x"
210 (synopsis "5-dimensional frobnicator"))))
211 (check-synopsis-style pkg)))
212
213(test-equal "synopsis: ends with a period"
214 "no period allowed at the end of the synopsis"
215 (single-lint-warning-message
216 (let ((pkg (dummy-package "x"
217 (synopsis "Bad synopsis."))))
218 (check-synopsis-style pkg))))
219
220(test-equal "synopsis: ends with 'etc.'"
221 '()
222 (let ((pkg (dummy-package "x"
223 (synopsis "Foo, bar, etc."))))
224 (check-synopsis-style pkg)))
225
226(test-equal "synopsis: starts with 'A'"
227 "no article allowed at the beginning of the synopsis"
228 (single-lint-warning-message
229 (let ((pkg (dummy-package "x"
230 (synopsis "A bad synopŝis"))))
231 (check-synopsis-style pkg))))
232
233(test-equal "synopsis: starts with 'An'"
234 "no article allowed at the beginning of the synopsis"
235 (single-lint-warning-message
236 (let ((pkg (dummy-package "x"
237 (synopsis "An awful synopsis"))))
238 (check-synopsis-style pkg))))
239
240(test-equal "synopsis: starts with 'a'"
241 '("no article allowed at the beginning of the synopsis"
242 "synopsis should start with an upper-case letter or digit")
243 (sort
244 (map
245 lint-warning-message
246 (let ((pkg (dummy-package "x"
247 (synopsis "a bad synopsis"))))
248 (check-synopsis-style pkg)))
249 string<?))
250
251(test-equal "synopsis: starts with 'an'"
252 '("no article allowed at the beginning of the synopsis"
253 "synopsis should start with an upper-case letter or digit")
254 (sort
255 (map
256 lint-warning-message
257 (let ((pkg (dummy-package "x"
258 (synopsis "an awful synopsis"))))
259 (check-synopsis-style pkg)))
260 string<?))
261
262(test-equal "synopsis: too long"
263 "synopsis should be less than 80 characters long"
264 (single-lint-warning-message
265 (let ((pkg (dummy-package "x"
266 (synopsis (make-string 80 #\X)))))
267 (check-synopsis-style pkg))))
268
269(test-equal "synopsis: start with package name"
270 "synopsis should not start with the package name"
271 (single-lint-warning-message
272 (let ((pkg (dummy-package "x"
273 (name "Foo")
274 (synopsis "Foo, a nice package"))))
275 (check-synopsis-style pkg))))
276
277(test-equal "synopsis: start with package name prefix"
278 '()
279 (let ((pkg (dummy-package "arb"
280 (synopsis "Arbitrary precision"))))
281 (check-synopsis-style pkg)))
282
283(test-equal "synopsis: start with abbreviation"
284 '()
285 (let ((pkg (dummy-package "uucp"
286 ;; Same problem with "APL interpreter", etc.
287 (synopsis "UUCP implementation")
288 (description "Imagine this is Taylor UUCP."))))
289 (check-synopsis-style pkg)))
290
04afb769
XC
291(test-equal "synopsis: contains trailing whitespace"
292 "synopsis contains trailing whitespace"
293 (single-lint-warning-message
294 (let ((pkg (dummy-package "x"
295 (synopsis "Whitespace "))))
296 (check-synopsis-style pkg))))
297
c68070e4
XC
298(test-equal "name: use underscore in package name"
299 "name should use hyphens instead of underscores"
300 (single-lint-warning-message
301 (let ((pkg (dummy-package "under_score")))
302 (check-name pkg))))
303
82b0e27d
MD
304(test-equal "tests-true: #:tests? must not be set to #t"
305 "#:tests? must not be explicitly set to #t"
306 (single-lint-warning-message
307 (let ((pkg (dummy-package "x" (arguments '(#:tests? #t)))))
308 (check-tests-true pkg))))
309
310(test-equal "tests-true: absent #:tests? is acceptable"
311 '()
312 (let ((pkg (dummy-package "x")))
313 (check-tests-true pkg)))
314
315(test-equal "tests-true: #:tests? #f is acceptable"
316 '()
317 (let ((pkg (dummy-package "x" (arguments '(#:tests? #f)))))
318 (check-tests-true pkg)))
319
320(test-equal "tests-true: #:tests? #t acceptable when compiling natively"
321 '()
322 (let ((pkg (dummy-package "x"
323 (arguments
324 `(#:tests? ,(not (%current-target-system)))))))
325 (check-tests-true pkg)))
326
50fc2384
CB
327(test-equal "inputs: pkg-config is probably a native input"
328 "'pkg-config' should probably be a native input"
329 (single-lint-warning-message
330 (let ((pkg (dummy-package "x"
331 (inputs `(("pkg-config" ,pkg-config))))))
332 (check-inputs-should-be-native pkg))))
333
334(test-equal "inputs: glib:bin is probably a native input"
335 "'glib:bin' should probably be a native input"
336 (single-lint-warning-message
337 (let ((pkg (dummy-package "x"
338 (inputs `(("glib" ,glib "bin"))))))
339 (check-inputs-should-be-native pkg))))
340
341(test-equal
891a843d 342 "inputs: python-setuptools should not be an input at all (input)"
50fc2384
CB
343 "'python-setuptools' should probably not be an input at all"
344 (single-lint-warning-message
345 (let ((pkg (dummy-package "x"
346 (inputs `(("python-setuptools"
347 ,python-setuptools))))))
348 (check-inputs-should-not-be-an-input-at-all pkg))))
349
350(test-equal
891a843d 351 "inputs: python-setuptools should not be an input at all (native-input)"
50fc2384
CB
352 "'python-setuptools' should probably not be an input at all"
353 (single-lint-warning-message
354 (let ((pkg (dummy-package "x"
355 (native-inputs
356 `(("python-setuptools"
357 ,python-setuptools))))))
358 (check-inputs-should-not-be-an-input-at-all pkg))))
359
360(test-equal
891a843d 361 "inputs: python-setuptools should not be an input at all (propagated-input)"
50fc2384
CB
362 "'python-setuptools' should probably not be an input at all"
363 (single-lint-warning-message
364 (let ((pkg (dummy-package "x"
365 (propagated-inputs
366 `(("python-setuptools" ,python-setuptools))))))
367 (check-inputs-should-not-be-an-input-at-all pkg))))
368
eac82c0e
MD
369(test-equal "explicit #:sh argument to 'wrap-program' is acceptable"
370 '()
371 (let* ((phases
372 ;; Loosely based on the "catfish" package
373 `(modify-phases %standard-phases
374 (add-after 'install 'wrap
375 (lambda* (#:key inputs outputs #:allow-other-keys)
376 (define catfish (string-append (assoc-ref outputs "out")
377 "/bin/catfish"))
378 (define hsab (string-append (assoc-ref inputs "hsab")
379 "/bin/hsab"))
380 (wrap-program catfish #:sh hsab
381 `("PYTHONPATH" = (,"blabla")))))))
382 (pkg (dummy-package "x" (arguments `(#:phases ,phases)))))
383 (check-wrapper-inputs pkg)))
384
385(test-equal
386 "'check-wrapper-inputs' detects 'wrap-program' without \"bash\" in inputs"
387 "\"bash-minimal\" should be in 'inputs' when 'wrap-program' is used"
388 (let* ((phases
389 `(modify-phases %standard-phases
390 (add-after 'install 'wrap
391 (lambda _
392 (wrap-program the-binary bla-bla)))))
393 (pkg (dummy-package "x" (arguments `(#:phases ,phases)))))
394 (single-lint-warning-message (check-wrapper-inputs pkg))))
395
396(test-equal
397 "'check-wrapper-inputs' detects 'wrap-qt-program' without \"bash\" in inputs"
398 "\"bash-minimal\" should be in 'inputs' when 'wrap-qt-program' is used"
399 (let* ((phases
400 `(modify-phases %standard-phases
401 (add-after 'install 'qtwrap
402 (lambda _
403 (wrap-qt-program the-binary bla-bla)))))
404 (pkg (dummy-package "x" (arguments `(#:phases ,phases)))))
405 (single-lint-warning-message (check-wrapper-inputs pkg))))
406
407(test-equal "\"bash\" in 'inputs' satisfies 'check-wrapper-inputs'"
408 '()
409 (let* ((phases
410 `(modify-phases %standard-phases
411 (add-after 'install 'wrap
412 (lambda _
413 (wrap-program the-binary bla-bla)))))
414 (pkg (dummy-package "x" (arguments `(#:phases ,phases))
415 (inputs `(("bash" ,bash))))))
416 (check-wrapper-inputs pkg)))
417
418(test-equal "\"bash-minimal\" in 'inputs' satisfies 'check-wrapper-inputs'"
419 '()
420 (let* ((phases
421 `(modify-phases %standard-phases
422 (add-after 'install 'wrap
423 (lambda _
424 (wrap-program THE-BINARY bla-bla)))))
425 (pkg (dummy-package "x" (arguments `(#:phases ,phases))
426 (inputs `(("bash-minimal" ,bash-minimal))))))
427 (check-wrapper-inputs pkg)))
428
429(test-equal "'cut' doesn't hide bad usages of 'wrap-program'"
430 "\"bash-minimal\" should be in 'inputs' when 'wrap-program' is used"
431 (let* ((phases
432 ;; Taken from the "straw-viewer" package
433 `(modify-phases %standard-phases
434 (add-after 'install 'wrap-program
435 (lambda* (#:key outputs #:allow-other-keys)
436 (let* ((out (assoc-ref outputs "out"))
437 (bin-dir (string-append out "/bin/"))
438 (site-dir (string-append out "/lib/perl5/site_perl/"))
439 (lib-path (getenv "PERL5LIB")))
440 (for-each (cut wrap-program <>
441 `("PERL5LIB" ":" prefix
442 (,lib-path ,site-dir)))
443 (find-files bin-dir)))))))
444 (pkg (dummy-package "x" (arguments `(#:phases ,phases)))))
445 (single-lint-warning-message (check-wrapper-inputs pkg))))
446
447(test-equal "bogus phase specifications don't crash the linter"
448 "invalid phase clause"
449 (let* ((phases
450 `(modify-phases %standard-phases
451 (add-invalid)))
452 (pkg (dummy-package "x" (arguments `(#:phases ,phases)))))
453 (single-lint-warning-message (check-wrapper-inputs pkg))))
454
d8ae7852 455(test-equal "file patches: different file name -> warning"
50fc2384
CB
456 "file names of patches should start with the package name"
457 (single-lint-warning-message
458 (let ((pkg (dummy-package "x"
459 (source
460 (dummy-origin
461 (patches (list "/path/to/y.patch")))))))
462 (check-patch-file-names pkg))))
463
d8ae7852
CM
464(test-equal "file patches: same file name -> no warnings"
465 '()
466 (let ((pkg (dummy-package "x"
467 (source
468 (dummy-origin
469 (patches (list "/path/to/x.patch")))))))
470 (check-patch-file-names pkg)))
471
472(test-equal "<origin> patches: different file name -> warning"
473 "file names of patches should start with the package name"
474 (single-lint-warning-message
475 (let ((pkg (dummy-package "x"
476 (source
477 (dummy-origin
478 (patches
479 (list
480 (dummy-origin
481 (file-name "y.patch")))))))))
482 (check-patch-file-names pkg))))
483
484(test-equal "<origin> patches: same file name -> no warnings"
485 '()
486 (let ((pkg (dummy-package "x"
487 (source
488 (dummy-origin
489 (patches
490 (list
491 (dummy-origin
492 (file-name "x.patch")))))))))
493 (check-patch-file-names pkg)))
494
50fc2384
CB
495(test-equal "patches: file name too long"
496 (string-append "x-"
497 (make-string 100 #\a)
498 ".patch: file name is too long")
499 (single-lint-warning-message
500 (let ((pkg (dummy-package
501 "x"
502 (source
503 (dummy-origin
504 (patches (list (string-append "x-"
505 (make-string 100 #\a)
506 ".patch"))))))))
507 (check-patch-file-names pkg))))
508
509(test-equal "patches: not found"
d51bfe24 510 "this-patch-does-not-exist!: patch not found\n"
50fc2384
CB
511 (single-lint-warning-message
512 (let ((pkg (dummy-package
513 "x"
514 (source
515 (dummy-origin
516 (patches
517 (list (search-patch "this-patch-does-not-exist!"))))))))
518 (check-patch-file-names pkg))))
519
4f156c25
LC
520(test-assert "patch headers: no warnings"
521 (call-with-temporary-directory
522 (lambda (directory)
523 (call-with-output-file (string-append directory "/t.patch")
524 (lambda (port)
525 (display "This is a patch.\n\n--- a\n+++ b\n"
526 port)))
527
528 (parameterize ((%patch-path (list directory)))
529 (let ((pkg (dummy-package "x"
530 (source (dummy-origin
531 (patches (search-patches "t.patch")))))))
532 (null? (check-patch-headers pkg)))))))
533
534(test-equal "patch headers: missing comment"
535 "t.patch: patch lacks comment and upstream status"
536 (call-with-temporary-directory
537 (lambda (directory)
538 (call-with-output-file (string-append directory "/t.patch")
539 (lambda (port)
540 (display "\n--- a\n+++ b\n"
541 port)))
542
543 (parameterize ((%patch-path (list directory)))
544 (let ((pkg (dummy-package "x"
545 (source (dummy-origin
546 (patches (search-patches "t.patch")))))))
547 (single-lint-warning-message (check-patch-headers pkg)))))))
548
549(test-equal "patch headers: empty"
550 "t.patch: empty patch"
551 (call-with-temporary-directory
552 (lambda (directory)
553 (call-with-output-file (string-append directory "/t.patch")
554 (const #t))
555
556 (parameterize ((%patch-path '()))
557 (let ((pkg (dummy-package "x"
558 (source (dummy-origin
559 (patches
560 (list (local-file
561 (string-append directory
562 "/t.patch")))))))))
563 (single-lint-warning-message (check-patch-headers pkg)))))))
564
565(test-equal "patch headers: patch not found"
566 "does-not-exist.patch: patch not found\n"
567 (parameterize ((%patch-path '()))
568 (let ((pkg (dummy-package "x"
569 (source (dummy-origin
570 (patches
571 (search-patches "does-not-exist.patch")))))))
572 (single-lint-warning-message (check-patch-headers pkg)))))
573
50fc2384
CB
574(test-equal "derivation: invalid arguments"
575 "failed to create x86_64-linux derivation: (wrong-type-arg \"map\" \"Wrong type argument: ~S\" (invalid-module) ())"
576 (match (let ((pkg (dummy-package "x"
577 (arguments
578 '(#:imported-modules (invalid-module))))))
579 (check-derivation pkg))
580 (((and (? lint-warning?) first-warning) others ...)
581 (lint-warning-message first-warning))))
582
993023a2
LC
583(test-equal "profile-collisions: no warnings"
584 '()
585 (check-profile-collisions (dummy-package "x")))
586
587(test-equal "profile-collisions: propagated inputs collide"
588 "propagated inputs p0@1 and p0@2 collide"
589 (let* ((p0 (dummy-package "p0" (version "1")))
590 (p0* (dummy-package "p0" (version "2")))
591 (p1 (dummy-package "p1" (propagated-inputs `(("p0" ,p0)))))
592 (p2 (dummy-package "p2" (propagated-inputs `(("p1" ,p1)))))
593 (p3 (dummy-package "p3" (propagated-inputs `(("p0" ,p0*)))))
594 (p4 (dummy-package "p4" (propagated-inputs
595 `(("p2" ,p2) ("p3", p3))))))
596 (single-lint-warning-message
597 (check-profile-collisions p4))))
598
599(test-assert "profile-collisions: propagated inputs collide, store items"
600 (string-match-or-error
601 "propagated inputs /[[:graph:]]+-p0-1 and /[[:graph:]]+-p0-1 collide"
602 (let* ((p0 (dummy-package "p0" (version "1")))
603 (p0* (dummy-package "p0" (version "1")
604 (inputs `(("x" ,(dummy-package "x"))))))
605 (p1 (dummy-package "p1" (propagated-inputs `(("p0" ,p0)))))
606 (p2 (dummy-package "p2" (propagated-inputs `(("p1" ,p1)))))
607 (p3 (dummy-package "p3" (propagated-inputs `(("p0" ,p0*)))))
608 (p4 (dummy-package "p4" (propagated-inputs
609 `(("p2" ,p2) ("p3", p3))))))
610 (single-lint-warning-message
611 (check-profile-collisions p4)))))
612
50fc2384
CB
613(test-equal "license: invalid license"
614 "invalid license field"
615 (single-lint-warning-message
616 (check-license (dummy-package "x" (license #f)))))
617
618(test-equal "home-page: wrong home-page"
619 "invalid value for home page"
620 (let ((pkg (package
621 (inherit (dummy-package "x"))
622 (home-page #f))))
623 (single-lint-warning-message
624 (check-home-page pkg))))
625
626(test-equal "home-page: invalid URI"
627 "invalid home page URL: \"foobar\""
628 (let ((pkg (package
629 (inherit (dummy-package "x"))
630 (home-page "foobar"))))
631 (single-lint-warning-message
632 (check-home-page pkg))))
633
37592014 634(test-assert "home-page: host not found"
50fc2384
CB
635 (let ((pkg (package
636 (inherit (dummy-package "x"))
637 (home-page "http://does-not-exist"))))
37592014 638 (warning-contains? "domain not found" (check-home-page pkg))))
907c98ac 639
c05ceaf2
MD
640(parameterize ((%http-server-port 9999))
641 ;; TODO skip this test if some process is currently listening at 9999
642 (test-equal "home-page: Connection refused"
643 "URI http://localhost:9999/foo/bar unreachable: Connection refused"
644 (let ((pkg (package
645 (inherit (dummy-package "x"))
646 (home-page (%local-url)))))
647 (single-lint-warning-message
648 (check-home-page pkg)))))
907c98ac 649
907c98ac 650(test-equal "home-page: 200"
50fc2384 651 '()
9323ab55 652 (with-http-server `((200 ,%long-string))
50fc2384
CB
653 (let ((pkg (package
654 (inherit (dummy-package "x"))
655 (home-page (%local-url)))))
656 (check-home-page pkg))))
907c98ac 657
c05ceaf2
MD
658(with-http-server `((200 "This is too small."))
659 (test-equal "home-page: 200 but short length"
660 (format #f "URI ~a returned suspiciously small file (18 bytes)"
661 (%local-url))
50fc2384
CB
662 (let ((pkg (package
663 (inherit (dummy-package "x"))
664 (home-page (%local-url)))))
665
666 (single-lint-warning-message
667 (check-home-page pkg)))))
bfcb3d76 668
c05ceaf2
MD
669(with-http-server `((404 ,%long-string))
670 (test-equal "home-page: 404"
671 (format #f "URI ~a not reachable: 404 (\"Such is life\")" (%local-url))
50fc2384
CB
672 (let ((pkg (package
673 (inherit (dummy-package "x"))
674 (home-page (%local-url)))))
675 (single-lint-warning-message
676 (check-home-page pkg)))))
b4f5e0e8 677
c05ceaf2
MD
678(with-http-server `((301 ,%long-string))
679 (test-equal "home-page: 301, invalid"
680 (format #f "invalid permanent redirect from ~a" (%local-url))
50fc2384
CB
681 (let ((pkg (package
682 (inherit (dummy-package "x"))
683 (home-page (%local-url)))))
684 (single-lint-warning-message
685 (check-home-page pkg)))))
61f28fe7 686
c05ceaf2
MD
687(with-http-server `((200 ,%long-string))
688 (let* ((initial-url (%local-url))
689 (redirect (build-response #:code 301
690 #:headers
691 `((location
692 . ,(string->uri initial-url))))))
693 (parameterize ((%http-server-port 0))
694 (with-http-server `((,redirect ""))
695 (test-equal "home-page: 301 -> 200"
696 (format #f "permanent redirect from ~a to ~a"
697 (%local-url) initial-url)
50fc2384
CB
698 (let ((pkg (package
699 (inherit (dummy-package "x"))
700 (home-page (%local-url)))))
701 (single-lint-warning-message
702 (check-home-page pkg))))))))
61f28fe7 703
c05ceaf2
MD
704(with-http-server `((404 "booh!"))
705 (let* ((initial-url (%local-url))
706 (redirect (build-response #:code 301
707 #:headers
708 `((location
709 . ,(string->uri initial-url))))))
710 (parameterize ((%http-server-port 0))
711 (with-http-server `((,redirect ""))
712 (test-equal "home-page: 301 -> 404"
713 (format #f "URI ~a not reachable: 404 (\"Such is life\")" (%local-url))
50fc2384
CB
714 (let ((pkg (package
715 (inherit (dummy-package "x"))
716 (home-page (%local-url)))))
717 (single-lint-warning-message
718 (check-home-page pkg))))))))
719
720
721(test-equal "source-file-name"
722 "the source file name should contain the package name"
723 (let ((pkg (dummy-package "x"
724 (version "3.2.1")
725 (source
726 (origin
727 (method url-fetch)
728 (uri "http://www.example.com/3.2.1.tar.gz")
729 (sha256 %null-sha256))))))
730 (single-lint-warning-message
731 (check-source-file-name pkg))))
732
733(test-equal "source-file-name: v prefix"
734 "the source file name should contain the package name"
735 (let ((pkg (dummy-package "x"
736 (version "3.2.1")
737 (source
738 (origin
739 (method url-fetch)
740 (uri "http://www.example.com/v3.2.1.tar.gz")
741 (sha256 %null-sha256))))))
742 (single-lint-warning-message
743 (check-source-file-name pkg))))
744
745(test-equal "source-file-name: bad checkout"
746 "the source file name should contain the package name"
747 (let ((pkg (dummy-package "x"
748 (version "3.2.1")
749 (source
750 (origin
751 (method git-fetch)
752 (uri (git-reference
753 (url "http://www.example.com/x.git")
754 (commit "0")))
755 (sha256 %null-sha256))))))
756 (single-lint-warning-message
757 (check-source-file-name pkg))))
758
759(test-equal "source-file-name: good checkout"
760 '()
761 (let ((pkg (dummy-package "x"
762 (version "3.2.1")
763 (source
764 (origin
765 (method git-fetch)
766 (uri (git-reference
767 (url "http://git.example.com/x.git")
768 (commit "0")))
769 (file-name (string-append "x-" version))
770 (sha256 %null-sha256))))))
771 (check-source-file-name pkg)))
772
773(test-equal "source-file-name: valid"
774 '()
775 (let ((pkg (dummy-package "x"
776 (version "3.2.1")
777 (source
778 (origin
779 (method url-fetch)
780 (uri "http://www.example.com/x-3.2.1.tar.gz")
781 (sha256 %null-sha256))))))
782 (check-source-file-name pkg)))
c180017b 783
50fc2384
CB
784(test-equal "source-unstable-tarball"
785 "the source URI should not be an autogenerated tarball"
786 (let ((pkg (dummy-package "x"
787 (source
788 (origin
789 (method url-fetch)
790 (uri "https://github.com/example/example/archive/v0.0.tar.gz")
791 (sha256 %null-sha256))))))
792 (single-lint-warning-message
793 (check-source-unstable-tarball pkg))))
794
795(test-equal "source-unstable-tarball: source #f"
796 '()
797 (let ((pkg (dummy-package "x"
798 (source #f))))
799 (check-source-unstable-tarball pkg)))
800
801(test-equal "source-unstable-tarball: valid"
802 '()
803 (let ((pkg (dummy-package "x"
804 (source
805 (origin
806 (method url-fetch)
807 (uri "https://github.com/example/example/releases/download/x-0.0/x-0.0.tar.gz")
808 (sha256 %null-sha256))))))
809 (check-source-unstable-tarball pkg)))
950d2ea4 810
50fc2384
CB
811(test-equal "source-unstable-tarball: package named archive"
812 '()
813 (let ((pkg (dummy-package "x"
814 (source
815 (origin
bfcb3d76 816 (method url-fetch)
50fc2384 817 (uri "https://github.com/example/archive/releases/download/x-0.0/x-0.0.tar.gz")
bfcb3d76 818 (sha256 %null-sha256))))))
50fc2384 819 (check-source-unstable-tarball pkg)))
bfcb3d76 820
50fc2384
CB
821(test-equal "source-unstable-tarball: not-github"
822 '()
823 (let ((pkg (dummy-package "x"
824 (source
825 (origin
950d2ea4 826 (method url-fetch)
50fc2384 827 (uri "https://bitbucket.org/archive/example/download/x-0.0.tar.gz")
950d2ea4 828 (sha256 %null-sha256))))))
50fc2384
CB
829 (check-source-unstable-tarball pkg)))
830
831(test-equal "source-unstable-tarball: git-fetch"
832 '()
833 (let ((pkg (dummy-package "x"
834 (source
835 (origin
836 (method git-fetch)
837 (uri (git-reference
b0e7b699 838 (url "https://github.com/archive/example")
50fc2384
CB
839 (commit "0")))
840 (sha256 %null-sha256))))))
841 (check-source-unstable-tarball pkg)))
842
5532371a
MD
843(define (package-with-phase-changes changes)
844 (dummy-package "x"
845 (arguments `(#:phases
846 ,(if (gexp? changes)
847 #~(modify-phases %standard-phases
848 #$@changes)
849 `(modify-phases %standard-phases
850 ,@changes))))))
851
852(test-equal "optional-tests: no check phase"
853 '()
854 (let ((pkg (package-with-phase-changes '())))
855 (check-optional-tests pkg)))
856
857(test-equal "optional-tests: check phase respects #:tests?"
858 '()
859 (let ((pkg (package-with-phase-changes
860 '((replace 'check
861 (lambda* (#:key tests? #:allow-other-keys?)
862 (when tests?
863 (invoke "./the-test-suite"))))))))
864 (check-optional-tests pkg)))
865
866(test-equal "optional-tests: check phase ignores #:tests?"
867 "the 'check' phase should respect #:tests?"
868 (let ((pkg (package-with-phase-changes
869 '((replace 'check
870 (lambda _
871 (invoke "./the-test-suite")))))))
872 (single-lint-warning-message
873 (check-optional-tests pkg))))
874
875(test-equal "optional-tests: do not crash when #:phases is invalid"
876 "incorrect call to ‘modify-phases’"
877 (let ((pkg (package-with-phase-changes 'this-is-not-a-list)))
878 (single-lint-warning-message
879 (check-optional-tests pkg))))
880
881(test-equal "optional-tests: allow G-exps (no warning)"
882 '()
883 (let ((pkg (package-with-phase-changes #~())))
884 (check-optional-tests pkg)))
885
886(test-equal "optional-tests: allow G-exps (warning)"
887 "the 'check' phase should respect #:tests?"
888 (let ((pkg (package-with-phase-changes
889 #~((replace 'check
890 (lambda _
891 (invoke "/the-test-suite")))))))
892 (single-lint-warning-message
893 (check-optional-tests pkg))))
894
895(test-equal "optional-tests: complicated 'check' phase"
896 "the 'check' phase should respect #:tests?"
897 (let ((pkg (package-with-phase-changes
898 '((replace 'check
899 (lambda* (#:key inputs tests? #:allow-other-keys)
900 (let ((something (stuff from inputs or native-inputs)))
901 (delete-file "dateutil/test/test_utils.py")
902 (invoke "pytest" "-vv"))))))))
903 (single-lint-warning-message
904 (check-optional-tests pkg))))
905
906(test-equal "optional-tests: 'check' phase is not first phase"
907 "the 'check' phase should respect #:tests?"
908 (let ((pkg (package-with-phase-changes
909 '((add-after 'unpack
910 (lambda _
911 (chdir "libtestcase-0.0.0")))
912 (replace 'check
913 (lambda _ (invoke "./test-suite")))))))
914 (single-lint-warning-message
915 (check-optional-tests pkg))))
916
50fc2384
CB
917(test-equal "source: 200"
918 '()
9323ab55 919 (with-http-server `((200 ,%long-string))
50fc2384
CB
920 (let ((pkg (package
921 (inherit (dummy-package "x"))
922 (source (origin
923 (method url-fetch)
924 (uri (%local-url))
925 (sha256 %null-sha256))))))
926 (check-source pkg))))
927
c05ceaf2
MD
928(with-http-server '((200 "This is too small."))
929 (test-equal "source: 200 but short length"
930 (format #f "URI ~a returned suspiciously small file (18 bytes)"
931 (%local-url))
50fc2384
CB
932 (let ((pkg (package
933 (inherit (dummy-package "x"))
934 (source (origin
935 (method url-fetch)
936 (uri (%local-url))
937 (sha256 %null-sha256))))))
938 (match (check-source pkg)
939 ((first-warning ; All source URIs are unreachable
940 (and (? lint-warning?) second-warning))
941 (lint-warning-message second-warning))))))
942
c05ceaf2
MD
943(with-http-server `((404 ,%long-string))
944 (test-equal "source: 404"
945 (format #f "URI ~a not reachable: 404 (\"Such is life\")"
946 (%local-url))
50fc2384
CB
947 (let ((pkg (package
948 (inherit (dummy-package "x"))
949 (source (origin
950 (method url-fetch)
951 (uri (%local-url))
952 (sha256 %null-sha256))))))
953 (match (check-source pkg)
954 ((first-warning ; All source URIs are unreachable
955 (and (? lint-warning?) second-warning))
956 (lint-warning-message second-warning))))))
950d2ea4 957
99b20428
LC
958(test-equal "source: 404 and 200"
959 '()
9323ab55 960 (with-http-server `((404 ,%long-string))
99b20428
LC
961 (let ((bad-url (%local-url)))
962 (parameterize ((%http-server-port (+ 1 (%http-server-port))))
9323ab55 963 (with-http-server `((200 ,%long-string))
99b20428
LC
964 (let ((pkg (package
965 (inherit (dummy-package "x"))
966 (source (origin
967 (method url-fetch)
968 (uri (list bad-url (%local-url)))
969 (sha256 %null-sha256))))))
970 ;; Since one of the two URLs is good, this should return the empty
971 ;; list.
972 (check-source pkg)))))))
973
c05ceaf2
MD
974(with-http-server `((200 ,%long-string))
975 (let* ((initial-url (%local-url))
976 (redirect (build-response #:code 301
977 #:headers
978 `((location
979 . ,(string->uri initial-url))))))
980 (parameterize ((%http-server-port 0))
981 (with-http-server `((,redirect ""))
982 (test-equal "source: 301 -> 200"
983 (format #f "permanent redirect from ~a to ~a"
984 (%local-url) initial-url)
50fc2384
CB
985 (let ((pkg (package
986 (inherit (dummy-package "x"))
987 (source (origin
988 (method url-fetch)
989 (uri (%local-url))
990 (sha256 %null-sha256))))))
991 (match (check-source pkg)
992 ((first-warning ; All source URIs are unreachable
993 (and (? lint-warning?) second-warning))
994 (lint-warning-message second-warning)))))))))
61f28fe7 995
c05ceaf2
MD
996(with-http-server `((200 ,%long-string))
997 (let* ((initial-url (%local-url))
998 (redirect (build-response #:code 301
999 #:headers
1000 `((location
1001 . ,(string->uri initial-url))))))
1002 (parameterize ((%http-server-port 0))
1003 (with-http-server `((,redirect ""))
1004 (test-equal "source, git-reference: 301 -> 200"
1005 (format #f "permanent redirect from ~a to ~a"
1006 (%local-url) initial-url)
c1052667
LC
1007 (let ((pkg (dummy-package
1008 "x"
1009 (source (origin
1010 (method git-fetch)
1011 (uri (git-reference (url (%local-url))
1012 (commit "v1.0.0")))
1013 (sha256 %null-sha256))))))
1014 (single-lint-warning-message (check-source pkg))))))))
1015
c05ceaf2
MD
1016(with-http-server '((404 "booh!"))
1017 (let* ((initial-url (%local-url))
1018 (redirect (build-response #:code 301
1019 #:headers
1020 `((location
1021 . ,(string->uri initial-url))))))
1022 (parameterize ((%http-server-port 0))
1023 (with-http-server `((,redirect ""))
1024 (test-equal "source: 301 -> 404"
1025 (format #f "URI ~a not reachable: 404 (\"Such is life\")"
1026 (%local-url))
50fc2384
CB
1027 (let ((pkg (package
1028 (inherit (dummy-package "x"))
1029 (source (origin
1030 (method url-fetch)
1031 (uri (%local-url))
1032 (sha256 %null-sha256))))))
1033 (match (check-source pkg)
1034 ((first-warning ; The first warning says that all URI's are
1035 ; unreachable
1036 (and (? lint-warning?) second-warning))
1037 (lint-warning-message second-warning)))))))))
1038
1039(test-equal "mirror-url"
1040 '()
1041 (let ((source (origin
1042 (method url-fetch)
1043 (uri "http://example.org/foo/bar.tar.gz")
1044 (sha256 %null-sha256))))
1045 (check-mirror-url (dummy-package "x" (source source)))))
1046
1047(test-equal "mirror-url: one suggestion"
1048 "URL should be 'mirror://gnu/foo/foo.tar.gz'"
1049 (let ((source (origin
1050 (method url-fetch)
1051 (uri "http://ftp.gnu.org/pub/gnu/foo/foo.tar.gz")
1052 (sha256 %null-sha256))))
1053 (single-lint-warning-message
1054 (check-mirror-url (dummy-package "x" (source source))))))
1055
1056(test-equal "github-url"
1057 '()
9323ab55 1058 (with-http-server `((200 ,%long-string))
50fc2384
CB
1059 (check-github-url
1060 (dummy-package "x" (source
1061 (origin
1062 (method url-fetch)
1063 (uri (%local-url))
1064 (sha256 %null-sha256)))))))
0865d8a8
AI
1065
1066(let ((github-url "https://github.com/foo/bar/bar-1.0.tar.gz"))
50fc2384
CB
1067 (test-equal "github-url: one suggestion"
1068 (string-append
1069 "URL should be '" github-url "'")
9323ab55
LC
1070 (let ((redirect (build-response #:code 301
1071 #:headers
1072 `((location
1073 . ,(string->uri github-url))))))
1074 (with-http-server `((,redirect ""))
1075 (let* ((initial-url (%local-url))
1076 (redirect (build-response #:code 302
1077 #:headers
1078 `((location
1079 . ,(string->uri initial-url))))))
c05ceaf2 1080 (parameterize ((%http-server-port 0))
9323ab55
LC
1081 (with-http-server `((,redirect ""))
1082 (single-lint-warning-message
1083 (check-github-url
1084 (dummy-package "x" (source
1085 (origin
1086 (method url-fetch)
1087 (uri (%local-url))
1088 (sha256 %null-sha256))))))))))))
95c2bc49 1089
50fc2384
CB
1090 (test-equal "github-url: already the correct github url"
1091 '()
1092 (check-github-url
1093 (dummy-package "x" (source
1094 (origin
1095 (method url-fetch)
1096 (uri github-url)
1097 (sha256 %null-sha256)))))))
1098
1099(test-equal "cve"
1100 '()
571f6e7f 1101 (mock ((guix lint) package-vulnerabilities (const '()))
50fc2384 1102 (check-vulnerabilities (dummy-package "x"))))
5432734b 1103
50fc2384
CB
1104(test-equal "cve: one vulnerability"
1105 "probably vulnerable to CVE-2015-1234"
fcb2318e 1106 (let ((dummy-vulnerabilities
5432734b 1107 (lambda (package)
fcb2318e
LC
1108 (list (make-struct/no-tail
1109 (@@ (guix cve) <vulnerability>)
1110 "CVE-2015-1234"
1111 (list (cons (package-name package)
1112 (package-version package))))))))
1113 (single-lint-warning-message
1114 (check-vulnerabilities (dummy-package "pi" (version "3.14"))
1115 dummy-vulnerabilities))))
5432734b 1116
50fc2384
CB
1117(test-equal "cve: one patched vulnerability"
1118 '()
571f6e7f 1119 (mock ((guix lint) package-vulnerabilities
4e70fe4d 1120 (lambda (package)
79c03e55
LC
1121 (list (make-struct/no-tail (@@ (guix cve) <vulnerability>)
1122 "CVE-2015-1234"
1123 (list (cons (package-name package)
1124 (package-version package)))))))
50fc2384
CB
1125 (check-vulnerabilities
1126 (dummy-package "pi"
1127 (version "3.14")
1128 (source
1129 (dummy-origin
1130 (patches
1131 (list "/a/b/pi-CVE-2015-1234.patch"))))))))
1132
1133(test-equal "cve: known safe from vulnerability"
1134 '()
571f6e7f 1135 (mock ((guix lint) package-vulnerabilities
f4007b25 1136 (lambda (package)
79c03e55
LC
1137 (list (make-struct/no-tail (@@ (guix cve) <vulnerability>)
1138 "CVE-2015-1234"
1139 (list (cons (package-name package)
1140 (package-version package)))))))
50fc2384
CB
1141 (check-vulnerabilities
1142 (dummy-package "pi"
1143 (version "3.14")
1144 (properties `((lint-hidden-cve . ("CVE-2015-1234"))))))))
1145
1146(test-equal "cve: vulnerability fixed in replacement version"
1147 '()
571f6e7f 1148 (mock ((guix lint) package-vulnerabilities
9bee2bd1
LC
1149 (lambda (package)
1150 (match (package-version package)
1151 ("0"
79c03e55
LC
1152 (list (make-struct/no-tail (@@ (guix cve) <vulnerability>)
1153 "CVE-2015-1234"
1154 (list (cons (package-name package)
1155 (package-version package))))))
9bee2bd1
LC
1156 ("1"
1157 '()))))
50fc2384
CB
1158 (check-vulnerabilities
1159 (dummy-package
1160 "foo" (version "0")
1161 (replacement (dummy-package "foo" (version "1")))))))
1162
1163(test-equal "cve: patched vulnerability in replacement"
1164 '()
571f6e7f 1165 (mock ((guix lint) package-vulnerabilities
5c6a062d 1166 (lambda (package)
79c03e55
LC
1167 (list (make-struct/no-tail (@@ (guix cve) <vulnerability>)
1168 "CVE-2015-1234"
1169 (list (cons (package-name package)
1170 (package-version package)))))))
50fc2384
CB
1171 (check-vulnerabilities
1172 (dummy-package
1173 "pi" (version "3.14") (source (dummy-origin))
1174 (replacement (dummy-package
1175 "pi" (version "3.14")
1176 (source
1177 (dummy-origin
1178 (patches
1179 (list "/a/b/pi-CVE-2015-1234.patch"))))))))))
1180
1181(test-equal "formatting: lonely parentheses"
1182 "parentheses feel lonely, move to the previous or next line"
1183 (single-lint-warning-message
1184 (check-formatting
1185 (dummy-package "ugly as hell!"
1186 )
1187 )))
e0566f12 1188
40a7d4e5 1189(test-assert "formatting: tabulation"
50fc2384
CB
1190 (string-match-or-error
1191 "tabulation on line [0-9]+, column [0-9]+"
1192 (single-lint-warning-message
1193 (check-formatting (dummy-package "leave the tab here: ")))))
40a7d4e5
LC
1194
1195(test-assert "formatting: trailing white space"
50fc2384
CB
1196 (string-match-or-error
1197 "trailing white space .*"
1198 ;; Leave the trailing white space on the next line!
1199 (single-lint-warning-message
1200 (check-formatting (dummy-package "x")))))
40a7d4e5
LC
1201
1202(test-assert "formatting: long line"
50fc2384
CB
1203 (string-match-or-error
1204 "line [0-9]+ is way too long \\([0-9]+ characters\\)"
1205 (single-lint-warning-message (check-formatting
1206 (dummy-package "x")) ;here is a stupid comment just to make a long line
1207 )))
1208
1209(test-equal "formatting: alright"
1210 '()
1211 (check-formatting (dummy-package "x")))
40a7d4e5 1212
55549c7b
LC
1213(test-assert "archival: missing content"
1214 (let* ((origin (origin
1215 (method url-fetch)
1216 (uri "http://example.org/foo.tgz")
1217 (sha256 (make-bytevector 32))))
bc4d81d2
LC
1218 (warnings (with-http-server '((404 "Not archived.")
1219 (404 "Not in Disarchive database."))
55549c7b 1220 (parameterize ((%swh-base-url (%local-url)))
bc4d81d2
LC
1221 (mock ((guix download) %disarchive-mirrors
1222 (list (%local-url)))
1223 (check-archival (dummy-package "x"
1224 (source origin))))))))
55549c7b
LC
1225 (warning-contains? "not archived" warnings)))
1226
1227(test-equal "archival: content available"
1228 '()
1229 (let* ((origin (origin
1230 (method url-fetch)
1231 (uri "http://example.org/foo.tgz")
1232 (sha256 (make-bytevector 32))))
1233 ;; https://archive.softwareheritage.org/api/1/content/
1234 (content "{ \"checksums\": {}, \"data_url\": \"xyz\",
1235 \"length\": 42 }"))
1236 (with-http-server `((200 ,content))
1237 (parameterize ((%swh-base-url (%local-url)))
1238 (check-archival (dummy-package "x" (source origin)))))))
1239
bc4d81d2
LC
1240(test-equal "archival: content unavailable but disarchive available"
1241 '()
1242 (let* ((origin (origin
1243 (method url-fetch)
1244 (uri "http://example.org/foo.tgz")
1245 (sha256 (make-bytevector 32))))
1246 (disarchive (object->string
1247 '(disarchive (version 0)
1248 ...
1249 "swh:1:dir:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")))
1250 ;; https://archive.softwareheritage.org/api/1/directory/
1251 (directory "[ { \"checksums\": {},
1252 \"dir_id\": \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",
1253 \"type\": \"file\",
1254 \"name\": \"README\"
1255 \"length\": 42 } ]"))
1256 (with-http-server `((404 "") ;lookup-content
1257 (200 ,disarchive) ;Disarchive database lookup
1258 (200 ,directory)) ;lookup-directory
1259 (mock ((guix download) %disarchive-mirrors (list (%local-url)))
1260 (parameterize ((%swh-base-url (%local-url)))
1261 (check-archival (dummy-package "x" (source origin))))))))
1262
55549c7b
LC
1263(test-assert "archival: missing revision"
1264 (let* ((origin (origin
1265 (method git-fetch)
1266 (uri (git-reference
1267 (url "http://example.org/foo.git")
1268 (commit "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")))
1269 (sha256 (make-bytevector 32))))
1270 ;; https://archive.softwareheritage.org/api/1/origin/save/
1271 (save "{ \"origin_url\": \"http://example.org/foo.git\",
1272 \"save_request_date\": \"2014-11-17T22:09:38+01:00\",
1273 \"save_request_status\": \"accepted\",
1274 \"save_task_status\": \"scheduled\" }")
1275 (warnings (with-http-server `((404 "No revision.") ;lookup-revision
1276 (404 "No origin.") ;lookup-origin
1277 (200 ,save)) ;save-origin
1278 (parameterize ((%swh-base-url (%local-url)))
1279 (check-archival (dummy-package "x" (source origin)))))))
1280 (warning-contains? "scheduled" warnings)))
1281
1282(test-equal "archival: revision available"
1283 '()
1284 (let* ((origin (origin
1285 (method git-fetch)
1286 (uri (git-reference
1287 (url "http://example.org/foo.git")
1288 (commit "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")))
1289 (sha256 (make-bytevector 32))))
1290 ;; https://archive.softwareheritage.org/api/1/revision/
1291 (revision "{ \"author\": {}, \"parents\": [],
1292 \"date\": \"2014-11-17T22:09:38+01:00\" }"))
1293 (with-http-server `((200 ,revision))
1294 (parameterize ((%swh-base-url (%local-url)))
1295 (check-archival (dummy-package "x" (source origin)))))))
1296
1297(test-assert "archival: rate limit reached"
1298 ;; We should get a single warning stating that the rate limit was reached,
1299 ;; and nothing more, in particular no other HTTP requests.
1300 (let* ((origin (origin
1301 (method url-fetch)
1302 (uri "http://example.org/foo.tgz")
1303 (sha256 (make-bytevector 32))))
1304 (too-many (build-response
1305 #:code 429
1306 #:reason-phrase "Too many requests"
1307 #:headers '((x-ratelimit-remaining . "0")
1308 (x-ratelimit-reset . "3000000000"))))
1309 (warnings (with-http-server `((,too-many "Rate limit reached."))
1310 (parameterize ((%swh-base-url (%local-url)))
1311 (append-map (lambda (name)
1312 (check-archival
1313 (dummy-package name (source origin))))
1314 '("x" "y" "z"))))))
1315 (string-contains (single-lint-warning-message warnings)
1316 "rate limit reached")))
1317
464b1fff
TS
1318(test-assert "haskell-stackage"
1319 (let* ((stackage (string-append "{ \"packages\": [{"
1320 " \"name\":\"x\","
1321 " \"version\":\"1.0\" }]}"))
1322 (packages (map (lambda (version)
1323 (dummy-package
1324 (string-append "ghc-x")
1325 (version version)
1326 (source
1327 (dummy-origin
1328 (method url-fetch)
1329 (uri (string-append
1330 "https://hackage.haskell.org/package/"
1331 "x-" version "/x-" version ".tar.gz"))))))
1332 '("0.9" "1.0" "2.0")))
1333 (warnings (pk (with-http-server `((200 ,stackage) ; memoized
1334 (200 "name: x\nversion: 1.0\n")
1335 (200 "name: x\nversion: 1.0\n")
1336 (200 "name: x\nversion: 1.0\n"))
1337 (parameterize ((%hackage-url (%local-url))
1338 (%stackage-url (%local-url)))
1339 (append-map check-haskell-stackage packages))))))
1340 (match warnings
1341 (((? lint-warning? warning))
1342 (and (string=? (package-version (lint-warning-package warning)) "2.0")
1343 (string-contains (lint-warning-message warning)
1344 "ahead of Stackage LTS version"))))))
1345
b4f5e0e8
CR
1346(test-end "lint")
1347
907c98ac 1348;; Local Variables:
9323ab55 1349;; eval: (put 'with-http-server 'scheme-indent-function 1)
4fbf4ca5 1350;; eval: (put 'with-warnings 'scheme-indent-function 0)
907c98ac 1351;; End: