rims 0.2.8 → 0.2.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -232,7 +232,7 @@ module RIMS
232
232
  @mail_store = mail_store
233
233
  @folder = folder
234
234
  @charset_aliases = charset_aliases
235
- @charset_convert_options = charset_convert_options
235
+ @charset_convert_options = charset_convert_options || {}
236
236
  @charset = nil
237
237
  @mail_cache = Hash.new{|hash, uid|
238
238
  if (msg_txt = @mail_store.msg_text(@folder.mbox_id, uid)) then
@@ -269,7 +269,7 @@ module RIMS
269
269
  if (string.encoding == @charset) then
270
270
  string
271
271
  else
272
- string.encode(@charset, @charset_convert_options)
272
+ string.encode(@charset, **@charset_convert_options)
273
273
  end
274
274
  end
275
275
  private :encode_charset
@@ -118,6 +118,7 @@ module RIMS
118
118
  # daemon:
119
119
  # daemonize: true
120
120
  # debug: false
121
+ # umask: 0037
121
122
  # status_file: rims.pid
122
123
  # server_polling_interval_seconds: 3
123
124
  # server_privileged_user: nobody
@@ -418,6 +419,10 @@ module RIMS
418
419
  end
419
420
  end
420
421
 
422
+ def daemon_umask
423
+ @config.dig('daemon', 'umask') || 0037
424
+ end
425
+
421
426
  def status_file
422
427
  file_path = @config.dig('daemon', 'status_file') || 'rims.pid'
423
428
  file_path = Pathname(file_path)
@@ -799,16 +804,16 @@ module RIMS
799
804
  using Logger::JointPlus
800
805
 
801
806
  def setup(server, daemon: false)
802
- file_logger_params = @config.make_file_logger_params
803
- logger = Logger.new(*file_logger_params)
807
+ *file_logger_params, file_logger_opts = @config.make_file_logger_params
808
+ logger = Logger.new(*file_logger_params, **file_logger_opts)
804
809
 
805
- stdout_logger_params = @config.make_stdout_logger_params
810
+ *stdout_logger_params, stdout_logger_opts = @config.make_stdout_logger_params
806
811
  unless (daemon && @config.daemonize?) then
807
- logger += Logger.new(*stdout_logger_params)
812
+ logger += Logger.new(*stdout_logger_params, **stdout_logger_opts)
808
813
  end
809
814
 
810
- protocol_logger_params = @config.make_protocol_logger_params
811
- protocol_logger = Logger.new(*protocol_logger_params)
815
+ *protocol_logger_params, protocol_logger_opts = @config.make_protocol_logger_params
816
+ protocol_logger = Logger.new(*protocol_logger_params, **protocol_logger_opts)
812
817
 
813
818
  logger.info('preload libraries.')
814
819
  Riser.preload
@@ -892,17 +897,17 @@ module RIMS
892
897
  file_logger_params[1..-2].each_with_index do |value, i|
893
898
  logger.info("file logging parameter: shift_args[#{i}]=#{value}")
894
899
  end
895
- for name, value in file_logger_params[-1]
900
+ for name, value in file_logger_opts
896
901
  logger.info("file logging parameter: #{name}=#{value}")
897
902
  end
898
- for name, value in stdout_logger_params[-1]
903
+ for name, value in stdout_logger_opts
899
904
  logger.info("stdout logging parameter: #{name}=#{value}")
900
905
  end
901
906
  logger.info("protocol logging parameter: path=#{protocol_logger_params[0]}")
902
907
  protocol_logger_params[1..-2].each_with_index do |value, i|
903
908
  logger.info("protocol logging parameter: shift_args[#{i}]=#{value}")
904
909
  end
905
- for name, value in protocol_logger_params[-1]
910
+ for name, value in protocol_logger_opts
906
911
  logger.info("protocol logging parameter: #{name}=#{value}")
907
912
  end
908
913
  logger.info("listen address: #{server_socket.local_address.inspect_sockaddr}")
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  module RIMS
4
- VERSION = '0.2.8'
4
+ VERSION = '0.2.9'
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
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.required_ruby_version = '>= 2.0.0'
28
28
 
29
29
  spec.add_runtime_dependency 'rims-rfc822', '>= 0.2.2'
30
- spec.add_runtime_dependency 'riser', '>= 0.1.11'
30
+ spec.add_runtime_dependency 'riser', '>= 0.1.12'
31
31
  spec.add_runtime_dependency 'logger-joint'
32
32
  spec.add_development_dependency 'bundler'
33
33
  spec.add_development_dependency 'rake'
@@ -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} ] ],
@@ -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)
@@ -5,6 +5,18 @@ require 'test/unit'
5
5
 
6
6
  module RIMS::Test
7
7
  class TestError < 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|
@@ -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
 
@@ -1966,7 +1964,7 @@ module RIMS::Test
1966
1964
  }
