rims 0.2.6 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -38,8 +38,7 @@ module RIMS
38
38
  module_function :message_data_list
39
39
 
40
40
  def make_body(description)
41
- reader = RIMS::Protocol::RequestReader.new(StringIO.new('', 'r'), StringIO.new('', 'w'), Logger.new(STDOUT))
42
- reader.parse(reader.scan_line(description))[0]
41
+ RIMS::Protocol::RequestReader.parse(RIMS::Protocol::RequestReader.scan(description))[0]
43
42
  end
44
43
  private :make_body
45
44
 
@@ -68,29 +67,30 @@ module RIMS
68
67
  end
69
68
 
70
69
  module ProtocolFetchMailSample
71
- def make_mail_simple
72
- @simple_mail_body = <<-'EOF'
70
+ simple_mail_body = <<-'EOF'.freeze
73
71
  Hello world.
74
- EOF
72
+ EOF
75
73
 
76
- md5_digest = Digest::MD5.digest(@simple_mail_body)
77
- @simple_mail = RIMS::RFC822::Message.new(<<-"EOF" + @simple_mail_body)
74
+ MAIL_SIMPLE_TEXT = (<<-"EOF" + simple_mail_body).freeze
78
75
  To: foo@nonet.org
79
76
  From: bar@nonet.org
80
77
  Subject: test
81
78
  MIME-Version: 1.0
82
79
  Content-Type: text/plain; charset=us-ascii
83
80
  Content-Transfer-Encoding: 7bit
84
- Content-MD5: #{[ md5_digest ].pack('m').strip}
81
+ Content-MD5: #{[ Digest::MD5.digest(simple_mail_body) ].pack('m').strip}
85
82
  Content-Language: en-US, en
86
83
  Date: Fri, 8 Nov 2013 06:47:50 +0900 (JST)
87
84
 
88
- EOF
85
+ EOF
86
+
87
+ def make_mail_simple
88
+ @simple_mail = RIMS::RFC822::Message.new(MAIL_SIMPLE_TEXT)
89
+ @simple_mail_body = @simple_mail.body.raw_source
89
90
  end
90
91
  private :make_mail_simple
91
92
 
92
- def make_mail_multipart
93
- @mpart_mail = RIMS::RFC822::Message.new(<<-'EOF')
93
+ MPART_MAIL_TEXT = <<-'EOF'.freeze
94
94
  To: bar@nonet.com
95
95
  From: foo@nonet.com
96
96
  Subject: multipart test
@@ -173,12 +173,14 @@ Content-Location: baz
173
173
  --1383.905529.351300--
174
174
  --1383.905529.351299--
175
175
  --1383.905529.351297--
176
- EOF
176
+ EOF
177
+
178
+ def make_mail_multipart
179
+ @mpart_mail = RIMS::RFC822::Message.new(MPART_MAIL_TEXT)
177
180
  end
178
181
  private :make_mail_multipart
179
182
 
180
- def make_mail_mime_subject
181
- @mime_subject_mail = RIMS::RFC822::Message.new(<<-'EOF')
183
+ MAIL_MIME_SUBJECT_TEXT = <<-'EOF'.freeze
182
184
  Date: Fri, 8 Nov 2013 19:31:03 +0900
183
185
  Subject: =?ISO-2022-JP?B?GyRCJEYkOSRIGyhC?=
184
186
  From: foo@nonet.com, bar <bar@nonet.com>
@@ -194,22 +196,28 @@ In-Reply-To: <20131106081723.5KJU1774292@smtp.test.com>
194
196
  Message-Id: <20131107214750.445A1255B9F@smtp.nonet.com>
195
197
 
196
198
  Hello world.
197
- EOF
199
+ EOF
200
+
201
+ def make_mail_mime_subject
202
+ @mime_subject_mail = RIMS::RFC822::Message.new(MAIL_MIME_SUBJECT_TEXT)
198
203
  end
199
204
  private :make_mail_mime_subject
200
205
 
206
+ MAIL_EMPTY_TEXT = ''.freeze
207
+
201
208
  def make_mail_empty
202
- @empty_mail = RIMS::RFC822::Message.new('')
209
+ @empty_mail = RIMS::RFC822::Message.new(MAIL_EMPTY_TEXT)
203
210
  end
204
211
  private :make_mail_empty
205
212
 
213
+ MAIL_NO_BODY_TEXT = "Subject: foo\r\n\r\n".freeze
214
+
206
215
  def make_mail_no_body
207
- @no_body_mail = RIMS::RFC822::Message.new("Subject: foo\r\n\r\n")
216
+ @no_body_mail = RIMS::RFC822::Message.new(MAIL_NO_BODY_TEXT)
208
217
  end
209
218
  private :make_mail_no_body
210
219
 
211
- def make_mail_address_header_pattern
212
- @address_header_pattern_mail = RIMS::RFC822::Message.new(<<-'EOF')
220
+ MAIL_ADDRESS_HEADER_PATTERN_TEXT = <<-'EOF'.freeze
213
221
  To: "foo@nonet.org" <foo@nonet.org>
214
222
  From: bar@nonet.org
215
223
  Subject: test
@@ -219,7 +227,10 @@ Content-Transfer-Encoding: 7bit
219
227
  Date: Fri, 8 Nov 2013 06:47:50 +0900 (JST)
220
228
 
221
229
  Hello world.
222
- EOF
230
+ EOF
231
+
232
+ def make_mail_address_header_pattern
233
+ @address_header_pattern_mail = RIMS::RFC822::Message.new(MAIL_ADDRESS_HEADER_PATTERN_TEXT)
223
234
  end
224
235
  private :make_mail_address_header_pattern
225
236
  end
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  module RIMS
4
- VERSION = '0.2.6'
4
+ VERSION = '0.3.1'
5
5
  MAILBOX_DATA_STRUCTURE_VERSION = 'mailbox.2'
6
6
  end
7
7
 
@@ -78,6 +78,8 @@ task :imap_append do
78
78
  end
79
79
  end
80
80
 
81
+ CLOBBER.include('imap_append')
82
+
81
83
  desc 'run server'
82
84
  task :run_server do
83
85
  run_server_conf('imap_server', USER_CONF, *%w[ -v debug -l debug --imap-host=localhost --imap-port=14300 ]) do
@@ -85,7 +87,7 @@ task :run_server do
85
87
  end
86
88
  end
87
89
 
88
- CLOBBER.include('imap_append')
90
+ CLOBBER.include('imap_server')
89
91
 
90
92
  # Local Variables:
91
93
  # mode: Ruby
@@ -5,10 +5,10 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require 'rims/version'
6
6
 
7
7
  Gem::Specification.new do |spec|
8
- spec.name = "rims"
8
+ spec.name = 'rims'
9
9
  spec.version = RIMS::VERSION
10
- spec.authors = ["TOKI Yoshinori"]
11
- spec.email = ["toki@freedom.ne.jp"]
10
+ spec.authors = ['TOKI Yoshinori']
11
+ spec.email = ['toki@freedom.ne.jp']
12
12
  spec.summary = %q{RIMS is Ruby IMap Server}
13
13
  spec.description = <<-'EOF'
14
14
  RIMS is Ruby IMap Server.
@@ -16,23 +16,24 @@ Gem::Specification.new do |spec|
16
16
  server can run as a daemon, mailboxes are provided and messages
17
17
  can be delivered to them.
18
18
  EOF
19
- spec.homepage = "https://github.com/y10k/rims"
20
- spec.license = "MIT"
19
+ spec.homepage = 'https://github.com/y10k/rims'
20
+ spec.license = 'MIT'
21
21
 
22
22
  spec.files = `git ls-files`.split($/)
23
23
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
24
24
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
25
- spec.require_paths = ["lib"]
25
+ spec.require_paths = ['lib']
26
26
 
27
27
  spec.required_ruby_version = '>= 2.0.0'
28
28
 
29
- spec.add_runtime_dependency "rims-rfc822", '>= 0.2.0'
30
- spec.add_runtime_dependency "riser", '>= 0.1.8'
31
- spec.add_runtime_dependency "logger-joint"
32
- spec.add_development_dependency "bundler"
33
- spec.add_development_dependency "rake"
34
- spec.add_development_dependency "test-unit"
35
- spec.add_development_dependency "rdoc"
29
+ spec.add_runtime_dependency 'rims-rfc822', '>= 0.2.2'
30
+ spec.add_runtime_dependency 'riser', '>= 0.2.0'
31
+ spec.add_runtime_dependency 'logger-joint'
32
+ spec.add_development_dependency 'bundler'
33
+ spec.add_development_dependency 'rake'
34
+ spec.add_development_dependency 'test-unit'
35
+ spec.add_development_dependency 'rdoc'
36
+ spec.add_development_dependency 'irb'
36
37
  end
