;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2022 Philip McGrath <philip@philipmcgrath.com>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; 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-elm)
#:use-module (guix build-system elm)
#:use-module (guix import elm)
#:use-module (guix base32)
#:use-module (guix hash)
#:use-module (guix utils)
#:autoload (gcrypt hash) (hash-algorithm sha256)
#:use-module (json)
#:use-module (ice-9 match)
#:use-module (srfi srfi-64))
(test-begin "elm")
(test-group "elm->package-name and infer-elm-package-name"
(test-group "round trip"
;; Cases when our heuristics can find the upstream name.
(define-syntax-rule (test-round-trip elm guix)
(test-group elm
(test-equal "elm->package-name" guix
(elm->package-name elm))
(test-equal "infer-elm-package-name" elm
(infer-elm-package-name guix))))
(test-round-trip "elm/core" "elm-core")
(test-round-trip "elm/html" "elm-html")
(test-round-trip "elm-explorations/markdown" "elm-explorations-markdown")
(test-round-trip "elm-explorations/test" "elm-explorations-test")
(test-round-trip "elm-explorations/foo-bar" "elm-explorations-foo-bar")
(test-round-trip "elm/explorations" "elm-explorations")
(test-round-trip "terezka/intervals" "elm-terezka-intervals")
(test-round-trip "justinmimbs/time-extra" "elm-justinmimbs-time-extra")
(test-round-trip "danhandrea/elm-date-format"
"elm-danhandrea-elm-date-format"))
(test-group "upstream-name needed"
;; Upstream names that our heuristic can't infer. We still check that the
;; round-trip behavior of 'infer-elm-package-name' works as promised for
;; the hypothetical Elm name it doesn't infer.
(define-syntax-rule (test-upstream-needed elm guix inferred)
(test-group elm
(test-equal "elm->package-name" guix
(elm->package-name elm))
(test-group "infer-elm-package-name"
(test-equal "infers other name" inferred
(infer-elm-package-name guix))
(test-equal "infered name round-trips" guix
(elm->package-name inferred)))))
(test-upstream-needed "elm/virtual-dom"
"elm-virtual-dom"
"virtual/dom")
(test-upstream-needed "elm/project-metadata-utils"
"elm-project-metadata-utils"
"project/metadata-utils")
(test-upstream-needed "explorations/foo"
"elm-explorations-foo"
"elm-explorations/foo")
(test-upstream-needed "explorations/foo-bar"
"elm-explorations-foo-bar"
"elm-explorations/foo-bar")
(test-upstream-needed "explorations-central/foo"
"elm-explorations-central-foo"
"elm-explorations/central-foo")
(test-upstream-needed "explorations-central/foo-bar"
"elm-explorations-central-foo-bar"
"elm-explorations/central-foo-bar")
(test-upstream-needed "elm-xyz/foo"
"elm-xyz-foo"
"xyz/foo")
(test-upstream-needed "elm-xyz/foo-bar"
"elm-xyz-foo-bar"
"xyz/foo-bar")
(test-upstream-needed "elm-explorations-xyz/foo"
"elm-explorations-xyz-foo"
"elm-explorations/xyz-foo")
(test-upstream-needed "elm-explorations-xyz/foo-bar"
"elm-explorations-xyz-foo-bar"
"elm-explorations/xyz-foo-bar"))
(test-group "no inferred Elm name"
;; Cases that 'infer-elm-package-name' should not attempt to handle,
;; because 'elm->package-name' would never produce such names.
(define-syntax-rule (test-not-inferred guix)
(test-assert guix (not (infer-elm-package-name guix))))
(test-not-inferred "elm")
(test-not-inferred "guile")
(test-not-inferred "gcc-toolchain")
(test-not-inferred "font-adobe-source-sans-pro")))
(define test-package-registry-json
;; we intentionally list versions in different orders here
"{
\"elm/core\": [\"1.0.0\", \"1.0.1\", \"1.0.2\", \"1.0.3\", \"1.0.4\"],
\"elm-guix/demo\": [\"2.0.0\", \"3.0.0\", \"1.0.0\"]
}")
(define test-elm-core-json
"{
\"type\": \"package\",
\"name\": \"elm/core\",
\"summary\": \"Elm's standard libraries\",
\"license\": \"BSD-3-Clause\",
\"version\": \"1.0.4\",
\"exposed-modules\": {
\"Primitives\": [
\"Basics\",
\"String\",
\"Char\",
\"Bitwise\",
\"Tuple\"
],
\"Collections\": [
\"List\",
\"Dict\",
\"Set\",
\"Array\"
],
\"Error Handling\": [
\"Maybe\",
\"Result\"
],
\"Debug\": [
\"Debug\"
],
\"Effects\": [
\"Platform.Cmd\",
\"Platform.Sub\",
\"Platform\",
\"Process\",
\"Task\"
]
},
\"elm-version\": \"0.19.0 <= v < 0.20.0\",
\"dependencies\": {},
\"test-dependencies\": {}
}")
(define test-elm-core-readme
"# Core Libraries
Every Elm project needs this package!
It provides **basic functionality** like addition and subtraction as well as
**data structures** like lists, dictionaries, and sets.")
(define test-elm-guix-demo-json
"{
\"type\": \"package\",
\"name\": \"elm-guix/demo\",
\"summary\": \"A test for `(guix import elm)`\",
\"license\": \"GPL-3.0-or-later\",
\"version\": \"3.0.0\",
\"exposed-modules\": [
\"Guix.Demo\"
],
\"elm-version\": \"0.19.0 <= v < 0.20.0\",
\"dependencies\": {
\"elm/core\": \"1.0.0 <= v < 2.0.0\"
},
\"test-dependencies\": {
\"elm/json\": \"1.0.0 <= v < 2.0.0\"
}
}")
(define test-elm-guix-demo-readme
;; intentionally left blank
"")
(define (directory-sha256 directory)
"Returns the string representing the hash of DIRECTORY as would be used in a
package definition."
(bytevector->nix-base32-string
(file-hash* directory
#:algorithm (hash-algorithm sha256)
#:recursive? #t)))
(test-group "(guix import elm)"
(call-with-temporary-directory
(lambda (dir)
;; Initialize our fake git checkouts.
(define elm-core-dir
(string-append dir "/test-elm-core-1.0.4"))
(define elm-guix-demo-dir
(string-append dir "/test-elm-guix-demo-3.0.0"))
(for-each (match-lambda
((dir json readme)
(mkdir dir)
(with-output-to-file (string-append dir "/elm.json")
(lambda ()
(display json)))
(with-output-to-file (string-append dir "/README.md")
(lambda ()
(display readme)))))
`((,elm-core-dir ,test-elm-core-json ,test-elm-core-readme)
(,elm-guix-demo-dir
,test-elm-guix-demo-json
,test-elm-guix-demo-readme)))
;; Replace network resources with sample data.
(parameterize ((%elm-package-registry
(lambda ()
(json-string->scm test-package-registry-json)))
(%current-elm-checkout
(lambda (name version)
(match (list name version)
(("elm/core" "1.0.4")
elm-core-dir)
(("elm-guix/demo" "3.0.0")
elm-guix-demo-dir)))))
(test-assert "(elm->guix-package \"elm/core\")"
(match (elm->guix-package "elm/core")
(`(package
(name "elm-core")
(version "1.0.4")
(source (elm-package-origin
"elm/core"
version
(base32 ,(? string? hash))))
(build-system elm-build-system)
(home-page
"https://package.elm-lang.org/packages/elm/core/1.0.4")
(synopsis "Elm's standard libraries")
(description "Every Elm project needs this package!")
(license license:bsd-3))
(equal? (directory-sha256 elm-core-dir)
hash))
(x
(raise-exception x))))
(test-assert "(elm-recursive-import \"elm-guix/demo\")"
(match (elm-recursive-import "elm-guix/demo")
(`((package
(name "elm-guix-demo")
(version "3.0.0")
(source (elm-package-origin
"elm-guix/demo"
version
(base32 ,(? string? hash))))
(build-system elm-build-system)
(propagated-inputs
,'`(("elm-core" ,elm-core)))
(inputs
,'`(("elm-json" ,elm-json)))
(home-page
"https://package.elm-lang.org/packages/elm-guix/demo/3.0.0")
(synopsis "A test for `(guix import elm)`")
(description
"This package provides a test for `(guix import elm)`")
(properties '((upstream-name . "elm-guix/demo")))
(license license:gpl3+)))
(equal? (directory-sha256 elm-guix-demo-dir)
hash))
(x
(raise-exception x))))))))
(test-end "elm")