1967
1965
 
1968
1966
  assert_imap_command('SELECT INBOX') {|assert|
1969
- assert.skip_while{|line| line =~ /^\* /}
1967
+ assert.skip_while{|line| line =~ /^\* / }
1970
1968
  assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
1971
1969
  }
1972
1970
 
@@ -5215,7 +5213,7 @@ module RIMS::Test
5215
5213
  }
5216
5214
 
5217
5215
  assert_imap_command('SELECT INBOX') {|assert|
5218
- assert.skip_while{|line| line =~ /^\* /}
5216
+ assert.skip_while{|line| line =~ /^\* / }
5219
5217
  assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
5220
5218
  }
5221
5219
 
@@ -5242,7 +5240,7 @@ module RIMS::Test
5242
5240
  }
5243
5241
 
5244
5242
  assert_imap_command('EXAMINE INBOX') {|assert|
5245
- assert.skip_while{|line| line =~ /^\* /}
5243
+ assert.skip_while{|line| line =~ /^\* / }
5246
5244
  assert.equal("#{tag} OK [READ-ONLY] EXAMINE completed")
5247
5245
  }
5248
5246
 
@@ -5303,7 +5301,7 @@ module RIMS::Test
5303
5301
  }
5304
5302
 
5305
5303
  assert_imap_command('SELECT INBOX') {|assert|
5306
- assert.skip_while{|line| line =~ /^\* /}
5304
+ assert.skip_while{|line| line =~ /^\* / }
5307
5305
  assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
5308
5306
  }
5309
5307
 
@@ -5349,7 +5347,7 @@ module RIMS::Test
5349
5347
  }
5350
5348
 
5351
5349
  assert_imap_command('EXAMINE INBOX') {|assert|
5352
- assert.skip_while{|line| line =~ /^\* /}
5350
+ assert.skip_while{|line| line =~ /^\* / }
5353
5351
  assert.equal("#{tag} OK [READ-ONLY] EXAMINE completed")
5354
5352
  }
5355
5353
 
@@ -5730,7 +5728,7 @@ module RIMS::Test
5730
5728
  }
5731
5729
 
5732
5730
  assert_imap_command('SELECT INBOX') {|assert|
5733
- assert.skip_while{|line| line =~ /^\* /}
5731
+ assert.skip_while{|line| line =~ /^\* / }
5734
5732
  assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
5735
5733
  }
5736
5734
 
@@ -5754,7 +5752,7 @@ module RIMS::Test
5754
5752
  }
5755
5753
 
5756
5754
  assert_imap_command('SELECT INBOX') {|assert|
5757
- assert.skip_while{|line| line =~ /^\* /}
5755
+ assert.skip_while{|line| line =~ /^\* / }
5758
5756
  assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
5759
5757
  }
5760
5758
 
@@ -5778,7 +5776,7 @@ module RIMS::Test
5778
5776
  }
5779
5777
 
5780
5778
  assert_imap_command('SELECT INBOX') {|assert|
5781
- assert.skip_while{|line| line =~ /^\* /}
5779
+ assert.skip_while{|line| line =~ /^\* / }
5782
5780
  assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
5783
5781
  }
5784
5782
 
@@ -5806,7 +5804,7 @@ module RIMS::Test
5806
5804
  }
5807
5805
 
5808
5806
  assert_imap_command('SELECT INBOX') {|assert|
5809
- assert.skip_while{|line| line =~ /^\* /}
5807
+ assert.skip_while{|line| line =~ /^\* / }
5810
5808
  assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
5811
5809
  }
5812
5810
 
@@ -5839,10 +5837,8 @@ module RIMS::Test
5839
5837
  }
5840
5838
 
5841
5839
  another_decoder = make_decoder
5842
- another_writer = proc{|res|
5843
- for line in res
5844
- p line if $DEBUG
5845
- end
5840
+ another_writer = proc{|response|
5841
+ p response if $DEBUG
5846
5842
  }
5847
5843
 
5848
5844
  another_decoder.login('tag', 'foo', 'open_sesame', &another_writer)
@@ -6117,10 +6113,8 @@ module RIMS::Test
6117
6113
  }
6118
6114
 
6119
6115
  another_decoder = make_decoder
6120
- another_writer = proc{|res|
6121
- for line in res
6122
- p line if $DEBUG
6123
- end
6116
+ another_writer = proc{|response|
6117
+ p response if $DEBUG
6124
6118
  }
6125
6119
 
6126
6120
  another_decoder.login('tag', 'foo', 'open_sesame', &another_writer)
@@ -6212,7 +6206,7 @@ module RIMS::Test
6212
6206
  end
6213
6207
 
6214
6208
  assert_imap_command('SELECT INBOX') {|assert|
6215
- assert.skip_while{|line| line =~ /^\* /}
6209
+ assert.skip_while{|line| line =~ /^\* / }
6216
6210
  assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
6217
6211
  }
6218
6212
 
@@ -6293,7 +6287,7 @@ module RIMS::Test
6293
6287
  end
6294
6288
 
6295
6289
  assert_imap_command('SELECT INBOX') {|assert|
6296
- assert.skip_while{|line| line =~ /^\* /}
6290
+ assert.skip_while{|line| line =~ /^\* / }
6297
6291
  assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
6298
6292
  }
6299
6293
 
@@ -6341,7 +6335,7 @@ module RIMS::Test
6341
6335
 
6342
6336
  def test_charset_convert_options_stream
6343
6337
  use_imap_stream_decode_engine
6344
- test_charset_aliases
6338
+ test_charset_convert_options
6345
6339
  end
6346
6340
  end
6347
6341
 
@@ -6365,6 +6359,93 @@ module RIMS::Test
6365
6359
  assert_equal(%w[ foo INBOX ], RIMS::Protocol::Decoder.decode_delivery_target_mailbox(encoded_mbox_name))
6366
6360
  end
6367
6361
  end
6362
+
6363
+ class ProtocolDecoderBulkResponseTest < Test::Unit::TestCase
6364
+ def setup
6365
+ limit_count = 10
6366
+ limit_size = 100
6367
+ @res = RIMS::Protocol::Decoder::BulkResponse.new(limit_count, limit_size)
6368
+ end
6369
+
6370
+ data('empty' => [ 0, 0, [] ],
6371
+ '1' => [ 1, 3, %w[ foo ] ],
6372
+ '2' => [ 2, 6, %w[ foo bar ] ],
6373
+ '3' => [ 3, 11, %w[ foo bar baaaz ] ])
6374
+ def test_add(data)
6375
+ expected_count, expected_size, response_list = data
6376
+
6377
+ assert_equal(0, @res.count)
6378
+ assert_equal(0, @res.size)
6379
+
6380
+ for response in response_list
6381
+ @res << response
6382
+ end
6383
+
6384
+ assert_equal(expected_count, @res.count)
6385
+ assert_equal(expected_size, @res.size)
6386
+ end
6387
+
6388
+ def test_emtpy?
6389
+ assert_true(@res.empty?)
6390
+ end
6391
+
6392
+ def test_not_empty?
6393
+ @res << 'foo'
6394
+ assert_false(@res.empty?)
6395
+ end
6396
+
6397
+ data('count: boundary' => %w[ 1 2 3 4 5 6 7 8 9 0 ],
6398
+ 'count: over' => %w[ 1 2 3 4 5 6 7 8 9 0 a ],
6399
+ 'size: boundary' => [ 'x' * 50, 'y' * 50 ],
6400
+ 'size: over' => [ 'x' * 50, 'y' * 50, 'z' ],
6401
+ 'count,size: boundary' => %w[ 1 2 3 4 5 6 7 8 9 0 ].map{|s| s * 10 },
6402
+ 'count,size: over' => %w[ 1 2 3 4 5 6 7 8 9 0 ].map{|s| s * 10 } + %w[ a ])
6403
+ def test_full?(data)
6404
+ response_list = data
6405
+ for response in response_list
6406
+ @res << response
6407
+ end
6408
+ assert_true(@res.full?)
6409
+ end
6410
+
6411
+ data('empty' => [],
6412
+ 'under' => %w[ foo bar baz ],
6413
+ 'count: boundary' => %w[ 1 2 3 4 5 6 7 8 9 ],
6414
+ 'size: boundary' => [ 'x' * 50, 'y' * 49 ])
6415
+ def test_not_full?(data)
6416
+ response_list = data
6417
+ for response in response_list
6418
+ @res << response
6419
+ end
6420
+ assert_false(@res.full?)
6421
+ end
6422
+
6423
+ def test_flush
6424
+ @res << 'foo'
6425
+ @res << 'bar'
6426
+ r1 = @res.flush
6427
+ assert_equal('foo' + 'bar', r1.join(''), 'responses may be joined.')
6428
+ assert_true(@res.empty?)
6429
+ assert_false(@res.full?)
6430
+
6431
+ @res << 'baz'
6432
+ r2 = @res.flush
6433
+ assert_equal('baz', r2.join(''), 'responses may be joined.')
6434
+ assert_true(@res.empty?)
6435
+ assert_false(@res.full?)
6436
+
6437
+ assert_not_equal(r1, r2)
6438
+ end
6439
+
6440
+ def test_flush_joined
6441
+ for c in ('a'..).first(10)
6442
+ @res << c
6443
+ end
6444
+ assert_equal([ ('a'..).first(10).join('') ], @res.flush)
6445
+ assert_true(@res.empty?)
6446
+ assert_false(@res.full?)
6447
+ end
6448
+ end
6368
6449
  end
6369
6450
 
6370
6451
  # Local Variables: