summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--alot/helper.py4
-rw-r--r--tests/helper_test.py78
-rw-r--r--tests/utilities.py10
3 files changed, 82 insertions, 10 deletions
diff --git a/alot/helper.py b/alot/helper.py
index 1c569a23..26787fa8 100644
--- a/alot/helper.py
+++ b/alot/helper.py
@@ -129,7 +129,7 @@ def string_decode(string, enc='ascii'):
def shorten(string, maxlen):
"""shortens string if longer than maxlen, appending ellipsis"""
if 1 < maxlen < len(string):
- string = string[:maxlen - 1] + u'\u2026'
+ string = string[:maxlen - 1] + u'…'
return string[:maxlen]
@@ -333,7 +333,7 @@ def call_cmd_async(cmdlist, stdin=None, env=None):
self.deferred.errback(terminated_obj)
d = Deferred()
- environment = os.environ
+ environment = os.environ.copy()
if env is not None:
environment.update(env)
logging.debug('ENV = %s', environment)
diff --git a/tests/helper_test.py b/tests/helper_test.py
index 62e37ed8..c2927725 100644
--- a/tests/helper_test.py
+++ b/tests/helper_test.py
@@ -18,17 +18,21 @@
"""Test suite for alot.helper module."""
from __future__ import absolute_import
-
import datetime
import email
import errno
+import os
import random
-import unittest
import mock
+from twisted.trial import unittest
+from twisted.internet.defer import inlineCallbacks
+from twisted.internet.error import ProcessTerminated
from alot import helper
+from . import utilities
+
# Descriptive names for tests often violate PEP8. That's not an issue, users
# aren't meant to call these functions.
# pylint: disable=invalid-name
@@ -257,7 +261,7 @@ class TestPrettyDatetime(unittest.TestCase):
self.assertEqual(actual, expected)
# Returns 'just now', instead of 'from future' or something similar
- @unittest.expectedFailure
+ @utilities.expected_failure
def test_future_minutes(self):
test = self.now + datetime.timedelta(minutes=5)
actual = helper.pretty_datetime(test)
@@ -265,7 +269,7 @@ class TestPrettyDatetime(unittest.TestCase):
self.assertEqual(actual, expected)
# Returns 'just now', instead of 'from future' or something similar
- @unittest.expectedFailure
+ @utilities.expected_failure
def test_future_hours(self):
test = self.now + datetime.timedelta(hours=1)
actual = helper.pretty_datetime(test)
@@ -273,7 +277,7 @@ class TestPrettyDatetime(unittest.TestCase):
self.assertEqual(actual, expected)
# Returns 'just now', instead of 'from future' or something similar
- @unittest.expectedFailure
+ @utilities.expected_failure
def test_future_days(self):
def make_expected():
# Uses the hourfmt instead of the hourminfmt from pretty_datetime
@@ -290,7 +294,7 @@ class TestPrettyDatetime(unittest.TestCase):
self.assertEqual(actual, expected)
# Returns 'just now', instead of 'from future' or something similar
- @unittest.expectedFailure
+ @utilities.expected_failure
def test_future_week(self):
test = self.now + datetime.timedelta(days=7)
actual = helper.pretty_datetime(test)
@@ -298,7 +302,7 @@ class TestPrettyDatetime(unittest.TestCase):
self.assertEqual(actual, expected)
# Returns 'just now', instead of 'from future' or something similar
- @unittest.expectedFailure
+ @utilities.expected_failure
def test_future_month(self):
test = self.now + datetime.timedelta(days=31)
actual = helper.pretty_datetime(test)
@@ -306,7 +310,7 @@ class TestPrettyDatetime(unittest.TestCase):
self.assertEqual(actual, expected)
# Returns 'just now', instead of 'from future' or something similar
- @unittest.expectedFailure
+ @utilities.expected_failure
def test_future_year(self):
test = self.now + datetime.timedelta(days=365)
actual = helper.pretty_datetime(test)
@@ -402,3 +406,61 @@ class TestEmailAsString(unittest.TestCase):
actual = helper.email_as_string(message)
expected = 'X-Unicode-Header: dummy value\r\n\r\n'
self.assertEqual(actual, expected)
+
+
+class TestShorten(unittest.TestCase):
+
+ def test_lt_maxlen(self):
+ expected = u'a string'
+ actual = helper.shorten(expected, 25)
+ self.assertEqual(expected, actual)
+
+ def test_eq_maxlen(self):
+ expected = 'a string'
+ actual = helper.shorten(expected, len(expected))
+ self.assertEqual(expected, actual)
+
+ def test_gt_maxlen(self):
+ expected = u'a long string…'
+ actual = helper.shorten('a long string that is full of text', 14)
+ self.assertEqual(expected, actual)
+
+
+class TestCallCmdAsync(unittest.TestCase):
+
+ @inlineCallbacks
+ def test_no_stdin(self):
+ ret = yield helper.call_cmd_async(['echo', '-n', 'foo'])
+ self.assertEqual(ret, 'foo')
+
+ @inlineCallbacks
+ def test_stdin(self):
+ ret = yield helper.call_cmd_async(['cat', '-'], stdin='foo')
+ self.assertEqual(ret, 'foo')
+
+ @inlineCallbacks
+ def test_env_set(self):
+ with mock.patch.dict(os.environ, {}, clear=True):
+ ret = yield helper.call_cmd_async(
+ # Thanks to the future import it doesn't matter if python is
+ # python2 or python3
+ ['python', '-c', 'from __future__ import print_function; '
+ 'import os; '
+ 'print(os.environ.get("foo", "fail"), end="")'
+ ],
+ env={'foo': 'bar'})
+ self.assertEqual(ret, 'bar')
+
+ @inlineCallbacks
+ def test_env_doesnt_pollute(self):
+ with mock.patch.dict(os.environ, {}, clear=True):
+ yield helper.call_cmd_async(['echo', '-n', 'foo'],
+ env={'foo': 'bar'})
+ self.assertEqual(os.environ, {})
+
+ @inlineCallbacks
+ def test_command_fails(self):
+ with self.assertRaises(ProcessTerminated) as cm:
+ yield helper.call_cmd_async(['_____better_not_exist'])
+ self.assertEqual(cm.exception.exitCode, 1)
+ self.assertTrue(cm.exception.stderr)
diff --git a/tests/utilities.py b/tests/utilities.py
index 402feb38..8123afd8 100644
--- a/tests/utilities.py
+++ b/tests/utilities.py
@@ -171,3 +171,13 @@ def make_key(revoked=False, expired=False, invalid=False, can_encrypt=True,
mock_key.can_sign = can_sign
return mock_key
+
+
+def expected_failure(func):
+ """For marking expected failures for twisted.trial based unit tests.
+
+ The builtin unittest.expectedFailure does not work with twisted.trail,
+ there is an outstanding bug for this, but no one has ever fixed it.
+ """
+ func.todo = 'expected failure'
+ return func