sup 0.22.1 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/checks.yml +70 -0
  3. data/.gitignore +1 -3
  4. data/.rubocop.yml +5 -0
  5. data/CONTRIBUTORS +14 -5
  6. data/Gemfile +6 -1
  7. data/History.txt +76 -0
  8. data/Manifest.txt +149 -0
  9. data/README.md +32 -5
  10. data/Rakefile +40 -1
  11. data/bin/sup +7 -5
  12. data/bin/sup-add +16 -20
  13. data/bin/sup-config +30 -44
  14. data/bin/sup-dump +2 -2
  15. data/bin/sup-import-dump +4 -4
  16. data/bin/sup-sync +3 -3
  17. data/bin/sup-sync-back-maildir +2 -2
  18. data/bin/sup-tweak-labels +5 -5
  19. data/ext/mkrf_conf_xapian.rb +10 -4
  20. data/lib/sup/colormap.rb +1 -1
  21. data/lib/sup/crypto.rb +17 -8
  22. data/lib/sup/hook.rb +9 -9
  23. data/lib/sup/index.rb +20 -7
  24. data/lib/sup/keymap.rb +1 -1
  25. data/lib/sup/logger.rb +1 -1
  26. data/lib/sup/maildir.rb +4 -4
  27. data/lib/sup/mbox.rb +4 -4
  28. data/lib/sup/message.rb +26 -15
  29. data/lib/sup/message_chunks.rb +29 -20
  30. data/lib/sup/mode.rb +1 -0
  31. data/lib/sup/modes/completion_mode.rb +0 -1
  32. data/lib/sup/modes/contact_list_mode.rb +1 -0
  33. data/lib/sup/modes/file_browser_mode.rb +2 -2
  34. data/lib/sup/modes/label_list_mode.rb +1 -1
  35. data/lib/sup/modes/reply_mode.rb +3 -1
  36. data/lib/sup/modes/search_list_mode.rb +2 -2
  37. data/lib/sup/modes/thread_index_mode.rb +1 -1
  38. data/lib/sup/modes/thread_view_mode.rb +15 -13
  39. data/lib/sup/rfc2047.rb +21 -6
  40. data/lib/sup/source.rb +9 -3
  41. data/lib/sup/textfield.rb +0 -1
  42. data/lib/sup/thread.rb +0 -1
  43. data/lib/sup/util/axe.rb +17 -0
  44. data/lib/sup/util/ncurses.rb +3 -3
  45. data/lib/sup/util.rb +42 -67
  46. data/lib/sup/version.rb +10 -1
  47. data/lib/sup.rb +13 -8
  48. data/man/sup-add.1 +34 -55
  49. data/man/sup-config.1 +23 -36
  50. data/man/sup-dump.1 +25 -35
  51. data/man/sup-import-dump.1 +33 -54
  52. data/man/sup-psych-ify-config-files.1 +25 -34
  53. data/man/sup-recover-sources.1 +34 -49
  54. data/man/sup-sync-back-maildir.1 +39 -60
  55. data/man/sup-sync.1 +49 -79
  56. data/man/sup-tweak-labels.1 +35 -58
  57. data/man/sup.1 +50 -62
  58. data/sup.gemspec +12 -9
  59. data/test/dummy_source.rb +21 -15
  60. data/test/fixtures/embedded-message.eml +34 -0
  61. data/test/fixtures/mailing-list-header.eml +80 -0
  62. data/test/fixtures/non-ascii-header-in-nested-message.eml +36 -0
  63. data/test/fixtures/non-ascii-header.eml +8 -0
  64. data/test/fixtures/rfc2047-header-encoding.eml +15 -0
  65. data/test/fixtures/text-attachments-with-charset.eml +60 -0
  66. data/test/fixtures/utf8-header.eml +17 -0
  67. data/test/fixtures/zimbra-quote-with-bottom-post.eml +27 -0
  68. data/test/gnupg_test_home/gpg.conf +2 -1
  69. data/test/gnupg_test_home/private-keys-v1.d/306D2EE90FF0014B5B9FD07E265C751791674140.key +0 -0
  70. data/test/gnupg_test_home/pubring.gpg +0 -0
  71. data/test/gnupg_test_home/receiver_pubring.gpg +0 -0
  72. data/test/gnupg_test_home/receiver_secring.gpg +0 -0
  73. data/test/gnupg_test_home/regen_keys.sh +69 -18
  74. data/test/gnupg_test_home/secring.gpg +0 -0
  75. data/test/gnupg_test_home/sup-test-2@foo.bar.asc +20 -22
  76. data/test/integration/test_mbox.rb +1 -1
  77. data/test/integration/test_sup-add.rb +83 -0
  78. data/test/test_crypto.rb +46 -0
  79. data/test/test_header_parsing.rb +9 -1
  80. data/test/test_helper.rb +7 -4
  81. data/test/test_message.rb +188 -22
  82. data/test/test_messages_dir.rb +13 -15
  83. data/test/unit/test_horizontal_selector.rb +4 -4
  84. data/test/unit/test_locale_fiddler.rb +1 -1
  85. data/test/unit/util/test_query.rb +10 -4
  86. data/test/unit/util/test_string.rb +9 -3
  87. data/test/unit/util/test_uri.rb +2 -2
  88. metadata +93 -51
  89. data/.travis.yml +0 -13
  90. data/bin/sup-psych-ify-config-files +0 -21
  91. data/test/gnupg_test_home/key1.gen +0 -15
  92. data/test/gnupg_test_home/key2.gen +0 -15
  93. data/test/gnupg_test_home/key_ecc.gen +0 -13
  94. data/test/gnupg_test_home/private-keys-v1.d/719C7455A7169C6EE8819C6E91002E4F9DD00A65.key +0 -1
  95. data/test/gnupg_test_home/private-keys-v1.d/8A130806A754AA29D59487D76BD355040D9F26C0.key +0 -0
  96. data/test/gnupg_test_home/private-keys-v1.d/B7AA46B22BD8A6AD1B4F266C19A3B124A32DDD71.key +0 -0
  97. data/test/gnupg_test_home/private-keys-v1.d/FA64ACD7CC871371BDF57285A6CDF0E618827783.key +0 -0
  98. data/test/integration/test_label_service.rb +0 -18
  99. 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 = [ message ]
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 = [ message ]
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 = [ message ]
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 = [ message ]
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
- # TODO: Add more asserts
171
+ assert_equal(1, chunks.length)
172
+ assert(chunks[0].is_a? Redwood::Chunk::Attachment)
182
173
  end