37
38
 
38
39
  # Local Variables:
@@ -119,6 +119,7 @@ module RIMS::Test
119
119
  '--no-daemonize' => [ %W[ -f #{BASE_DIR}/config.yml --no-daemonize ] ],
120
120
  '--daemon-debug' => [ %W[ -f #{BASE_DIR}/config.yml --daemon-debug ] ],
121
121
  '--no-daemon-debug' => [ %W[ -f #{BASE_DIR}/config.yml --no-daemon-debug ] ],
122
+ '--daemon-umask' => [ %W[ -f #{BASE_DIR}/config.yml --daemon-umask=0022 ] ],
122
123
  '--status-file' => [ %W[ -f #{BASE_DIR}/config.yml --status-file=status.yml ] ],
123
124
  '--privilege-user' => [ %W[ -f #{BASE_DIR}/config.yml --privilege-user=#{Process::UID.eid} ] ],
124
125
  '--privilege-group' => [ %W[ -f #{BASE_DIR}/config.yml --privilege-group=#{Process::GID.eid} ] ],
@@ -140,11 +141,30 @@ module RIMS::Test
140
141
  '--read-polling-interval' => [ %W[ -f #{BASE_DIR}/config.yml --read-polling-interval=5 ] ],
141
142
  '--command-wait-timeout' => [ %W[ -f #{BASE_DIR}/config.yml --command-wait-timeout=3600 ] ],
142
143
 
144
+ # protocol:
145
+ '--line-length-limit' => [ %W[ -f #{BASE_DIR}/config.yml --line-length-limit=16384 ] ],
146
+ '--literal-size-limit' => [ %W[ -f #{BASE_DIR}/config.yml --literal-size-limit=16777216 ] ],
147
+ '--command-size-limit' => [ %W[ -f #{BASE_DIR}/config.yml --command-size-limit=16777216 ] ],
148
+
149
+ # charset aliases:
150
+ '--use-default-charset-aliases' => [ %W[ -f #{BASE_DIR}/config.yml --use-default-charset-aliases ] ],
151
+ '--no-use-default-charset-aliases' => [ %W[ -f #{BASE_DIR}/config.yml --no-use-default-charset-aliases ] ],
152
+ '--add-charset-alias' => [ %W[ -f #{BASE_DIR}/config.yml --no-use-default-charset-aliases --add-charset-alias=iso-2022-jp,CP50221 ] ],
153
+
154
+ # charset convert_options:
155
+ '--replace-charset-invalid' => [ %W[ -f #{BASE_DIR}/config.yml --replace-charset-invalid ] ],
156
+ '--no-replace-charset-invalid' => [ %W[ -f #{BASE_DIR}/config.yml --no-replace-charset-invalid ] ],
157
+ '--replace-charset-undef' => [ %W[ -f #{BASE_DIR}/config.yml --replace-charset-undef ] ],
158
+ '--no-replace-charset-undef' => [ %W[ -f #{BASE_DIR}/config.yml --no-replace-charset-undef ] ],
159
+ '--charset-replaced-mark' => [ %W[ -f #{BASE_DIR}/config.yml --charset-replaced-mark=? ] ],
160
+
143
161
  # drb_services:
144
162
  '--drb-process-num' => [ %W[ -f #{BASE_DIR}/config.yml --drb-process-num=4 ] ],
163
+ '--drb-load-limit' => [ %W[ -f #{BASE_DIR}/config.yml --drb-load-limit=134217728 ] ],
145
164
 
146
165
  # drb_services engine:
147
166
  '--bulk-response-count' => [ %W[ -f #{BASE_DIR}/config.yml --bulk-response-count=128 ] ],
167
+ '--bulk-response-size' => [ %W[ -f #{BASE_DIR}/config.yml --bulk-response-size=33554432 ] ],
148
168
  '--read-lock-timeout' => [ %W[ -f #{BASE_DIR}/config.yml --read-lock-timeout=10 ] ],
149
169
  '--write-lock-timeout' => [ %W[ -f #{BASE_DIR}/config.yml --write-lock-timeout=10 ] ],
150
170
  '--clenup-write-lock-timeout' => [ %W[ -f #{BASE_DIR}/config.yml --write-lock-timeout=5 ] ],
@@ -1232,7 +1252,7 @@ Hello world.
1232
1252
  assert_equal(seqno[1], imap_search.call([ 'ANSWERED' ])) # *a
1233
1253
  assert_equal(seqno[3], imap_search.call([ 'BCC', 'foo' ])) # *b
1234
1254
  assert_equal(seqno[1], imap_search.call([ 'BEFORE', @mpart_mail.date ]))
1235
- assert_equal(seqno[1, 3], imap_search.call([ 'BODY', 'Hello world.' ]))
1255
+ assert_equal(seqno[1, 2, 3], imap_search.call([ 'BODY', 'Hello world.' ]))
1236
1256
  assert_equal(seqno[3], imap_search.call([ 'CC', 'kate' ]))
1237
1257
  assert_equal(seqno[], imap_search.call([ 'DELETED' ]))
1238
1258
  assert_equal(seqno[2], imap_search.call([ 'DRAFT' ]))
@@ -55,7 +55,8 @@ module RIMS::Test
55
55
  pub1.publish('msg1')
56
56
  pub2.publish('msg2')
57
57
 
58
- error = assert_raise(RuntimeError) { pub3.publish('msg3') }
58
+ error = assert_raise(RIMS::ServerResponseChannelPublishError) { pub3.publish('msg3') }
59
+ pp error, error.optional_data if $DEBUG
59
60
  assert_match(/detached/, error.message)
60
61
 
61
62
  assert_equal(%w[ msg2 ], sub1.enum_for(:fetch).to_a)
@@ -4,7 +4,19 @@ require 'rims'
4
4
  require 'test/unit'
5
5
 
6
6
  module RIMS::Test
7
- class TestError < Test::Unit::TestCase
7
+ class ErrorTest < Test::Unit::TestCase
8
+ def test_optional_data
9
+ error = RIMS::Error.new('test', foo: 1, bar: '2')
10
+ assert_equal('test', error.message)
11
+ assert_equal({ foo: 1, bar: '2' }, error.optional_data)
12
+ end
13
+
14
+ def test_no_optional_data
15
+ error = RIMS::Error.new('test')
16
+ assert_equal('test', error.message)
17
+ assert_predicate(error.optional_data, :empty?)
18
+ end
19
+
8
20
  def test_trace_error_chain
9
21
  exception = assert_raise(RuntimeError) {
10
22
  begin
@@ -32,6 +44,26 @@ module RIMS::Test
32
44
  'error level 0'
33
45
  ], errors.map(&:message))
34
46
  end
47
+
48
+ def test_optional_data_block
49
+ count = 0
50
+ error = RIMS::Error.new('test', foo: 1, bar: '2')
51
+ RIMS::Error.optional_data(error) do |e, data|
52
+ count += 1
53
+ assert_equal(error, e)
54
+ assert_equal({ foo: 1, bar: '2' }, data)
55
+ end
56
+ assert_equal(1, count)
57
+ end
58
+
59
+ data('not a RIMS::Error' => StandardError.new('test'),
60
+ 'no optional data' => RIMS::Error.new('test'))
61
+ def test_no_optional_data_block(data)
62
+ error = data
63
+ RIMS::Error.optional_data(error) do |e, data|
64
+ flunk
65
+ end
66
+ end
35
67
  end
36
68
  end
37
69
 
@@ -51,7 +51,7 @@ module RIMS::Test
51
51
  assert_equal('write-lock wait timeout', error.message)
52
52
  end
53
53
 
54
- def calculate_threa_work_seconds
54
+ def calculate_thread_work_seconds
55
55
  t0 = Time.now
56
56
  1000.times{|i| i.succ }
57
57
  t1 = Time.now
@@ -60,10 +60,10 @@ module RIMS::Test
60
60
 
61
61
  wait_seconds
62
62
  end
63
- private :calculate_threa_work_seconds
63
+ private :calculate_thread_work_seconds
64
64
 
65
65
  def test_read_write_lock_multithread
66
- lock_wait_seconds = calculate_threa_work_seconds
66
+ lock_wait_seconds = calculate_thread_work_seconds
67
67
 
68
68
  count = 0
69
69
  read_thread_num = 10
@@ -116,7 +116,7 @@ module RIMS::Test
116
116
  def test_write_lock_timeout_detach
117
117
  logger = Logger.new(STDOUT)
118
118
  logger.level = ($DEBUG) ? Logger::DEBUG : Logger::FATAL
119
- wait_seconds = calculate_threa_work_seconds
119
+ wait_seconds = calculate_thread_work_seconds
120
120
 
121
121
  t_list = []
122
122
  assert_nil(RIMS::ReadWriteLock.write_lock_timeout_detach(wait_seconds, wait_seconds * 2, logger: logger ) {|timeout_seconds|
@@ -61,7 +61,7 @@ module RIMS::Test
61
61
  end
62
62
  end
63
63
 
64
- class PasswordHashSourceEntry < Test::Unit::TestCase
64
+ class PasswordHashSourceEntryTest < Test::Unit::TestCase
65
65
  def setup
66
66
  @digest_factory = Digest::SHA256
67
67
  @hash_type = 'SHA256'
@@ -127,6 +127,7 @@ module RIMS::Test
127
127
  cmd_name, cmd_args, cmd_client_output = parse_imap_command(tag, imap_command_message)
128
128
  normalized_cmd_name = RIMS::Protocol::Decoder.imap_command_normalize(cmd_name)
129
129
  cmd_id = RIMS::Protocol::Decoder::IMAP_CMDs[normalized_cmd_name] or flunk("not a imap command: #{cmd_name}")
130
+ cmd_kw_args = {}
130
131
 
131
132
  input = nil
132
133
  output = nil
@@ -146,32 +147,29 @@ module RIMS::Test
146
147
  cmd_args = inout_args + cmd_args
147
148
  end
148
149
  unless (uid.nil?) then
149
- cmd_args += [ { uid: uid } ]
150
+ cmd_kw_args[:uid] = uid
150
151
  end
151
152
 
152
153
  block_call = 0
153
154
  ret_val = nil
154
155
 
156
+ response_message = cmd_client_output.b
155
157
  pp [ :debug_imap_command, imap_command_message, cmd_id, cmd_args ] if $DEBUG
156
- @decoder.__send__(cmd_id, tag, *cmd_args) {|responses|
158
+ @decoder.__send__(cmd_id, tag, *cmd_args, **cmd_kw_args) {|response|
157
159
  block_call += 1
158
- response_message = cmd_client_output.b
159
- if (output) then
160
+ if (block_call == 1 && output) then
160
161
  response_message << output.string
161
162
  end
162
- for response in responses
163
- if (response != :flush) then
164
- response_message << response
165
- end
163
+ if (response != :flush) then
164
+ response_message << response
166
165
  end
167
- response_lines = StringIO.new(response_message, 'r').each_line
168
- ret_val = yield(response_lines)
169
- assert_raise(StopIteration) { response_lines.next }
170
166
  }
167
+ response_lines = StringIO.new(response_message, 'r').each_line
168
+ ret_val = yield(response_lines)
169
+ assert_raise(StopIteration) { response_lines.next }
171
170
  if (client_input_text) then
172
171
  pp input.string, output.string if $DEBUG
173
172
  end
174
- assert_equal(1, block_call, 'IMAP command block should be called only once.')
175
173
 
176
174
  @decoder = @decoder.next_decoder
177
175
 
@@ -259,8 +257,15 @@ module RIMS::Test
259
257
  end
260
258
  private :open_mail_store
261
259
 
260
+ LINE_LENGTH_LIMIT = 128
261
+ LITERAL_SIZE_LIMIT = 1024**2
262
+ COMMAND_SIZE_LIMIT = LITERAL_SIZE_LIMIT + LINE_LENGTH_LIMIT
263
+
262
264
  def make_decoder
263
- RIMS::Protocol::Decoder.new_decoder(@drb_services, @auth, @logger)
265
+ RIMS::Protocol::Decoder.new_decoder(@drb_services, @auth, @logger,
266
+ line_length_limit: LINE_LENGTH_LIMIT,
267
+ literal_size_limit: LITERAL_SIZE_LIMIT,
268
+ command_size_limit: COMMAND_SIZE_LIMIT)
264
269
  end
265
270
  private :make_decoder
266
271
 
@@ -293,13 +298,17 @@ module RIMS::Test
293
298
  @unique_user_id = RIMS::Authentication.unique_user_id('foo')
294
299
 
295
300
  @bulk_response_count = 10
301
+ @charset_aliases = RIMS::RFC822::CharsetAliases.new
302
+ @charset_convert_options = {}
296
303
  @drb_services = Riser::DRbServices.new(0)
297
304
  @drb_services.add_sticky_process_service(:engine,
298
305
  Riser::ResourceSet.build{|builder|
299
306
  builder.at_create{|unique_user_id|
300
307
  mail_store = RIMS::MailStore.build(unique_user_id, @kvs_open, @kvs_open)
301
308
  RIMS::Protocol::Decoder::Engine.new(unique_user_id, mail_store, @logger,
302
- bulk_response_count: @bulk_response_count)
309
+ bulk_response_count: @bulk_response_count,
310
+ charset_aliases: @charset_aliases,
311
+ charset_convert_options: @charset_convert_options)
303
312
  }
304
313
  builder.at_destroy{|engine|
305
314
  engine.destroy
@@ -378,6 +387,17 @@ module RIMS::Test
378
387
  end
379
388
  private :assert_imap_command
380
389
 
390
+ def assert_imap_closed
391
+ if (stream_test?) then
392
+ assert_raise(Errno::EPIPE, StopIteration) {
393
+ assert_imap_command('NOOP') {|assert|
394
+ assert.equal("#{tag} OK NOOP completed")
395
+ }
396
+ }
397
+ end
398
+ end
399
+ private :assert_imap_closed
400
+
381
401
  def client_plain_response_base64(authentication_id, plain_password)
382
402
  response_txt = [ authentication_id, authentication_id, plain_password ].join("\0")
383
403
  RIMS::Protocol.encode_base64(response_txt)
@@ -560,6 +580,8 @@ module RIMS::Test
560
580
  assert.match(/^\* BYE /)
561
581
  assert.equal("#{tag} OK LOGOUT completed")
562
582
  }
583
+
584
+ assert_imap_closed
563
585
  }
564
586
  end
565
587
 
@@ -605,6 +627,8 @@ module RIMS::Test
605
627
  }
606
628
 
607
629
  assert_equal(false, @decoder.auth?) if command_test?
630
+
631
+ assert_imap_closed
608
632
  }
609
633
  end
610
634
 
@@ -656,6 +680,8 @@ module RIMS::Test
656
680
  }
657
681
 
658
682
  assert_equal(false, @decoder.auth?) if command_test?
683
+
684
+ assert_imap_closed
659
685
  }
660
686
  end
661
687
 
@@ -711,6 +737,8 @@ module RIMS::Test
711
737
  }
712
738
 
713
739
  assert_equal(false, @decoder.auth?) if command_test?
740
+
741
+ assert_imap_closed
714
742
  }
715
743
  end
716
744
 
@@ -753,6 +781,8 @@ module RIMS::Test
753
781
  }
754
782
 
755
783
  assert_equal(false, @decoder.auth?) if command_test?
784
+
785
+ assert_imap_closed
756
786
  }
757
787
  end
758
788
 
@@ -834,6 +864,8 @@ module RIMS::Test
834
864
  assert_equal(false, @decoder.selected?)
835
865
  end
836
866
 
867
+ assert_imap_closed
868
+
837
869
  open_mail_store{
838
870
  assert_msg_uid( 2, 3)
839
871
  assert_flag_enabled_msgs('answered', )
@@ -884,6 +916,8 @@ module RIMS::Test
884
916
  assert.match(/^\* BYE /)
885
917
  assert.equal("#{tag} OK LOGOUT completed")
886
918
  }
919
+
920
+ assert_imap_closed
887
921
  }
888
922
  end
889
923
 
@@ -965,6 +999,8 @@ module RIMS::Test
965
999
  assert_equal(false, @decoder.selected?)
966
1000
  end
967
1001
 
1002
+ assert_imap_closed
1003
+
968
1004
  open_mail_store{
969
1005
  assert_msg_uid( 1, 2, 3)
970
1006
  assert_flag_enabled_msgs('answered', )
@@ -1015,6 +1051,8 @@ module RIMS::Test
1015
1051
  assert.match(/^\* BYE /)
1016
1052
  assert.equal("#{tag} OK LOGOUT completed")
1017
1053
  }
1054
+
1055
+ assert_imap_closed
1018
1056
  }
1019
1057
  end
1020
1058
 
@@ -1064,6 +1102,8 @@ module RIMS::Test
1064
1102
  assert.match(/^\* BYE /)
1065
1103
  assert.equal("#{tag} OK LOGOUT completed")
1066
1104
  }
1105
+
1106
+ assert_imap_closed
1067
1107
  }
1068
1108
  end
1069
1109
 
@@ -1100,6 +1140,8 @@ module RIMS::Test
1100
1140
  assert.match(/^\* BYE /)
1101
1141
  assert.equal("#{tag} OK LOGOUT completed")
1102
1142
  }
1143
+
1144
+ assert_imap_closed
1103
1145
  }
1104
1146
  end
1105
1147
 
@@ -1172,6 +1214,8 @@ module RIMS::Test
1172
1214
  assert.match(/^\* BYE /)
1173
1215
  assert.equal("#{tag} OK LOGOUT completed")
1174
1216
  }
1217
+
1218
+ assert_imap_closed
1175
1219
  }
1176
1220
  end
1177
1221
 
@@ -1212,6 +1256,8 @@ module RIMS::Test
1212
1256
  assert.match(/^\* BYE /)
1213
1257
  assert.equal("#{tag} OK LOGOUT completed")
1214
1258
  }
1259
+
1260
+ assert_imap_closed
1215
1261
  }
1216
1262
  end
1217
1263
 
@@ -1291,6 +1337,8 @@ module RIMS::Test
1291
1337
  assert.match(/^\* BYE /)
1292
1338
  assert.equal("#{tag} OK LOGOUT completed")
1293
1339
  }
1340
+
1341
+ assert_imap_closed
1294
1342
  }
1295
1343
  end
1296
1344
 
@@ -1338,6 +1386,8 @@ module RIMS::Test
1338
1386
  assert.match(/^\* BYE /)
1339
1387
  assert.equal("#{tag} OK LOGOUT completed")
1340
1388
  }
1389
+
1390
+ assert_imap_closed
1341
1391
  }
1342
1392
  end
1343
1393
 
@@ -1407,6 +1457,8 @@ module RIMS::Test
1407
1457
  assert.match(/^\* BYE /)
1408
1458
  assert.equal("#{tag} OK LOGOUT completed")
1409
1459
  }
1460
+
1461
+ assert_imap_closed
1410
1462
  }
1411
1463
  end
1412
1464
 
@@ -1517,6 +1569,8 @@ module RIMS::Test
1517
1569
  assert.match(/^\* BYE /)
1518
1570
  assert.equal("#{tag} OK LOGOUT completed")
1519
1571
  }
1572
+
1573
+ assert_imap_closed
1520
1574
  }
1521
1575
  end
1522
1576
 
@@ -1555,6 +1609,8 @@ module RIMS::Test
1555
1609
  assert.match(/^\* BYE /)
1556
1610
  assert.equal("#{tag} OK LOGOUT completed")
1557
1611
  }
1612
+
1613
+ assert_imap_closed
1558
1614
  }
1559
1615
  end
1560
1616
 
@@ -1661,6 +1717,8 @@ module RIMS::Test
1661
1717
  assert.match(/^\* BYE /)
1662
1718
  assert.equal("#{tag} OK LOGOUT completed")
1663
1719
  }
1720
+
1721
+ assert_imap_closed
1664
1722
  }
1665
1723
  end
1666
1724
 
@@ -1692,6 +1750,8 @@ module RIMS::Test
1692
1750
  assert.match(/^\* BYE /)
1693
1751
  assert.equal("#{tag} OK LOGOUT completed")
1694
1752
  }
1753
+
1754
+ assert_imap_closed
1695
1755
  }
1696
1756
  end
1697
1757
 
@@ -1759,6 +1819,8 @@ module RIMS::Test
1759
1819
  assert.match(/^\* BYE /)
1760
1820
  assert.equal("#{tag} OK LOGOUT completed")
1761
1821
  }
1822
+
1823
+ assert_imap_closed
1762
1824
  }
1763
1825
  end
1764
1826
 
@@ -1879,6 +1941,8 @@ module RIMS::Test
1879
1941
  assert.match(/^\* BYE /)
1880
1942
  assert.equal("#{tag} OK LOGOUT completed")
1881
1943
  }
1944
+
1945
+ assert_imap_closed
1882
1946
  }
1883
1947
  end
1884
1948
 
@@ -1918,6 +1982,8 @@ module RIMS::Test
1918
1982
  assert.match(/^\* BYE /)
1919
1983
  assert.equal("#{tag} OK LOGOUT completed")
1920
1984
  }
1985
+
1986
+ assert_imap_closed
1921
1987
  }
1922
1988
  end
1923
1989
 
@@ -1926,6 +1992,69 @@ module RIMS::Test
1926
1992
  test_append_utf7_mbox_name
1927
1993
  end
1928
1994
 
1995
+ def test_append_literal_stream
1996
+ make_mail_simple
1997
+ make_mail_multipart
1998
+ make_mail_mime_subject
1999
+
2000
+ use_imap_stream_decode_engine # always run in stream
2001
+ imap_decode_engine_evaluate{
2002
+ if (stream_test?) then
2003
+ assert_untagged_response{|assert|
2004
+ assert.equal("* OK RIMS v#{RIMS::VERSION} IMAP4rev1 service ready.")
2005
+ }
2006
+ end
2007
+
2008
+ assert_imap_command('LOGIN foo open_sesame') {|assert|
2009
+ assert.equal("#{tag} OK LOGIN completed")
2010
+ }
2011
+
2012
+ open_mail_store{
2013
+ assert_msg_uid()
2014
+ }
2015
+
2016
+ assert_imap_command("APPEND INBOX #{literal(@simple_mail.raw_source)}") {|assert|
2017
+ assert.match(/^\+ /)
2018
+ assert.match(/^#{tag} OK \[APPENDUID \d+ \d+\] APPEND completed/)
2019
+ }
2020
+
2021
+ open_mail_store{
2022
+ assert_msg_uid(1)
2023
+ assert_equal(@simple_mail.raw_source, get_msg_text(1))
2024
+ assert_msg_flags(1, recent: true)
2025
+ }
2026
+
2027
+ assert_imap_command("APPEND INBOX #{literal(@mpart_mail.raw_source)}") {|assert|
2028
+ assert.match(/^\+ /)
2029
+ assert.match(/^#{tag} OK \[APPENDUID \d+ \d+\] APPEND completed/)
2030
+ }
2031
+
2032
+ open_mail_store{
2033
+ assert_msg_uid(1, 2)
2034
+ assert_equal(@mpart_mail.raw_source, get_msg_text(2))
2035
+ assert_msg_flags(2, recent: true)
2036
+ }
2037
+
2038
+ assert_imap_command("APPEND INBOX #{literal(@mime_subject_mail.raw_source)}") {|assert|
2039
+ assert.match(/^\+ /)
2040
+ assert.match(/^#{tag} OK \[APPENDUID \d+ \d+\] APPEND completed/)
2041
+ }
2042
+
2043
+ open_mail_store{
2044
+ assert_msg_uid(1, 2, 3)
2045
+ assert_equal(@mime_subject_mail.raw_source, get_msg_text(3))
2046
+ assert_msg_flags(3, recent: true)
2047
+ }
2048
+
2049
+ assert_imap_command('LOGOUT') {|assert|
2050
+ assert.match(/^\* BYE /)
2051
+ assert.equal("#{tag} OK LOGOUT completed")
2052
+ }
2053
+
2054
+ assert_imap_closed
2055
+ }
2056
+ end
2057
+
1929
2058
  def test_check
1930
2059
  imap_decode_engine_evaluate{
1931
2060
  if (stream_test?) then
@@ -1962,7 +2091,7 @@ module RIMS::Test
1962
2091
  }
1963
2092
 
1964
2093
  assert_imap_command('SELECT INBOX') {|assert|
1965
- assert.skip_while{|line| line =~ /^\* /}
2094
+ assert.skip_while{|line| line =~ /^\* / }
1966
2095
  assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
1967
2096
  }
1968
2097
 
@@ -1979,6 +2108,8 @@ module RIMS::Test
1979
2108
  assert.match(/^\* BYE /)
1980
2109
  assert.equal("#{tag} OK LOGOUT completed")
1981
2110
  }
2111
+
2112
+ assert_imap_closed
1982
2113
  }
1983
2114
  end
1984
2115
 
@@ -2090,6 +2221,8 @@ module RIMS::Test
2090
2221
  assert_equal(false, @decoder.auth?)
2091
2222
  assert_equal(false, @decoder.selected?)
2092
2223
  end
2224
+
2225
+ assert_imap_closed
2093
2226
  }
2094
2227
  end
2095
2228
 
@@ -2194,6 +2327,8 @@ module RIMS::Test
2194
2327
  assert_equal(false, @decoder.auth?)
2195
2328
  assert_equal(false, @decoder.selected?)
2196
2329
  end
2330
+
2331
+ assert_imap_closed
2197
2332
  }
2198
2333
  end
2199
2334
 
@@ -2344,6 +2479,8 @@ module RIMS::Test
2344
2479
  assert.match(/^\* BYE /)
2345
2480
  assert.equal("#{tag} OK LOGOUT completed")
2346
2481
  }
2482
+
2483
+ assert_imap_closed
2347
2484
  }
2348
2485
  end
2349
2486
 
@@ -2420,6 +2557,8 @@ module RIMS::Test
2420
2557
  assert.match(/^\* BYE /)
2421
2558
  assert.equal("#{tag} OK LOGOUT completed")
2422
2559
  }
2560
+
2561
+ assert_imap_closed
2423
2562
  }
2424
2563
  end
2425
2564
 
@@ -2549,6 +2688,8 @@ module RIMS::Test
2549
2688
  assert.match(/^\* BYE /)
2550
2689
  assert.equal("#{tag} OK LOGOUT completed")
2551
2690
  }
2691
+
2692
+ assert_imap_closed
2552
2693
  }
2553
2694
  end
2554
2695
 
@@ -2635,13 +2776,13 @@ module RIMS::Test
2635
2776
  }
2636
2777
 
2637
2778
  utf8_msg = "\u306F\u306B\u307B"
2638
- assert_imap_command("SEARCH CHARSET utf-8 BODY {#{utf8_msg.bytesize}}\r\n#{utf8_msg}".b) {|assert|
2779
+ assert_imap_command("SEARCH CHARSET utf-8 BODY #{literal(utf8_msg)}".b) {|assert|
2639
2780
  assert.match(/^\+ /)
2640
2781
  assert.equal("* SEARCH 4 5\r\n")
2641
2782
  assert.equal("#{tag} OK SEARCH completed\r\n")
2642
2783
  }
2643
2784
 
2644
- assert_imap_command("SEARCH CHARSET euc-jp BODY {#{utf8_msg.bytesize}}\r\n#{utf8_msg}".b) {|assert|
2785
+ assert_imap_command("SEARCH CHARSET euc-jp BODY #{literal(utf8_msg)}".b) {|assert|
2645
2786
  assert.match(/^\+ /)
2646
2787
  assert.match(/^#{tag} BAD /, peek_next_line: true).match(/syntax error/)
2647
2788
  }
@@ -2666,6 +2807,8 @@ module RIMS::Test
2666
2807
  assert.match(/^\* BYE /)
2667
2808
  assert.equal("#{tag} OK LOGOUT completed")
2668
2809
  }
2810
+
2811
+ assert_imap_closed
2669
2812
  }
2670
2813
  end
2671
2814
 
@@ -2759,13 +2902,13 @@ module RIMS::Test
2759
2902
  }
2760
2903
 
2761
2904
  utf8_msg = "\u306F\u306B\u307B"
2762
- assert_imap_command("SEARCH CHARSET utf-8 TEXT {#{utf8_msg.bytesize}}\r\n#{utf8_msg}".b) {|assert|
2905
+ assert_imap_command("SEARCH CHARSET utf-8 TEXT #{literal(utf8_msg)}".b) {|assert|
2763
2906
  assert.match(/^\+ /)
2764
2907
  assert.equal("* SEARCH 4 5\r\n")
2765
2908
  assert.equal("#{tag} OK SEARCH completed\r\n")
2766
2909
  }
2767
2910
 
2768
- assert_imap_command("SEARCH CHARSET euc-jp TEXT {#{utf8_msg.bytesize}}\r\n#{utf8_msg}".b) {|assert|
2911
+ assert_imap_command("SEARCH CHARSET euc-jp TEXT #{literal(utf8_msg)}".b) {|assert|
2769
2912
  assert.match(/^\+ /)
2770
2913
  assert.match(/^#{tag} BAD /, peek_next_line: true).match(/syntax error/)
2771
2914
  }
@@ -2790,6 +2933,8 @@ module RIMS::Test
2790
2933
  assert.match(/^\* BYE /)
2791
2934
  assert.equal("#{tag} OK LOGOUT completed")
2792
2935
  }
2936
+
2937
+ assert_imap_closed
2793
2938
  }
2794
2939
  end
2795
2940
 
@@ -2851,7 +2996,7 @@ module RIMS::Test
2851
2996
  }
2852
2997
 
2853
2998
  utf8_msg = "\u306F\u306B\u307B"
2854
- assert_imap_command("SEARCH CHARSET utf-8 TEXT {#{utf8_msg.bytesize}}\r\n#{utf8_msg}".b) {|assert|
2999
+ assert_imap_command("SEARCH CHARSET utf-8 TEXT #{literal(utf8_msg)}".b) {|assert|
2855
3000
  assert.match(/^\+ /)
2856
3001
  assert.equal("* SEARCH\r\n")
2857
3002
  assert.equal("#{tag} OK SEARCH completed\r\n")
@@ -2861,6 +3006,8 @@ module RIMS::Test
2861
3006
  assert.match(/^\* BYE /)
2862
3007
  assert.equal("#{tag} OK LOGOUT completed")
2863
3008
  }
3009
+
3010
+ assert_imap_closed
2864
3011
  }
2865
3012
  end
2866
3013
 
@@ -2869,7 +3016,8 @@ module RIMS::Test
2869
3016
  test_search_charset_skip_encoding_error
2870
3017
  end
2871
3018
 
2872
- def test_search_interrupt_by_bad_response
3019
+ # skip this test because `EncodingError' is ignored.
3020
+ def _test_search_interrupt_by_bad_response
2873
3021
  imap_decode_engine_evaluate{
2874
3022
  if (stream_test?) then
2875
3023
  assert_untagged_response{|assert|
@@ -2915,7 +3063,7 @@ module RIMS::Test
2915
3063
  assert_equal(true, @decoder.selected?)
2916
3064
  end
2917
3065
 
2918
- assert_imap_command('SEARCH TEXT foo') {|assert|
3066
+ assert_imap_command('SEARCH CHARSET utf-8 TEXT foo') {|assert|
2919
3067
  assert.match(/\A\* SEARCH( \d+)+\r\n\z/, peek_next_line: true).no_match(/ #{@bulk_response_count.succ}/)
2920
3068
  assert.equal("#{tag} BAD internal server error\r\n")
2921
3069
  }
@@ -2924,10 +3072,13 @@ module RIMS::Test
2924
3072
  assert.match(/^\* BYE /)
2925
3073
  assert.equal("#{tag} OK LOGOUT completed")
2926
3074
  }
3075
+
3076
+ assert_imap_closed
2927
3077
  }
2928
3078
  end
2929
3079
 
2930
- def test_search_interrupt_by_bad_response_stream
3080
+ # skip this test because `EncodingError' is ignored.
3081
+ def _test_search_interrupt_by_bad_response_stream
2931
3082
  use_imap_stream_decode_engine
2932
3083
  test_search_interrupt_by_bad_response
2933
3084
  end
@@ -3076,6 +3227,8 @@ module RIMS::Test
3076
3227
  assert.match(/^\* BYE /)
3077
3228
  assert.equal("#{tag} OK LOGOUT completed")
3078
3229
  }
3230
+
3231
+ assert_imap_closed
3079
3232
  }
3080
3233
  end
3081
3234
 
@@ -3228,6 +3381,8 @@ module RIMS::Test
3228
3381
  assert.match(/^\* BYE /)
3229
3382
  assert.equal("#{tag} OK LOGOUT completed")
3230
3383
  }
3384
+
3385
+ assert_imap_closed
3231
3386
  }
3232
3387
  end
3233
3388
 
@@ -3580,6 +3735,8 @@ module RIMS::Test
3580
3735
  assert.match(/^\* BYE /)
3581
3736
  assert.equal("#{tag} OK LOGOUT completed")
3582
3737
  }
3738
+
3739
+ assert_imap_closed
3583
3740
  }
3584
3741
  end
3585
3742
 
@@ -3882,6 +4039,8 @@ module RIMS::Test
3882
4039
  assert.match(/^\* BYE /)
3883
4040
  assert.equal("#{tag} OK LOGOUT completed")
3884
4041
  }
4042
+
4043
+ assert_imap_closed
3885
4044
  }
3886
4045
  end
3887
4046
 
@@ -4234,6 +4393,8 @@ module RIMS::Test
4234
4393
  assert.match(/^\* BYE /)
4235
4394
  assert.equal("#{tag} OK LOGOUT completed")
4236
4395
  }
4396
+
4397
+ assert_imap_closed
4237
4398
  }
4238
4399
  end
4239
4400
 
@@ -4536,6 +4697,8 @@ module RIMS::Test
4536
4697
  assert.match(/^\* BYE /)
4537
4698
  assert.equal("#{tag} OK LOGOUT completed")
4538
4699
  }
4700
+
4701
+ assert_imap_closed
4539
4702
  }
