store_agent 1.0.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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +3 -0
  4. data/Gemfile +4 -0
  5. data/Guardfile +5 -0
  6. data/LICENSE +202 -0
  7. data/README.md +433 -0
  8. data/Rakefile +2 -0
  9. data/lib/store_agent.rb +31 -0
  10. data/lib/store_agent/config.rb +152 -0
  11. data/lib/store_agent/data_encoder.rb +32 -0
  12. data/lib/store_agent/data_encoder/gzip_encoder.rb +50 -0
  13. data/lib/store_agent/data_encoder/openssl_aes_256_cbc_encoder.rb +65 -0
  14. data/lib/store_agent/exceptions.rb +87 -0
  15. data/lib/store_agent/node.rb +26 -0
  16. data/lib/store_agent/node/attachment.rb +93 -0
  17. data/lib/store_agent/node/attachment/metadata.rb +120 -0
  18. data/lib/store_agent/node/attachment/permission.rb +121 -0
  19. data/lib/store_agent/node/object.rb +233 -0
  20. data/lib/store_agent/node/object/directory_object.rb +264 -0
  21. data/lib/store_agent/node/object/file_object.rb +197 -0
  22. data/lib/store_agent/node/object/virtual_object.rb +25 -0
  23. data/lib/store_agent/node/prepend_module/locker.rb +125 -0
  24. data/lib/store_agent/node/prepend_module/path_validator.rb +138 -0
  25. data/lib/store_agent/node/prepend_module/permission_checker.rb +96 -0
  26. data/lib/store_agent/user.rb +111 -0
  27. data/lib/store_agent/validator.rb +60 -0
  28. data/lib/store_agent/version.rb +19 -0
  29. data/lib/store_agent/version_manager.rb +101 -0
  30. data/lib/store_agent/version_manager/ruby_git.rb +100 -0
  31. data/lib/store_agent/version_manager/rugged_git.rb +133 -0
  32. data/lib/store_agent/workspace.rb +88 -0
  33. data/spec/spec_helper.rb +47 -0
  34. data/spec/store_agent/data_encoder/encoder_shared_context.rb +74 -0
  35. data/spec/store_agent/data_encoder/gzip_encoder_spec.rb +41 -0
  36. data/spec/store_agent/data_encoder/openssl_aes_256_cbc_encoder_spec.rb +42 -0
  37. data/spec/store_agent/data_encoder_spec.rb +78 -0
  38. data/spec/store_agent/node/directory_object_spec.rb +563 -0
  39. data/spec/store_agent/node/file_object_spec.rb +379 -0
  40. data/spec/store_agent/node/locker_spec.rb +191 -0
  41. data/spec/store_agent/node/metadata_spec.rb +339 -0
  42. data/spec/store_agent/node/object_spec.rb +73 -0
  43. data/spec/store_agent/node/path_validator_spec.rb +121 -0
  44. data/spec/store_agent/node/permission_spec.rb +232 -0
  45. data/spec/store_agent/user_spec.rb +127 -0
  46. data/spec/store_agent/version_manager/git_shared_context.rb +286 -0
  47. data/spec/store_agent/version_manager/ruby_git_spec.rb +32 -0
  48. data/spec/store_agent/version_manager/rugged_git_spec.rb +32 -0
  49. data/spec/store_agent/workspace_spec.rb +107 -0
  50. data/spec/store_agent_spec.rb +53 -0
  51. data/store_agent.gemspec +33 -0
  52. metadata +252 -0
@@ -0,0 +1,379 @@
1
+ #--
2
+ # Copyright 2015 realglobe, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #++
16
+
17
+ require "spec_helper"
18
+
19
+ RSpec.describe StoreAgent::Node::FileObject do
20
+ let :user do
21
+ StoreAgent::User.new("foo", "bar")
22
+ end
23
+ let :workspace do
24
+ user.workspace("test_file_workspace")
25
+ end
26
+ before do
27
+ workspace.create if !workspace.exists?
28
+ end
29
+
30
+ context "ファイル作成のテスト" do
31
+ context "引数が無い場合" do
32
+ it "空のファイルが作成される" do
33
+ workspace.file("foo.txt").create
34
+ expect(workspace.file("foo.txt").read).to eq ""
35
+ expect(workspace.file("foo.txt").file?).to eq true
36
+ end
37
+ end
38
+ context "引数に文字列を渡す場合" do
39
+ it "ファイルの中身はその文字列になる" do
40
+ workspace.file("bar.txt").create("bar")
41
+ expect(workspace.file("bar.txt").read).to eq "bar"
42
+ end
43
+ end
44
+ context "引数にハッシュを渡す場合" do
45
+ it "body パラメータがファイルの中身になる" do
46
+ workspace.file(".git").create("body" => "hoge")
47
+ expect(workspace.file(".git").read).to eq "hoge"
48
+ end
49
+ it "body パラメータはシンボルでも良い" do
50
+ workspace.file(".keep").create(body: "fuga")
51
+ expect(workspace.file(".keep").read).to eq "fuga"
52
+ end
53
+ end
54
+ context "引数にブロックを渡す場合" do
55
+ it "ファイルの中身は、ブロック内で body に設定した値になる" do
56
+ workspace.file("foobar.txt").create do |f|
57
+ f.body = "foobar"
58
+ end
59
+ expect(workspace.file("foobar.txt").read).to eq "foobar"
60
+ end
61
+ end
62
+ context "作成失敗するケース" do
63
+ it "既に同名のディレクトリがある場合、作成できない" do
64
+ workspace.directory("/foo").create
65
+ expect do
66
+ workspace.file("foo").create
67
+ end.to raise_error
68
+ end
69
+ it "既に同名のファイルがある場合、作成できない" do
70
+ workspace.file("hogefuga.txt").create
71
+ expect do
72
+ workspace.directory("hogefuga.txt").create
73
+ end.to raise_error
74
+ end
75
+ it "ファイル名がメタデータの拡張子で終わる場合、作成できない" do
76
+ expect do
77
+ workspace.file("hoge.meta").create
78
+ end.to raise_error
79
+ end
80
+ it "ファイル名がパーミッションデータの拡張子で終わる場合、作成できない" do
81
+ expect do
82
+ workspace.file("hoge.perm").create
83
+ end.to raise_error
84
+ end
85
+ end
86
+ end
87
+
88
+ context "ファイル更新のテスト" do
89
+ before do
90
+ file = workspace.file("update_test.txt")
91
+ if !file.exists?
92
+ file.create("1234567890")
93
+ end
94
+ end
95
+
96
+ context "引数が無い場合" do
97
+ it "エラーになる" do
98
+ expect do
99
+ workspace.file("update_test.txt").update
100
+ end.to raise_error
101
+ end
102
+ end
103
+ context "引数に文字列を渡す場合" do
104
+ it "ファイルの中身はその文字列になる" do
105
+ workspace.file("update_test.txt").update("update_01")
106
+ expect(workspace.file("update_test.txt").read).to eq "update_01"
107
+ end
108
+ end
109
+ context "引数にハッシュを渡す場合" do
110
+ it "body パラメータがファイルの中身になる" do
111
+ workspace.file("update_test.txt").update("update_02")
112
+ expect(workspace.file("update_test.txt").read).to eq "update_02"
113
+ end
114
+ it "body パラメータはシンボルでも良い" do
115
+ workspace.file("update_test.txt").update("update_03")
116
+ expect(workspace.file("update_test.txt").read).to eq "update_03"
117
+ end
118
+ end
119
+ context "引数にブロックを渡す場合" do
120
+ it "ファイルの中身は、ブロック内で body に設定した値になる" do
121
+ workspace.file("update_test.txt").update do |f|
122
+ f.body = "update_04"
123
+ end
124
+ expect(workspace.file("update_test.txt").read).to eq "update_04"
125
+ end
126
+ end
127
+ end
128
+
129
+ context "ファイル削除のテスト" do
130
+ before do
131
+ file = workspace.file("delete_test.txt")
132
+ if !file.exists?
133
+ file.create
134
+ end
135
+ end
136
+
137
+ context "削除権限がある場合" do
138
+ before do
139
+ workspace.file("delete_test.txt").delete
140
+ end
141
+
142
+ it "ファイルが削除される" do
143
+ expect(workspace.file("delete_test.txt").exists?).to be false
144
+ end
145
+ it "メタデータファイルが削除される" do
146
+ expect(File.exists?(workspace.file("delete_test.txt").metadata.file_path)).to be false
147
+ end
148
+ it "パーミッションファイルが削除される" do
149
+ expect(File.exists?(workspace.file("delete_test.txt").permission.file_path)).to be false
150
+ end
151
+ end
152
+ context "削除権限が無い場合" do
153
+ before do
154
+ begin
155
+ StoreAgent::User.new.workspace("test_file_workspace").file("delete_test.txt").delete
156
+ rescue
157
+ end
158
+ end
159
+
160
+ it "ファイルは削除されない" do
161
+ expect(workspace.file("delete_test.txt").exists?).to be true
162
+ end
163
+ it "メタデータファイルは削除されない" do
164
+ end
165
+ it "パーミッションファイルは削除されない" do
166
+ end
167
+ end
168
+ end
169
+
170
+ context "メタデータ取得のテスト" do
171
+ it "get_metadata でメタデータをハッシュ形式で取得できる" do
172
+ workspace.file("get_metadata.txt").create
173
+ expect(workspace.file("get_metadata.txt").get_metadata.class).to eq Hash
174
+ end
175
+ end
176
+
177
+ context "パーミッション情報取得のテスト" do
178
+ it "get_permissions でパーミッション情報をハッシュ形式で取得できる" do
179
+ workspace.file("get_permissions.txt").create
180
+ expect(workspace.file("get_permissions.txt").get_permissions.class).to eq Hash
181
+ end
182
+ end
183
+
184
+ context "オーナー変更のテスト" do
185
+ before do
186
+ if !(file = workspace.file("chown.txt")).exists?
187
+ file.create
188
+ end
189
+ end
190
+ it "userは権限がないので、オーナー変更できない" do
191
+ expect do
192
+ workspace.file("chown.txt").chown(identifier: "hoge")
193
+ end.to raise_error
194
+ end
195
+ it "superuserはオーナー変更できる" do
196
+ superuser = StoreAgent::Superuser.new
197
+ superuser.workspace("test_file_workspace").file("chown.txt").chown(identifier: "hoge")
198
+ expect(workspace.file("chown.txt").metadata["owner"]).to eq "hoge"
199
+ end
200
+ end
201
+
202
+ context "配下オブジェクトを取得しようとする" do
203
+ let :file do
204
+ workspace.file("search_children.txt")
205
+ end
206
+ before do
207
+ if !file.exists?
208
+ file.create
209
+ end
210
+ end
211
+
212
+ it "ディレクトリを取得しようとするとエラーになる" do
213
+ expect do
214
+ file.directory("hoge")
215
+ end.to raise_error
216
+ end
217
+ it "ファイルを取得しようとするとエラーになる" do
218
+ expect do
219
+ file.file("hoge.txt")
220
+ end.to raise_error
221
+ end
222
+ it "タイプが不明なオブジェクトを取得しようとするとエラーになる" do
223
+ expect do
224
+ file.find_object("hoge")
225
+ end.to raise_error
226
+ end
227
+ it "直下のファイル一覧を取得しようとすると、空の配列が返ってくる" do
228
+ expect(file.children).to eq []
229
+ end
230
+ end
231
+
232
+ context "ファイルのコピー" do
233
+ let :directory do
234
+ workspace.directory("copy")
235
+ end
236
+ let :src_file do
237
+ workspace.file("copy/src.txt")
238
+ end
239
+ before do
240
+ if !directory.exists?
241
+ directory.create
242
+ src_file.create("copy")
243
+ end
244
+ end
245
+
246
+ context "コピー先にオブジェクトが無い場合" do
247
+ it "コピー先にファイルが作成され、メタデータが更新される" do
248
+ dest_create_path = "copy/dest_create.txt"
249
+
250
+ prev_count = workspace.directory("copy").directory_file_count
251
+ src_file.copy(dest_create_path)
252
+ expect(workspace.file(dest_create_path).read).to eq "copy"
253
+ expect(workspace.directory("copy").directory_file_count).to eq prev_count + 1
254
+ end
255
+ end
256
+ context "コピー先にファイルが存在する場合" do
257
+ it "コピー先のファイルが上書きされ、メタデータが更新される" do
258
+ dest_update_path = "copy/dest_update.txt"
259
+ workspace.file(dest_update_path).create("dest update file")
260
+
261
+ prev_count = workspace.directory("copy").directory_file_count
262
+ prev_bytesize = workspace.file(dest_update_path).metadata["bytes"]
263
+ src_file.copy(dest_update_path)
264
+ expect(workspace.file(dest_update_path).read).to eq "copy"
265
+ expect(workspace.file(dest_update_path).metadata["bytes"]).to eq 4
266
+ expect(workspace.directory("copy").directory_file_count).to eq prev_count
267
+ end
268
+ end
269
+ context "コピー先にディレクトリが存在する場合" do
270
+ it "コピー先のディレクトリ内に同名のオブジェクトが存在しない場合、ファイルが作成される" do
271
+ dest_directory_path = "copy/dest_dir"
272
+ workspace.directory(dest_directory_path).create
273
+
274
+ prev_count = workspace.directory(dest_directory_path).directory_file_count
275
+ prev_bytesize = workspace.directory(dest_directory_path).metadata["directory_bytes"]
276
+ src_file.copy(dest_directory_path)
277
+ expect(workspace.directory(dest_directory_path).file("src.txt").read).to eq "copy"
278
+ expect(workspace.directory(dest_directory_path).metadata["directory_bytes"]).to eq prev_bytesize + 4
279
+ expect(workspace.directory(dest_directory_path).directory_file_count).to eq prev_count + 1
280
+ end
281
+ it "コピー先のディレクトリ内に同名のファイルが存在する場合、そのファイルが上書きされる" do
282
+ dest_directory_path = "copy/dest_exists_file"
283
+ workspace.directory(dest_directory_path).create
284
+ workspace.directory(dest_directory_path).file("src.txt").create("file already exists")
285
+
286
+ prev_count = workspace.directory(dest_directory_path).directory_file_count
287
+ prev_bytesize = workspace.directory(dest_directory_path).metadata["directory_bytes"]
288
+ src_file.copy(dest_directory_path)
289
+ expect(workspace.directory(dest_directory_path).file("src.txt").read).to eq "copy"
290
+ expect(workspace.directory(dest_directory_path).metadata["directory_bytes"]).to eq prev_bytesize - 15
291
+ expect(workspace.directory(dest_directory_path).directory_file_count).to eq prev_count
292
+ end
293
+ it "コピー先のディレクトリ内に同名のディレクトリが存在する場合、例外が発生する" do
294
+ dest_directory_path = "copy/dest_exists_dir"
295
+ workspace.directory(dest_directory_path).create
296
+ workspace.directory(dest_directory_path).directory("src.txt").create
297
+
298
+ expect do
299
+ src_file.copy(dest_directory_path)
300
+ end.to raise_error StoreAgent::InvalidNodeTypeError
301
+ end
302
+ end
303
+ end
304
+
305
+ context "ファイルの移動" do
306
+ let :directory do
307
+ workspace.directory("move")
308
+ end
309
+ let :src_file do
310
+ workspace.file("move/src.txt")
311
+ end
312
+ before do
313
+ if !directory.exists?
314
+ directory.create
315
+ end
316
+ if !src_file.exists?
317
+ src_file.create("move")
318
+ end
319
+ end
320
+
321
+ context "移動先にオブジェクトが無い場合" do
322
+ it "移動先にファイルが作成され、メタデータが更新される" do
323
+ dest_create_path = "move/dest_create.txt"
324
+ prev_count = workspace.directory("move").directory_file_count
325
+ prev_bytesize = workspace.directory("move").metadata["bytes"]
326
+ src_file.move(dest_create_path)
327
+ expect(workspace.file(dest_create_path).read).to eq "move"
328
+ expect(workspace.directory("move").metadata["bytes"]).to eq prev_bytesize
329
+ expect(workspace.directory("move").directory_file_count).to eq prev_count
330
+ end
331
+ end
332
+ context "移動先にファイルが存在する場合" do
333
+ it "移動先のファイルが上書きされ、メタデータが更新される" do
334
+ dest_update_path = "move/dest_update.txt"
335
+ workspace.file(dest_update_path).create("dest update file")
336
+ prev_count = workspace.directory("move").directory_file_count
337
+ prev_bytesize = workspace.file(dest_update_path).metadata["bytes"]
338
+ src_file.move(dest_update_path)
339
+ expect(workspace.file(dest_update_path).read).to eq "move"
340
+ expect(workspace.file(dest_update_path).metadata["bytes"]).to eq 4
341
+ expect(workspace.directory("move").directory_file_count).to eq prev_count - 1
342
+ end
343
+ end
344
+ context "移動先にディレクトリが存在する場合" do
345
+ it "移動先のディレクトリ内に同名のオブジェクトが存在しない場合、ファイルが作成される" do
346
+ dest_directory_path = "move/dest_dir"
347
+ workspace.directory(dest_directory_path).create
348
+
349
+ prev_count = workspace.directory(dest_directory_path).directory_file_count
350
+ prev_bytesize = workspace.directory(dest_directory_path).metadata["directory_bytes"]
351
+ src_file.move(dest_directory_path)
352
+ expect(workspace.directory(dest_directory_path).file("src.txt").read).to eq "move"
353
+ expect(workspace.directory(dest_directory_path).metadata["directory_bytes"]).to eq prev_bytesize + 4
354
+ expect(workspace.directory(dest_directory_path).directory_file_count).to eq prev_count + 1
355
+ end
356
+ it "移動先のディレクトリ内に同名のファイルが存在する場合、そのファイルが上書きされる" do
357
+ dest_directory_path = "move/dest_exists_file"
358
+ workspace.directory(dest_directory_path).create
359
+ workspace.directory(dest_directory_path).file("src.txt").create("file already exists")
360
+
361
+ prev_count = workspace.directory(dest_directory_path).directory_file_count
362
+ prev_bytesize = workspace.directory(dest_directory_path).metadata["directory_bytes"]
363
+ src_file.move(dest_directory_path)
364
+ expect(workspace.directory(dest_directory_path).file("src.txt").read).to eq "move"
365
+ expect(workspace.directory(dest_directory_path).metadata["directory_bytes"]).to eq prev_bytesize - 15
366
+ expect(workspace.directory(dest_directory_path).directory_file_count).to eq prev_count
367
+ end
368
+ it "移動先のディレクトリ内に同名のディレクトリが存在する場合、例外が発生する" do
369
+ dest_directory_path = "move/dest_exists_dir"
370
+ workspace.directory(dest_directory_path).create
371
+ workspace.directory(dest_directory_path).directory("src.txt").create
372
+
373
+ expect do
374
+ src_file.move(dest_directory_path)
375
+ end.to raise_error StoreAgent::InvalidNodeTypeError
376
+ end
377
+ end
378
+ end
379
+ end
@@ -0,0 +1,191 @@
1
+ #--
2
+ # Copyright 2015 realglobe, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #++
16
+
17
+ require "spec_helper"
18
+
19
+ RSpec.describe StoreAgent::Node::Locker do
20
+ let :user do
21
+ StoreAgent::User.new("foo")
22
+ end
23
+ let :workspace do
24
+ user.workspace("test_lock")
25
+ end
26
+ before do
27
+ skip "時間かかるのでスキップ"
28
+ end
29
+ before :all do
30
+ workspace = StoreAgent::User.new("foo").workspace("test_lock")
31
+ workspace.create
32
+ workspace.directory("create").create
33
+ workspace.directory("read").create
34
+ workspace.file("read/foo.txt").create("foo")
35
+ workspace.directory("update").create
36
+ workspace.file("update/bar.txt").create{|f| f.body = "bar"}
37
+ workspace.directory("delete").create
38
+ workspace.file("delete/hoge.txt").create(:hoge)
39
+ workspace.file("delete/fuga.txt").create(:fuga)
40
+
41
+ class StoreAgent::Node::Object
42
+ prepend Module.new {
43
+ def test_sleep
44
+ sleep 0.2
45
+ end
46
+
47
+ def create(*)
48
+ super do
49
+ test_sleep
50
+ yield
51
+ end
52
+ end
53
+ def read(*)
54
+ super do
55
+ test_sleep
56
+ yield
57
+ end
58
+ end
59
+ def update(*)
60
+ super do
61
+ test_sleep
62
+ yield
63
+ end
64
+ end
65
+ def delete(*)
66
+ super do
67
+ test_sleep
68
+ yield
69
+ end
70
+ end
71
+ }
72
+ end
73
+ end
74
+ after :all do
75
+ class StoreAgent::Node::Object
76
+ prepend Module.new {
77
+ def test_sleep
78
+ end
79
+ }
80
+ end
81
+ end
82
+
83
+ context "オブジェクトcreate時のロック" do
84
+ it "作成中のオブジェクトは排他ロックされている" do
85
+ Process.fork do
86
+ workspace.directory("create/dir").create
87
+ end
88
+ sleep 0.1
89
+ response = true
90
+ open(workspace.directory("create/dir").send(:lock_file_path)) do |f|
91
+ response = f.flock File::LOCK_SH | File::LOCK_NB
92
+ end
93
+ Process.waitall
94
+ expect(response).to be false
95
+ end
96
+ it "作成中のオブジェクトの親ディレクトリは排他ロックされている" do
97
+ Process.fork do
98
+ workspace.file("create/file.txt").create
99
+ end
100
+ sleep 0.1
101
+ response = true
102
+ open(workspace.directory("create").send(:lock_file_path)) do |f|
103
+ response = f.flock File::LOCK_SH | File::LOCK_NB
104
+ end
105
+ Process.waitall
106
+ expect(response).to be false
107
+ end
108
+ end
109
+
110
+ context "オブジェクトread時のロック" do
111
+ it "読み込み中のオブジェクトは共有ロックされている" do
112
+ Process.fork do
113
+ workspace.file("read/foo.txt").read
114
+ end
115
+ sleep 0.1
116
+ response = true
117
+ open(workspace.file("read/foo.txt").send(:lock_file_path)) do |f|
118
+ response = f.flock File::LOCK_EX | File::LOCK_NB
119
+ end
120
+ Process.waitall
121
+ expect(response).to be false
122
+ expect(workspace.file("read/foo.txt").read).to eq "foo"
123
+ end
124
+ it "読み込み中のオブジェクトの親ディレクトリは共有ロックされている" do
125
+ Process.fork do
126
+ workspace.file("read/foo.txt").read
127
+ end
128
+ sleep 0.1
129
+ response = true
130
+ open(workspace.directory("read").send(:lock_file_path)) do |f|
131
+ response = f.flock File::LOCK_EX | File::LOCK_NB
132
+ end
133
+ Process.waitall
134
+ expect(response).to be false
135
+ end
136
+ end
137
+
138
+ context "オブジェクトupdate時のロック" do
139
+ it "更新中のオブジェクトは排他ロックされている" do
140
+ Process.fork do
141
+ workspace.file("update/bar.txt").update("test")
142
+ end
143
+ sleep 0.1
144
+ response = true
145
+ open(workspace.file("update/bar.txt").send(:lock_file_path)) do |f|
146
+ response = f.flock File::LOCK_EX | File::LOCK_NB
147
+ end
148
+ Process.waitall
149
+ expect(response).to be false
150
+ end
151
+ it "更新中のオブジェクトの親ディレクトリは排他ロックされている" do
152
+ Process.fork do
153
+ workspace.file("update/bar.txt").update("test")
154
+ end
155
+ sleep 0.1
156
+ response = true
157
+ open(workspace.directory("update").send(:lock_file_path)) do |f|
158
+ response = f.flock File::LOCK_EX | File::LOCK_NB
159
+ end
160
+ Process.waitall
161
+ expect(response).to be false
162
+ end
163
+ end
164
+
165
+ context "オブジェクトdelete時のロック" do
166
+ it "削除中のオブジェクトは排他ロックされている" do
167
+ Process.fork do
168
+ workspace.file("delete/hoge.txt").delete
169
+ end
170
+ sleep 0.1
171
+ response = true
172
+ open(workspace.file("delete/hoge.txt").send(:lock_file_path)) do |f|
173
+ response = f.flock File::LOCK_EX | File::LOCK_NB
174
+ end
175
+ Process.waitall
176
+ expect(response).to be false
177
+ end
178
+ it "削除中のオブジェクトの親ディレクトリは排他ロックされている" do
179
+ Process.fork do
180
+ workspace.file("delete/fuga.txt").delete
181
+ end
182
+ sleep 0.1
183
+ response = true
184
+ open(workspace.directory("delete").send(:lock_file_path)) do |f|
185
+ response = f.flock File::LOCK_EX | File::LOCK_NB
186
+ end
187
+ Process.waitall
188
+ expect(response).to be false
189
+ end
190
+ end
191
+ end