python: Port more tests.
authorJustus Winter <justus@gnupg.org>
Tue, 31 May 2016 14:21:06 +0000 (16:21 +0200)
committerJustus Winter <justus@gnupg.org>
Tue, 31 May 2016 14:22:31 +0000 (16:22 +0200)
* lang/python/gpgme.i: Hide length fields of notations.
* lang/python/tests/Makefile.am (pytests): Add new tests.
* lang/python/tests/t-decrypt-verify.py: New file.
* lang/python/tests/t-sig-notation.py: Likewise.
* lang/python/tests/t-verify.py: Likewise.

Signed-off-by: Justus Winter <justus@gnupg.org>
lang/python/gpgme.i
lang/python/tests/Makefile.am
lang/python/tests/t-decrypt-verify.py [new file with mode: 0755]
lang/python/tests/t-sig-notation.py [new file with mode: 0755]
lang/python/tests/t-verify.py [new file with mode: 0755]

index 5b3c193..87fe90d 100644 (file)
@@ -255,11 +255,37 @@ PyObject* object_to_gpgme_t(PyObject* input, const char* objtype, int argnum) {
     $2 = $input;
 }
 
-// Include the header file both for cc (first) and for swig (second)
-// Include for swig locally since we need to fix 'class' usage there.
-%{
-#include <gpgme.h>
-%}
+/* Include the unmodified <gpgme.h> for cc, and the cleaned-up local
+   version for SWIG.  We do, however, want to hide certain fields on
+   some structs, which we provide prior to including the version for
+   SWIG.  */
+ %{ #include <gpgme.h> %}
+
+/* This is for notations, where we want to hide the length fields, and
+   the unused bit field block.  */
+struct _gpgme_sig_notation
+{
+  struct _gpgme_sig_notation *next;
+
+  /* If NAME is a null pointer, then VALUE contains a policy URL
+     rather than a notation.  */
+  char *name;
+
+  /* The value of the notation data.  */
+  char *value;
+
+  /* The accumulated flags.  */
+  gpgme_sig_notation_flags_t flags;
+
+  /* Notation data is human-readable.  */
+  unsigned int human_readable : 1;
+
+  /* Notation data is critical.  */
+  unsigned int critical : 1;
+};
+
+/* Now include our local modified version.  Any structs defined above
+   are ignored.  */
 %include "gpgme.h"
 
 %include "errors.i"
index 0bc8c7f..b85e82e 100644 (file)
@@ -38,6 +38,9 @@ py_tests = t-wrapper.py \
        t-sign.py \
        t-signers.py \
        t-decrypt.py \
+       t-verify.py \
+       t-decrypt-verify.py \
+       t-sig-notation.py \
        t-export.py \
        t-trustlist.py \
        t-edit.py \
diff --git a/lang/python/tests/t-decrypt-verify.py b/lang/python/tests/t-decrypt-verify.py
new file mode 100755 (executable)
index 0000000..433e0a1
--- /dev/null
@@ -0,0 +1,50 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME 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 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME 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 Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from pyme import core, constants, errors
+import support
+
+def check_verify_result(result, summary, fpr, status):
+    assert len(result.signatures) == 1, "Unexpected number of signatures"
+    sig = result.signatures[0]
+    assert sig.summary == summary, "Unexpected signature summary"
+    assert sig.fpr == fpr
+    assert errors.GPGMEError(sig.status).getcode() == status
+    assert len(sig.notations) == 0
+    assert not sig.wrong_key_usage
+    assert sig.validity == constants.VALIDITY_UNKNOWN
+    assert errors.GPGMEError(sig.validity_reason).getcode() == errors.NO_ERROR
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+c = core.Context()
+
+source = core.Data(file=support.make_filename("cipher-2.asc"))
+sink = core.Data()
+
+c.op_decrypt_verify(source, sink)
+result = c.op_decrypt_result()
+assert not result.unsupported_algorithm, \
+    "Unsupported algorithm: {}".format(result.unsupported_algorithm)
+
+support.print_data(sink)
+
+verify_result = c.op_verify_result()
+check_verify_result(verify_result, 0,
+                    "A0FF4590BB6122EDEF6E3C542D727CC768697734",
+                    errors.NO_ERROR)
diff --git a/lang/python/tests/t-sig-notation.py b/lang/python/tests/t-sig-notation.py
new file mode 100755 (executable)
index 0000000..2d832ef
--- /dev/null
@@ -0,0 +1,68 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME 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 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME 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 Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+import os
+from pyme import core, constants, errors
+import support
+
+expected_notations = {
+    "laughing@me": ("Just Squeeze Me", constants.SIG_NOTATION_HUMAN_READABLE),
+    "preferred-email-encoding@pgp.com": ("pgpmime",
+                                         constants.SIG_NOTATION_HUMAN_READABLE
+                                         | constants.SIG_NOTATION_CRITICAL),
+    None: ("http://www.gnu.org/policy/", 0),
+}
+
+def check_result(result):
+    assert len(result.signatures) == 1, "Unexpected number of signatures"
+    sig = result.signatures[0]
+    assert len(sig.notations) == len(expected_notations)
+
+    for r in sig.notations:
+        assert not 'name_len' in dir(r)
+        assert not 'value_len' in dir(r)
+        assert r.name in expected_notations
+        value, flags = expected_notations.pop(r.name)
+
+        assert r.value == value, \
+            "Expected {!r}, got {!r}".format(value, r.value)
+        assert r.human_readable \
+            == bool(flags&constants.SIG_NOTATION_HUMAN_READABLE)
+        # xxx notyet
+        #assert r.human_readable \
+        #    == bool(flags&constants.SIG_NOTATION_CRITICAL)
+
+    assert len(expected_notations) == 0
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+
+source = core.Data("Hallo Leute\n")
+signed = core.Data()
+
+c = core.Context()
+for name, (value, flags) in expected_notations.items():
+    c.sig_notation_add(name, value, flags)
+
+c.op_sign(source, signed, constants.SIG_MODE_NORMAL)
+
+signed.seek(0, os.SEEK_SET)
+sink = core.Data()
+c.op_verify(signed, None, sink)
+result = c.op_verify_result()
+check_result(result)
diff --git a/lang/python/tests/t-verify.py b/lang/python/tests/t-verify.py
new file mode 100755 (executable)
index 0000000..333ee4e
--- /dev/null
@@ -0,0 +1,128 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME 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 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME 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 Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+import os
+from pyme import core, constants, errors
+import support
+
+test_text1 = "Just GNU it!\n"
+test_text1f= "Just GNU it?\n"
+test_sig1 = """-----BEGIN PGP SIGNATURE-----
+
+iN0EABECAJ0FAjoS+i9FFIAAAAAAAwA5YmFyw7bDpMO8w58gZGFzIHdhcmVuIFVt
+bGF1dGUgdW5kIGpldHp0IGVpbiBwcm96ZW50JS1aZWljaGVuNRSAAAAAAAgAJGZv
+b2Jhci4xdGhpcyBpcyBhIG5vdGF0aW9uIGRhdGEgd2l0aCAyIGxpbmVzGhpodHRw
+Oi8vd3d3Lmd1Lm9yZy9wb2xpY3kvAAoJEC1yfMdoaXc0JBIAoIiLlUsvpMDOyGEc
+dADGKXF/Hcb+AKCJWPphZCphduxSvrzH0hgzHdeQaA==
+=nts1
+-----END PGP SIGNATURE-----
+"""
+
+test_sig2 = """-----BEGIN PGP MESSAGE-----
+
+owGbwMvMwCSoW1RzPCOz3IRxjXQSR0lqcYleSUWJTZOvjVdpcYmCu1+oQmaJIleH
+GwuDIBMDGysTSIqBi1MApi+nlGGuwDeHao53HBr+FoVGP3xX+kvuu9fCMJvl6IOf
+y1kvP4y+8D5a11ang0udywsA
+=Crq6
+-----END PGP MESSAGE-----
+"""
+
+# A message with a prepended but unsigned plaintext packet.
+double_plaintext_sig = """-----BEGIN PGP MESSAGE-----
+
+rDRiCmZvb2Jhci50eHRF4pxNVGhpcyBpcyBteSBzbmVha3kgcGxhaW50ZXh0IG1l
+c3NhZ2UKowGbwMvMwCSoW1RzPCOz3IRxTWISa6JebnG666MFD1wzSzJSixQ81XMV
+UlITUxTyixRyKxXKE0uSMxQyEosVikvyCwpSU/S4FNCArq6Ce1F+aXJGvoJvYlGF
+erFCTmJxiUJ5flFKMVeHGwuDIBMDGysTyA4GLk4BmO036xgWzMgzt9V85jCtfDFn
+UqVooWlGXHwNw/xg/fVzt9VNbtjtJ/fhUqYo0/LyCGEA
+=6+AK
+-----END PGP MESSAGE-----
+"""
+
+def check_result(result, summary, fpr, status, notation):
+    assert len(result.signatures) == 1, "Unexpected number of signatures"
+    sig = result.signatures[0]
+    assert sig.summary == summary, "Unexpected signature summary"
+    assert sig.fpr == fpr
+    assert errors.GPGMEError(sig.status).getcode() == status
+
+    if notation:
+        expected_notations = {
+            "bar": b"\xc3\xb6\xc3\xa4\xc3\xbc\xc3\x9f".decode() +
+            " das waren Umlaute und jetzt ein prozent%-Zeichen",
+            "foobar.1":  "this is a notation data with 2 lines",
+            None: "http://www.gu.org/policy/",
+        }
+        assert len(sig.notations) == len(expected_notations)
+
+        for r in sig.notations:
+            assert not 'name_len' in dir(r)
+            assert not 'value_len' in dir(r)
+            assert r.name in expected_notations
+            assert r.value == expected_notations[r.name], \
+                "Expected {!r}, got {!r}".format(expected_notations[r.name],
+                                                 r.value)
+            expected_notations.pop(r.name)
+
+        assert len(expected_notations) == 0
+
+    assert not sig.wrong_key_usage
+    assert sig.validity == constants.VALIDITY_UNKNOWN
+    assert errors.GPGMEError(sig.validity_reason).getcode() == errors.NO_ERROR
+
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+c = core.Context()
+c.set_armor(True)
+
+# Checking a valid message.
+text = core.Data(test_text1)
+sig = core.Data(test_sig1)
+c.op_verify(sig, text, None)
+result = c.op_verify_result()
+check_result(result, 0, "A0FF4590BB6122EDEF6E3C542D727CC768697734",
+             errors.NO_ERROR, True)
+
+
+# Checking a manipulated message.
+text = core.Data(test_text1f)
+sig.seek(0, os.SEEK_SET)
+c.op_verify(sig, text, None)
+result = c.op_verify_result()
+check_result(result, constants.SIGSUM_RED, "2D727CC768697734",
+             errors.BAD_SIGNATURE, False)
+
+# Checking a normal signature.
+text = core.Data()
+sig = core.Data(test_sig2)
+c.op_verify(sig, None, text)
+result = c.op_verify_result()
+check_result(result, 0, "A0FF4590BB6122EDEF6E3C542D727CC768697734",
+             errors.NO_ERROR, False)
+
+# Checking an invalid message.
+text = core.Data()
+sig = core.Data(double_plaintext_sig)
+try:
+    c.op_verify(sig, None, text)
+except Exception as e:
+    assert type(e) == errors.GPGMEError
+    assert e.getcode() == errors.BAD_DATA
+else:
+    assert False, "Expected an error but got none."