4540
4703
  end
4541
4704
 
@@ -4705,6 +4868,8 @@ module RIMS::Test
4705
4868
  assert.match(/^\* BYE /)
4706
4869
  assert.equal("#{tag} OK LOGOUT completed")
4707
4870
  }
4871
+
4872
+ assert_imap_closed
4708
4873
  }
4709
4874
  end
4710
4875
 
@@ -4909,6 +5074,8 @@ module RIMS::Test
4909
5074
  assert.match(/^\* BYE /)
4910
5075
  assert.equal("#{tag} OK LOGOUT completed")
4911
5076
  }
5077
+
5078
+ assert_imap_closed
4912
5079
  }
4913
5080
  end
4914
5081
 
@@ -5113,6 +5280,8 @@ module RIMS::Test
5113
5280
  assert.match(/^\* BYE /)
5114
5281
  assert.equal("#{tag} OK LOGOUT completed")
5115
5282
  }
5283
+
5284
+ assert_imap_closed
5116
5285
  }
5117
5286
  end
5118
5287
 
@@ -5166,6 +5335,8 @@ module RIMS::Test
5166
5335
  assert.match(/^\* BYE /)
5167
5336
  assert.equal("#{tag} OK LOGOUT completed")
5168
5337
  }
5338
+
5339
+ assert_imap_closed
5169
5340
  }
5170
5341
  end
5171
5342
 
@@ -5209,7 +5380,7 @@ module RIMS::Test
5209
5380
  }
5210
5381
 
5211
5382
  assert_imap_command('SELECT INBOX') {|assert|
5212
- assert.skip_while{|line| line =~ /^\* /}
5383
+ assert.skip_while{|line| line =~ /^\* / }
5213
5384
  assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
5214
5385
  }
5215
5386
 
@@ -5236,7 +5407,7 @@ module RIMS::Test
5236
5407
  }
5237
5408
 
5238
5409
  assert_imap_command('EXAMINE INBOX') {|assert|
5239
- assert.skip_while{|line| line =~ /^\* /}
5410
+ assert.skip_while{|line| line =~ /^\* / }
5240
5411
  assert.equal("#{tag} OK [READ-ONLY] EXAMINE completed")
5241
5412
  }
5242
5413
 
@@ -5258,6 +5429,8 @@ module RIMS::Test
5258
5429
  assert_equal(false, @decoder.auth?)
5259
5430
  assert_equal(false, @decoder.selected?)
5260
5431
  end
5432
+
5433
+ assert_imap_closed
5261
5434
  }
5262
5435
  end
5263
5436
 
@@ -5297,7 +5470,7 @@ module RIMS::Test
5297
5470
  }
