projects/guix·blob javascript-team · refs

670 lines · 17.4 KiB

1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2015 Federico Beffa <[email protected]>
3;;; Copyright © 2019 Robert Vollmert <[email protected]>
4;;; Copyright © 2021 Xinglu Chen <[email protected]>
5;;; Copyright © 2021 Sarah Morgensen <[email protected]>
6;;;
7;;; This file is part of GNU Guix.
8;;;
9;;; GNU Guix is free software; you can redistribute it and/or modify it
10;;; under the terms of the GNU General Public License as published by
11;;; the Free Software Foundation; either version 3 of the License, or (at
12;;; your option) any later version.
13;;;
14;;; GNU Guix is distributed in the hope that it will be useful, but
15;;; WITHOUT ANY WARRANTY; without even the implied warranty of
16;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;;; GNU General Public License for more details.
18;;;
19;;; You should have received a copy of the GNU General Public License
20;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
21
22(define-module (test-hackage)
23 #:use-module (guix import cabal)
24 #:use-module (guix import hackage)
25 #:use-module (guix tests)
26 #:use-module (srfi srfi-64)
27 #:use-module (ice-9 match))
28
29(define test-cabal-1
30 "name: foo
31version: 1.0.0
32homepage: http://test.org
33synopsis: synopsis
34description: description
35license: BSD3
36executable cabal
37 build-depends:
38 HTTP >= 4000.2.5 && < 4000.3,
39 mtl >= 2.0 && < 3
40")
41
42(define test-cabal-2
43 "name: foo
44version: 1.0.0
45homepage: http://test.org
46synopsis: synopsis
47description: description
48license: BSD3
49executable cabal {
50build-depends:
51 HTTP >= 4000.2.5 && < 4000.3,
52 mtl >= 2.0 && < 3
53}
54")
55
56;; Check compiler implementation test with and without spaces.
57(define test-cabal-3
58 "name: foo
59version: 1.0.0
60homepage: http://test.org
61synopsis: synopsis
62description: description
63license: BSD3
64library
65 if impl(ghc >= 7.2 && < 7.6)
66 Build-depends: ghc-a
67 if impl(ghc>=7.2&&<7.6)
68 Build-depends: ghc-b
69 if impl(ghc == 7.8)
70 Build-depends:
71 HTTP >= 4000.2.5 && < 4000.3,
72 mtl >= 2.0 && < 3
73")
74
75;; Check "-any", "-none" when name is different.
76(define test-cabal-4
77 "name: foo
78version: 1.0.0
79homepage: http://test.org
80synopsis: synopsis
81description: description
82license: BSD3
83library
84 if impl(ghcjs -any)
85 Build-depends: ghc-a
86 if impl(ghc>=7.2&&<7.6)
87 Build-depends: ghc-b
88 if impl(ghc == 7.8)
89 Build-depends:
90 HTTP >= 4000.2.5 && < 4000.3,
91 mtl >= 2.0 && < 3
92")
93
94;; Check "-any", "-none".
95(define test-cabal-5
96 "name: foo
97version: 1.0.0
98homepage: http://test.org
99synopsis: synopsis
100description: description
101license: BSD3
102library
103 if impl(ghc == 7.8)
104 Build-depends:
105 HTTP >= 4000.2.5 && < 4000.3,
106 if impl(ghc -any)
107 Build-depends: mtl >= 2.0 && < 3
108 if impl(ghc>=7.2&&<7.6)
109 Build-depends: ghc-b
110")
111
112;; Check "custom-setup".
113(define test-cabal-6
114 "name: foo
115build-type: Custom
116version: 1.0.0
117homepage: http://test.org
118synopsis: synopsis
119description: description
120license: BSD3
121custom-setup
122 setup-depends: base >= 4.7 && < 5,
123 Cabal >= 1.24,
124 haskell-gi == 0.21.*
125library
126 if impl(ghc>=7.2&&<7.6)
127 Build-depends: ghc-b
128 if impl(ghc == 7.8)
129 Build-depends:
130 HTTP >= 4000.2.5 && < 4000.3,
131 mtl >= 2.0 && < 3
132")
133
134;; A fragment of a real Cabal file with minor modification to check precedence
135;; of 'and' over 'or', missing final newline, spaces between keywords and
136;; parentheses and between key and column.
137(define test-read-cabal-1
138 "name: test-me
139library
140 -- Choose which library versions to use.
141 if flag(base4point8)
142 Build-depends: base >= 4.8 && < 5
143 else
144 if flag(base4)
145 Build-depends: base >= 4 && < 4.8
146 else
147 if flag(base3)
148 Build-depends: base >= 3 && < 4
149 else
150 Build-depends: base < 3
151 if flag(base4point8) || flag (base4) && flag(base3)
152 Build-depends: random
153 Build-depends : containers
154
155 -- Modules that are always built.
156 Exposed-Modules:
157 Test.QuickCheck.Exception")
158
159(define test-read-cabal-2
160 "name: test-me
161common defaults
162 if os(foobar) { cc-options: -DBARBAZ }
163") ; Intentional newline.
164
165;; Test opening bracket on new line.
166(define test-read-cabal-brackets-newline
167 "name: test-me
168common defaults
169 build-depends:
170 { foobar
171 , barbaz
172 }
173")
174
175;; Test library with (since Cabal 2.0) and without names.
176(define test-read-cabal-library-name
177 "name: test-me
178library foobar
179 build-depends: foo, bar
180library
181 build-depends: bar, baz
182")
183
184(test-begin "hackage")
185
186(define-syntax-rule (define-package-matcher name pattern)
187 (define* (name obj)
188 (match obj
189 (pattern #t)
190 (x (pk 'fail x #f)))))
191
192(define-package-matcher match-ghc-foo
193 ('package
194 ('name "ghc-foo")
195 ('version "1.0.0")
196 ('source
197 ('origin
198 ('method 'url-fetch)
199 ('uri ('hackage-uri "foo" 'version))
200 ('sha256
201 ('base32
202 (? string? hash)))))
203 ('build-system 'haskell-build-system)
204 ('properties '(quote ((upstream-name . "foo"))))
205 ('inputs ('list 'ghc-http))
206 ('home-page "http://test.org")
207 ('synopsis (? string?))
208 ('description (? string?))
209 ('license 'license:bsd-3)))
210
211(define* (eval-test-with-cabal test-cabal matcher #:key (cabal-environment '()))
212 (define port (open-input-string test-cabal))
213 (matcher (hackage->guix-package "foo" #:port port #:cabal-environment cabal-environment)))
214
215(test-assert "hackage->guix-package test 1"
216 (eval-test-with-cabal test-cabal-1 match-ghc-foo))
217
218(test-assert "hackage->guix-package test 2"
219 (eval-test-with-cabal test-cabal-2 match-ghc-foo))
220
221(test-assert "hackage->guix-package test 3"
222 (eval-test-with-cabal test-cabal-3 match-ghc-foo
223 #:cabal-environment '(("impl" . "ghc-7.8"))))
224
225(test-assert "hackage->guix-package test 4"
226 (eval-test-with-cabal test-cabal-4 match-ghc-foo
227 #:cabal-environment '(("impl" . "ghc-7.8"))))
228
229(test-assert "hackage->guix-package test 5"
230 (eval-test-with-cabal test-cabal-5 match-ghc-foo
231 #:cabal-environment '(("impl" . "ghc-7.8"))))
232
233(define-package-matcher match-ghc-foo-6
234 ('package
235 ('name "ghc-foo")
236 ('version "1.0.0")
237 ('source
238 ('origin
239 ('method 'url-fetch)
240 ('uri ('hackage-uri "foo" 'version))
241 ('sha256
242 ('base32
243 (? string? hash)))))
244 ('build-system 'haskell-build-system)
245 ('properties '(quote ((upstream-name . "foo"))))
246 ('inputs ('list 'ghc-b 'ghc-http))
247 ('native-inputs ('list 'ghc-haskell-gi))
248 ('home-page "http://test.org")
249 ('synopsis (? string?))
250 ('description (? string?))
251 ('license 'license:bsd-3)))
252
253(test-assert "hackage->guix-package test 6"
254 (eval-test-with-cabal test-cabal-6 match-ghc-foo-6))
255
256;; Check multi-line layouted description.
257(define test-cabal-multiline-layout
258 "name: foo
259version: 1.0.0
260homepage: http://test.org
261synopsis: synopsis
262description: first line
263 second line
264license: BSD3
265executable cabal
266 build-depends:
267 HTTP >= 4000.2.5 && < 4000.3,
268 mtl >= 2.0 && < 3
269")
270
271(test-assert "hackage->guix-package test multiline desc (layout)"
272 (eval-test-with-cabal test-cabal-multiline-layout match-ghc-foo))
273
274;; Check multi-line braced description.
275(define test-cabal-multiline-braced
276 "name: foo
277version: 1.0.0
278homepage: http://test.org
279synopsis: synopsis
280description: {
281first line
282second line
283}
284license: BSD3
285executable cabal
286 build-depends:
287 HTTP >= 4000.2.5 && < 4000.3,
288 mtl >= 2.0 && < 3
289")
290
291(test-assert "hackage->guix-package test multiline desc (braced)"
292 (eval-test-with-cabal test-cabal-multiline-braced match-ghc-foo))
293
294;; Check mixed layout. Compare e.g. warp.
295(define test-cabal-mixed-layout
296 "name: foo
297version: 1.0.0
298homepage: http://test.org
299synopsis: synopsis
300description: description
301license: BSD3
302executable cabal
303 build-depends:
304 HTTP >= 4000.2.5 && < 4000.3,
305 mtl >= 2.0 && < 3
306 ghc-options: -Wall
307")
308
309(test-assert "hackage->guix-package test mixed layout"
310 (eval-test-with-cabal test-cabal-mixed-layout match-ghc-foo))
311
312;; Check flag executable. Compare e.g. darcs.
313(define test-cabal-flag-executable
314 "name: foo
315version: 1.0.0
316homepage: http://test.org
317synopsis: synopsis
318description: description
319license: BSD3
320flag executable
321 description: Build executable
322 default: True
323executable cabal
324 if !flag(executable)
325 buildable: False
326 else
327 buildable: True
328
329 build-depends:
330 HTTP >= 4000.2.5 && < 4000.3,
331 mtl >= 2.0 && < 3
332")
333
334(test-assert "hackage->guix-package test flag executable"
335 (eval-test-with-cabal test-cabal-flag-executable match-ghc-foo))
336
337;; There is no mandatory space between property name and value.
338(define test-cabal-property-no-space
339 "name:foo
340version:1.0.0
341homepage:http://test.org
342synopsis:synopsis
343description:description
344license:BSD3
345common bench-defaults
346 ghc-options:-Wall
347executable cabal
348 build-depends:
349 HTTP >= 4000.2.5 && < 4000.3,
350 mtl >= 2.0 && < 3
351")
352
353(test-assert "hackage->guix-package test properties without space"
354 (eval-test-with-cabal test-cabal-property-no-space match-ghc-foo))
355
356;; There may be no final newline terminating a property.
357(define test-cabal-no-final-newline
358"name: foo
359version: 1.0.0
360homepage: http://test.org
361synopsis: synopsis
362description: description
363license: BSD3
364executable cabal
365 build-depends: HTTP >= 4000.2.5 && < 4000.3, mtl >= 2.0 && < 3")
366
367(test-expect-fail 1)
368(test-assert "hackage->guix-package test without final newline"
369 (eval-test-with-cabal test-cabal-no-final-newline match-ghc-foo))
370
371;; Make sure internal libraries will not be part of the dependencies,
372;; ignore case.
373(define test-cabal-internal-library-ignored
374 "name: foo
375version: 1.0.0
376homepage: http://test.org
377synopsis: synopsis
378description: description
379license: BSD3
380executable cabal
381 build-depends:
382 HTTP >= 4000.2.5 && < 4000.3,
383 internAl
384library internaL
385 build-depends: mtl >= 2.0 && < 3
386")
387
388(test-assert "hackage->guix-package test internal libraries are ignored"
389 (eval-test-with-cabal test-cabal-internal-library-ignored match-ghc-foo))
390
391;; Check if-elif-else statements
392(define test-cabal-if
393 "name: foo
394version: 1.0.0
395homepage: http://test.org
396synopsis: synopsis
397description: description
398license: BSD3
399library
400 if os(first)
401 Build-depends: ghc-c
402")
403
404(define test-cabal-else
405 "name: foo
406version: 1.0.0
407homepage: http://test.org
408synopsis: synopsis
409description: description
410license: BSD3
411library
412 if os(first)
413 Build-depends: ghc-a
414 else
415 Build-depends: ghc-c
416")
417
418(define test-cabal-elif
419 "name: foo
420version: 1.0.0
421homepage: http://test.org
422synopsis: synopsis
423description: description
424license: BSD3
425library
426 if os(first)
427 Build-depends: ghc-a
428 elif os(second)
429 Build-depends: ghc-b
430 elif os(guix)
431 Build-depends: ghc-c
432 elif os(third)
433 Build-depends: ghc-d
434 else
435 Build-depends: ghc-e
436")
437
438;; Try the same with different bracket styles
439(define test-cabal-elif-brackets
440 "name: foo
441version: 1.0.0
442homepage: http://test.org
443synopsis: synopsis
444description: description
445license: BSD3
446library
447 if os(first) {
448 Build-depends: ghc-a
449 }
450 elif os(second)
451 Build-depends: ghc-b
452 elif os(guix) { Build-depends: ghc-c }
453 elif os(third) {
454 Build-depends: ghc-d }
455 elif os(fourth)
456 {
457 Build-depends: ghc-d
458 } else
459 Build-depends: ghc-e
460")
461
462(define-package-matcher match-ghc-elif
463 ('package
464 ('name "ghc-foo")
465 ('version "1.0.0")
466 ('source
467 ('origin
468 ('method 'url-fetch)
469 ('uri ('hackage-uri "foo" 'version))
470 ('sha256
471 ('base32
472 (? string? hash)))))
473 ('build-system 'haskell-build-system)
474 ('properties '(quote ((upstream-name . "foo"))))
475 ('inputs ('list 'ghc-c))
476 ('home-page "http://test.org")
477 ('synopsis (? string?))
478 ('description (? string?))
479 ('license 'license:bsd-3)))
480
481(test-assert "hackage->guix-package test lonely if statement"
482 (eval-test-with-cabal test-cabal-else match-ghc-elif
483 #:cabal-environment '(("os" . "guix"))))
484
485(test-assert "hackage->guix-package test else statement"
486 (eval-test-with-cabal test-cabal-else match-ghc-elif
487 #:cabal-environment '(("os" . "guix"))))
488
489(test-assert "hackage->guix-package test elif statement"
490 (eval-test-with-cabal test-cabal-elif match-ghc-elif
491 #:cabal-environment '(("os" . "guix"))))
492
493(test-assert "hackage->guix-package test elif statement with brackets"
494 (eval-test-with-cabal test-cabal-elif-brackets match-ghc-elif
495 #:cabal-environment '(("os" . "guix"))))
496
497;; Check Hackage Cabal revisions.
498(define test-cabal-revision
499 "name: foo
500version: 1.0.0
501x-revision: 2
502homepage: http://test.org
503synopsis: synopsis
504description: description
505license: BSD3
506executable cabal
507 build-depends:
508 HTTP >= 4000.2.5 && < 4000.3,
509 mtl >= 2.0 && < 3
510")
511
512(define-package-matcher match-ghc-foo-revision
513 ('package
514 ('name "ghc-foo")
515 ('version "1.0.0")
516 ('source
517 ('origin
518 ('method 'url-fetch)
519 ('uri ('hackage-uri "foo" 'version))
520 ('sha256
521 ('base32
522 (? string? hash)))))
523 ('build-system 'haskell-build-system)
524 ('properties '(quote ((upstream-name . "foo"))))
525 ('inputs ('list 'ghc-http))
526 ('arguments
527 ('quasiquote
528 ('#:cabal-revision
529 ("2" "0xxd88fb659f0krljidbvvmkh9ppjnx83j0nqzx8whcg4n5qbyng"))))
530 ('home-page "http://test.org")
531 ('synopsis (? string?))
532 ('description (? string?))
533 ('license 'license:bsd-3)))
534
535(test-assert "hackage->guix-package test cabal revision"
536 (eval-test-with-cabal test-cabal-revision match-ghc-foo-revision))
537
538(test-assert "read-cabal test 1"
539 (match (call-with-input-string test-read-cabal-1 read-cabal)
540 ((("name" ("test-me"))
541 ('section 'library #f
542 (('if ('flag "base4point8")
543 (("build-depends" ("base >= 4.8 && < 5")))
544 (('if ('flag "base4")
545 (("build-depends" ("base >= 4 && < 4.8")))
546 (('if ('flag "base3")
547 (("build-depends" ("base >= 3 && < 4")))
548 (("build-depends" ("base < 3"))))))))
549 ('if ('or ('flag "base4point8")
550 ('and ('flag "base4") ('flag "base3")))
551 (("build-depends" ("random")))
552 ())
553 ("build-depends" ("containers"))
554 ("exposed-modules" ("Test.QuickCheck.Exception")))))
555 #t)
556 (x (pk 'fail x #f))))
557
558(test-assert "read-cabal test: if brackets on the same line"
559 (match (call-with-input-string test-read-cabal-2 read-cabal)
560 ((("name" ("test-me"))
561 ('section 'common "defaults"
562 (('if ('os "foobar")
563 (("cc-options" ("-DBARBAZ ")))
564 ()))))
565 #t)
566 (x (pk 'fail x #f))))
567
568(test-expect-fail 1)
569(test-assert "read-cabal test: property brackets on new line"
570 (match (call-with-input-string test-read-cabal-brackets-newline read-cabal)
571 ((("name" ("test-me"))
572 ('section 'common "defaults"
573 (("build-depends" ("foobar , barbaz")))))
574 #t)
575 (x (pk 'fail x #f))))
576
577(test-assert "read-cabal test: library name"
578 (match (call-with-input-string test-read-cabal-library-name read-cabal)
579 ((("name" ("test-me"))
580 ('section 'library "foobar"
581 (("build-depends" ("foo, bar"))))
582 ('section 'library #f
583 (("build-depends" ("bar, baz")))))
584 #t)
585 (x (pk 'fail x #f))))
586
587(define test-cabal-import
588 "name: foo
589version: 1.0.0
590homepage: http://test.org
591synopsis: synopsis
592description: description
593license: BSD3
594common commons
595 build-depends:
596 HTTP >= 4000.2.5 && < 4000.3,
597 mtl >= 2.0 && < 3
598
599executable cabal
600 import: commons
601")
602
603(define-package-matcher match-ghc-foo-import
604 ('package
605 ('name "ghc-foo")
606 ('version "1.0.0")
607 ('source
608 ('origin
609 ('method 'url-fetch)
610 ('uri ('hackage-uri "foo" 'version))
611 ('sha256
612 ('base32
613 (? string? hash)))))
614 ('build-system 'haskell-build-system)
615 ('properties '(quote ((upstream-name . "foo"))))
616 ('inputs ('list 'ghc-http))
617 ('home-page "http://test.org")
618 ('synopsis (? string?))
619 ('description (? string?))
620 ('license 'license:bsd-3)))
621
622(test-assert "hackage->guix-package test cabal import"
623 (eval-test-with-cabal test-cabal-import match-ghc-foo-import))
624
625(define test-cabal-multiple-imports
626 "name: foo
627version: 1.0.0
628homepage: http://test.org
629synopsis: synopsis
630description: description
631license: BSD3
632common commons
633 build-depends:
634 HTTP >= 4000.2.5 && < 4000.3,
635 mtl >= 2.0 && < 3
636
637common others
638 build-depends:
639 base == 4.16.*,
640 stm-chans == 3.0.*
641
642executable cabal
643 import:
644 commons
645 , others
646")
647
648(define-package-matcher match-ghc-foo-multiple-imports
649 ('package
650 ('name "ghc-foo")
651 ('version "1.0.0")
652 ('source
653 ('origin
654 ('method 'url-fetch)
655 ('uri ('hackage-uri "foo" 'version))
656 ('sha256
657 ('base32
658 (? string? hash)))))
659 ('build-system 'haskell-build-system)
660 ('properties '(quote ((upstream-name . "foo"))))
661 ('inputs ('list 'ghc-http 'ghc-stm-chans))
662 ('home-page "http://test.org")
663 ('synopsis (? string?))
664 ('description (? string?))
665 ('license 'license:bsd-3)))
666
667(test-assert "hackage->guix-package test cabal multiple imports"
668 (eval-test-with-cabal test-cabal-multiple-imports match-ghc-foo-multiple-imports))
669
670(test-end "hackage")