sugar_utils 0.5.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,3 @@
1
- # encoding : utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require 'spec_helper'
@@ -6,7 +5,9 @@ require 'spec_helper'
6
5
  describe SugarUtils::File do
7
6
  describe '.flock_shared' do
8
7
  subject { described_class.flock_shared(file, options) }
8
+
9
9
  let(:file) { instance_double(File) }
10
+
10
11
  before do
11
12
  allow(Timeout).to receive(:timeout).with(expected_timeout).and_yield
12
13
  expect(file).to receive(:flock).with(::File::LOCK_SH)
@@ -20,7 +21,9 @@ describe SugarUtils::File do
20
21
 
21
22
  describe '.flock_exclusive' do
22
23
  subject { described_class.flock_exclusive(file, options) }
24
+
23
25
  let(:file) { instance_double(File) }
26
+
24
27
  before do
25
28
  allow(Timeout).to receive(:timeout).with(expected_timeout).and_yield
26
29
  expect(file).to receive(:flock).with(::File::LOCK_EX)
@@ -32,6 +35,65 @@ describe SugarUtils::File do
32
35
  side_effects_with Hash[timeout: 5], 5
33
36
  end
34
37
 
38
+ describe '.change_access', :fakefs do
39
+ subject do
40
+ described_class.change_access(filename, owner, group, permission)
41
+ end
42
+
43
+ let(:filename) { 'filename' }
44
+
45
+ context 'when file does not exist' do
46
+ let(:owner) { 'nobody' }
47
+ let(:group) { 'nogroup' }
48
+ let(:permission) { 0o777 }
49
+
50
+ it { expect_raise_error("Unable to change access on #{filename}") }
51
+ end
52
+
53
+ context 'when file exists' do
54
+ before { write(filename, 'foobar') }
55
+
56
+ context 'with no values specified' do # rubocop:disable RSpec/NestedGroups
57
+ let(:owner) { nil }
58
+ let(:group) { nil }
59
+ let(:permission) { nil }
60
+
61
+ it { expect_not_to_raise_error }
62
+ its_side_effects_are do
63
+ expect(filename).not_to have_owner('nobody')
64
+ expect(filename).not_to have_group('nogroup')
65
+ expect(filename).not_to have_file_permission(0o100777)
66
+ end
67
+ end
68
+
69
+ context 'with all values(Integer) specified' do # rubocop:disable RSpec/NestedGroups
70
+ let(:owner) { Etc.getpwnam('nobody').uid }
71
+ let(:group) { Etc.getgrnam('nogroup').gid }
72
+ let(:permission) { 0o777 }
73
+
74
+ it { expect_not_to_raise_error }
75
+ its_side_effects_are do
76
+ expect(filename).to have_owner('nobody')
77
+ expect(filename).to have_group('nogroup')
78
+ expect(filename).to have_file_permission(0o100777)
79
+ end
80
+ end
81
+
82
+ context 'with all values specified' do # rubocop:disable RSpec/NestedGroups
83
+ let(:owner) { 'nobody' }
84
+ let(:group) { 'nogroup' }
85
+ let(:permission) { 0o777 }
86
+
87
+ it { expect_not_to_raise_error }
88
+ its_side_effects_are do
89
+ expect(filename).to have_owner('nobody')
90
+ expect(filename).to have_group('nogroup')
91
+ expect(filename).to have_file_permission(0o100777)
92
+ end
93
+ end
94
+ end
95
+ end
96
+
35
97
  describe '.read', :fakefs do
36
98
  subject { described_class.read('filename', options) }
37
99
 
@@ -45,43 +107,49 @@ describe SugarUtils::File do
45
107
  it_with Hash[raise_on_missing: false, value_on_missing: 'hi'], 'hi'
46
108
  end
47
109
 
48
- context 'missing file' do
110
+ context 'when missing file' do
49
111
  it_behaves_like 'handles the missing file error'
50
112
  end
51
113
 
52
114
  context 'with IOError' do
53
115
  before { allow(File).to receive(:open).and_raise(IOError) }
116
+
54
117
  it_behaves_like 'handles the missing file error'
55
118
  end
56
119
 
57
- context 'file present' do
58
- before { write('filename', "foo\x92bar") }
120
+ context 'when file present' do
121
+ before { write('filename', 'foobar') }
59
122
 
60
- context 'and locked' do
123
+ # rubocop:disable RSpec/NestedGroups
124
+ context 'when locked' do
61
125
  let(:options) { { key: :value } }
126
+
62
127
  before do
63
- expect(described_class).to receive(:flock_shared)
128
+ allow(described_class).to receive(:flock_shared)
64
129
  .with(kind_of(File), options)
65
130
  .and_raise(Timeout::Error)
66
131
  end
132
+
67
133
  it { expect_raise_error('Cannot read filename because it is locked') }
68
134
  end
69
135
 
70
- context 'and unlocked' do
136
+ context 'when unlocked' do
71
137
  let(:options) { { key: :value, scrub_encoding: scrub_encoding } }
138
+
72
139
  before do
73
140
  expect(described_class).to receive(:flock_shared)
74
141
  .with(kind_of(File), options)
142
+ allow(SugarUtils).to receive(:scrub_encoding)
143
+ .with('foobar', scrub_encoding)
144
+ .and_return(:scrubbed_data)
75
145
  end
76
146
 
77
147
  inputs :scrub_encoding
78
- it_with nil, "foo\x92bar"
79
- it_with false, "foo\x92bar"
80
- it_with true, 'foobar'
81
- it_with '', 'foobar'
82
- it_with 'x', 'fooxbar'
83
- it_with 'xxx', 'fooxxxbar'
148
+ it_with nil, 'foobar'
149
+ it_with false, 'foobar'
150
+ it_with :scrub_encoding, :scrubbed_data
84
151
  end
152
+ # rubocop:enable RSpec/NestedGroups
85
153
  end
86
154
  end
87
155
 
@@ -94,7 +162,7 @@ describe SugarUtils::File do
94
162
 
95
163
  before do
96
164
  allow(described_class).to receive(:read)
97
- .with(:filename, key: :value, value_on_missing: :missing)
165
+ .with(:filename, { key: :value, value_on_missing: :missing })
98
166
  .and_return(file_content)
99
167
  end
100
168
 
@@ -110,109 +178,241 @@ describe SugarUtils::File do
110
178
 
111
179
  let(:filename) { 'path1/path2/filename' }
112
180
 
113
- before { subject }
114
-
115
- inputs :options # rubocop:disable ExtraSpacing, SpaceBeforeFirstArg
116
- specify_with([]) { expect(File.exist?(filename)).to eq(true) }
117
- specify_with([{ owner: 'nobody' }]) { expect(filename).to have_owner('nobody') }
118
- specify_with([{ group: 'nogroup' }]) { expect(filename).to have_group('nogroup') }
119
- specify_with([{ mode: 0o600 }]) { expect(filename).to have_file_permission(0o100600) }
120
- specify_with([{ perm: 0o600 }]) { expect(filename).to have_file_permission(0o100600) }
121
- specify_with([{ mtime: 0 }]) { expect(filename).to have_mtime(0) }
122
- specify_with([{ owner: 'nobody', group: 'nogroup', mode: 0o600, mtime: 0 }]) do
123
- expect(filename).to have_owner('nobody')
124
- expect(filename).to have_group('nogroup')
125
- expect(filename).to have_file_permission(0o100600)
126
- expect(filename).to have_mtime(0)
181
+ context 'without options' do
182
+ let(:options) { [] }
183
+
184
+ it { expect_not_to_raise_error }
185
+ its_side_effects_are { expect(File.exist?(filename)).to be(true) }
186
+ end
187
+
188
+ context 'with options, and :mode key' do
189
+ let(:options) { [{ owner: 'nobody', group: 'nogroup', mode: 0o600, mtime: 0 }] }
190
+
191
+ it { expect_not_to_raise_error }
192
+ its_side_effects_are do
193
+ expect(filename).to have_owner('nobody')
194
+ expect(filename).to have_group('nogroup')
195
+ expect(filename).to have_file_permission(0o100600)
196
+ expect(filename).to have_mtime(0)
197
+ end
198
+ end
199
+
200
+ context 'with options, and :perm key' do
201
+ let(:options) { [{ owner: 'nobody', group: 'nogroup', perm: 0o600, mtime: 0 }] }
202
+
203
+ it { expect_not_to_raise_error }
204
+ its_side_effects_are do
205
+ expect(filename).to have_owner('nobody')
206
+ expect(filename).to have_group('nogroup')
207
+ expect(filename).to have_file_permission(0o100600)
208
+ expect(filename).to have_mtime(0)
209
+ end
127
210
  end
128
211
  end
129
212
 
130
213
  describe '.write', :fakefs do
131
214
  subject { described_class.write(filename, data, options) }
215
+
132
216
  let(:data) { 'content' }
133
217
  let(:filename) { 'dir1/dir2/filename' }
134
218
 
135
- context 'SystemCallError' do
219
+ context 'when SystemCallError' do
136
220
  let(:options) { {} }
137
221
  let(:exception) { SystemCallError.new(nil) }
222
+
138
223
  before { allow(File).to receive(:open).and_raise(exception) }
224
+
139
225
  it { expect_raise_error("Unable to write #{filename} with #{exception}") }
140
226
  end
141
227
 
142
- context 'IOError' do
228
+ context 'when IOError' do
143
229
  let(:options) { {} }
144
230
  let(:exception) { IOError.new(nil) }
231
+
145
232
  before { allow(File).to receive(:open).and_raise(exception) }
233
+
146
234
  it { expect_raise_error("Unable to write #{filename} with #{exception}") }
147
235
  end
148
236
 
149
- context 'locked' do
237
+ context 'when locked' do
150
238
  let(:options) { {} }
239
+
151
240
  before do
152
- expect(described_class).to receive(:flock_exclusive)
241
+ allow(described_class).to receive(:flock_exclusive)
153
242
  .with(kind_of(File), options)
154
243
  .and_raise(Timeout::Error)
155
244
  end
245
+
156
246
  it { expect_raise_error("Unable to write #{filename} because it is locked") }
157
247
  end
158
248
 
159
- context 'unlocked' do
160
- shared_examples_for 'file is written' do
161
- before do
162
- expect(described_class).to receive(:flock_exclusive)
163
- .with(kind_of(File), options)
249
+ shared_examples_for 'file is correctly written' do
250
+ before do
251
+ expect(described_class).to receive(:flock_exclusive)
252
+ .with(kind_of(File), options)
253
+ end
254
+
255
+ # rubocop:disable RSpec/NestedGroups
256
+ context 'without options' do
257
+ let(:options) { {} }
258
+
259
+ it { expect_not_to_raise_error }
260
+ its_side_effects_are do
261
+ expect(filename).to have_content(data)
262
+ expect(filename).to have_file_permission(0o100644)
164
263
  end
264
+ end
165
265
 
166
- context 'default options' do
167
- let(:options) { {} }
168
- before { subject }
169
- specify { expect(filename).to have_content(data) }
170
- specify { expect(filename).to have_file_permission(0o100644) }
266
+ context 'with options' do
267
+ let(:options) do
268
+ { flush: true, owner: 'nobody', group: 'nogroup', mode_or_perm_key => 0o600 }
171
269
  end
172
270
 
173
- context 'with deprecated options' do
174
- let(:options) { { mode: 0o600 } }
175
- before { subject }
176
- specify { expect(filename).to have_content(data) }
177
- specify { expect(filename).to have_file_permission(0o100600) }
271
+ before do
272
+ # rubocop:disable RSpec/AnyInstance
273
+ expect_any_instance_of(File).to receive(:flush)
274
+ expect_any_instance_of(File).to receive(:fsync)
275
+ # rubocop:enable RSpec/AnyInstance
178
276
  end
179
277
 
180
- context 'without deprecated options' do
181
- let(:options) do
182
- { flush: true, owner: 'nobody', group: 'nogroup', mode: 'w', perm: 0o600 }
278
+ context 'with mode key' do
279
+ let(:mode_or_perm_key) { :mode }
280
+
281
+ it { expect_not_to_raise_error }
282
+ its_side_effects_are do
283
+ expect(filename).to have_content(data)
284
+ expect(filename).to have_owner('nobody')
285
+ expect(filename).to have_group('nogroup')
286
+ expect(filename).to have_file_permission(0o100600)
183
287
  end
184
- before do
185
- expect_any_instance_of(File).to receive(:flush)
186
- expect_any_instance_of(File).to receive(:fsync)
187
- subject
288
+ end
289
+
290
+ context 'with perm key' do
291
+ let(:mode_or_perm_key) { :perm }
292
+
293
+ it { expect_not_to_raise_error }
294
+ its_side_effects_are do
295
+ expect(filename).to have_content(data)
296
+ expect(filename).to have_owner('nobody')
297
+ expect(filename).to have_group('nogroup')
298
+ expect(filename).to have_file_permission(0o100600)
188
299
  end
189
- specify { expect(filename).to have_content(data) }
190
- specify { expect(filename).to have_owner('nobody') }
191
- specify { expect(filename).to have_group('nogroup') }
192
- specify { expect(filename).to have_file_permission(0o100600) }
193
300
  end
194
301
  end
302
+ # rubocop:enable RSpec/NestedGroups
303
+ end
304
+
305
+ context 'when file does not exist' do
306
+ it_behaves_like 'file is correctly written'
307
+ end
308
+
309
+ context 'when file exists' do
310
+ before { write(filename, 'foobar', 0o777) }
311
+
312
+ it_behaves_like 'file is correctly written'
313
+ end
314
+ end
315
+
316
+ describe '.atomic_write', :fakefs do
317
+ subject { described_class.atomic_write(filename, data, options) }
195
318
 
196
- context 'and not exist' do
197
- it_behaves_like 'file is written'
319
+ let(:data) { 'content' }
320
+ let(:filename) { 'dir1/dir2/filename' }
321
+
322
+ context 'when SystemCallError' do
323
+ let(:options) { {} }
324
+ let(:exception) { SystemCallError.new(nil) }
325
+
326
+ before { allow(File).to receive(:open).and_raise(exception) }
327
+
328
+ it { expect_raise_error("Unable to write #{filename} with #{exception}") }
329
+ end
330
+
331
+ context 'when IOError' do
332
+ let(:options) { {} }
333
+ let(:exception) { IOError.new(nil) }
334
+
335
+ before { allow(File).to receive(:open).and_raise(exception) }
336
+
337
+ it { expect_raise_error("Unable to write #{filename} with #{exception}") }
338
+ end
339
+
340
+ context 'when locked' do
341
+ let(:options) { {} }
342
+
343
+ before do
344
+ allow(described_class).to receive(:flock_exclusive)
345
+ .with(kind_of(File), options)
346
+ .and_raise(Timeout::Error)
347
+ end
348
+
349
+ it { expect_raise_error("Unable to write #{filename} because it is locked") }
350
+ end
351
+
352
+ shared_examples_for 'file is correctly written' do
353
+ before do
354
+ expect(described_class).to receive(:flock_exclusive)
355
+ .with(kind_of(File), options)
198
356
  end
199
357
 
200
- context 'and exists' do
201
- before { write(filename, 'foobar', 0o777) }
202
- context 'not locked' do
203
- it_behaves_like 'file is written'
358
+ # rubocop:disable RSpec/NestedGroups
359
+ context 'without options' do
360
+ let(:options) { {} }
361
+
362
+ it { expect_not_to_raise_error }
363
+ its_side_effects_are do
364
+ expect(filename).to have_content(data)
365
+ expect(filename).to have_file_permission(0o100644)
366
+ end
367
+ end
204
368
 
205
- context 'with append mode' do
206
- let(:options) { { mode: 'a+' } }
207
- before do
208
- expect(described_class).to receive(:flock_exclusive)
209
- .with(kind_of(File), options)
210
- subject
211
- end
212
- specify { expect(filename).to have_content("foobar#{data}") }
369
+ context 'with options' do
370
+ let(:options) do
371
+ { flush: true, owner: 'nobody', group: 'nogroup', mode_or_perm_key => 0o600 }
372
+ end
373
+
374
+ before do
375
+ # rubocop:disable RSpec/AnyInstance
376
+ expect_any_instance_of(File).to receive(:flush)
377
+ expect_any_instance_of(File).to receive(:fsync)
378
+ # rubocop:enable RSpec/AnyInstance
379
+ end
380
+
381
+ context 'with mode key' do
382
+ let(:mode_or_perm_key) { :mode }
383
+
384
+ it { expect_not_to_raise_error }
385
+ its_side_effects_are do
386
+ expect(filename).to have_content(data)
387
+ expect(filename).to have_owner('nobody')
388
+ expect(filename).to have_group('nogroup')
389
+ expect(filename).to have_file_permission(0o100600)
390
+ end
391
+ end
392
+
393
+ context 'with perm key' do
394
+ let(:mode_or_perm_key) { :perm }
395
+
396
+ it { expect_not_to_raise_error }
397
+ its_side_effects_are do
398
+ expect(filename).to have_content(data)
399
+ expect(filename).to have_owner('nobody')
400
+ expect(filename).to have_group('nogroup')
401
+ expect(filename).to have_file_permission(0o100600)
213
402
  end
214
403
  end
215
404
  end
405
+ # rubocop:enable RSpec/NestedGroups
406
+ end
407
+
408
+ context 'when file does not exist' do
409
+ it_behaves_like 'file is correctly written'
410
+ end
411
+
412
+ context 'when file exists' do
413
+ before { write(filename, 'foobar', 0o777) }
414
+
415
+ it_behaves_like 'file is correctly written'
216
416
  end
217
417
  end
218
418
 
@@ -220,30 +420,142 @@ describe SugarUtils::File do
220
420
  subject { described_class.write_json(:filename, data, :options) }
221
421
 
222
422
  let(:data) { { 'key' => 'value' } }
423
+
223
424
  before do
224
- expect(described_class).to receive(:write).with(
425
+ expect(described_class).to receive(:atomic_write).with(
225
426
  :filename, MultiJson.dump(data, pretty: true), :options
226
427
  )
227
428
  end
228
429
 
229
- specify { subject }
430
+ it_has_side_effects
431
+ end
432
+
433
+ describe '.append', :fakefs do
434
+ subject { described_class.append(filename, data, options) }
435
+
436
+ let(:data) { 'content' }
437
+ let(:filename) { 'dir1/dir2/filename' }
438
+
439
+ context 'when SystemCallError' do
440
+ let(:options) { {} }
441
+ let(:exception) { SystemCallError.new(nil) }
442
+
443
+ before { allow(File).to receive(:open).and_raise(exception) }
444
+
445
+ it { expect_raise_error("Unable to write #{filename} with #{exception}") }
446
+ end
447
+
448
+ context 'when IOError' do
449
+ let(:options) { {} }
450
+ let(:exception) { IOError.new(nil) }
451
+
452
+ before { allow(File).to receive(:open).and_raise(exception) }
453
+
454
+ it { expect_raise_error("Unable to write #{filename} with #{exception}") }
455
+ end
456
+
457
+ context 'when locked' do
458
+ let(:options) { {} }
459
+
460
+ before do
461
+ allow(described_class).to receive(:flock_exclusive)
462
+ .with(kind_of(File), options)
463
+ .and_raise(Timeout::Error)
464
+ end
465
+
466
+ it { expect_raise_error("Unable to write #{filename} because it is locked") }
467
+ end
468
+
469
+ shared_examples_for 'file is correctly appended' do
470
+ before do
471
+ expect(described_class).to receive(:flock_exclusive)
472
+ .with(kind_of(File), options)
473
+ end
474
+
475
+ # rubocop:disable RSpec/NestedGroups
476
+ context 'without options' do
477
+ let(:options) { {} }
478
+
479
+ it { expect_not_to_raise_error }
480
+ its_side_effects_are do
481
+ expect(filename).to have_content(expected_file_data)
482
+ expect(filename).to have_file_permission(0o100644)
483
+ end
484
+ end
485
+
486
+ context 'with options' do
487
+ let(:options) do
488
+ { flush: true, owner: 'nobody', group: 'nogroup', mode_or_perm_key => 0o600 }
489
+ end
490
+
491
+ before do
492
+ # rubocop:disable RSpec/AnyInstance
493
+ expect_any_instance_of(File).to receive(:flush)
494
+ expect_any_instance_of(File).to receive(:fsync)
495
+ # rubocop:enable RSpec/AnyInstance
496
+ end
497
+
498
+ context 'with mode key' do
499
+ let(:mode_or_perm_key) { :mode }
500
+
501
+ it { expect_not_to_raise_error }
502
+ its_side_effects_are do
503
+ expect(filename).to have_content(expected_file_data)
504
+ expect(filename).to have_owner('nobody')
505
+ expect(filename).to have_group('nogroup')
506
+ expect(filename).to have_file_permission(0o100600)
507
+ end
508
+ end
509
+
510
+ context 'with perm key' do
511
+ let(:mode_or_perm_key) { :perm }
512
+
513
+ it { expect_not_to_raise_error }
514
+ its_side_effects_are do
515
+ expect(filename).to have_content(expected_file_data)
516
+ expect(filename).to have_owner('nobody')
517
+ expect(filename).to have_group('nogroup')
518
+ expect(filename).to have_file_permission(0o100600)
519
+ end
520
+ end
521
+ end
522
+ # rubocop:enable RSpec/NestedGroups
523
+ end
524
+
525
+ context 'when file does not exist' do
526
+ let(:expected_file_data) { data }
527
+
528
+ it_behaves_like 'file is correctly appended'
529
+ end
530
+
531
+ context 'when file exists' do
532
+ let(:expected_file_data) { "foobar#{data}" }
533
+
534
+ before { write(filename, 'foobar', 0o777) }
535
+
536
+ it_behaves_like 'file is correctly appended'
537
+ end
230
538
  end
231
539
 
232
540
  ##############################################################################
233
541
 
234
- # @param [String] message
542
+ # @param message [String]
235
543
  def expect_raise_error(message)
236
544
  expect { subject }.to raise_error(described_class::Error, message)
237
545
  end
238
546
 
547
+ def expect_not_to_raise_error
548
+ expect { subject }.not_to raise_error
549
+ end
550
+
239
551
  # @overload write(filename, content)
240
- # @param [String] filename
241
- # @param [String] content
552
+ # @param filename [String]
553
+ # @param content [String]
242
554
  #
243
555
  # @overload write(filename, content, perm)
244
- # @param [String] filename
245
- # @param [String] content
246
- # @param [Integer] perm
556
+ # @param filename [String]
557
+ # @param content [String]
558
+ # @param perm [Integer]
247
559
  #
248
560
  # @return [void]
249
561
  def write(filename, content, perm = nil)
@@ -1,28 +1,38 @@
1
- # encoding : utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require 'spec_helper'
5
4
 
6
5
  describe SugarUtils do
7
6
  it 'has a version number' do
8
- expect(SugarUtils::VERSION).not_to be nil
7
+ expect(SugarUtils::VERSION).not_to be_nil
9
8
  end
10
9
 
11
10
  describe '.ensure_boolean' do
12
11
  subject { described_class.ensure_boolean(value) }
13
12
 
14
13
  inputs :value
15
- it_with nil, false
16
- it_with false, false
17
- it_with true, true
18
- it_with :value, true
19
- it_with 'value', true
20
- it_with 'false', false
21
- it_with 'FALSE', false
22
- it_with 'FaLsE', false
23
- it_with :false, false
24
- it_with :FALSE, false
25
- it_with :FaLsE, false
14
+ it_with nil, false
15
+ it_with false, false
16
+ it_with true, true
17
+ it_with 0, false
18
+ it_with 1, true
19
+ it_with 2, true
20
+ it_with 42, true
21
+ it_with :value, true
22
+ it_with 'value', true
23
+ it_with ' value ', true
24
+ it_with 'false', false
25
+ it_with ' false ', false
26
+ it_with "\n false \n", false
27
+ it_with 'FALSE', false
28
+ it_with ' FALSE ', false
29
+ it_with "\n FALSE \n", false
30
+ it_with 'FaLsE', false
31
+ it_with ' FaLsE ', false
32
+ it_with "\n FaLsE \n", false
33
+ it_with :false, false # rubocop:disable Lint/BooleanSymbol
34
+ it_with :FALSE, false
35
+ it_with :FaLsE, false
26
36
  end
27
37
 
28
38
  describe '.ensure_integer' do
@@ -37,4 +47,22 @@ describe SugarUtils do
37
47
  it_with '123', 123
38
48
  it_with '123.234', 123
39
49
  end
50
+
51
+ describe '.scrub_encoding' do
52
+ subject { described_class.scrub_encoding(data, *args) }
53
+
54
+ inputs :data, :args
55
+ it_with 'foobar', [], 'foobar'
56
+ it_with 'foobar', [nil], 'foobar'
57
+ it_with 'foobar', [111], 'foobar'
58
+ it_with 'foobar', [''], 'foobar'
59
+ it_with 'foobar', ['x'], 'foobar'
60
+ it_with 'foobar', ['xxx'], 'foobar'
61
+ it_with "foo\x92bar\x93", [], 'foobar'
62
+ it_with "foo\x92bar\x93", [nil], 'foobar'
63
+ it_with "foo\x92bar\x93", [111], 'foobar'
64
+ it_with "foo\x92bar\x93", [''], 'foobar'
65
+ it_with "foo\x92bar\x93", ['x'], 'fooxbarx'
66
+ it_with "foo\x92bar\x93", ['xxx'], 'fooxxxbarxxx'
67
+ end
40
68
  end