5298
5471
 
5299
5472
  assert_imap_command('SELECT INBOX') {|assert|
5300
- assert.skip_while{|line| line =~ /^\* /}
5473
+ assert.skip_while{|line| line =~ /^\* / }
5301
5474
  assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
5302
5475
  }
5303
5476
 
@@ -5343,7 +5516,7 @@ module RIMS::Test
5343
5516
  }
5344
5517
 
5345
5518
  assert_imap_command('EXAMINE INBOX') {|assert|
5346
- assert.skip_while{|line| line =~ /^\* /}
5519
+ assert.skip_while{|line| line =~ /^\* / }
5347
5520
  assert.equal("#{tag} OK [READ-ONLY] EXAMINE completed")
5348
5521
  }
5349
5522
 
@@ -5366,6 +5539,8 @@ module RIMS::Test
5366
5539
  assert_equal(false, @decoder.auth?)
5367
5540
  assert_equal(false, @decoder.selected?)
5368
5541
  end
5542
+
5543
+ assert_imap_closed
5369
5544
  }
5370
5545
  end
5371
5546
 
@@ -5375,11 +5550,11 @@ module RIMS::Test
5375
5550
  end
5376
5551
 
5377
5552
  def test_error_handling_stream
5378
- use_imap_stream_decode_engine
5553
+ use_imap_stream_decode_engine # always run in stream
5379
5554
  imap_decode_engine_evaluate{
5380
5555
  assert_imap_command('') {|assert|
5381
5556
  assert.equal("* OK RIMS v#{RIMS::VERSION} IMAP4rev1 service ready.")
5382
- assert.equal('* BAD client command syntax error')
5557
+ assert.equal("#{tag} BAD client command syntax error")
5383
5558
  }
5384
5559
 
5385
5560
  assert_imap_command('no_command') {|assert|
@@ -5397,6 +5572,30 @@ module RIMS::Test
5397
5572
  assert_imap_command('noop detarame') {|assert|
5398
5573
  assert.equal("#{tag} BAD invalid command parameter")
5399
5574
  }
5575
+
5576
+ assert_imap_command("APPEND INBOX {#{LITERAL_SIZE_LIMIT + 1}}") {|assert|
5577
+ assert.equal("#{tag} BAD literal size too large")
5578
+ }
5579
+
5580
+ assert_imap_command("APPEND #{literal('x' * LITERAL_SIZE_LIMIT)} #{'y' * (LINE_LENGTH_LIMIT - 3)}") {|assert|
5581
+ assert.match(/^\+ /)
5582
+ assert.equal("#{tag} BAD command size too large") # by last line
5583
+ }
5584
+
5585
+ assert_imap_command("APPEND #{literal('x' * LITERAL_SIZE_LIMIT)} {#{LITERAL_SIZE_LIMIT}}") {|assert|
5586
+ assert.match(/^\+ /)
5587
+ assert.equal("#{tag} BAD command size too large") # by last literal
5588
+ }
5589
+
5590
+ @tag = '*T000'
5591
+ assert_imap_command('noop') {|assert|
5592
+ assert.equal('* BAD client command syntax error')
5593
+ }
5594
+
5595
+ @tag = '+T000'
5596
+ assert_imap_command('noop') {|assert|
5597
+ assert.equal('* BAD client command syntax error')
5598
+ }
5400
5599
  }
5401
5600
  end
5402
5601
 
@@ -5428,6 +5627,8 @@ module RIMS::Test
5428
5627
  }
5429
5628
 
5430
5629
  assert_equal(false, @decoder.auth?) if command_test?
5630
+
5631
+ assert_imap_closed
5431
5632
  }
5432
5633
  end
5433
5634
 
@@ -5584,6 +5785,8 @@ module RIMS::Test
5584
5785
  }
5585
5786
 
5586
5787
  assert_equal(false, @decoder.auth?) if command_test?
5788
+
5789
+ assert_imap_closed
5587
5790
  }
5588
5791
  end
5589
5792
 
@@ -5642,6 +5845,8 @@ module RIMS::Test
5642
5845
  }
5643
5846
 
5644
5847
  assert_equal(false, @decoder.auth?) if command_test?
5848
+
5849
+ assert_imap_closed
5645
5850
  }
5646
5851
  end
5647
5852
 
@@ -5724,7 +5929,7 @@ module RIMS::Test
5724
5929
  }
5725
5930
 
5726
5931
  assert_imap_command('SELECT INBOX') {|assert|
5727
- assert.skip_while{|line| line =~ /^\* /}
5932
+ assert.skip_while{|line| line =~ /^\* / }
5728
5933
  assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
5729
5934
  }
5730
5935
 
@@ -5748,7 +5953,7 @@ module RIMS::Test
5748
5953
  }
