diff options
-rw-r--r-- | alot/db/utils.py | 38 | ||||
-rw-r--r-- | tests/crypto_test.py | 80 | ||||
-rw-r--r-- | tests/db/utils_test.py | 59 | ||||
-rw-r--r-- | tests/utilities.py | 28 |
4 files changed, 136 insertions, 69 deletions
diff --git a/alot/db/utils.py b/alot/db/utils.py index ac91098a..3cad7dd2 100644 --- a/alot/db/utils.py +++ b/alot/db/utils.py @@ -39,39 +39,39 @@ def add_signature_headers(mail, sigs, error_msg): :param error_msg: `str` containing an error message, the empty string indicating no error ''' - sig_from = '' + sig_from = u'' - if len(sigs) == 0: - error_msg = error_msg or 'no signature found' - else: + if isinstance(error_msg, str): + error_msg = error_msg.decode('utf-8') + + if not sigs: + error_msg = error_msg or u'no signature found' + elif not error_msg: try: key = crypto.get_key(sigs[0].fpr) for uid in key.uids: if crypto.check_uid_validity(key, uid.email): - sig_from = uid.uid + sig_from = uid.uid.decode('utf-8') uid_trusted = True break else: # No trusted uid found, we did not break but drop from the # for loop. uid_trusted = False - sig_from = key.uids[0].uid + sig_from = key.uids[0].uid.decode('utf-8') except: - sig_from = sigs[0].fpr + sig_from = sigs[0].fpr.decode('utf-8') uid_trusted = False - mail.add_header( - X_SIGNATURE_VALID_HEADER, - 'False' if error_msg else 'True', - ) - mail.add_header( - X_SIGNATURE_MESSAGE_HEADER, - u'Invalid: {0}'.format(error_msg) - if error_msg else - u'Valid: {0}'.format(sig_from) - if uid_trusted else - u'Untrusted: {0}'.format(sig_from) - ) + if error_msg: + msg = u'Invalid: {}'.format(error_msg) + elif uid_trusted: + msg = u'Valid: {}'.format(sig_from) + else: + msg = u'Untrusted: {}'.format(sig_from) + + mail.add_header(X_SIGNATURE_VALID_HEADER, 'False' if error_msg else 'True') + mail.add_header(X_SIGNATURE_MESSAGE_HEADER, msg) def get_params(mail, failobj=None, header='content-type', unquote=True): diff --git a/tests/crypto_test.py b/tests/crypto_test.py index 506d5868..e0e52cee 100644 --- a/tests/crypto_test.py +++ b/tests/crypto_test.py @@ -66,29 +66,6 @@ def tearDownModule(): os.kill(int(pid), signal.SIGKILL) -def make_key(revoked=False, expired=False, invalid=False, can_encrypt=True, - can_sign=True): - mock_key = mock.create_autospec(gpgme.Key) - mock_key.uids = [mock.Mock(uid=u'mocked')] - mock_key.revoked = revoked - mock_key.expired = expired - mock_key.invalid = invalid - mock_key.can_encrypt = can_encrypt - mock_key.can_sign = can_sign - - return mock_key - - -def make_uid(email, revoked=False, invalid=False, validity=gpgme.VALIDITY_FULL): - uid = mock.Mock() - uid.email = email - uid.revoked = revoked - uid.invalid = invalid - uid.validity = validity - - return uid - - class TestHashAlgorithmHelper(unittest.TestCase): """Test cases for the helper function RFC3156_canonicalize.""" @@ -154,49 +131,49 @@ class TestValidateKey(unittest.TestCase): def test_valid(self): try: - crypto.validate_key(make_key()) + crypto.validate_key(utilities.make_key()) except GPGProblem as e: raise AssertionError(e) def test_revoked(self): with self.assertRaises(GPGProblem) as caught: - crypto.validate_key(make_key(revoked=True)) + crypto.validate_key(utilities.make_key(revoked=True)) self.assertEqual(caught.exception.code, GPGCode.KEY_REVOKED) def test_expired(self): with self.assertRaises(GPGProblem) as caught: - crypto.validate_key(make_key(expired=True)) + crypto.validate_key(utilities.make_key(expired=True)) self.assertEqual(caught.exception.code, GPGCode.KEY_EXPIRED) def test_invalid(self): with self.assertRaises(GPGProblem) as caught: - crypto.validate_key(make_key(invalid=True)) + crypto.validate_key(utilities.make_key(invalid=True)) self.assertEqual(caught.exception.code, GPGCode.KEY_INVALID) def test_encrypt(self): with self.assertRaises(GPGProblem) as caught: - crypto.validate_key(make_key(can_encrypt=False), encrypt=True) + crypto.validate_key(utilities.make_key(can_encrypt=False), encrypt=True) self.assertEqual(caught.exception.code, GPGCode.KEY_CANNOT_ENCRYPT) def test_encrypt_no_check(self): try: - crypto.validate_key(make_key(can_encrypt=False)) + crypto.validate_key(utilities.make_key(can_encrypt=False)) except GPGProblem as e: raise AssertionError(e) def test_sign(self): with self.assertRaises(GPGProblem) as caught: - crypto.validate_key(make_key(can_sign=False), sign=True) + crypto.validate_key(utilities.make_key(can_sign=False), sign=True) self.assertEqual(caught.exception.code, GPGCode.KEY_CANNOT_SIGN) def test_sign_no_check(self): try: - crypto.validate_key(make_key(can_sign=False)) + crypto.validate_key(utilities.make_key(can_sign=False)) except GPGProblem as e: raise AssertionError(e) @@ -204,43 +181,44 @@ class TestValidateKey(unittest.TestCase): class TestCheckUIDValidity(unittest.TestCase): def test_valid_single(self): - key = make_key() - key.uids[0] = make_uid(mock.sentinel.EMAIL) + key = utilities.make_key() + key.uids[0] = utilities.make_uid(mock.sentinel.EMAIL) ret = crypto.check_uid_validity(key, mock.sentinel.EMAIL) self.assertTrue(ret) def test_valid_multiple(self): - key = make_key() + key = utilities.make_key() key.uids = [ - make_uid(mock.sentinel.EMAIL), - make_uid(mock.sentinel.EMAIL1), + utilities.make_uid(mock.sentinel.EMAIL), + utilities.make_uid(mock.sentinel.EMAIL1), ] ret = crypto.check_uid_validity(key, mock.sentinel.EMAIL1) self.assertTrue(ret) def test_invalid_email(self): - key = make_key() - key.uids[0] = make_uid(mock.sentinel.EMAIL) + key = utilities.make_key() + key.uids[0] = utilities.make_uid(mock.sentinel.EMAIL) ret = crypto.check_uid_validity(key, mock.sentinel.EMAIL1) self.assertFalse(ret) def test_invalid_revoked(self): - key = make_key() - key.uids[0] = make_uid(mock.sentinel.EMAIL, revoked=True) + key = utilities.make_key() + key.uids[0] = utilities.make_uid(mock.sentinel.EMAIL, revoked=True) ret = crypto.check_uid_validity(key, mock.sentinel.EMAIL) self.assertFalse(ret) def test_invalid_invalid(self): - key = make_key() - key.uids[0] = make_uid(mock.sentinel.EMAIL, invalid=True) + key = utilities.make_key() + key.uids[0] = utilities.make_uid(mock.sentinel.EMAIL, invalid=True) ret = crypto.check_uid_validity(key, mock.sentinel.EMAIL) self.assertFalse(ret) def test_invalid_not_enough_trust(self): - key = make_key() - key.uids[0] = make_uid(mock.sentinel.EMAIL, - validity=gpgme.VALIDITY_UNDEFINED) + key = utilities.make_key() + key.uids[0] = utilities.make_uid( + mock.sentinel.EMAIL, + validity=gpgme.VALIDITY_UNDEFINED) ret = crypto.check_uid_validity(key, mock.sentinel.EMAIL) self.assertFalse(ret) @@ -304,8 +282,8 @@ class TestGetKey(unittest.TestCase): return context_mock def test_ambiguous_one_valid(self): - invalid_key = make_key(invalid=True) - valid_key = make_key() + invalid_key = utilities.make_key(invalid=True) + valid_key = utilities.make_key() with mock.patch('alot.crypto.gpgme.Context', mock.Mock(return_value=self._context_mock())), \ @@ -318,7 +296,8 @@ class TestGetKey(unittest.TestCase): with mock.patch('alot.crypto.gpgme.Context', mock.Mock(return_value=self._context_mock())), \ mock.patch('alot.crypto.list_keys', - mock.Mock(return_value=[make_key(), make_key()])): + mock.Mock(return_value=[utilities.make_key(), + utilities.make_key()])): with self.assertRaises(crypto.GPGProblem) as cm: crypto.get_key('placeholder') self.assertEqual(cm.exception.code, GPGCode.AMBIGUOUS_NAME) @@ -327,8 +306,9 @@ class TestGetKey(unittest.TestCase): with mock.patch('alot.crypto.gpgme.Context', mock.Mock(return_value=self._context_mock())), \ mock.patch('alot.crypto.list_keys', - mock.Mock(return_value=[make_key(invalid=True), - make_key(invalid=True)])): + mock.Mock(return_value=[ + utilities.make_key(invalid=True), + utilities.make_key(invalid=True)])): with self.assertRaises(crypto.GPGProblem) as cm: crypto.get_key('placeholder') self.assertEqual(cm.exception.code, GPGCode.NOT_FOUND) diff --git a/tests/db/utils_test.py b/tests/db/utils_test.py index d07dd56a..48daef30 100644 --- a/tests/db/utils_test.py +++ b/tests/db/utils_test.py @@ -11,7 +11,10 @@ import os import os.path import unittest +import mock + from alot.db import utils +from ..utilities import make_key, make_uid class TestGetParams(unittest.TestCase): @@ -321,3 +324,59 @@ class TestDecodeHeader(unittest.TestCase): expected = u'first\nsecond third fourth fifth' actual = utils.decode_header(text, normalize=True) self.assertEqual(actual, expected) + + +class TestAddSignatureHeaders(unittest.TestCase): + + class FakeMail(object): + def __init__(self): + self.headers = [] + + def add_header(self, header, value): + self.headers.append((header, value)) + + def check(self, key, valid): + mail = self.FakeMail() + + with mock.patch('alot.db.utils.crypto.get_key', + mock.Mock(return_value=key)), \ + mock.patch('alot.db.utils.crypto.check_uid_validity', + mock.Mock(return_value=valid)): + utils.add_signature_headers(mail, [mock.Mock(fpr='')], u'') + + return mail + + def test_length_0(self): + mail = self.FakeMail() + utils.add_signature_headers(mail, [], u'') + self.assertIn((utils.X_SIGNATURE_VALID_HEADER, u'False'), mail.headers) + self.assertIn( + (utils.X_SIGNATURE_MESSAGE_HEADER, u'Invalid: no signature found'), + mail.headers) + + def test_valid(self): + key = make_key() + mail = self.check(key, True) + + self.assertIn((utils.X_SIGNATURE_VALID_HEADER, u'True'), mail.headers) + self.assertIn( + (utils.X_SIGNATURE_MESSAGE_HEADER, u'Valid: mocked'), mail.headers) + + def test_untrusted(self): + key = make_key() + mail = self.check(key, False) + + self.assertIn((utils.X_SIGNATURE_VALID_HEADER, u'True'), mail.headers) + self.assertIn( + (utils.X_SIGNATURE_MESSAGE_HEADER, u'Untrusted: mocked'), mail.headers) + + def test_unicode_as_bytes(self): + mail = self.FakeMail() + key = make_key() + key.uids = [make_uid('andreá@example.com', + uid=u'Andreá'.encode('utf-8'))] + mail = self.check(key, True) + + self.assertIn((utils.X_SIGNATURE_VALID_HEADER, u'True'), mail.headers) + self.assertIn( + (utils.X_SIGNATURE_MESSAGE_HEADER, u'Valid: Andreá'), mail.headers) diff --git a/tests/utilities.py b/tests/utilities.py index ed169b59..45433c99 100644 --- a/tests/utilities.py +++ b/tests/utilities.py @@ -21,6 +21,9 @@ from __future__ import absolute_import import functools import unittest +import gpgme +import mock + def _tear_down_class_wrapper(original, cls): """Ensure that doClassCleanups is called after tearDownClass.""" @@ -143,3 +146,28 @@ class ModuleCleanup(object): raise return wrapper + + +def make_uid(email, uid=u'mocked', revoked=False, invalid=False, + validity=gpgme.VALIDITY_FULL): + uid_ = mock.Mock() + uid_.email = email + uid_.uid = uid + uid_.revoked = revoked + uid_.invalid = invalid + uid_.validity = validity + + return uid_ + + +def make_key(revoked=False, expired=False, invalid=False, can_encrypt=True, + can_sign=True): + mock_key = mock.create_autospec(gpgme.Key) + mock_key.uids = [make_uid(u'foo@example.com')] + mock_key.revoked = revoked + mock_key.expired = expired + mock_key.invalid = invalid + mock_key.can_encrypt = can_encrypt + mock_key.can_sign = can_sign + + return mock_key |