183
174
 
184
- def test_blank_header_lines
185
- message = fixture('blank-header-fields.eml')
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 = [ message ]
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 test_malicious_attachment_names
207
- message = fixture('malicious-attachment-names.eml')
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 = [ message ]
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
@@ -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 = [ message ]
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 = [ message ]
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 = [ message ]
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.must_equal first_value
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.must_equal second_value
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.wont_be :can_set_to?, strange_value
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.must_equal old_value
37
+ assert_equal old_value, @selector.val
38
38
  end
39
39
  end
40
40
  end
@@ -1,7 +1,7 @@
1
1
  require 'test_helper'
2
2
  require 'sup/util/locale_fiddler'
3
3
 
4
- class TestFiddle < ::Minitest::Unit::TestCase
4
+ class TestFiddle < Minitest::Test
5
5
  # TODO this is a silly test
6
6
  def test_fiddle_set_locale
7
7
  before = LocaleDummy.setlocale(6, nil).to_s
@@ -24,9 +24,14 @@ describe Redwood::Util::Query do
24
24
  query = Xapian::Query.new msg
25
25
  life = 'hæi'
26
26
 
27
- # this is now possibly UTF-8 string with possibly invalid chars
28
- assert_raises Redwood::Util::Query::QueryDescriptionError do
29
- desc = Redwood::Util::Query.describe (query)
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
- assert_equal("invalid query", desc)
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.must_equal 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).must_equal sliced
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).must_equal wrapped
59
+ assert_equal wrapped, str.wrap(length)
54
60
  end
55
61
  end
56
62
  end
@@ -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
- uri.to_s.must_equal "mbox:/var/mail/foo"
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
- uri.to_s.must_equal "maildir:#{ENV["HOME"]}/foo"
16
+ assert_equal "maildir:#{ENV["HOME"]}/foo", uri.to_s
17
17
  end
18
18
  end
19
19
  end