5749
5954
 
5750
5955
  assert_imap_command('SELECT INBOX') {|assert|
5751
- assert.skip_while{|line| line =~ /^\* /}
5956
+ assert.skip_while{|line| line =~ /^\* / }
5752
5957
  assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
5753
5958
  }
5754
5959
 
@@ -5772,7 +5977,7 @@ module RIMS::Test
5772
5977
  }
5773
5978
 
5774
5979
  assert_imap_command('SELECT INBOX') {|assert|
5775
- assert.skip_while{|line| line =~ /^\* /}
5980
+ assert.skip_while{|line| line =~ /^\* / }
5776
5981
  assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
5777
5982
  }
5778
5983
 
@@ -5800,7 +6005,7 @@ module RIMS::Test
5800
6005
  }
5801
6006
 
5802
6007
  assert_imap_command('SELECT INBOX') {|assert|
5803
- assert.skip_while{|line| line =~ /^\* /}
6008
+ assert.skip_while{|line| line =~ /^\* / }
5804
6009
  assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
5805
6010
  }
5806
6011
 
@@ -5833,10 +6038,8 @@ module RIMS::Test
5833
6038
  }
5834
6039
 
5835
6040
  another_decoder = make_decoder
5836
- another_writer = proc{|res|
5837
- for line in res
5838
- p line if $DEBUG
5839
- end
6041
+ another_writer = proc{|response|
6042
+ p response if $DEBUG
5840
6043
  }
5841
6044
 
5842
6045
  another_decoder.login('tag', 'foo', 'open_sesame', &another_writer)
@@ -6111,10 +6314,8 @@ module RIMS::Test
6111
6314
  }
6112
6315
 
6113
6316
  another_decoder = make_decoder
