tests: Reuse GPGME's tests.
authorJustus Winter <justus@g10code.com>
Thu, 17 Nov 2016 12:11:48 +0000 (13:11 +0100)
committerJustus Winter <justus@g10code.com>
Wed, 14 Dec 2016 15:50:44 +0000 (16:50 +0100)
* configure.ac (AC_CONFIG_FILES): Add new Makefile.
* tests/Makefile.am (SUBDIRS): Add new directory.
* tests/gpgme/Makefile.am: New file.
* tests/gpgme/gpgme-defs.scm: Likewise.
* tests/gpgme/run-tests.scm: Likewise.
* tests/gpgme/setup.scm: Likewise.
* tests/gpgme/wrap.scm: Likewise.

Signed-off-by: Justus Winter <justus@g10code.com>
configure.ac
tests/Makefile.am
tests/gpgme/Makefile.am [new file with mode: 0644]
tests/gpgme/gpgme-defs.scm [new file with mode: 0644]
tests/gpgme/run-tests.scm [new file with mode: 0644]
tests/gpgme/setup.scm [new file with mode: 0644]
tests/gpgme/wrap.scm [new file with mode: 0644]

index 066e963..1c467bf 100644 (file)
@@ -1888,6 +1888,7 @@ tests/Makefile
 tests/gpgscm/Makefile
 tests/openpgp/Makefile
 tests/migrations/Makefile
+tests/gpgme/Makefile
 tests/pkits/Makefile
 g10/gpg.w32-manifest
 ])
index 2fbdc7f..c022e2a 100644 (file)
@@ -18,7 +18,7 @@
 
 ## Process this file with automake to produce Makefile.in
 
-SUBDIRS = gpgscm openpgp migrations pkits .
+SUBDIRS = gpgscm openpgp migrations gpgme pkits .
 
 GPGSM = ../sm/gpgsm
 
diff --git a/tests/gpgme/Makefile.am b/tests/gpgme/Makefile.am
new file mode 100644 (file)
index 0000000..21e0e14
--- /dev/null
@@ -0,0 +1,58 @@
+# Makefile.am - For tests/gpgme
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GnuPG.
+#
+# GnuPG 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.
+#
+# GnuPG 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 this program; if not, see <https://www.gnu.org/licenses/>.
+# Process this file with automake to create Makefile.in
+
+
+# Programs required before we can run these tests.
+required_pgms = ../../g10/gpg$(EXEEXT) ../../agent/gpg-agent$(EXEEXT) \
+                ../../tools/gpg-connect-agent$(EXEEXT) \
+               ../gpgscm/gpgscm$(EXEEXT)
+
+AM_CPPFLAGS = -I$(top_srcdir)/common
+include $(top_srcdir)/am/cmacros.am
+
+AM_CFLAGS =
+
+TMP ?= /tmp
+
+TESTS_ENVIRONMENT = LC_ALL=C \
+       EXEEXT=$(EXEEXT) \
+       PATH=../gpgscm:$(PATH) \
+       TMP=$(TMP) \
+       srcdir=$(abs_srcdir) \
+       objdir=$(abs_top_builddir) \
+       GPGSCM_PATH=$(abs_top_srcdir)/tests/gpgscm:$(abs_top_srcdir)/tests/openpgp:$(abs_top_srcdir)/tests/gpgme
+
+# XXX: Currently, one cannot override automake's 'check' target.  As a
+# workaround, we avoid defining 'TESTS', thus automake will not emit
+# the 'check' target.  For extra robustness, we merely define a
+# dependency on 'xcheck', so this hack should also work even if
+# automake would emit the 'check' target, as adding dependencies to
+# targets is okay.
+check: xcheck
+
+.PHONY: xcheck
+xcheck:
+       $(TESTS_ENVIRONMENT) $(abs_top_builddir)/tests/gpgscm/gpgscm \
+         $(abs_srcdir)/run-tests.scm $(TESTFLAGS) $(XTESTS)
+
+EXTRA_DIST = gpgme-defs.scm run-tests.scm setup.scm wrap.scm
+
+# We need to depend on a couple of programs so that the tests don't
+# start before all programs are built.
+all-local: $(required_pgms)
diff --git a/tests/gpgme/gpgme-defs.scm b/tests/gpgme/gpgme-defs.scm
new file mode 100644 (file)
index 0000000..2490666
--- /dev/null
@@ -0,0 +1,167 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG 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.
+;;
+;; GnuPG 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 this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (with-path "defs.scm"))
+
+(define gpgme-srcdir (getenv "XTEST_GPGME_SRCDIR"))
+(when (string=? "" gpgme-srcdir)
+    (info
+     "SKIP: Environment variable 'XTEST_GPGME_SRCDIR' not set.  Please"
+     "point it to a recent GPGME source tree to run the GPGME test suite.")
+    (exit 0))
+
+(define (in-gpgme-srcdir . names)
+  (canonical-path (apply path-join (cons gpgme-srcdir names))))
+
+(define gpgme-builddir (getenv "XTEST_GPGME_BUILDDIR"))
+(when (string=? "" gpgme-builddir)
+    (info
+     "SKIP: Environment variable 'XTEST_GPGME_BUILDDIR' not set.  Please"
+     "point it to a recent GPGME build tree to run the GPGME test suite.")
+    (exit 0))
+
+;; Make sure that GPGME picks up our gpgconf.  This makes GPGME use
+;; and thus executes the tests with GnuPG components from the build
+;; tree.
+(setenv "PATH" (string-append (path-join (getenv "GNUPG_BUILDDIR") "tools")
+                             (string *pathsep*) (getenv "PATH")) #t)
+
+(define (create-file name content)
+  (letfd ((fd (open name (logior O_WRONLY O_CREAT O_BINARY) #o600)))
+    (display content (fdopen fd "wb"))))
+
+(define (create-gpgmehome . path)
+  (create-file "gpg.conf" "no-force-v3-sigs\n")
+  (create-file
+   "gpg-agent.conf"
+   (string-append "pinentry-program "
+                 (in-gpgme-srcdir "tests" "gpg" "pinentry") "\n"))
+  (mkdir "private-keys-v1.d" "-rwx")
+
+  (log "Storing private keys")
+  (for-each
+   (lambda (name)
+     (file-copy (apply in-gpgme-srcdir `(,@path ,name))
+               (path-join "private-keys-v1.d"
+                          (string-append name ".key"))))
+   '("13CD0F3BDF24BE53FE192D62F18737256FF6E4FD"
+     "76F7E2B35832976B50A27A282D9B87E44577EB66"
+     "A0747D5F9425E6664F4FFBEED20FBCA79FDED2BD"
+     "13CBE3758AFE42B5E5E2AE4CED27AFA455E3F87F"
+     "7A030357C0F253A5BBCD282FFC4E521B37558F5C"))
+
+  (log "Importing public demo and test keys")
+  (for-each
+   (lambda (file)
+     (call-check `(,@GPG --yes --import ,(apply in-gpgme-srcdir
+                                               `(,@path ,file)))))
+   (list "pubdemo.asc" "secdemo.asc"))
+  (stop-agent))
+
+;; Initialize the test environment, install appropriate configuration
+;; and start the agent, with the keys from the legacy test suite.
+(define (setup-gpgme-environment . path)
+  (if (member "--unpack-tarball" *args*)
+      (begin
+       (call-check `(,(tool 'gpgtar) --extract --directory=. ,(cadr *args*)))
+       (start-agent))
+      (apply create-gpgme-gpghome path)))
+
+;; Command line flag handling.  Returns the elements following KEY in
+;; ARGUMENTS up to the next argument, or #f if KEY is not in
+;; ARGUMENTS.
+(define (flag key arguments)
+  (cond
+   ((null? arguments)
+    #f)
+   ((string=? key (car arguments))
+    (let loop ((acc '())
+              (args (cdr arguments)))
+      (if (or (null? args) (string-prefix? (car args) "--"))
+         (reverse acc)
+         (loop (cons (car args) acc) (cdr args)))))
+   ((string=? "--" (car arguments))
+    #f)
+   (else
+    (flag key (cdr arguments)))))
+(assert (equal? (flag "--xxx" '("--yyy")) #f))
+(assert (equal? (flag "--xxx" '("--xxx")) '()))
+(assert (equal? (flag "--xxx" '("--xxx" "yyy")) '("yyy")))
+(assert (equal? (flag "--xxx" '("--xxx" "yyy" "zzz")) '("yyy" "zzz")))
+(assert (equal? (flag "--xxx" '("--xxx" "yyy" "zzz" "--")) '("yyy" "zzz")))
+(assert (equal? (flag "--xxx" '("--xxx" "yyy" "--" "zzz")) '("yyy")))
+(assert (equal? (flag "--" '("--" "xxx" "yyy" "--" "zzz")) '("xxx" "yyy")))
+
+(define (parse-makefile port key)
+  (define (is-continuation? tokens)
+    (string=? (last tokens) "\\"))
+  (define (valid-token? s)
+    (< 0 (string-length s)))
+  (define (drop-continuations tokens)
+    (let loop ((acc '()) (tks tokens))
+      (if (null? tks)
+         (reverse acc)
+         (loop (if (string=? "\\" (car tks))
+                   acc
+                   (cons (car tks) acc)) (cdr tks)))))
+  (let next ((acc '()) (found #f))
+    (let ((line (read-line port)))
+      (if (eof-object? line)
+         acc
+         (let ((tokens (filter valid-token?
+                               (string-splitp (string-trim char-whitespace?
+                                                           line)
+                                              char-whitespace? -1))))
+           (cond
+            ((or (null? tokens)
+                 (string-prefix? (car tokens) "#")
+                 (and (not found) (not (and (string=? key (car tokens))
+                                            (string=? "=" (cadr tokens))))))
+             (next acc found))
+            ((not found)
+             (assert (and (string=? key (car tokens))
+                          (string=? "=" (cadr tokens))))
+             (if (is-continuation? tokens)
+                 (next (drop-continuations (cddr tokens)) #t)
+                 (drop-continuations (cddr tokens))))
+            (else
+             (assert found)
+             (if (is-continuation? tokens)
+                 (next (append acc (drop-continuations tokens)) found)
+                 (append acc (drop-continuations tokens))))))))))
+
+(define (parse-makefile-expand filename expand key)
+  (define (variable? v)
+    (and (string-prefix? v "$(") (string-suffix? v ")")))
+
+  (let expand-all ((values (parse-makefile (open-input-file filename) key)))
+    (if (any variable? values)
+       (expand-all
+        (let expand-one ((acc '()) (v values))
+          (cond
+           ((null? v)
+            acc)
+           ((variable? (car v))
+            (let ((makefile (open-input-file filename))
+                  (key (substring (car v) 2 (- (string-length (car v)) 1))))
+              (expand-one (append acc (expand filename makefile key))
+                          (cdr v))))
+           (else
+            (expand-one (append acc (list (car v))) (cdr v))))))
+       values)))
diff --git a/tests/gpgme/run-tests.scm b/tests/gpgme/run-tests.scm
new file mode 100644 (file)
index 0000000..bce5584
--- /dev/null
@@ -0,0 +1,69 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG 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.
+;;
+;; GnuPG 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 this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (with-path "gpgme-defs.scm"))
+
+(info "Running GPGME's test suite...")
+
+(define (gpgme-makefile-expand filename port key)
+  ;;(interactive-repl (current-environment))
+  (cond
+   ((string=? key "tests_unix")
+    (if *win32*
+       (parse-makefile port key)   ;; Use win32 definition.
+       (begin
+         (parse-makefile port key) ;; Skip win32 definition.
+         (parse-makefile port key))))
+   (else
+    (parse-makefile port key))))
+
+(define (all-tests filename key)
+  (parse-makefile-expand filename gpgme-makefile-expand key))
+
+(let* ((runner (if (member "--parallel" *args*)
+                  run-tests-parallel
+                  run-tests-sequential))
+       (tests (filter (lambda (arg) (not (string-prefix? arg "--"))) *args*)))
+  (runner
+   (test::scm "setup.scm" (in-srcdir "setup.scm") "--" "tests" "gpg")
+   (apply
+    append
+    (map (lambda (cmpnts)
+          (define (compiled? name)
+            (not (or (string-suffix? name ".py")
+                     (string-suffix? name ".test"))))
+          (define :path car)
+          (define :key cadr)
+          (define (find-test name)
+            (apply path-join
+                   `(,(if (compiled? name)
+                          gpgme-builddir
+                          gpgme-srcdir) ,@(:path cmpnts),name)))
+          (let ((makefile (apply path-join `(,gpgme-srcdir ,@(:path cmpnts)
+                                                           "Makefile.am"))))
+            (map (lambda (name)
+                   (apply test::scm
+                          `(,name ,(in-srcdir "wrap.scm") --executable
+                                  ,(find-test name)
+                                  -- ,@(:path cmpnts))))
+                 (if (null? tests) (all-tests makefile (:key cmpnts)) tests))))
+        '((("tests" "gpg") "c_tests")
+          ;; XXX: Not yet.
+          ;; (("lang" "python" "tests") "py_tests")
+          (("lang" "qt" "tests") "TESTS"))))))
diff --git a/tests/gpgme/setup.scm b/tests/gpgme/setup.scm
new file mode 100644 (file)
index 0000000..0116a74
--- /dev/null
@@ -0,0 +1,35 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG 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.
+;;
+;; GnuPG 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 this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (with-path "gpgme-defs.scm"))
+
+(define tarball (flag "--create-tarball" *args*))
+(unless (and tarball (not (null? tarball)))
+       (error "Usage: setup.scm --create-tarball <file> ..."))
+
+(define components (flag "--" *args*))
+(unless (and components (not (null? components)))
+       (error "Usage: setup.scm --create-tarball " (cadr tarball)
+              " -- component [component ...]"))
+
+(with-temporary-working-directory
+ (setenv "GNUPGHOME" (getcwd) #t)
+ (apply create-gpgmehome components)
+ (stop-agent)
+ (call-check `(,(tool 'gpgtar) --create --output ,(car tarball) ".")))
diff --git a/tests/gpgme/wrap.scm b/tests/gpgme/wrap.scm
new file mode 100644 (file)
index 0000000..4f3ae7d
--- /dev/null
@@ -0,0 +1,60 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG 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.
+;;
+;; GnuPG 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 this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (with-path "gpgme-defs.scm"))
+
+(define executable (flag "--executable" *args*))
+(unless (and executable (not (null? executable)))
+       (error "Usage: wrap.scm --executable <file> [args...]"))
+
+(setup-gpgme-environment "tests" "gpg")
+
+(setenv "abs_builddir" (getcwd) #t)
+(setenv "top_srcdir" gpgme-srcdir #t)
+(setenv "srcdir" (path-join gpgme-srcdir "tests" "gpg") #t)
+
+(define (run what)
+  (if (string-suffix? (car what) ".py")
+      (begin
+       (setenv "LD_LIBRARY_PATH"
+               (if (< 0 (string-length (getenv "LD_LIBRARY_PATH")))
+                   (string-append (path-join gpgme-builddir "src/.libs")
+                                  (string *pathsep*)
+                                  (getenv "LD_LIBRARY_PATH"))
+                   (path-join gpgme-builddir "src/.libs"))
+               #t)
+       (call-with-fds
+        `("/usr/bin/python"
+          ,(in-gpgme-srcdir "lang" "python" "tests" "run-tests.py")
+          --quiet
+          --interpreters=/usr/bin/python
+          --builddir ,(path-join gpgme-builddir "lang" "python" "tests")
+          ,@what)
+        STDIN_FILENO STDOUT_FILENO STDERR_FILENO))
+      (if #f 77 (call-with-fds what STDIN_FILENO STDOUT_FILENO STDERR_FILENO))))
+
+(let ((name (basename (car executable))))
+  (cond
+   ((string=? "t-keylist" name)
+    ;; This test assumes that 't-import' imported a key.
+    (log "Importing extra key...")
+    (call-check `(,@GPG --yes --import ,(in-srcdir "pubkey-1.asc"))))))
+
+(log "Running" (car executable))
+(exit (run executable))