tests: Add 'with-derivation-substitute' and use it.

* guix/tests.scm (%substitute-directory): New variable.
  (call-with-derivation-narinfo): Use it.
  (call-with-derivation-substitute): New procedure.
  (with-derivation-substitute): New macro.
* tests/store.scm ("substitute"): Use 'with-derivation-substitute'.
  ("substitute, corrupt output hash"): Likewise.
This commit is contained in:
Ludovic Courtès 2015-02-02 11:24:24 +01:00
parent 6eebbab562
commit e6c8839c18
3 changed files with 73 additions and 50 deletions

View File

@ -43,7 +43,7 @@
(eval . (put 'emacs-substitute-sexps 'scheme-indent-function 1)) (eval . (put 'emacs-substitute-sexps 'scheme-indent-function 1))
(eval . (put 'emacs-substitute-variables 'scheme-indent-function 1)) (eval . (put 'emacs-substitute-variables 'scheme-indent-function 1))
(eval . (put 'with-derivation-narinfo 'scheme-indent-function 1)) (eval . (put 'with-derivation-narinfo 'scheme-indent-function 1))
(eval . (put 'with-derivation-substitute 'scheme-indent-function 1))
(eval . (put 'syntax-parameterize 'scheme-indent-function 1)) (eval . (put 'syntax-parameterize 'scheme-indent-function 1))
(eval . (put 'with-monad 'scheme-indent-function 1)) (eval . (put 'with-monad 'scheme-indent-function 1))

View File

