sup 0.22.1 → 1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/workflows/checks.yml +70 -0
- data/.gitignore +1 -3
- data/.rubocop.yml +5 -0
- data/CONTRIBUTORS +14 -5
- data/Gemfile +6 -1
- data/History.txt +76 -0
- data/Manifest.txt +149 -0
- data/README.md +32 -5
- data/Rakefile +40 -1
- data/bin/sup +7 -5
- data/bin/sup-add +16 -20
- data/bin/sup-config +30 -44
- data/bin/sup-dump +2 -2
- data/bin/sup-import-dump +4 -4
- data/bin/sup-sync +3 -3
- data/bin/sup-sync-back-maildir +2 -2
- data/bin/sup-tweak-labels +5 -5
- data/ext/mkrf_conf_xapian.rb +10 -4
- data/lib/sup/colormap.rb +1 -1
- data/lib/sup/crypto.rb +17 -8
- data/lib/sup/hook.rb +9 -9
- data/lib/sup/index.rb +20 -7
- data/lib/sup/keymap.rb +1 -1
- data/lib/sup/logger.rb +1 -1
- data/lib/sup/maildir.rb +4 -4
- data/lib/sup/mbox.rb +4 -4
- data/lib/sup/message.rb +26 -15
- data/lib/sup/message_chunks.rb +29 -20
- data/lib/sup/mode.rb +1 -0
- data/lib/sup/modes/completion_mode.rb +0 -1
- data/lib/sup/modes/contact_list_mode.rb +1 -0
- data/lib/sup/modes/file_browser_mode.rb +2 -2
- data/lib/sup/modes/label_list_mode.rb +1 -1
- data/lib/sup/modes/reply_mode.rb +3 -1
- data/lib/sup/modes/search_list_mode.rb +2 -2
- data/lib/sup/modes/thread_index_mode.rb +1 -1
- data/lib/sup/modes/thread_view_mode.rb +15 -13
- data/lib/sup/rfc2047.rb +21 -6
- data/lib/sup/source.rb +9 -3
- data/lib/sup/textfield.rb +0 -1
- data/lib/sup/thread.rb +0 -1
- data/lib/sup/util/axe.rb +17 -0
- data/lib/sup/util/ncurses.rb +3 -3
- data/lib/sup/util.rb +42 -67
- data/lib/sup/version.rb +10 -1
- data/lib/sup.rb +13 -8
- data/man/sup-add.1 +34 -55
- data/man/sup-config.1 +23 -36
- data/man/sup-dump.1 +25 -35
- data/man/sup-import-dump.1 +33 -54
- data/man/sup-psych-ify-config-files.1 +25 -34
- data/man/sup-recover-sources.1 +34 -49
- data/man/sup-sync-back-maildir.1 +39 -60
- data/man/sup-sync.1 +49 -79
- data/man/sup-tweak-labels.1 +35 -58
- data/man/sup.1 +50 -62
- data/sup.gemspec +12 -9
- data/test/dummy_source.rb +21 -15
- data/test/fixtures/embedded-message.eml +34 -0
- data/test/fixtures/mailing-list-header.eml +80 -0
- data/test/fixtures/non-ascii-header-in-nested-message.eml +36 -0
- data/test/fixtures/non-ascii-header.eml +8 -0
- data/test/fixtures/rfc2047-header-encoding.eml +15 -0
- data/test/fixtures/text-attachments-with-charset.eml +60 -0
- data/test/fixtures/utf8-header.eml +17 -0
- data/test/fixtures/zimbra-quote-with-bottom-post.eml +27 -0
- data/test/gnupg_test_home/gpg.conf +2 -1
- data/test/gnupg_test_home/private-keys-v1.d/306D2EE90FF0014B5B9FD07E265C751791674140.key +0 -0
- data/test/gnupg_test_home/pubring.gpg +0 -0
- data/test/gnupg_test_home/receiver_pubring.gpg +0 -0
- data/test/gnupg_test_home/receiver_secring.gpg +0 -0
- data/test/gnupg_test_home/regen_keys.sh +69 -18
- data/test/gnupg_test_home/secring.gpg +0 -0
- data/test/gnupg_test_home/sup-test-2@foo.bar.asc +20 -22
- data/test/integration/test_mbox.rb +1 -1
- data/test/integration/test_sup-add.rb +83 -0
- data/test/test_crypto.rb +46 -0
- data/test/test_header_parsing.rb +9 -1
- data/test/test_helper.rb +7 -4
- data/test/test_message.rb +188 -22
- data/test/test_messages_dir.rb +13 -15
- data/test/unit/test_horizontal_selector.rb +4 -4
- data/test/unit/test_locale_fiddler.rb +1 -1
- data/test/unit/util/test_query.rb +10 -4
- data/test/unit/util/test_string.rb +9 -3
- data/test/unit/util/test_uri.rb +2 -2
- metadata +93 -51
- data/.travis.yml +0 -13
- data/bin/sup-psych-ify-config-files +0 -21
- data/test/gnupg_test_home/key1.gen +0 -15
- data/test/gnupg_test_home/key2.gen +0 -15
- data/test/gnupg_test_home/key_ecc.gen +0 -13
- data/test/gnupg_test_home/private-keys-v1.d/719C7455A7169C6EE8819C6E91002E4F9DD00A65.key +0 -1
- data/test/gnupg_test_home/private-keys-v1.d/8A130806A754AA29D59487D76BD355040D9F26C0.key +0 -0
- data/test/gnupg_test_home/private-keys-v1.d/B7AA46B22BD8A6AD1B4F266C19A3B124A32DDD71.key +0 -0
- data/test/gnupg_test_home/private-keys-v1.d/FA64ACD7CC871371BDF57285A6CDF0E618827783.key +0 -0
- data/test/integration/test_label_service.rb +0 -18
- data/test/test_yaml_migration.rb +0 -85
data/test/test_message.rb
CHANGED
|
@@ -21,10 +21,8 @@ class TestMessage < Minitest::Test
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def test_simple_message
|
|
24
|
-
message = fixture('simple-message.eml')
|
|
25
|
-
|
|
26
24
|
source = DummySource.new("sup-test://test_simple_message")
|
|
27
|
-
source.messages = [ message ]
|
|
25
|
+
source.messages = [ fixture_path('simple-message.eml') ]
|
|
28
26
|
source_info = 0
|
|
29
27
|
|
|
30
28
|
sup_message = Message.build_from_source(source, source_info)
|
|
@@ -99,10 +97,8 @@ class TestMessage < Minitest::Test
|
|
|
99
97
|
end
|
|
100
98
|
|
|
101
99
|
def test_multipart_message
|
|
102
|
-
message = fixture('multi-part.eml')
|
|
103
|
-
|
|
104
100
|
source = DummySource.new("sup-test://test_multipart_message")
|
|
105
|
-
source.messages = [
|
|
101
|
+
source.messages = [ fixture_path('multi-part.eml') ]
|
|
106
102
|
source_info = 0
|
|
107
103
|
|
|
108
104
|
sup_message = Message.build_from_source(source, source_info)
|
|
@@ -126,10 +122,8 @@ class TestMessage < Minitest::Test
|
|
|
126
122
|
end
|
|
127
123
|
|
|
128
124
|
def test_broken_message_1
|
|
129
|
-
message = fixture('missing-from-to.eml')
|
|
130
|
-
|
|
131
125
|
source = DummySource.new("sup-test://test_broken_message_1")
|
|
132
|
-
source.messages = [
|
|
126
|
+
source.messages = [ fixture_path('missing-from-to.eml') ]
|
|
133
127
|
source_info = 0
|
|
134
128
|
|
|
135
129
|
sup_message = Message.build_from_source(source, source_info)
|
|
@@ -150,10 +144,8 @@ class TestMessage < Minitest::Test
|
|
|
150
144
|
end
|
|
151
145
|
|
|
152
146
|
def test_broken_message_2
|
|
153
|
-
message = fixture('no-body.eml')
|
|
154
|
-
|
|
155
147
|
source = DummySource.new("sup-test://test_broken_message_1")
|
|
156
|
-
source.messages = [
|
|
148
|
+
source.messages = [ fixture_path('no-body.eml') ]
|
|
157
149
|
source_info = 0
|
|
158
150
|
|
|
159
151
|
sup_message = Message.build_from_source(source, source_info)
|
|
@@ -167,10 +159,8 @@ class TestMessage < Minitest::Test
|
|
|
167
159
|
end
|
|
168
160
|
|
|
169
161
|
def test_multipart_message_2
|
|
170
|
-
message = fixture('multi-part-2.eml')
|
|
171
|
-
|
|
172
162
|
source = DummySource.new("sup-test://test_multipart_message_2")
|
|
173
|
-
source.messages = [
|
|
163
|
+
source.messages = [ fixture_path('multi-part-2.eml') ]
|
|
174
164
|
source_info = 0
|
|
175
165
|
|
|
176
166
|
sup_message = Message.build_from_source(source, source_info)
|
|
@@ -178,14 +168,61 @@ class TestMessage < Minitest::Test
|
|
|
178
168
|
|
|
179
169
|
chunks = sup_message.load_from_source! # read the message body chunks
|
|
180
170
|
|
|
181
|
-
|
|
171
|
+
assert_equal(1, chunks.length)
|
|
172
|
+
assert(chunks[0].is_a? Redwood::Chunk::Attachment)
|
|
182
173
|
end
|
|
183
174
|
|
|
184
|
-
def
|
|
185
|
-
|
|
175
|
+
def test_text_attachment_decoding
|
|
176
|
+
source = DummySource.new("sup-test://test_text_attachment_decoding")
|
|
177
|
+
source.messages = [ fixture_path('text-attachments-with-charset.eml') ]
|
|
178
|
+
source_info = 0
|
|
179
|
+
|
|
180
|
+
sup_message = Message.build_from_source(source, source_info)
|
|
181
|
+
sup_message.load_from_source!
|
|
182
|
+
|
|
183
|
+
chunks = sup_message.load_from_source!
|
|
184
|
+
assert_equal(7, chunks.length)
|
|
185
|
+
assert(chunks[0].is_a? Redwood::Chunk::Text)
|
|
186
|
+
## The first attachment declares charset=us-ascii
|
|
187
|
+
assert(chunks[1].is_a? Redwood::Chunk::Attachment)
|
|
188
|
+
assert_equal(["This is ASCII"], chunks[1].lines)
|
|
189
|
+
## The second attachment declares charset=koi8-r and has some Cyrillic
|
|
190
|
+
assert(chunks[2].is_a? Redwood::Chunk::Attachment)
|
|
191
|
+
assert_equal(["\u041f\u0440\u0438\u0432\u0435\u0442"], chunks[2].lines)
|
|
192
|
+
## The third attachment declares charset=utf-8 and has an emoji
|
|
193
|
+
assert(chunks[3].is_a? Redwood::Chunk::Attachment)
|
|
194
|
+
assert_equal(["\u{1f602}"], chunks[3].lines)
|
|
195
|
+
## The fourth attachment declares no charset and has a non-ASCII byte,
|
|
196
|
+
## which will be replaced with U+FFFD REPLACEMENT CHARACTER
|
|
197
|
+
assert(chunks[4].is_a? Redwood::Chunk::Attachment)
|
|
198
|
+
assert_equal(["Embedded\ufffdgarbage"], chunks[4].lines)
|
|
199
|
+
## The fifth attachment has an invalid charset, which should still
|
|
200
|
+
## be handled gracefully
|
|
201
|
+
assert(chunks[5].is_a? Redwood::Chunk::Attachment)
|
|
202
|
+
assert_equal(["Example invalid charset"], chunks[5].lines)
|
|
203
|
+
## The sixth attachment is UTF-7 encoded
|
|
204
|
+
assert(chunks[6].is_a? Redwood::Chunk::Attachment)
|
|
205
|
+
assert_equal(["This is ✨UTF-7✨"], chunks[6].lines)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def test_mailing_list_header
|
|
209
|
+
source = DummySource.new("sup-test://test_mailing_list_header")
|
|
210
|
+
source.messages = [ fixture_path('mailing-list-header.eml') ]
|
|
211
|
+
source_info = 0
|
|
186
212
|
|
|
213
|
+
sup_message = Message.build_from_source(source, source_info)
|
|
214
|
+
sup_message.load_from_source!
|
|
215
|
+
|
|
216
|
+
assert(sup_message.list_subscribe.nil?)
|
|
217
|
+
assert_equal("<https://lists.openembedded.org/g/openembedded-devel/unsub>",
|
|
218
|
+
sup_message.list_unsubscribe)
|
|
219
|
+
assert_equal("openembedded-devel@lists.openembedded.org", sup_message.list_address.email)
|
|
220
|
+
assert_equal("openembedded-devel", sup_message.list_address.name)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def test_blank_header_lines
|
|
187
224
|
source = DummySource.new("sup-test://test_blank_header_lines")
|
|
188
|
-
source.messages = [
|
|
225
|
+
source.messages = [ fixture_path('blank-header-fields.eml') ]
|
|
189
226
|
source_info = 0
|
|
190
227
|
|
|
191
228
|
sup_message = Message.build_from_source(source, source_info)
|
|
@@ -203,11 +240,113 @@ class TestMessage < Minitest::Test
|
|
|
203
240
|
|
|
204
241
|
end
|
|
205
242
|
|
|
206
|
-
def
|
|
207
|
-
|
|
243
|
+
def test_rfc2047_header_encoding
|
|
244
|
+
source = DummySource.new("sup-test://test_rfc2047_header_encoding")
|
|
245
|
+
source.messages = [ fixture_path("rfc2047-header-encoding.eml") ]
|
|
246
|
+
source_info = 0
|
|
247
|
+
|
|
248
|
+
sup_message = Message.build_from_source(source, source_info)
|
|
249
|
+
sup_message.load_from_source!
|
|
250
|
+
|
|
251
|
+
assert_equal("Hans Martin Djupvik, Ingrid Bø, Ирина Сидорова, " +
|
|
252
|
+
"Jesper Berg, Frida Engø " +
|
|
253
|
+
"bad: =?UTF16?q?badcharsetname?==?US-ASCII?b?/w?=" +
|
|
254
|
+
"=?UTF-7?Q?=41=6D=65=72=69=63=61=E2=80=99=73?=",
|
|
255
|
+
sup_message.subj)
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def test_nonascii_header
|
|
259
|
+
## Spammers sometimes send invalid high bytes in the headers.
|
|
260
|
+
## They will be replaced with U+FFFD REPLACEMENT CHARACTER.
|
|
261
|
+
source = DummySource.new("sup-test://test_nonascii_header")
|
|
262
|
+
source.messages = [ fixture_path("non-ascii-header.eml") ]
|
|
263
|
+
source_info = 0
|
|
264
|
+
|
|
265
|
+
sup_message = Message.build_from_source(source, source_info)
|
|
266
|
+
sup_message.load_from_source!
|
|
208
267
|
|
|
268
|
+
assert_equal("SPAM \ufffd", sup_message.from.name)
|
|
269
|
+
assert_equal("spammer@example.com", sup_message.from.email)
|
|
270
|
+
assert_equal("spam \ufffd spam", sup_message.subj)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def test_utf8_header
|
|
274
|
+
## UTF-8 is allowed in header values according to RFC6532.
|
|
275
|
+
source = DummySource.new("sup-test://test_utf8_header")
|
|
276
|
+
source.messages = [ fixture_path("utf8-header.eml") ]
|
|
277
|
+
source_info = 0
|
|
278
|
+
|
|
279
|
+
sup_message = Message.build_from_source(source, source_info)
|
|
280
|
+
sup_message.load_from_source!
|
|
281
|
+
|
|
282
|
+
assert_equal(Encoding::UTF_8, sup_message.subj.encoding)
|
|
283
|
+
assert_equal("LibraryThing: State of the Thing — January", sup_message.subj)
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def test_nonascii_header_in_nested_message
|
|
287
|
+
source = DummySource.new("sup-test://test_nonascii_header_in_nested_message")
|
|
288
|
+
source.messages = [ fixture_path("non-ascii-header-in-nested-message.eml") ]
|
|
289
|
+
source_info = 0
|
|
290
|
+
|
|
291
|
+
sup_message = Message.build_from_source(source, source_info)
|
|
292
|
+
chunks = sup_message.load_from_source!
|
|
293
|
+
|
|
294
|
+
assert_equal(3, chunks.length)
|
|
295
|
+
|
|
296
|
+
assert(chunks[0].is_a? Redwood::Chunk::Text)
|
|
297
|
+
|
|
298
|
+
assert(chunks[1].is_a? Redwood::Chunk::EnclosedMessage)
|
|
299
|
+
assert_equal(4, chunks[1].lines.length)
|
|
300
|
+
assert_equal("From: SPAM \ufffd <spammer@example.com>", chunks[1].lines[0])
|
|
301
|
+
assert_equal("To: enclosed <enclosed@example.invalid>", chunks[1].lines[1])
|
|
302
|
+
assert_equal("Subject: spam \ufffd spam", chunks[1].lines[3])
|
|
303
|
+
|
|
304
|
+
assert(chunks[2].is_a? Redwood::Chunk::Text)
|
|
305
|
+
assert_equal(1, chunks[2].lines.length)
|
|
306
|
+
assert_equal("This is a spam.", chunks[2].lines[0])
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def test_embedded_message
|
|
310
|
+
source = DummySource.new("sup-test://test_embedded_message")
|
|
311
|
+
source.messages = [ fixture_path("embedded-message.eml") ]
|
|
312
|
+
source_info = 0
|
|
313
|
+
|
|
314
|
+
sup_message = Message.build_from_source(source, source_info)
|
|
315
|
+
|
|
316
|
+
chunks = sup_message.load_from_source!
|
|
317
|
+
assert_equal(3, chunks.length)
|
|
318
|
+
|
|
319
|
+
assert_equal("sender@example.com", sup_message.from.email)
|
|
320
|
+
assert_equal("Sender", sup_message.from.name)
|
|
321
|
+
assert_equal(1, sup_message.to.length)
|
|
322
|
+
assert_equal("recipient@example.invalid", sup_message.to[0].email)
|
|
323
|
+
assert_equal("recipient", sup_message.to[0].name)
|
|
324
|
+
assert_equal("Email with embedded message", sup_message.subj)
|
|
325
|
+
|
|
326
|
+
assert(chunks[0].is_a? Redwood::Chunk::Text)
|
|
327
|
+
assert_equal("Example outer message.", chunks[0].lines[0])
|
|
328
|
+
assert_equal("Example second line.", chunks[0].lines[1])
|
|
329
|
+
|
|
330
|
+
assert(chunks[1].is_a? Redwood::Chunk::EnclosedMessage)
|
|
331
|
+
assert_equal(4, chunks[1].lines.length)
|
|
332
|
+
assert_equal("From: Embed sender <embed@example.com>", chunks[1].lines[0])
|
|
333
|
+
assert_equal("To: rcpt2 <rcpt2@example.invalid>", chunks[1].lines[1])
|
|
334
|
+
assert_equal("Date: ", chunks[1].lines[2][0..5])
|
|
335
|
+
assert_equal(
|
|
336
|
+
Time.rfc2822("Wed, 15 Jul 2020 12:34:56 +0000"),
|
|
337
|
+
Time.rfc2822(chunks[1].lines[2][6..-1])
|
|
338
|
+
)
|
|
339
|
+
assert_equal("Subject: Embedded subject line", chunks[1].lines[3])
|
|
340
|
+
|
|
341
|
+
assert(chunks[2].is_a? Redwood::Chunk::Text)
|
|
342
|
+
assert_equal(2, chunks[2].lines.length)
|
|
343
|
+
assert_equal("Example embedded message.", chunks[2].lines[0])
|
|
344
|
+
assert_equal("Second line.", chunks[2].lines[1])
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def test_malicious_attachment_names
|
|
209
348
|
source = DummySource.new("sup-test://test_blank_header_lines")
|
|
210
|
-
source.messages = [
|
|
349
|
+
source.messages = [ fixture_path('malicious-attachment-names.eml') ]
|
|
211
350
|
source_info = 0
|
|
212
351
|
|
|
213
352
|
sup_message = Message.build_from_source(source, source_info)
|
|
@@ -225,6 +364,33 @@ class TestMessage < Minitest::Test
|
|
|
225
364
|
# TODO: test different quoting styles, see that they are all divided
|
|
226
365
|
# to chunks properly
|
|
227
366
|
|
|
367
|
+
def test_zimbra_quote_with_bottom_post
|
|
368
|
+
# Zimbra does an Outlook-style "Original Message" delimiter and then *also*
|
|
369
|
+
# prefixes each quoted line with a > marker. That's okay until the sender
|
|
370
|
+
# tries to do the right thing and reply after the quote.
|
|
371
|
+
# In this case we want to just look at the > markers when determining where
|
|
372
|
+
# the quoted chunk ends.
|
|
373
|
+
source = DummySource.new("sup-test://test_zimbra_quote_with_bottom_post")
|
|
374
|
+
source.messages = [ fixture_path('zimbra-quote-with-bottom-post.eml') ]
|
|
375
|
+
source_info = 0
|
|
376
|
+
|
|
377
|
+
sup_message = Message.build_from_source(source, source_info)
|
|
378
|
+
chunks = sup_message.load_from_source!
|
|
379
|
+
|
|
380
|
+
assert_equal(3, chunks.length)
|
|
381
|
+
|
|
382
|
+
# TODO this chunk should ideally be part of the quote chunk after it.
|
|
383
|
+
assert(chunks[0].is_a? Redwood::Chunk::Text)
|
|
384
|
+
assert_equal(1, chunks[0].lines.length)
|
|
385
|
+
assert_equal("----- Original Message -----", chunks[0].lines.first)
|
|
386
|
+
|
|
387
|
+
assert(chunks[1].is_a? Redwood::Chunk::Quote)
|
|
388
|
+
|
|
389
|
+
assert(chunks[2].is_a? Redwood::Chunk::Text)
|
|
390
|
+
assert_equal(3, chunks[2].lines.length)
|
|
391
|
+
assert_equal("This is the reply from the Zimbra user.",
|
|
392
|
+
chunks[2].lines[2])
|
|
393
|
+
end
|
|
228
394
|
end
|
|
229
395
|
|
|
230
396
|
end
|
data/test/test_messages_dir.rb
CHANGED
|
@@ -13,19 +13,22 @@ class TestMessagesDir < ::Minitest::Test
|
|
|
13
13
|
def setup
|
|
14
14
|
@path = Dir.mktmpdir
|
|
15
15
|
Redwood::HookManager.init File.join(@path, 'hooks')
|
|
16
|
+
@log = StringIO.new
|
|
17
|
+
Redwood::Logger.add_sink @log
|
|
18
|
+
Redwood::Logger.remove_sink $stderr
|
|
16
19
|
end
|
|
17
20
|
|
|
18
21
|
def teardown
|
|
22
|
+
Redwood::Logger.clear!
|
|
23
|
+
Redwood::Logger.remove_sink @log
|
|
24
|
+
Redwood::Logger.add_sink $stderr
|
|
19
25
|
Redwood::HookManager.deinstantiate!
|
|
20
26
|
FileUtils.rm_r @path
|
|
21
27
|
end
|
|
22
28
|
|
|
23
29
|
def test_binary_content_transfer_encoding
|
|
24
|
-
message = ''
|
|
25
|
-
File.open('test/fixtures/binary-content-transfer-encoding-2.eml') { |f| message = f.read }
|
|
26
|
-
|
|
27
30
|
source = DummySource.new("sup-test://test_messages")
|
|
28
|
-
source.messages = [
|
|
31
|
+
source.messages = [ fixture_path('binary-content-transfer-encoding-2.eml') ]
|
|
29
32
|
source_info = 0
|
|
30
33
|
|
|
31
34
|
sup_message = Message.build_from_source(source, source_info)
|
|
@@ -41,7 +44,6 @@ class TestMessagesDir < ::Minitest::Test
|
|
|
41
44
|
assert_equal("Important", subj)
|
|
42
45
|
|
|
43
46
|
chunks = sup_message.load_from_source!
|
|
44
|
-
indexable_chunks = sup_message.indexable_chunks
|
|
45
47
|
|
|
46
48
|
# there should be only one chunk
|
|
47
49
|
#assert_equal(1, chunks.length)
|
|
@@ -50,14 +52,13 @@ class TestMessagesDir < ::Minitest::Test
|
|
|
50
52
|
|
|
51
53
|
# lines should contain an error message
|
|
52
54
|
assert (lines.join.include? "An error occurred while loading this message."), "This message should not load successfully"
|
|
55
|
+
|
|
56
|
+
assert_match(/WARNING: problem reading message/, @log.string)
|
|
53
57
|
end
|
|
54
58
|
|
|
55
59
|
def test_bad_content_transfer_encoding
|
|
56
|
-
message = ''
|
|
57
|
-
File.open('test/fixtures/bad-content-transfer-encoding-1.eml') { |f| message = f.read }
|
|
58
|
-
|
|
59
60
|
source = DummySource.new("sup-test://test_messages")
|
|
60
|
-
source.messages = [
|
|
61
|
+
source.messages = [ fixture_path('bad-content-transfer-encoding-1.eml') ]
|
|
61
62
|
source_info = 0
|
|
62
63
|
|
|
63
64
|
sup_message = Message.build_from_source(source, source_info)
|
|
@@ -73,7 +74,6 @@ class TestMessagesDir < ::Minitest::Test
|
|
|
73
74
|
assert_equal("Content-Transfer-Encoding:-bug in sup", subj)
|
|
74
75
|
|
|
75
76
|
chunks = sup_message.load_from_source!
|
|
76
|
-
indexable_chunks = sup_message.indexable_chunks
|
|
77
77
|
|
|
78
78
|
# there should be only one chunk
|
|
79
79
|
#assert_equal(1, chunks.length)
|
|
@@ -82,14 +82,13 @@ class TestMessagesDir < ::Minitest::Test
|
|
|
82
82
|
|
|
83
83
|
# lines should contain an error message
|
|
84
84
|
assert (lines.join.include? "An error occurred while loading this message."), "This message should not load successfully"
|
|
85
|
+
|
|
86
|
+
assert_match(/WARNING: problem reading message/, @log.string)
|
|
85
87
|
end
|
|
86
88
|
|
|
87
89
|
def test_missing_line
|
|
88
|
-
message = ''
|
|
89
|
-
File.open('test/fixtures/missing-line.eml') { |f| message = f.read }
|
|
90
|
-
|
|
91
90
|
source = DummySource.new("sup-test://test_messages")
|
|
92
|
-
source.messages = [
|
|
91
|
+
source.messages = [ fixture_path('missing-line.eml') ]
|
|
93
92
|
source_info = 0
|
|
94
93
|
|
|
95
94
|
sup_message = Message.build_from_source(source, source_info)
|
|
@@ -105,7 +104,6 @@ class TestMessagesDir < ::Minitest::Test
|
|
|
105
104
|
assert_equal("Encoding bug", subj)
|
|
106
105
|
|
|
107
106
|
chunks = sup_message.load_from_source!
|
|
108
|
-
indexable_chunks = sup_message.indexable_chunks
|
|
109
107
|
|
|
110
108
|
# there should be only one chunk
|
|
111
109
|
#assert_equal(1, chunks.length)
|
|
@@ -13,18 +13,18 @@ describe Redwood::HorizontalSelector do
|
|
|
13
13
|
|
|
14
14
|
it "init w/ the first value selected" do
|
|
15
15
|
first_value = values.first
|
|
16
|
-
@selector.val
|
|
16
|
+
assert_equal first_value, @selector.val
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
it "stores value for selection" do
|
|
20
20
|
second_value = values[1]
|
|
21
21
|
@selector.set_to second_value
|
|
22
|
-
@selector.val
|
|
22
|
+
assert_equal second_value, @selector.val
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
describe "for unknown value" do
|
|
26
26
|
it "cannot select unknown value" do
|
|
27
|
-
@selector.
|
|
27
|
+
assert_equal false, @selector.can_set_to?(strange_value)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
it "refuses selecting unknown value" do
|
|
@@ -34,7 +34,7 @@ describe Redwood::HorizontalSelector do
|
|
|
34
34
|
@selector.set_to strange_value
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
@selector.val
|
|
37
|
+
assert_equal old_value, @selector.val
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
end
|
|
@@ -24,9 +24,14 @@ describe Redwood::Util::Query do
|
|
|
24
24
|
query = Xapian::Query.new msg
|
|
25
25
|
life = 'hæi'
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
if query.description.force_encoding("UTF-8").valid_encoding?
|
|
28
|
+
# xapian 1.4 internally handles this bad input
|
|
29
|
+
assert true
|
|
30
|
+
else
|
|
31
|
+
# xapian 1.2 doesn't handle this bad input, so we do
|
|
32
|
+
assert_raises Redwood::Util::Query::QueryDescriptionError do
|
|
33
|
+
_desc = Redwood::Util::Query.describe (query)
|
|
34
|
+
end
|
|
30
35
|
end
|
|
31
36
|
|
|
32
37
|
assert_raises Encoding::CompatibilityError do
|
|
@@ -40,7 +45,8 @@ describe Redwood::Util::Query do
|
|
|
40
45
|
|
|
41
46
|
desc = Redwood::Util::Query.describe(query, "invalid query")
|
|
42
47
|
|
|
43
|
-
|
|
48
|
+
assert desc.force_encoding("UTF-8").valid_encoding?
|
|
49
|
+
|
|
44
50
|
end
|
|
45
51
|
end
|
|
46
52
|
end
|
|
@@ -11,12 +11,14 @@ describe "Sup's String extension" do
|
|
|
11
11
|
['some words', 10,],
|
|
12
12
|
['中文', 4,],
|
|
13
13
|
['ä', 1,],
|
|
14
|
+
['😱', 2],
|
|
15
|
+
#['🏳️🌈', 2], # Emoji ZWJ sequence not yet supported (see PR #563)
|
|
14
16
|
]
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
it "calculates display length of a string" do
|
|
18
20
|
data.each do |(str, length)|
|
|
19
|
-
str.display_length
|
|
21
|
+
assert_equal length, str.display_length
|
|
20
22
|
end
|
|
21
23
|
end
|
|
22
24
|
end
|
|
@@ -27,12 +29,14 @@ describe "Sup's String extension" do
|
|
|
27
29
|
['some words', 6, 'some w'],
|
|
28
30
|
['中文', 2, '中'],
|
|
29
31
|
['älpha', 3, 'älp'],
|
|
32
|
+
['😱😱', 2, '😱'],
|
|
33
|
+
#['🏳️🌈', 2, '🏳️🌈'], # Emoji ZWJ sequence not yet supported (see PR #563)
|
|
30
34
|
]
|
|
31
35
|
end
|
|
32
36
|
|
|
33
37
|
it "slices string by display length" do
|
|
34
38
|
data.each do |(str, length, sliced)|
|
|
35
|
-
str.slice_by_display_length(length)
|
|
39
|
+
assert_equal sliced, str.slice_by_display_length(length)
|
|
36
40
|
end
|
|
37
41
|
end
|
|
38
42
|
end
|
|
@@ -45,12 +49,14 @@ describe "Sup's String extension" do
|
|
|
45
49
|
['中文', 2, ['中', '文']],
|
|
46
50
|
['中文', 5, ['中文']],
|
|
47
51
|
['älpha', 3, ['älp', 'ha']],
|
|
52
|
+
['😱😱', 2, ['😱', '😱']],
|
|
53
|
+
#['🏳️🌈🏳️🌈', 2, ['🏳️🌈', '🏳️🌈']], # Emoji ZWJ sequence not yet supported (see PR #563)
|
|
48
54
|
]
|
|
49
55
|
end
|
|
50
56
|
|
|
51
57
|
it "wraps string by display length" do
|
|
52
58
|
data.each do |(str, length, wrapped)|
|
|
53
|
-
str.wrap(length)
|
|
59
|
+
assert_equal wrapped, str.wrap(length)
|
|
54
60
|
end
|
|
55
61
|
end
|
|
56
62
|
end
|
data/test/unit/util/test_uri.rb
CHANGED
|
@@ -7,13 +7,13 @@ describe Redwood::Util::Uri do
|
|
|
7
7
|
it "builds uri from hash" do
|
|
8
8
|
components = {:path => "/var/mail/foo", :scheme => "mbox"}
|
|
9
9
|
uri = Redwood::Util::Uri.build(components)
|
|
10
|
-
|
|
10
|
+
assert_equal "mbox:/var/mail/foo", uri.to_s
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
it "expands ~ in path" do
|
|
14
14
|
components = {:path => "~/foo", :scheme => "maildir"}
|
|
15
15
|
uri = Redwood::Util::Uri.build(components)
|
|
16
|
-
|
|
16
|
+
assert_equal "maildir:#{ENV["HOME"]}/foo", uri.to_s
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
end
|