-
Notifications
You must be signed in to change notification settings - Fork 2
/
tests.py
197 lines (147 loc) · 5.86 KB
/
tests.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
from __future__ import unicode_literals
import datetime
import re
import unittest
from mock import MagicMock, sentinel
import pytz
import six
from llic import(
CalendarWriter,
TypesCalendarWriterHelperMixin
)
class BackportTestCaseMixin(object):
"""
TestCase methods backported for older Python versions.
Include after unittest.TestCase so that standard methods are used
when present.
"""
# Backported for Python < 2.7
def assertIsNone(self, x):
if x is not None:
raise self.failureException("{!r} is not None".format(x))
# Backported for Python < 3.2
def assertRegex(self, test, regex, msg=None):
if not re.search(regex, test):
msg = "{}: {!r} not found in {!r}".format(
msg or "Regexp didn't match", regex, test
)
raise self.failureException(msg)
class TestCalendarWriter(unittest.TestCase):
def test_write(self):
mock_out = MagicMock()
writer = CalendarWriter(mock_out)
writer.write("I like writing stuff")
mock_out.write.assert_called_once_with(b"I like writing stuff")
def test_write_wrap(self):
out = six.BytesIO()
writer = CalendarWriter(out)
message = (
"This is a very long piece of text which will have to be wrapped "
"otherwise it would be toooooooo long. It might even have to be "
"wrapped twice because it's just that long."
)
writer.write(message)
value = out.getvalue()
# Don't strip the space after newline, otherwise line length would
# be off by 1.
lines = value.split(b"\r\n")
self.assertEqual(max(len(l) for l in lines), 75)
self.assertFalse(value.endswith(b"\r\n "))
def test_write_start_contenetline(self):
out = six.BytesIO()
writer = CalendarWriter(out)
writer.start_contentline("foo")
self.assertEqual(out.getvalue(), b"foo:")
def test_write_end_contenetline(self):
out = six.BytesIO()
writer = CalendarWriter(out)
writer.end_contentline()
self.assertEqual(out.getvalue(), b"\r\n")
class TestCalendarWriterHelperMixin(unittest.TestCase):
def test_contentline(self):
writer = CalendarWriter(six.BytesIO())
writer.start_contentline = MagicMock()
writer.value = MagicMock()
writer.end_contentline = MagicMock()
writer.contentline(sentinel.name, sentinel.value)
writer.start_contentline.assert_called_once_with(sentinel.name)
writer.value.assert_called_once_with(sentinel.value)
writer.end_contentline.assert_called_once()
def test_begin(self):
writer = CalendarWriter(six.BytesIO())
writer.start_contentline = MagicMock()
writer.value = MagicMock()
writer.end_contentline = MagicMock()
writer.begin(sentinel.section)
writer.start_contentline.assert_called_once_with("BEGIN")
writer.value.assert_called_once_with(sentinel.section)
writer.end_contentline.assert_called_once()
def test_end(self):
writer = CalendarWriter(six.BytesIO())
writer.start_contentline = MagicMock()
writer.value = MagicMock()
writer.end_contentline = MagicMock()
writer.end(sentinel.section)
writer.start_contentline.assert_called_once_with("END")
writer.value.assert_called_once_with(sentinel.section)
writer.end_contentline.assert_called_once()
class TypesTestMixin(object):
"""
A TestCase mixin to set self.instance to an instance of
TypesCalendarWriterHelperMixin.
"""
def setUp(self):
super(TypesTestMixin, self).setUp()
self.instance = TypesCalendarWriterHelperMixin()
class TestAsTest(TypesTestMixin, unittest.TestCase):
"""
Verify that special characters are escaped in encoded iCalendar TEXT
values.
"""
def test_newline_chars_are_escaped(self):
self.assertEqual(b"\\n", self.instance.as_text("\n"))
def test_backslash_chars_are_escaped(self):
self.assertEqual(b"\\\\", self.instance.as_text("\\"))
def test_semicolon_chars_are_escaped(self):
self.assertEqual(b"\\;", self.instance.as_text(";"))
def test_comma_chars_are_escaped(self):
self.assertEqual(b"\\,", self.instance.as_text(","))
def test_low_chars_are_stripped(self):
"""
Characters < 0x20 are not allowed in iCalendar TEXT values.
"""
low_chars = b"".join(
six.int2byte(c) for c in range(0x0, 0x20)
if c != ord(b"\n") # Ignore \n as it's handled by escaping
)
self.assertEqual(b"", self.instance.as_text(low_chars))
class TestAsDate(TypesTestMixin, unittest.TestCase, BackportTestCaseMixin):
def test_naive_date_raises_value_error(self):
"""
Verify that dates without timezone information are rejected with
a ValueError.
"""
dt = datetime.datetime(2013, 6, 21, 12, 0)
self.assertIsNone(dt.tzinfo)
try:
self.instance.as_datetime(dt)
self.fail()
except ValueError:
pass
def test_encoded_dates_have_z_suffix(self):
"""
Verify that encoded dates have a Z suffix to signify being in UTC.s
"""
dt = pytz.utc.localize(datetime.datetime(2013, 6, 21, 12, 0))
encoded = self.instance.as_datetime(dt)
self.assertRegex(encoded, "[zZ]$")
def test_datetimes_are_converted_to_utc(self):
"""
Verify that datetimes in timezones other than UTC are converted
to UTC in the output. In this case 12:00PM BST becomes 11:00AM UTC.
"""
zone = pytz.timezone("Europe/London")
# In BST, so UTC+1
dt = zone.localize(datetime.datetime(2013, 6, 21, 12, 0))
encoded = self.instance.as_datetime(dt)
self.assertEqual("20130621T110000Z", encoded)