sup 0.22.1 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|