@ -21,6 +21,8 @@
#:use-module (guix derivations) #:use-module (guix derivations)
#:use-module (guix packages) #:use-module (guix packages)
#:use-module (guix base32) #:use-module (guix base32)
#:use-module (guix serialization)
#:use-module (guix hash)
#:use-module (gnu packages bootstrap) #:use-module (gnu packages bootstrap)
#:use-module (srfi srfi-34) #:use-module (srfi srfi-34)
#:use-module (rnrs bytevectors) #:use-module (rnrs bytevectors)
@ -29,7 +31,9 @@
random-text random-text
random-bytevector random-bytevector
mock mock
%substitute-directory
with-derivation-narinfo with-derivation-narinfo
with-derivation-substitute
dummy-package)) dummy-package))
;;; Commentary: ;;; Commentary:
@ -107,14 +111,18 @@ Deriver: ~a~%"
(basename (basename
(derivation-file-name drv)))) ; Deriver (derivation-file-name drv)))) ; Deriver
(define %substitute-directory
(make-parameter
(and=> (getenv "GUIX_BINARY_SUBSTITUTE_URL")
(compose uri-path string->uri))))
(define* (call-with-derivation-narinfo drv thunk (define* (call-with-derivation-narinfo drv thunk
#:key (sha256 (make-bytevector 32 0))) #:key (sha256 (make-bytevector 32 0)))
"Call THUNK in a context where fake substituter data, as read by 'guix "Call THUNK in a context where fake substituter data, as read by 'guix
substitute-binary', has been installed for DRV. SHA256 is the hash of the substitute-binary', has been installed for DRV. SHA256 is the hash of the
expected output of DRV." expected output of DRV."
(let* ((output (derivation->output-path drv)) (let* ((output (derivation->output-path drv))
(dir (uri-path (dir (%substitute-directory))
(string->uri (getenv "GUIX_BINARY_SUBSTITUTE_URL"))))
(info (string-append dir "/nix-cache-info")) (info (string-append dir "/nix-cache-info"))
(narinfo (string-append dir "/" (store-path-hash-part output) (narinfo (string-append dir "/" (store-path-hash-part output)
".narinfo"))) ".narinfo")))
@ -145,6 +153,45 @@ substituter's viewpoint."
(lambda () (lambda ()
body ...))))) body ...)))))
(define* (call-with-derivation-substitute drv contents thunk
#:key sha256)
"Call THUNK in a context where a substitute for DRV has been installed,
using CONTENTS, a string, as its contents. If SHA256 is true, use it as the
expected hash of the substitute; otherwise use the hash of the nar containing
CONTENTS."
(define dir (%substitute-directory))
(dynamic-wind
(lambda ()
(call-with-output-file (string-append dir "/example.out")
(lambda (port)
(display contents port)))
(call-with-output-file (string-append dir "/example.nar")
(lambda (p)
(write-file (string-append dir "/example.out") p))))
(lambda ()
(let ((hash (call-with-input-file (string-append dir "/example.nar")
port-sha256)))
;; Create fake substituter data, to be read by `substitute-binary'.
(call-with-derivation-narinfo drv
thunk
#:sha256 (or sha256 hash))))
(lambda ()
(delete-file (string-append dir "/example.out"))
(delete-file (string-append dir "/example.nar")))))
(define-syntax with-derivation-substitute
(syntax-rules (sha256 =>)
"Evaluate BODY in a context where DRV is substitutable with the given
CONTENTS."
((_ drv contents (sha256 => hash) body ...)
(call-with-derivation-substitute drv contents
(lambda () body ...)
#:sha256 hash))
((_ drv contents body ...)
(call-with-derivation-substitute drv contents
(lambda ()
body ...)))))
(define-syntax-rule (dummy-package name* extra-fields ...) (define-syntax-rule (dummy-package name* extra-fields ...)
"Return a \"dummy\" package called NAME*, with all its compulsory fields "Return a \"dummy\" package called NAME*, with all its compulsory fields
initialized with default values, and with EXTRA-FIELDS set as specified." initialized with default values, and with EXTRA-FIELDS set as specified."
@ -156,6 +203,7 @@ initialized with default values, and with EXTRA-FIELDS set as specified."
;; Local Variables: ;; Local Variables:
;; eval: (put 'call-with-derivation-narinfo 'scheme-indent-function 1) ;; eval: (put 'call-with-derivation-narinfo 'scheme-indent-function 1)
;; eval: (put 'call-with-derivation-substitute 'scheme-indent-function 2)
;; End: ;; End:
;;; tests.scm ends here ;;; tests.scm ends here

View File

@ -343,27 +343,12 @@
(display ,c p))) (display ,c p)))
#:guile-for-build #:guile-for-build
(package-derivation s %bootstrap-guile (%current-system)))) (package-derivation s %bootstrap-guile (%current-system))))
(o (derivation->output-path d)) (o (derivation->output-path d)))
(dir (and=> (getenv "GUIX_BINARY_SUBSTITUTE_URL") (with-derivation-substitute d c
(compose uri-path string->uri)))) (set-build-options s #:use-substitutes? #t)
(call-with-output-file (string-append dir "/example.out") (and (has-substitutes? s o)
(lambda (p) (build-derivations s (list d))
(display c p))) (equal? c (call-with-input-file o get-string-all)))))))
(call-with-output-file (string-append dir "/example.nar")
(lambda (p)
(write-file (string-append dir "/example.out") p)))
(let ((h (call-with-input-file (string-append dir "/example.nar")
port-sha256)))
;; Create fake substituter data, to be read by `substitute-binary'.
(with-derivation-narinfo d
(sha256 => h)
;; Make sure we use `substitute-binary'.
(set-build-options s #:use-substitutes? #t)
(and (has-substitutes? s o)
(build-derivations s (list d))
(equal? c (call-with-input-file o get-string-all))))))))
(test-assert "substitute, corrupt output hash" (test-assert "substitute, corrupt output hash"
;; Tweak the substituter into installing a substitute whose hash doesn't ;; Tweak the substituter into installing a substitute whose hash doesn't
@ -376,33 +361,23 @@
`(mkdir %output) `(mkdir %output)
#:guile-for-build #:guile-for-build
(package-derivation s %bootstrap-guile (%current-system)))) (package-derivation s %bootstrap-guile (%current-system))))
(o (derivation->output-path d)) (o (derivation->output-path d)))
(dir (and=> (getenv "GUIX_BINARY_SUBSTITUTE_URL") (with-derivation-substitute d c
(compose uri-path string->uri)))) (sha256 => (make-bytevector 32 0)) ;select a hash that doesn't match C
;; Create fake substituter data, to be read by `substitute-binary'.
(with-derivation-narinfo d
(sha256 => (sha256 (string->utf8 c)))
(call-with-output-file (string-append dir "/example.out") ;; Make sure we use `substitute-binary'.
(lambda (p) (set-build-options s
(display "The contents here do not match C." p))) #:use-substitutes? #t
(call-with-output-file (string-append dir "/example.nar") #:fallback? #f)
(lambda (p) (and (has-substitutes? s o)
(write-file (string-append dir "/example.out") p))) (guard (c ((nix-protocol-error? c)
;; XXX: the daemon writes "hash mismatch in downloaded
;; Make sure we use `substitute-binary'. ;; path", but the actual error returned to the client
(set-build-options s ;; doesn't mention that.
#:use-substitutes? #t (pk 'corrupt c)
#:fallback? #f) (not (zero? (nix-protocol-error-status c)))))
(and (has-substitutes? s o) (build-derivations s (list d))
(guard (c ((nix-protocol-error? c) #f))))))
;; XXX: the daemon writes "hash mismatch in downloaded
;; path", but the actual error returned to the client
;; doesn't mention that.
(pk 'corrupt c)
(not (zero? (nix-protocol-error-status c)))))
(build-derivations s (list d))
#f))))))
(test-assert "substitute --fallback" (test-assert "substitute --fallback"
(with-store s (with-store s