6114
- another_writer = proc{|res|
6115
- for line in res
6116
- p line if $DEBUG
6117
- end
6317
+ another_writer = proc{|response|
6318
+ p response if $DEBUG
6118
6319
  }
6119
6320
 
6120
6321
  another_decoder.login('tag', 'foo', 'open_sesame', &another_writer)
@@ -6175,6 +6376,232 @@ module RIMS::Test
6175
6376
  use_imap_stream_decode_engine
6176
6377
  test_idle_untagged_server_response
6177
6378
  end
6379
+
6380
+ def test_charset_aliases
6381
+ imap_decode_engine_evaluate{
6382
+ if (stream_test?) then
6383
+ assert_untagged_response{|assert|
6384
+ assert.equal("* OK RIMS v#{RIMS::VERSION} IMAP4rev1 service ready.")
6385
+ }
6386
+ end
6387
+
6388
+ platform_dependent_character = "\u2460"
6389
+ open_mail_store{
6390
+ add_msg("Content-Type: text/plain; charset=iso-2022-jp\r\n" +
6391
+ "\r\n" +
6392
+ "#{platform_dependent_character.encode(Encoding::CP50221).b}")
6393
+ }
6394
+
6395
+ if (command_test?) then
6396
+ assert_equal(false, @decoder.auth?)
6397
+ assert_equal(false, @decoder.selected?)
6398
+ end
6399
+
6400
+ assert_imap_command('LOGIN foo open_sesame') {|assert|
6401
+ assert.equal("#{tag} OK LOGIN completed")
6402
+ }
6403
+
6404
+ if (command_test?) then
6405
+ assert_equal(true, @decoder.auth?)
6406
+ assert_equal(false, @decoder.selected?)
6407
+ end
6408
+
6409
+ assert_imap_command('SELECT INBOX') {|assert|
6410
+ assert.skip_while{|line| line =~ /^\* / }
6411
+ assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
6412
+ }
6413
+
6414
+ if (command_test?) then
6415
+ assert_equal(true, @decoder.auth?)
6416
+ assert_equal(true, @decoder.selected?)
6417
+ end
6418
+
6419
+ assert_imap_command("SEARCH CHARSET utf-8 TEXT #{literal(platform_dependent_character)}") {|assert|
6420
+ assert.match(/^\+ /)
6421
+ assert.equal("* SEARCH\r\n") # skip by `EncodingError'
6422
+ assert.equal("#{tag} OK SEARCH completed\r\n")
6423
+ }
6424
+
6425
+ # not recommend changing charset aliases after passing them to the decoder.
6426
+ # here, the charset aliases are reluctantly changed for testing.
6427
+ @charset_aliases.add_alias('iso-2022-jp', Encoding::CP50221)
6428
+
6429
+ assert_imap_command("SEARCH CHARSET utf-8 TEXT #{literal(platform_dependent_character)}") {|assert|
6430
+ assert.match(/^\+ /)
6431
+ assert.equal("* SEARCH 1\r\n") # matched!
6432
+ assert.equal("#{tag} OK SEARCH completed\r\n")
6433
+ }
6434
+
6435
+ assert_imap_command('CLOSE') {|assert|
6436
+ assert.equal("#{tag} OK CLOSE completed")
6437
+ }
6438
+
6439
+ if (command_test?) then
6440
+ assert_equal(true, @decoder.auth?)
6441
+ assert_equal(false, @decoder.selected?)
6442
+ end
6443
+
6444
+ assert_imap_command('LOGOUT') {|assert|
6445
+ assert.match(/^\* BYE /)
6446
+ assert.equal("#{tag} OK LOGOUT completed")
6447
+ }
6448
+
6449
+ if (command_test?) then
6450
+ assert_equal(false, @decoder.auth?)
6451
+ assert_equal(false, @decoder.selected?)
6452
+ end
6453
+
6454
+ assert_imap_closed
6455
+ }
6456
+ end
6457
+
6458
+ def test_charset_aliases_stream
6459
+ use_imap_stream_decode_engine
6460
+ test_charset_aliases
6461
+ end
6462
+
6463
+ def test_charset_convert_options
6464
+ imap_decode_engine_evaluate{
6465
+ if (stream_test?) then
6466
+ assert_untagged_response{|assert|
6467
+ assert.equal("* OK RIMS v#{RIMS::VERSION} IMAP4rev1 service ready.")
6468
+ }
6469
+ end
6470
+
6471
+ platform_dependent_character = "\u2460"
6472
+ open_mail_store{
6473
+ add_msg("Content-Type: text/plain; charset=iso-2022-jp\r\n" +
6474
+ "\r\n" +
6475
+ "#{platform_dependent_character.encode(Encoding::CP50221).b}")
6476
+ }
6477
+
6478
+ if (command_test?) then
6479
+ assert_equal(false, @decoder.auth?)
6480
+ assert_equal(false, @decoder.selected?)
6481
+ end
6482
+
6483
+ assert_imap_command('LOGIN foo open_sesame') {|assert|
6484
+ assert.equal("#{tag} OK LOGIN completed")
6485
+ }
6486
+
6487
+ if (command_test?) then
6488
+ assert_equal(true, @decoder.auth?)
6489
+ assert_equal(false, @decoder.selected?)
6490
+ end
6491
+
6492
+ assert_imap_command('SELECT INBOX') {|assert|
6493
+ assert.skip_while{|line| line =~ /^\* / }
6494
+ assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
6495
+ }
6496
+
6497
+ if (command_test?) then
6498
+ assert_equal(true, @decoder.auth?)
6499
+ assert_equal(true, @decoder.selected?)
6500
+ end
6501
+
6502
+ assert_imap_command(%Q'SEARCH CHARSET utf-8 TEXT #{literal("\uFFFD")}') {|assert|
6503
+ assert.match(/^\+ /)
6504
+ assert.equal("* SEARCH\r\n") # skip by `EncodingError'
6505
+ assert.equal("#{tag} OK SEARCH completed\r\n")
6506
+ }
6507
+
6508
+ # not recommend changing charset convert options after passing them to the decoder.
6509
+ # here, the options are reluctantly changed for testing.
6510
+ @charset_convert_options[:undef] = :replace
6511
+
6512
+ assert_imap_command("SEARCH CHARSET utf-8 TEXT #{literal("\uFFFD")}") {|assert|
6513
+ assert.match(/^\+ /)
6514
+ assert.equal("* SEARCH 1\r\n") # matched!
6515
+ assert.equal("#{tag} OK SEARCH completed\r\n")
6516
+ }
6517
+
6518
+ assert_imap_command('CLOSE') {|assert|
6519
+ assert.equal("#{tag} OK CLOSE completed")
6520
+ }
6521
+
6522
+ if (command_test?) then
6523
+ assert_equal(true, @decoder.auth?)
6524
+ assert_equal(false, @decoder.selected?)
6525
+ end
6526
+
6527
+ assert_imap_command('LOGOUT') {|assert|
6528
+ assert.match(/^\* BYE /)
6529
+ assert.equal("#{tag} OK LOGOUT completed")
6530
+ }
6531
+
6532
+ if (command_test?) then
6533
+ assert_equal(false, @decoder.auth?)
6534
+ assert_equal(false, @decoder.selected?)
6535
+ end
6536
+
6537
+ assert_imap_closed
6538
+ }
6539
+ end
6540
+
6541
+ def test_charset_convert_options_stream
6542
+ use_imap_stream_decode_engine
6543
+ test_charset_convert_options
6544
+ end
6545
+
6546
+ def test_command_line_too_long_error_stream
6547
+ use_imap_stream_decode_engine # always run in stream
6548
+ imap_decode_engine_evaluate{
6549
+ assert_untagged_response{|assert|
6550
+ assert.equal("* OK RIMS v#{RIMS::VERSION} IMAP4rev1 service ready.")
6551
+ }
6552
+
6553
+ assert_imap_command('APPEND INBOX ' + 'x' * LINE_LENGTH_LIMIT) {|assert|
6554
+ assert.equal('* BAD line too long')
6555
+ assert.equal('* BYE server autologout: connection terminated')
6556
+ }
6557
+
6558
+ assert_imap_closed
6559
+ }
6560
+ end
6561
+
6562
+ def test_authenticate_line_too_long_error_stream
6563
+ use_imap_stream_decode_engine # always run in stream
6564
+ imap_decode_engine_evaluate{
6565
+ assert_untagged_response{|assert|
6566
+ assert.equal("* OK RIMS v#{RIMS::VERSION} IMAP4rev1 service ready.")
6567
+ }
6568
+
6569
+ assert_imap_command('AUTHENTICATE plain',
6570
+ client_input_text: 'x' * LINE_LENGTH_LIMIT + "\r\n") {|assert|
6571
+ assert.equal('+ ')
6572
+ assert.equal('* BAD line too long')
6573
+ assert.equal('* BYE server autologout: connection terminated')
6574
+ }
6575
+
6576
+ assert_imap_closed
6577
+ }
6578
+ end
6579
+
6580
+ def test_idle_line_too_long_error_stream
6581
+ use_imap_stream_decode_engine # always run in stream
6582
+ imap_decode_engine_evaluate{
6583
+ assert_untagged_response{|assert|
6584
+ assert.equal("* OK RIMS v#{RIMS::VERSION} IMAP4rev1 service ready.")
6585
+ }
6586
+
6587
+ assert_imap_command('LOGIN foo open_sesame') {|assert|
6588
+ assert.equal("#{tag} OK LOGIN completed")
6589
+ }
6590
+
6591
+ assert_imap_command('SELECT INBOX') {|assert|
6592
+ assert.skip_while{|line| line =~ /^\* / }
6593
+ assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
6594
+ }
6595
+
6596
+ assert_imap_command('IDLE', client_input_text: 'DONE' + ' ' * LINE_LENGTH_LIMIT + "\r\n") {|assert|
6597
+ assert.match(/^\+ /)
6598
+ assert.equal('* BAD line too long')
6599
+ assert.equal('* BYE server autologout: connection terminated')
6600
+ }
6601
+
6602
+ assert_imap_closed
6603
+ }
6604
+ end
6178
6605
  end
6179
6606
 
6180
6607
  class ProtocolMailDeliveryDecoderTest < Test::Unit::TestCase
@@ -6197,6 +6624,93 @@ module RIMS::Test
6197
6624
  assert_equal(%w[ foo INBOX ], RIMS::Protocol::Decoder.decode_delivery_target_mailbox(encoded_mbox_name))
6198
6625
  end
6199
6626
  end
6627
+
6628
+ class ProtocolDecoderBulkResponseTest < Test::Unit::TestCase
6629
+ def setup
6630
+ limit_count = 10
6631
+ limit_size = 100
6632
+ @res = RIMS::Protocol::Decoder::BulkResponse.new(limit_count, limit_size)
6633
+ end
6634
+
6635
+ data('empty' => [ 0, 0, [] ],
6636
+ '1' => [ 1, 3, %w[ foo ] ],
6637
+ '2' => [ 2, 6, %w[ foo bar ] ],
6638
+ '3' => [ 3, 11, %w[ foo bar baaaz ] ])
6639
+ def test_add(data)
6640
+ expected_count, expected_size, response_list = data
6641
+
6642
+ assert_equal(0, @res.count)
6643
+ assert_equal(0, @res.size)
6644
+
6645
+ for response in response_list
6646
+ @res << response
6647
+ end
6648
+
6649
+ assert_equal(expected_count, @res.count)
6650
+ assert_equal(expected_size, @res.size)
6651
+ end
6652
+
6653
+ def test_emtpy?
6654
+ assert_true(@res.empty?)
6655
+ end
6656
+
6657
+ def test_not_empty?
6658
+ @res << 'foo'
6659
+ assert_false(@res.empty?)
6660
+ end
6661
+
6662
+ data('count: boundary' => %w[ 1 2 3 4 5 6 7 8 9 0 ],
6663
+ 'count: over' => %w[ 1 2 3 4 5 6 7 8 9 0 a ],
6664
+ 'size: boundary' => [ 'x' * 50, 'y' * 50 ],
6665
+ 'size: over' => [ 'x' * 50, 'y' * 50, 'z' ],
6666
+ 'count,size: boundary' => %w[ 1 2 3 4 5 6 7 8 9 0 ].map{|s| s * 10 },
6667
+ 'count,size: over' => %w[ 1 2 3 4 5 6 7 8 9 0 ].map{|s| s * 10 } + %w[ a ])
6668
+ def test_full?(data)
6669
+ response_list = data
6670
+ for response in response_list
6671
+ @res << response
6672
+ end
6673
+ assert_true(@res.full?)
6674
+ end
6675
+
6676
+ data('empty' => [],
6677
+ 'under' => %w[ foo bar baz ],
6678
+ 'count: boundary' => %w[ 1 2 3 4 5 6 7 8 9 ],
6679
+ 'size: boundary' => [ 'x' * 50, 'y' * 49 ])
6680
+ def test_not_full?(data)
6681
+ response_list = data
6682
+ for response in response_list
6683
+ @res << response
6684
+ end
6685
+ assert_false(@res.full?)
6686
+ end
6687
+
6688
+ def test_flush
6689
+ @res << 'foo'
6690
+ @res << 'bar'
6691
+ r1 = @res.flush
6692
+ assert_equal('foo' + 'bar', r1.join(''), 'responses may be joined.')
6693
+ assert_true(@res.empty?)
6694
+ assert_false(@res.full?)
6695
+
6696
+ @res << 'baz'
6697
+ r2 = @res.flush
6698
+ assert_equal('baz', r2.join(''), 'responses may be joined.')
6699
+ assert_true(@res.empty?)
6700
+ assert_false(@res.full?)
6701
+
6702
+ assert_not_equal(r1, r2)
6703
+ end
6704
+
6705
+ def test_flush_joined
6706
+ for c in ('a'..).first(10)
6707
+ @res << c
6708
+ end
6709
+ assert_equal([ ('a'..).first(10).join('') ], @res.flush)
6710
+ assert_true(@res.empty?)
6711
+ assert_false(@res.full?)
6712
+ end
6713
+ end
6200
6714
  end
6201
6715
 
6202
6716
  # Local Variables: