rims 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/ChangeLog +379 -0
  4. data/Gemfile +11 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +566 -0
  7. data/Rakefile +29 -0
  8. data/bin/rims +11 -0
  9. data/lib/rims.rb +45 -0
  10. data/lib/rims/auth.rb +133 -0
  11. data/lib/rims/cksum_kvs.rb +68 -0
  12. data/lib/rims/cmd.rb +809 -0
  13. data/lib/rims/daemon.rb +338 -0
  14. data/lib/rims/db.rb +793 -0
  15. data/lib/rims/error.rb +23 -0
  16. data/lib/rims/gdbm_kvs.rb +76 -0
  17. data/lib/rims/hash_kvs.rb +66 -0
  18. data/lib/rims/kvs.rb +101 -0
  19. data/lib/rims/lock.rb +151 -0
  20. data/lib/rims/mail_store.rb +663 -0
  21. data/lib/rims/passwd.rb +251 -0
  22. data/lib/rims/pool.rb +88 -0
  23. data/lib/rims/protocol.rb +71 -0
  24. data/lib/rims/protocol/decoder.rb +1469 -0
  25. data/lib/rims/protocol/parser.rb +1114 -0
  26. data/lib/rims/rfc822.rb +456 -0
  27. data/lib/rims/server.rb +567 -0
  28. data/lib/rims/test.rb +391 -0
  29. data/lib/rims/version.rb +11 -0
  30. data/load_test/Rakefile +93 -0
  31. data/rims.gemspec +38 -0
  32. data/test/test_auth.rb +174 -0
  33. data/test/test_cksum_kvs.rb +121 -0
  34. data/test/test_config.rb +533 -0
  35. data/test/test_daemon_status_file.rb +169 -0
  36. data/test/test_daemon_waitpid.rb +72 -0
  37. data/test/test_db.rb +602 -0
  38. data/test/test_db_recovery.rb +732 -0
  39. data/test/test_error.rb +97 -0
  40. data/test/test_gdbm_kvs.rb +32 -0
  41. data/test/test_hash_kvs.rb +116 -0
  42. data/test/test_lock.rb +161 -0
  43. data/test/test_mail_store.rb +750 -0
  44. data/test/test_passwd.rb +203 -0
  45. data/test/test_protocol.rb +91 -0
  46. data/test/test_protocol_auth.rb +121 -0
  47. data/test/test_protocol_decoder.rb +6490 -0
  48. data/test/test_protocol_fetch.rb +994 -0
  49. data/test/test_protocol_request.rb +332 -0
  50. data/test/test_protocol_search.rb +974 -0
  51. data/test/test_rfc822.rb +696 -0
  52. metadata +174 -0
@@ -0,0 +1,696 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'pp' if $DEBUG
4
+ require 'rims'
5
+ require 'test/unit'
6
+
7
+ module RIMS::Test
8
+ class RFC822ParserTest < Test::Unit::TestCase
9
+ include AssertUtility
10
+
11
+ def test_split_message
12
+ msg =
13
+ "Content-Type: text/plain\r\n" +
14
+ "Subject: test\r\n" +
15
+ "\r\n" +
16
+ "HALO\r\n"
17
+ header_body_pair = RIMS::RFC822.split_message(msg.b)
18
+ assert_strenc_equal('ascii-8bit',
19
+ "Content-Type: text/plain\r\n" +
20
+ "Subject: test\r\n" +
21
+ "\r\n",
22
+ header_body_pair[0])
23
+ assert_strenc_equal('ascii-8bit',
24
+ "HALO\r\n",
25
+ header_body_pair[1])
26
+
27
+ msg =
28
+ "Content-Type: text/plain\n" +
29
+ "Subject: test\n" +
30
+ "\n" +
31
+ "HALO\n"
32
+ header_body_pair = RIMS::RFC822.split_message(msg.b)
33
+ assert_strenc_equal('ascii-8bit',
34
+ "Content-Type: text/plain\n" +
35
+ "Subject: test\n" +
36
+ "\n",
37
+ header_body_pair[0])
38
+ assert_strenc_equal('ascii-8bit',
39
+ "HALO\n",
40
+ header_body_pair[1])
41
+
42
+ msg =
43
+ "\n" +
44
+ "\r\n" +
45
+ " \t\n" +
46
+ "Content-Type: text/plain\r\n" +
47
+ "Subject: test\r\n" +
48
+ "\r\n" +
49
+ "HALO\r\n"
50
+ header_body_pair = RIMS::RFC822.split_message(msg.b)
51
+ assert_strenc_equal('ascii-8bit',
52
+ "Content-Type: text/plain\r\n" +
53
+ "Subject: test\r\n" +
54
+ "\r\n",
55
+ header_body_pair[0])
56
+ assert_strenc_equal('ascii-8bit',
57
+ "HALO\r\n",
58
+ header_body_pair[1])
59
+
60
+ msg =
61
+ "Content-Type: text/plain\r\n" +
62
+ "Subject: test\r\n" +
63
+ "\r\n"
64
+ header_body_pair = RIMS::RFC822.split_message(msg.b)
65
+ assert_strenc_equal('ascii-8bit',
66
+ "Content-Type: text/plain\r\n" +
67
+ "Subject: test\r\n" +
68
+ "\r\n",
69
+ header_body_pair[0])
70
+ assert_strenc_equal('ascii-8bit', '', header_body_pair[1])
71
+
72
+ msg =
73
+ "Content-Type: text/plain\r\n" +
74
+ "Subject: test\r\n"
75
+ header_body_pair = RIMS::RFC822.split_message(msg.b)
76
+ assert_strenc_equal('ascii-8bit',
77
+ "Content-Type: text/plain\r\n" +
78
+ "Subject: test\r\n",
79
+ header_body_pair[0])
80
+ assert_nil(header_body_pair[1])
81
+ end
82
+
83
+ def test_parse_header
84
+ assert_equal([], RIMS::RFC822.parse_header(''.b))
85
+
86
+ field_pair_list = RIMS::RFC822.parse_header("Content-Type: text/plain; charset=utf-8\r\n".b +
87
+ "Subject: This is a test\r\n".b +
88
+ "\r\n".b)
89
+ assert_equal(2, field_pair_list.length)
90
+ assert_strenc_equal('ascii-8bit', 'Content-Type', field_pair_list[0][0])
91
+ assert_strenc_equal('ascii-8bit', 'text/plain; charset=utf-8', field_pair_list[0][1])
92
+ assert_strenc_equal('ascii-8bit', 'Subject', field_pair_list[1][0])
93
+ assert_strenc_equal('ascii-8bit', 'This is a test', field_pair_list[1][1])
94
+
95
+ field_pair_list = RIMS::RFC822.parse_header("Content-Type: text/plain; charset=utf-8\r\n".b +
96
+ "Subject: This is a test\r\n".b)
97
+ assert_equal(2, field_pair_list.length)
98
+ assert_strenc_equal('ascii-8bit', 'Content-Type', field_pair_list[0][0])
99
+ assert_strenc_equal('ascii-8bit', 'text/plain; charset=utf-8', field_pair_list[0][1])
100
+ assert_strenc_equal('ascii-8bit', 'Subject', field_pair_list[1][0])
101
+ assert_strenc_equal('ascii-8bit', 'This is a test', field_pair_list[1][1])
102
+
103
+ field_pair_list = RIMS::RFC822.parse_header("Content-Type: text/plain; charset=utf-8\r\n".b +
104
+ "Subject: This is a test".b)
105
+ assert_equal(2, field_pair_list.length)
106
+ assert_strenc_equal('ascii-8bit', 'Content-Type', field_pair_list[0][0])
107
+ assert_strenc_equal('ascii-8bit', 'text/plain; charset=utf-8', field_pair_list[0][1])
108
+ assert_strenc_equal('ascii-8bit', 'Subject', field_pair_list[1][0])
109
+ assert_strenc_equal('ascii-8bit', 'This is a test', field_pair_list[1][1])
110
+
111
+ field_pair_list = RIMS::RFC822.parse_header("Content-Type:\r\n".b +
112
+ " text/plain;\r\n".b +
113
+ " charset=utf-8\r\n".b +
114
+ "Subject: This\n".b +
115
+ " is a test\r\n".b +
116
+ "\r\n".b)
117
+ assert_equal(2, field_pair_list.length)
118
+ assert_strenc_equal('ascii-8bit', 'Content-Type', field_pair_list[0][0])
119
+ assert_strenc_equal('ascii-8bit', "text/plain;\r\n charset=utf-8", field_pair_list[0][1])
120
+ assert_strenc_equal('ascii-8bit', 'Subject', field_pair_list[1][0])
121
+ assert_strenc_equal('ascii-8bit', "This\n is a test", field_pair_list[1][1])
122
+
123
+ field_pair_list = RIMS::RFC822.parse_header('foo'.b)
124
+ assert_equal(0, field_pair_list.length)
125
+
126
+ field_pair_list = RIMS::RFC822.parse_header('foo:bar:baz'.b)
127
+ assert_equal(1, field_pair_list.length)
128
+ assert_strenc_equal('ascii-8bit', 'foo', field_pair_list[0][0])
129
+ assert_strenc_equal('ascii-8bit', 'bar:baz', field_pair_list[0][1])
130
+ end
131
+
132
+ def test_parse_content_type
133
+ content_type = RIMS::RFC822.parse_content_type('text/plain'.b)
134
+ assert_equal([ 'text', 'plain', {} ], content_type)
135
+ assert(content_type[0..1].all?{|s| s.encoding == Encoding::ASCII_8BIT })
136
+
137
+ content_type = RIMS::RFC822.parse_content_type('text/plain; charset=utf-8'.b)
138
+ assert_equal([ 'text', 'plain', { 'charset' => %w[ charset utf-8 ] } ], content_type)
139
+ assert(content_type[0..1].all?{|s| s.encoding == Encoding::ASCII_8BIT })
140
+ assert(content_type[2].each_pair.to_a.flatten.all?{|s| s.encoding == Encoding::ASCII_8BIT })
141
+
142
+ content_type = RIMS::RFC822.parse_content_type('text/plain; CHARSET=UTF-8; Foo=apple; Bar="banana"'.b)
143
+ assert_equal([ 'text', 'plain',
144
+ { 'charset' => %w[ CHARSET UTF-8 ],
145
+ 'foo' => %w[ Foo apple ],
146
+ 'bar' => %w[ Bar banana ]
147
+ }
148
+ ], content_type)
149
+ assert(content_type[0..1].all?{|s| s.encoding == Encoding::ASCII_8BIT })
150
+ assert(content_type[2].each_pair.to_a.flatten.all?{|s| s.encoding == Encoding::ASCII_8BIT })
151
+
152
+ content_type = RIMS::RFC822.parse_content_type('text/plain;CHARSET=UTF-8;Foo=apple;Bar="banana"'.b)
153
+ assert_equal([ 'text', 'plain',
154
+ { 'charset' => %w[ CHARSET UTF-8 ],
155
+ 'foo' => %w[ Foo apple ],
156
+ 'bar' => %w[ Bar banana ]
157
+ }
158
+ ], content_type)
159
+ assert(content_type[0..1].all?{|s| s.encoding == Encoding::ASCII_8BIT })
160
+ assert(content_type[2].each_pair.to_a.flatten.all?{|s| s.encoding == Encoding::ASCII_8BIT })
161
+
162
+ content_type = RIMS::RFC822.parse_content_type('multipart/mixed; boundary=----=_Part_1459890_1462677911.1383882437398'.b)
163
+ assert_equal([ 'multipart', 'mixed',
164
+ { 'boundary' => %w[ boundary ----=_Part_1459890_1462677911.1383882437398 ] }
165
+ ], content_type)
166
+ assert(content_type[0..1].all?{|s| s.encoding == Encoding::ASCII_8BIT })
167
+ assert(content_type[2].each_pair.to_a.flatten.all?{|s| s.encoding == Encoding::ASCII_8BIT })
168
+
169
+ content_type = RIMS::RFC822.parse_content_type("multipart/alternative; \r\n boundary=\"----=_Part_1459891_982342968.1383882437398\"".b)
170
+ assert_equal([ 'multipart', 'alternative',
171
+ { 'boundary' => %w[ boundary ----=_Part_1459891_982342968.1383882437398 ] }
172
+ ], content_type)
173
+ assert(content_type[0..1].all?{|s| s.encoding == Encoding::ASCII_8BIT })
174
+ assert(content_type[2].each_pair.to_a.flatten.all?{|s| s.encoding == Encoding::ASCII_8BIT })
175
+
176
+ assert_equal([ 'application', 'octet-stream', {} ], RIMS::RFC822.parse_content_type(''))
177
+ end
178
+
179
+ def test_parse_multipart_body
180
+ body_txt = <<-'MULTIPART'.b
181
+ ------=_Part_1459890_1462677911.1383882437398
182
+ Content-Type: multipart/alternative;
183
+ boundary="----=_Part_1459891_982342968.1383882437398"
184
+
185
+ ------=_Part_1459891_982342968.1383882437398
186
+ Content-Type: text/plain; charset=UTF-8
187
+ Content-Transfer-Encoding: base64
188
+
189
+ Cgo9PT09PT09PT09CkFNQVpPTi5DTy5KUAo9PT09PT09PT09CkFtYXpvbi5jby5qcOOBp+WVhuWT
190
+ rpvjgavpgIHkv6HjgZXjgozjgb7jgZfjgZ86IHRva2lAZnJlZWRvbS5uZS5qcAoKCg==
191
+ ------=_Part_1459891_982342968.1383882437398
192
+ Content-Type: text/html; charset=UTF-8
193
+ Content-Transfer-Encoding: quoted-printable
194
+
195
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.=
196
+
197
+ ------=_Part_1459891_982342968.1383882437398--
198
+
199
+ ------=_Part_1459890_1462677911.1383882437398--
200
+ MULTIPART
201
+
202
+ part_list = RIMS::RFC822.parse_multipart_body('----=_Part_1459890_1462677911.1383882437398'.b, body_txt)
203
+ assert_equal(1, part_list.length)
204
+ assert_strenc_equal('ascii-8bit', <<-'PART', part_list[0])
205
+ Content-Type: multipart/alternative;
206
+ boundary="----=_Part_1459891_982342968.1383882437398"
207
+
208
+ ------=_Part_1459891_982342968.1383882437398
209
+ Content-Type: text/plain; charset=UTF-8
210
+ Content-Transfer-Encoding: base64
211
+
212
+ Cgo9PT09PT09PT09CkFNQVpPTi5DTy5KUAo9PT09PT09PT09CkFtYXpvbi5jby5qcOOBp+WVhuWT
213
+ rpvjgavpgIHkv6HjgZXjgozjgb7jgZfjgZ86IHRva2lAZnJlZWRvbS5uZS5qcAoKCg==
214
+ ------=_Part_1459891_982342968.1383882437398
215
+ Content-Type: text/html; charset=UTF-8
216
+ Content-Transfer-Encoding: quoted-printable
217
+
218
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.=
219
+
220
+ ------=_Part_1459891_982342968.1383882437398--
221
+ PART
222
+
223
+ header_txt, body_txt = RIMS::RFC822.split_message(part_list[0])
224
+ content_type_txt = RIMS::RFC822.parse_header(header_txt).find{|n, v| n == 'Content-Type' }[1]
225
+ boundary = RIMS::RFC822.parse_content_type(content_type_txt)[2]['boundary'][1]
226
+
227
+ part_list = RIMS::RFC822.parse_multipart_body(boundary, body_txt)
228
+ assert_equal(2, part_list.length)
229
+ assert_strenc_equal('ascii-8bit', <<-'PART1'.chomp, part_list[0])
230
+ Content-Type: text/plain; charset=UTF-8
231
+ Content-Transfer-Encoding: base64
232
+
233
+ Cgo9PT09PT09PT09CkFNQVpPTi5DTy5KUAo9PT09PT09PT09CkFtYXpvbi5jby5qcOOBp+WVhuWT
234
+ rpvjgavpgIHkv6HjgZXjgozjgb7jgZfjgZ86IHRva2lAZnJlZWRvbS5uZS5qcAoKCg==
235
+ PART1
236
+ assert_strenc_equal('ascii-8bit', <<-'PART2', part_list[1])
237
+ Content-Type: text/html; charset=UTF-8
238
+ Content-Transfer-Encoding: quoted-printable
239
+
240
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.=
241
+ PART2
242
+ end
243
+
244
+ def test_parse_multipart_body_bad_format
245
+ assert_equal(%w[ foo bar baz ], RIMS::RFC822.parse_multipart_body('sep', <<-EOF))
246
+ --sep
247
+ foo
248
+ --sep
249
+ bar
250
+ --sep
251
+ baz
252
+ EOF
253
+
254
+ assert_equal([], RIMS::RFC822.parse_multipart_body('sep', <<-EOF))
255
+ --sep--
256
+ EOF
257
+
258
+ assert_equal([], RIMS::RFC822.parse_multipart_body('sep', 'detarame'))
259
+ assert_equal([], RIMS::RFC822.parse_multipart_body('sep', ''))
260
+ end
261
+
262
+ def test_unquote_phrase_raw
263
+ assert_strenc_equal('ascii-8bit', '', RIMS::RFC822.unquote_phrase(''.b))
264
+ assert_strenc_equal('ascii-8bit', 'Hello world.', RIMS::RFC822.unquote_phrase('Hello world.'.b))
265
+ assert_strenc_equal('ascii-8bit', "\" ( ) \\", RIMS::RFC822.unquote_phrase("\\\" \\( \\) \\\\".b))
266
+ end
267
+
268
+ def test_unquote_phrase_quote
269
+ assert_strenc_equal('ascii-8bit', '', RIMS::RFC822.unquote_phrase('""'.b))
270
+ assert_strenc_equal('ascii-8bit', 'Hello world.', RIMS::RFC822.unquote_phrase('"Hello world."'.b))
271
+ assert_strenc_equal('ascii-8bit', 'foo "bar" baz', RIMS::RFC822.unquote_phrase("\"foo \\\"bar\\\" baz\"".b))
272
+ assert_strenc_equal('ascii-8bit', 'foo (bar) baz', RIMS::RFC822.unquote_phrase('"foo (bar) baz"'.b))
273
+ end
274
+
275
+ def test_unquote_phrase_comment
276
+ assert_strenc_equal('ascii-8bit', '', RIMS::RFC822.unquote_phrase('()'.b))
277
+ assert_strenc_equal('ascii-8bit', '', RIMS::RFC822.unquote_phrase('(Hello world.)'.b))
278
+ assert_strenc_equal('ascii-8bit', '', RIMS::RFC822.unquote_phrase("( \" \\( \\) \\\\ )".b))
279
+ end
280
+
281
+ def test_unquote_phrase_abnormal_patterns
282
+ assert_strenc_equal('ascii-8bit', '', RIMS::RFC822.unquote_phrase("\\".b))
283
+ assert_strenc_equal('ascii-8bit', 'foo', RIMS::RFC822.unquote_phrase('"foo'.b))
284
+ assert_strenc_equal('ascii-8bit', 'foo', RIMS::RFC822.unquote_phrase(%Q'"foo\\'.b))
285
+ assert_strenc_equal('ascii-8bit', '', RIMS::RFC822.unquote_phrase('(foo'.b))
286
+ assert_strenc_equal('ascii-8bit', '', RIMS::RFC822.unquote_phrase("(foo\\".b))
287
+ end
288
+
289
+ def test_parse_mail_address_list_addr_spec
290
+ assert_equal([], RIMS::RFC822.parse_mail_address_list(''.b))
291
+ assert_equal([ [ nil, nil, 'toki', 'freedom.ne.jp' ] ],
292
+ RIMS::RFC822.parse_mail_address_list('toki@freedom.ne.jp'.b))
293
+ assert_equal([ [ nil, nil, 'toki', 'freedom.ne.jp' ] ],
294
+ RIMS::RFC822.parse_mail_address_list(' toki@freedom.ne.jp '.b))
295
+ end
296
+
297
+ def test_parse_mail_address_list_name_addr
298
+ assert_equal([ [ 'TOKI Yoshinori', nil, 'toki', 'freedom.ne.jp' ] ],
299
+ RIMS::RFC822.parse_mail_address_list('TOKI Yoshinori <toki@freedom.ne.jp>'.b))
300
+ assert_equal([ [ 'TOKI Yoshinori', nil, 'toki', 'freedom.ne.jp' ] ],
301
+ RIMS::RFC822.parse_mail_address_list('"TOKI Yoshinori" <toki@freedom.ne.jp>'.b))
302
+ assert_equal([ [ 'TOKI Yoshinori', nil, 'toki', 'freedom.ne.jp' ] ],
303
+ RIMS::RFC822.parse_mail_address_list('TOKI(土岐) Yoshinori <toki@freedom.ne.jp>'.b))
304
+ assert_equal([ [ 'TOKI,Yoshinori', nil, 'toki', 'freedom.ne.jp' ] ],
305
+ RIMS::RFC822.parse_mail_address_list('TOKI\,Yoshinori <toki@freedom.ne.jp>'.b))
306
+ assert_equal([ [ 'toki@freedom.ne.jp', nil, 'toki', 'freedom.ne.jp' ] ],
307
+ RIMS::RFC822.parse_mail_address_list('"toki@freedom.ne.jp" <toki@freedom.ne.jp>'.b))
308
+ end
309
+
310
+ def test_parse_mail_address_list_route_addr
311
+ assert_equal([ [ 'TOKI Yoshinori', '@mail.freedom.ne.jp,@smtp.gmail.com', 'toki', 'freedom.ne.jp' ] ],
312
+ RIMS::RFC822.parse_mail_address_list('TOKI Yoshinori <@mail.freedom.ne.jp,@smtp.gmail.com:toki@freedom.ne.jp>'.b))
313
+ end
314
+
315
+ def test_parse_mail_address_list_group
316
+ assert_equal([ [ nil, nil, 'toki', nil ],
317
+ [ nil, nil, 'toki', 'freedom.ne.jp' ],
318
+ [ 'TOKI Yoshinori', nil, 'toki', 'freedom.ne.jp' ],
319
+ [ 'TOKI Yoshinori', '@mail.freedom.ne.jp,@smtp.gmail.com', 'toki', 'freedom.ne.jp' ],
320
+ [ nil, nil, nil, nil ]
321
+ ],
322
+ RIMS::RFC822.parse_mail_address_list('toki: ' +
323
+ 'toki@freedom.ne.jp, ' +
324
+ 'TOKI Yoshinori <toki@freedom.ne.jp>, ' +
325
+ 'TOKI Yoshinori <@mail.freedom.ne.jp,@smtp.gmail.com:toki@freedom.ne.jp>' +
326
+ ';'.b))
327
+ end
328
+
329
+ def test_parse_mail_address_list_multiline
330
+ assert_equal([ [ nil, nil, 'toki', 'freedom.ne.jp' ],
331
+ [ 'TOKI Yoshinori', nil, 'toki', 'freedom.ne.jp' ],
332
+ [ 'Yoshinori Toki', nil, 'toki', 'freedom.ne.jp' ]
333
+ ],
334
+ RIMS::RFC822.parse_mail_address_list("toki@freedom.ne.jp,\n" +
335
+ " TOKI Yoshinori <toki@freedom.ne.jp>\n" +
336
+ " , Yoshinori Toki <toki@freedom.ne.jp> "))
337
+ end
338
+ end
339
+
340
+ class RFC822HeaderText < Test::Unit::TestCase
341
+ def setup
342
+ @header = RIMS::RFC822::Header.new("foo: apple\r\n" +
343
+ "bar: Bob\r\n" +
344
+ "Foo: banana\r\n" +
345
+ "FOO: orange\r\n" +
346
+ "\r\n")
347
+ pp @header if $DEBUG
348
+ end
349
+
350
+ def teardown
351
+ pp @header if $DEBUG
352
+ end
353
+
354
+ def test_each
355
+ assert_equal([ %w[ foo apple ], %w[ bar Bob ], %w[ Foo banana ], %w[ FOO orange ] ],
356
+ @header.each.to_a)
357
+ end
358
+
359
+ def test_key?
360
+ assert_equal(true, (@header.key? 'foo'))
361
+ assert_equal(true, (@header.key? 'Foo'))
362
+ assert_equal(true, (@header.key? 'FOO'))
363
+
364
+ assert_equal(true, (@header.key? 'bar'))
365
+ assert_equal(true, (@header.key? 'Bar'))
366
+ assert_equal(true, (@header.key? 'BAR'))
367
+
368
+ assert_equal(false, (@header.key? 'baz'))
369
+ assert_equal(false, (@header.key? 'Baz'))
370
+ assert_equal(false, (@header.key? 'BAZ'))
371
+ end
372
+
373
+ def test_fetch
374
+ assert_equal('apple', @header['foo'])
375
+ assert_equal('apple', @header['Foo'])
376
+ assert_equal('apple', @header['FOO'])
377
+
378
+ assert_equal('Bob', @header['bar'])
379
+ assert_equal('Bob', @header['Bar'])
380
+ assert_equal('Bob', @header['BAR'])
381
+
382
+ assert_nil(@header['baz'])
383
+ assert_nil(@header['Baz'])
384
+ assert_nil(@header['BAZ'])
385
+ end
386
+
387
+ def test_fetch_upcase
388
+ assert_equal('APPLE', @header.fetch_upcase('foo'))
389
+ assert_equal('APPLE', @header.fetch_upcase('Foo'))
390
+ assert_equal('APPLE', @header.fetch_upcase('FOO'))
391
+
392
+ assert_equal('BOB', @header.fetch_upcase('bar'))
393
+ assert_equal('BOB', @header.fetch_upcase('Bar'))
394
+ assert_equal('BOB', @header.fetch_upcase('BAR'))
395
+
396
+ assert_nil(@header.fetch_upcase('baz'))
397
+ assert_nil(@header.fetch_upcase('Baz'))
398
+ assert_nil(@header.fetch_upcase('BAZ'))
399
+ end
400
+
401
+ def test_field_value_list
402
+ assert_equal(%w[ apple banana orange ], @header.field_value_list('foo'))
403
+ assert_equal(%w[ apple banana orange ], @header.field_value_list('Foo'))
404
+ assert_equal(%w[ apple banana orange ], @header.field_value_list('FOO'))
405
+
406
+ assert_equal(%w[ Bob ], @header.field_value_list('bar'))
407
+ assert_equal(%w[ Bob ], @header.field_value_list('Bar'))
408
+ assert_equal(%w[ Bob ], @header.field_value_list('BAR'))
409
+
410
+ assert_nil(@header.field_value_list('baz'))
411
+ assert_nil(@header.field_value_list('Baz'))
412
+ assert_nil(@header.field_value_list('BAZ'))
413
+ end
414
+ end
415
+
416
+ class RFC822MessageTest < Test::Unit::TestCase
417
+ def setup_message(headers={},
418
+ content_type: 'text/plain; charset=utf-8',
419
+ body: "Hello world.\r\n")
420
+ @msg = RIMS::RFC822::Message.new(headers.map{|n, v| "#{n}: #{v}\r\n" }.join('') +
421
+ "Content-Type: #{content_type}\r\n" +
422
+ "Subject: test\r\n" +
423
+ "\r\n" +
424
+ body)
425
+ pp @msg if $DEBUG
426
+ end
427
+
428
+ def teardown
429
+ pp @msg if $DEBUG
430
+ end
431
+
432
+ def test_header
433
+ setup_message
434
+ assert_equal("Content-Type: text/plain; charset=utf-8\r\n" +
435
+ "Subject: test\r\n" +
436
+ "\r\n",
437
+ @msg.header.raw_source)
438
+ end
439
+
440
+ def test_body
441
+ setup_message
442
+ assert_equal("Hello world.\r\n", @msg.body.raw_source)
443
+ end
444
+
445
+ def test_media_main_type
446
+ setup_message
447
+ assert_equal('text', @msg.media_main_type)
448
+ assert_equal('TEXT', @msg.media_main_type_upcase)
449
+ end
450
+
451
+ def test_media_sub_type
452
+ setup_message
453
+ assert_equal('plain', @msg.media_sub_type)
454
+ assert_equal('PLAIN', @msg.media_sub_type_upcase)
455
+ end
456
+
457
+ def test_content_type
458
+ setup_message
459
+ assert_equal('text/plain', @msg.content_type)
460
+ assert_equal('TEXT/PLAIN', @msg.content_type_upcase)
461
+ end
462
+
463
+ def test_content_type_parameters
464
+ setup_message(content_type: 'text/plain; charset=utf-8; foo=apple; Bar=Banana')
465
+ assert_equal([ %w[ charset utf-8 ], %w[ foo apple ], %w[ Bar Banana ] ], @msg.content_type_parameters)
466
+ end
467
+
468
+ def test_charset
469
+ setup_message
470
+ assert_equal('utf-8', @msg.charset)
471
+ end
472
+
473
+ def test_charset_no_value
474
+ setup_message(content_type: 'text/plain')
475
+ assert_nil(@msg.charset)
476
+ end
477
+
478
+ def test_boundary
479
+ setup_message(content_type: "multipart/alternative; \r\n boundary=\"----=_Part_1459891_982342968.1383882437398\"")
480
+ assert_equal('----=_Part_1459891_982342968.1383882437398', @msg.boundary)
481
+ end
482
+
483
+ def test_boundary_no_value
484
+ setup_message
485
+ assert_nil(@msg.boundary)
486
+ end
487
+
488
+ def test_text?
489
+ setup_message
490
+ assert_equal(true, @msg.text?)
491
+ end
492
+
493
+ def test_not_text?
494
+ setup_message(content_type: 'application/octet-stream')
495
+ assert_equal(false, @msg.text?)
496
+ end
497
+
498
+ def test_multipart?
499
+ setup_message(content_type: 'multipart/mixed')
500
+ assert_equal(true, @msg.multipart?)
501
+ end
502
+
503
+ def test_not_multipart?
504
+ setup_message
505
+ assert_equal(false, @msg.multipart?)
506
+ end
507
+
508
+ def test_parts
509
+ setup_message(content_type: 'multipart/mixed; boundary="----=_Part_1459890_1462677911.1383882437398"', body: <<-'EOF')
510
+ ------=_Part_1459890_1462677911.1383882437398
511
+ Content-Type: multipart/alternative;
512
+ boundary="----=_Part_1459891_982342968.1383882437398"
513
+
514
+ ------=_Part_1459891_982342968.1383882437398
515
+ Content-Type: text/plain; charset=UTF-8
516
+ Content-Transfer-Encoding: base64
517
+
518
+ Cgo9PT09PT09PT09CkFNQVpPTi5DTy5KUAo9PT09PT09PT09CkFtYXpvbi5jby5qcOOBp+WVhuWT
519
+ rpvjgavpgIHkv6HjgZXjgozjgb7jgZfjgZ86IHRva2lAZnJlZWRvbS5uZS5qcAoKCg==
520
+ ------=_Part_1459891_982342968.1383882437398
521
+ Content-Type: text/html; charset=UTF-8
522
+ Content-Transfer-Encoding: quoted-printable
523
+
524
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.=
525
+
526
+ ------=_Part_1459891_982342968.1383882437398--
527
+
528
+ ------=_Part_1459890_1462677911.1383882437398--
529
+ EOF
530
+
531
+ assert_equal(1, @msg.parts.length)
532
+ assert_equal(<<-'EOF', @msg.parts[0].raw_source)
533
+ Content-Type: multipart/alternative;
534
+ boundary="----=_Part_1459891_982342968.1383882437398"
535
+
536
+ ------=_Part_1459891_982342968.1383882437398
537
+ Content-Type: text/plain; charset=UTF-8
538
+ Content-Transfer-Encoding: base64
539
+
540
+ Cgo9PT09PT09PT09CkFNQVpPTi5DTy5KUAo9PT09PT09PT09CkFtYXpvbi5jby5qcOOBp+WVhuWT
541
+ rpvjgavpgIHkv6HjgZXjgozjgb7jgZfjgZ86IHRva2lAZnJlZWRvbS5uZS5qcAoKCg==
542
+ ------=_Part_1459891_982342968.1383882437398
543
+ Content-Type: text/html; charset=UTF-8
544
+ Content-Transfer-Encoding: quoted-printable
545
+
546
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.=
547
+
548
+ ------=_Part_1459891_982342968.1383882437398--
549
+ EOF
550
+
551
+ assert_equal(2, @msg.parts[0].parts.length)
552
+ assert_equal(<<-'EOF'.chomp, @msg.parts[0].parts[0].raw_source)
553
+ Content-Type: text/plain; charset=UTF-8
554
+ Content-Transfer-Encoding: base64
555
+
556
+ Cgo9PT09PT09PT09CkFNQVpPTi5DTy5KUAo9PT09PT09PT09CkFtYXpvbi5jby5qcOOBp+WVhuWT
557
+ rpvjgavpgIHkv6HjgZXjgozjgb7jgZfjgZ86IHRva2lAZnJlZWRvbS5uZS5qcAoKCg==
558
+ EOF
559
+ assert_equal(<<-'EOF', @msg.parts[0].parts[1].raw_source)
560
+ Content-Type: text/html; charset=UTF-8
561
+ Content-Transfer-Encoding: quoted-printable
562
+
563
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.=
564
+ EOF
565
+ end
566
+
567
+ def test_parts_not_multipart
568
+ setup_message
569
+ assert_nil(@msg.parts)
570
+ end
571
+
572
+ def test_parts_no_boundary
573
+ setup_message(content_type: 'multipart/mixed')
574
+ assert_equal([], @msg.parts)
575
+ end
576
+
577
+ def test_message?
578
+ setup_message(content_type: 'message/rfc822')
579
+ assert_equal(true, @msg.message?)
580
+ end
581
+
582
+ def test_not_message?
583
+ setup_message
584
+ assert_equal(false, @msg.message?)
585
+ end
586
+
587
+ def test_message
588
+ setup_message(content_type: 'message/rfc822', body: <<-'EOF')
589
+ To: bar@nonet.com
590
+ From: foo@nonet.com
591
+ Subject: inner multipart
592
+ MIME-Version: 1.0
593
+ Date: Fri, 8 Nov 2013 19:31:03 +0900
594
+ Content-Type: multipart/mixed; boundary="1383.905529.351298"
595
+
596
+ --1383.905529.351298
597
+ Content-Type: text/plain; charset=us-ascii
598
+
599
+ Hello world.
600
+ --1383.905529.351298
601
+ Content-Type: application/octet-stream
602
+
603
+ 9876543210
604
+ --1383.905529.351298--
605
+ EOF
606
+
607
+ assert_equal(<<-'EOF', @msg.message.raw_source)
608
+ To: bar@nonet.com
609
+ From: foo@nonet.com
610
+ Subject: inner multipart
611
+ MIME-Version: 1.0
612
+ Date: Fri, 8 Nov 2013 19:31:03 +0900
613
+ Content-Type: multipart/mixed; boundary="1383.905529.351298"
614
+
615
+ --1383.905529.351298
616
+ Content-Type: text/plain; charset=us-ascii
617
+
618
+ Hello world.
619
+ --1383.905529.351298
620
+ Content-Type: application/octet-stream
621
+
622
+ 9876543210
623
+ --1383.905529.351298--
624
+ EOF
625
+ assert_equal(true, @msg.message.multipart?)
626
+ assert_equal(2, @msg.message.parts.length)
627
+ assert_equal('text/plain', @msg.message.parts[0].content_type)
628
+ assert_equal('us-ascii', @msg.message.parts[0].charset)
629
+ assert_equal('Hello world.', @msg.message.parts[0].body.raw_source)
630
+ assert_equal('application/octet-stream', @msg.message.parts[1].content_type)
631
+ assert_equal('9876543210', @msg.message.parts[1].body.raw_source)
632
+ end
633
+
634
+ def test_message_no_msg
635
+ setup_message
636
+ assert_nil(@msg.message)
637
+ end
638
+
639
+ def test_date
640
+ setup_message('Date' => 'Fri, 8 Nov 2013 03:47:17 +0000')
641
+ assert_equal(Time.utc(2013, 11, 8, 3, 47, 17), @msg.date)
642
+ end
643
+
644
+ def test_date_no_value
645
+ setup_message
646
+ assert_nil(@msg.date)
647
+ end
648
+
649
+ def test_date_bad_format
650
+ setup_message('Date' => 'no_date')
651
+ assert_equal(Time.at(0), @msg.date)
652
+ end
653
+
654
+ def test_mail_address_header_field
655
+ setup_message('From' => 'Foo <foo@mail.example.com>',
656
+ 'Sender' => 'Bar <bar@mail.example.com>',
657
+ 'Reply-To' => 'Baz <baz@mail.example.com>',
658
+ 'To' => 'Alice <alice@mail.example.com>',
659
+ 'Cc' => 'Bob <bob@mail.example.com>',
660
+ 'Bcc' => 'Kate <kate@mail.example.com>')
661
+
662
+ assert_equal([ [ 'Foo', nil, 'foo', 'mail.example.com' ] ], @msg.from)
663
+ assert_equal([ [ 'Bar', nil, 'bar', 'mail.example.com' ] ], @msg.sender)
664
+ assert_equal([ [ 'Baz', nil, 'baz', 'mail.example.com' ] ], @msg.reply_to)
665
+ assert_equal([ [ 'Alice', nil, 'alice', 'mail.example.com' ] ], @msg.to)
666
+ assert_equal([ [ 'Bob', nil, 'bob', 'mail.example.com' ] ], @msg.cc)
667
+ assert_equal([ [ 'Kate', nil, 'kate', 'mail.example.com' ] ], @msg.bcc)
668
+ end
669
+
670
+ def test_mail_address_header_field_multi_header_field
671
+ setup_message([ [ 'From', 'Foo <foo@mail.example.com>, Bar <bar@mail.example.com>' ],
672
+ [ 'from', 'Baz <baz@mail.example.com>' ]
673
+ ])
674
+ assert_equal([ [ 'Foo', nil, 'foo', 'mail.example.com' ],
675
+ [ 'Bar', nil, 'bar', 'mail.example.com' ],
676
+ [ 'Baz', nil, 'baz', 'mail.example.com' ]
677
+ ],
678
+ @msg.from)
679
+ end
680
+
681
+ def test_mail_address_header_field_no_value
682
+ setup_message
683
+ assert_nil(@msg.from)
684
+ end
685
+
686
+ def test_mail_address_header_field_bad_format
687
+ setup_message('From' => 'no_mail_address')
688
+ assert_equal([], @msg.from)
689
+ end
690
+ end
691
+ end
692
+
693
+ # Local Variables:
694
+ # mode: Ruby
695
+ # indent-tabs-mode: nil
696
+ # End: