sugar_utils 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/workflows/ci.yml +17 -0
- data/.gitignore +0 -1
- data/.rubocop.yml +30 -3
- data/.ruby-version +1 -0
- data/CHANGELOG.md +23 -0
- data/README.md +47 -19
- data/Rakefile +36 -8
- data/doc/dependency_decisions.yml +25 -0
- data/features/append_file.feature +46 -0
- data/features/atomic_write_file.feature +46 -0
- data/features/change_file_access.feature +27 -0
- data/features/ensure_boolean.feature +34 -0
- data/features/ensure_integer.feature +19 -0
- data/features/lock_file.feature +26 -0
- data/features/read_file.feature +30 -0
- data/features/read_json_file.feature +43 -0
- data/features/scrub_encoding.feature +25 -0
- data/features/step_definitions/steps.rb +38 -0
- data/features/support/env.rb +34 -0
- data/features/touch_file.feature +28 -0
- data/features/write_file.feature +46 -0
- data/features/write_json_file.feature +52 -0
- data/lib/sugar_utils/file/write_options.rb +56 -0
- data/lib/sugar_utils/file.rb +219 -76
- data/lib/sugar_utils/version.rb +1 -2
- data/lib/sugar_utils.rb +34 -4
- data/spec/spec_helper.rb +8 -6
- data/spec/sugar_utils/file/write_options_spec.rb +77 -0
- data/spec/sugar_utils/file_spec.rb +392 -80
- data/spec/sugar_utils_spec.rb +41 -13
- data/sugar_utils.gemspec +21 -13
- metadata +125 -40
- data/.travis.yml +0 -22
@@ -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',
|
120
|
+
context 'when file present' do
|
121
|
+
before { write('filename', 'foobar') }
|
59
122
|
|
60
|
-
|
123
|
+
# rubocop:disable RSpec/NestedGroups
|
124
|
+
context 'when locked' do
|
61
125
|
let(:options) { { key: :value } }
|
126
|
+
|
62
127
|
before do
|
63
|
-
|
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 '
|
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,
|
79
|
-
it_with false,
|
80
|
-
it_with
|
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
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
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
|
-
|
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
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
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
|
-
|
167
|
-
|
168
|
-
|
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
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
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 '
|
181
|
-
let(:
|
182
|
-
|
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
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
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
|
-
|
197
|
-
|
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
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
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
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
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(:
|
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
|
-
|
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]
|
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]
|
241
|
-
# @param [String]
|
552
|
+
# @param filename [String]
|
553
|
+
# @param content [String]
|
242
554
|
#
|
243
555
|
# @overload write(filename, content, perm)
|
244
|
-
# @param [String]
|
245
|
-
# @param [String]
|
246
|
-
# @param [Integer]
|
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)
|
data/spec/sugar_utils_spec.rb
CHANGED
@@ -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
|
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,
|
16
|
-
it_with false,
|
17
|
-
it_with true,
|
18
|
-
it_with
|
19
|
-
it_with
|
20
|
-
it_with
|
21
|
-
it_with
|
22
|
-
it_with
|
23
|
-
it_with
|
24
|
-
it_with
|
25
|
-
it_with
|
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
|