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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/Gemfile +4 -0
- data/Guardfile +5 -0
- data/LICENSE +202 -0
- data/README.md +433 -0
- data/Rakefile +2 -0
- data/lib/store_agent.rb +31 -0
- data/lib/store_agent/config.rb +152 -0
- data/lib/store_agent/data_encoder.rb +32 -0
- data/lib/store_agent/data_encoder/gzip_encoder.rb +50 -0
- data/lib/store_agent/data_encoder/openssl_aes_256_cbc_encoder.rb +65 -0
- data/lib/store_agent/exceptions.rb +87 -0
- data/lib/store_agent/node.rb +26 -0
- data/lib/store_agent/node/attachment.rb +93 -0
- data/lib/store_agent/node/attachment/metadata.rb +120 -0
- data/lib/store_agent/node/attachment/permission.rb +121 -0
- data/lib/store_agent/node/object.rb +233 -0
- data/lib/store_agent/node/object/directory_object.rb +264 -0
- data/lib/store_agent/node/object/file_object.rb +197 -0
- data/lib/store_agent/node/object/virtual_object.rb +25 -0
- data/lib/store_agent/node/prepend_module/locker.rb +125 -0
- data/lib/store_agent/node/prepend_module/path_validator.rb +138 -0
- data/lib/store_agent/node/prepend_module/permission_checker.rb +96 -0
- data/lib/store_agent/user.rb +111 -0
- data/lib/store_agent/validator.rb +60 -0
- data/lib/store_agent/version.rb +19 -0
- data/lib/store_agent/version_manager.rb +101 -0
- data/lib/store_agent/version_manager/ruby_git.rb +100 -0
- data/lib/store_agent/version_manager/rugged_git.rb +133 -0
- data/lib/store_agent/workspace.rb +88 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/store_agent/data_encoder/encoder_shared_context.rb +74 -0
- data/spec/store_agent/data_encoder/gzip_encoder_spec.rb +41 -0
- data/spec/store_agent/data_encoder/openssl_aes_256_cbc_encoder_spec.rb +42 -0
- data/spec/store_agent/data_encoder_spec.rb +78 -0
- data/spec/store_agent/node/directory_object_spec.rb +563 -0
- data/spec/store_agent/node/file_object_spec.rb +379 -0
- data/spec/store_agent/node/locker_spec.rb +191 -0
- data/spec/store_agent/node/metadata_spec.rb +339 -0
- data/spec/store_agent/node/object_spec.rb +73 -0
- data/spec/store_agent/node/path_validator_spec.rb +121 -0
- data/spec/store_agent/node/permission_spec.rb +232 -0
- data/spec/store_agent/user_spec.rb +127 -0
- data/spec/store_agent/version_manager/git_shared_context.rb +286 -0
- data/spec/store_agent/version_manager/ruby_git_spec.rb +32 -0
- data/spec/store_agent/version_manager/rugged_git_spec.rb +32 -0
- data/spec/store_agent/workspace_spec.rb +107 -0
- data/spec/store_agent_spec.rb +53 -0
- data/store_agent.gemspec +33 -0
- metadata +252 -0
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require "simplecov"
|
|
2
|
+
|
|
3
|
+
SimpleCov.start do
|
|
4
|
+
require "bundler"
|
|
5
|
+
add_filter Bundler::bundle_path.to_s
|
|
6
|
+
add_filter File.dirname(__FILE__)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
require "store_agent"
|
|
10
|
+
|
|
11
|
+
RSpec.configure do |config|
|
|
12
|
+
config.expect_with :rspec do |expectations|
|
|
13
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
config.mock_with :rspec do |mocks|
|
|
17
|
+
mocks.verify_partial_doubles = true
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
config.filter_run :focus
|
|
21
|
+
config.run_all_when_everything_filtered = true
|
|
22
|
+
|
|
23
|
+
config.disable_monkey_patching!
|
|
24
|
+
|
|
25
|
+
config.profile_examples = 10
|
|
26
|
+
config.order = :random
|
|
27
|
+
# config.order = "16118"
|
|
28
|
+
# config.fail_fast = true
|
|
29
|
+
|
|
30
|
+
Kernel.srand config.seed
|
|
31
|
+
|
|
32
|
+
config.before(:suite) do
|
|
33
|
+
StoreAgent.configure do |config|
|
|
34
|
+
config.json_indent_level = 2
|
|
35
|
+
config.default_owner_permission = {
|
|
36
|
+
"read" => true,
|
|
37
|
+
"write" => true,
|
|
38
|
+
"execute" => true,
|
|
39
|
+
# "chown" => true,
|
|
40
|
+
"chmod" => true
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
if File.exists?(StoreAgent.config.storage_root)
|
|
44
|
+
FileUtils.remove_dir(StoreAgent.config.storage_root)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
RSpec.shared_context "encoder" do
|
|
18
|
+
after :all do
|
|
19
|
+
StoreAgent.configure do |c|
|
|
20
|
+
c.storage_data_encoders = []
|
|
21
|
+
c.attachment_data_encoders = []
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
let :user do
|
|
25
|
+
StoreAgent::User.new("foo")
|
|
26
|
+
end
|
|
27
|
+
let :workspace do
|
|
28
|
+
user.workspace(workspace_name)
|
|
29
|
+
end
|
|
30
|
+
before do
|
|
31
|
+
if !workspace.exists?
|
|
32
|
+
workspace.create
|
|
33
|
+
workspace.directory("foo").create
|
|
34
|
+
workspace.file("foo/bar.txt").create("テスト")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
context "encode/decode のテスト" do
|
|
39
|
+
it "バイナリ文字列を encode してから decode すると、元の文字列に戻る" do
|
|
40
|
+
100.times.each do
|
|
41
|
+
string = OpenSSL::Random.random_bytes(256)
|
|
42
|
+
string.force_encoding("UTF-8")
|
|
43
|
+
encoded_string = encoder.encode(string)
|
|
44
|
+
expect(encoder.decode(encoded_string)).to eq string
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
it "日本語文字列を encode してから decode すると、元の文字列に戻る" do
|
|
48
|
+
100.times.each do
|
|
49
|
+
string = "日本語を含むUTF-8文字列"
|
|
50
|
+
encoded_string = encoder.encode(string)
|
|
51
|
+
expect(encoder.decode(encoded_string)).to eq string
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
context "作成されたファイルのテスト" do
|
|
56
|
+
it "メタデータはエンコードされているので、JSON 形式ではない" do
|
|
57
|
+
encoded_data = open(workspace.root.metadata.file_path).read
|
|
58
|
+
expect do
|
|
59
|
+
Oj.load(encoded_data)
|
|
60
|
+
end.to raise_error
|
|
61
|
+
end
|
|
62
|
+
it "パーミッション情報はエンコードされているので、JSON 形式ではない" do
|
|
63
|
+
encoded_data = open(workspace.directory("foo").permission.file_path).read
|
|
64
|
+
expect do
|
|
65
|
+
Oj.load(encoded_data)
|
|
66
|
+
end.to raise_error
|
|
67
|
+
end
|
|
68
|
+
it "ファイルはエンコードされている" do
|
|
69
|
+
encoded_data = open(workspace.file("foo/bar.txt").storage_object_path).read
|
|
70
|
+
expect(encoded_data).to_not eq "テスト"
|
|
71
|
+
expect(workspace.file("foo/bar.txt").read).to eq "テスト"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
require "store_agent/data_encoder/encoder_shared_context"
|
|
19
|
+
|
|
20
|
+
RSpec.describe StoreAgent::DataEncoder::GzipEncoder do
|
|
21
|
+
before :all do
|
|
22
|
+
StoreAgent.configure do |c|
|
|
23
|
+
c.storage_data_encoders = [StoreAgent::DataEncoder::GzipEncoder.new]
|
|
24
|
+
c.attachment_data_encoders = [StoreAgent::DataEncoder::GzipEncoder.new]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
let :workspace_name do
|
|
28
|
+
"gzip_encoder_test"
|
|
29
|
+
end
|
|
30
|
+
let :encoder do
|
|
31
|
+
StoreAgent::DataEncoder::GzipEncoder.new
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
include_context "encoder"
|
|
35
|
+
|
|
36
|
+
it "データは gzip ... でエンコードされた形式で保存される" do
|
|
37
|
+
file = workspace.file("enc_data").create("encode のテスト")
|
|
38
|
+
command = "gunzip -c #{file.storage_object_path}"
|
|
39
|
+
expect(`#{command}`).to eq "encode のテスト"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
require "store_agent/data_encoder/encoder_shared_context"
|
|
19
|
+
|
|
20
|
+
RSpec.describe StoreAgent::DataEncoder::OpensslAes256CbcEncoder do
|
|
21
|
+
before :all do
|
|
22
|
+
StoreAgent.configure do |c|
|
|
23
|
+
c.storage_data_encoders = [StoreAgent::DataEncoder::OpensslAes256CbcEncoder.new]
|
|
24
|
+
c.attachment_data_encoders = [StoreAgent::DataEncoder::OpensslAes256CbcEncoder.new]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
let :workspace_name do
|
|
28
|
+
"openssl_aes_256_cbc_encoder_test"
|
|
29
|
+
end
|
|
30
|
+
let :encoder do
|
|
31
|
+
StoreAgent::DataEncoder::OpensslAes256CbcEncoder.new
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
include_context "encoder"
|
|
35
|
+
|
|
36
|
+
it "データは openssl enc -e -aes-256-cbc ... でエンコードされた形式で保存される" do
|
|
37
|
+
password = ENV["STORE_AGENT_DATA_ENCODER_PASSWORD"] || ""
|
|
38
|
+
file = workspace.file("enc_data").create("encode のテスト")
|
|
39
|
+
command = "openssl enc -d -aes-256-cbc -in #{file.storage_object_path} -k '#{password}'"
|
|
40
|
+
expect(`#{command}`).to eq "encode のテスト"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
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::DataEncoder do
|
|
20
|
+
before :all do
|
|
21
|
+
StoreAgent.configure do |c|
|
|
22
|
+
c.storage_data_encoders = [] <<
|
|
23
|
+
StoreAgent::DataEncoder::GzipEncoder.new <<
|
|
24
|
+
StoreAgent::DataEncoder::OpensslAes256CbcEncoder.new
|
|
25
|
+
c.attachment_data_encoders = [] <<
|
|
26
|
+
StoreAgent::DataEncoder::GzipEncoder.new <<
|
|
27
|
+
StoreAgent::DataEncoder::OpensslAes256CbcEncoder.new
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
after :all do
|
|
31
|
+
StoreAgent.configure do |c|
|
|
32
|
+
c.storage_data_encoders = []
|
|
33
|
+
c.attachment_data_encoders = []
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
let :user do
|
|
37
|
+
StoreAgent::User.new("foo")
|
|
38
|
+
end
|
|
39
|
+
let :workspace do
|
|
40
|
+
user.workspace("gzip_and_openssl_encoder_test")
|
|
41
|
+
end
|
|
42
|
+
let :password do
|
|
43
|
+
ENV["STORE_AGENT_DATA_ENCODER_PASSWORD"] || ""
|
|
44
|
+
end
|
|
45
|
+
before do
|
|
46
|
+
if !workspace.exists?
|
|
47
|
+
workspace.create
|
|
48
|
+
workspace.directory("foo").create
|
|
49
|
+
workspace.file("foo/bar.txt").create("encode のテスト")
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "データは gzip -c ... | openssl ... でエンコードされた形式で保存される" do
|
|
54
|
+
file = workspace.file("foo/bar.txt")
|
|
55
|
+
command = "openssl enc -d -aes-256-cbc -in #{file.storage_object_path} -k '#{password}' | gunzip"
|
|
56
|
+
expect(`#{command}`).to eq "encode のテスト"
|
|
57
|
+
end
|
|
58
|
+
it "メタデータは gzip -c ... | openssl ... でエンコードされた形式で保存される" do
|
|
59
|
+
dir = workspace.directory("foo")
|
|
60
|
+
command = "openssl enc -d -aes-256-cbc -in #{dir.metadata.file_path} -k '#{password}' | gunzip"
|
|
61
|
+
expect do
|
|
62
|
+
Oj.load(`#{command}`)
|
|
63
|
+
end.to_not raise_error
|
|
64
|
+
end
|
|
65
|
+
it "メタデータのファイルサイズはエンコード前のサイズ" do
|
|
66
|
+
dir = workspace.directory("bitesize_test").create
|
|
67
|
+
file = workspace.file("bitesize_test/hoge.txt").create("12 byte file")
|
|
68
|
+
expect(file.metadata["bytes"]).to eq 12
|
|
69
|
+
expect(workspace.directory("bitesize_test").metadata.disk_usage).to eq 4108
|
|
70
|
+
end
|
|
71
|
+
it "パーミッション情報は gzip -c ... | openssl ... でエンコードされた形式で保存される" do
|
|
72
|
+
file = workspace.file("foo/bar.txt")
|
|
73
|
+
command = "openssl enc -d -aes-256-cbc -in #{file.permission.file_path} -k '#{password}' | gunzip"
|
|
74
|
+
expect do
|
|
75
|
+
Oj.load(`#{command}`)
|
|
76
|
+
end.to_not raise_error
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,563 @@
|
|
|
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::DirectoryObject do
|
|
20
|
+
let :user do
|
|
21
|
+
StoreAgent::User.new("foo")
|
|
22
|
+
end
|
|
23
|
+
let :workspace do
|
|
24
|
+
user.workspace(workspace_name)
|
|
25
|
+
end
|
|
26
|
+
before do
|
|
27
|
+
workspace.create if !workspace.exists?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context "初期化時に path の末尾に / を追加する" do
|
|
31
|
+
let :workspace_name do
|
|
32
|
+
"test_dir_workspace_initialize"
|
|
33
|
+
end
|
|
34
|
+
let :directory do
|
|
35
|
+
workspace.directory(@path)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it ". は / に変換される" do
|
|
39
|
+
@path = "."
|
|
40
|
+
expect(directory.path).to eq "/"
|
|
41
|
+
end
|
|
42
|
+
it "/././. は / に変換される" do
|
|
43
|
+
@path = "/././."
|
|
44
|
+
expect(directory.path).to eq "/"
|
|
45
|
+
end
|
|
46
|
+
it "foo は /foo/ に変換される" do
|
|
47
|
+
@path = "foo"
|
|
48
|
+
expect(directory.path).to eq "/foo/"
|
|
49
|
+
end
|
|
50
|
+
it "///foo///bar/// は /foo/bar/ に変換される" do
|
|
51
|
+
@path = "///foo///bar///"
|
|
52
|
+
expect(directory.path).to eq "/foo/bar/"
|
|
53
|
+
end
|
|
54
|
+
it "../foo/bar は /foo/bar/ に変換される" do
|
|
55
|
+
@path = "../foo/bar"
|
|
56
|
+
expect(directory.path).to eq "/foo/bar/"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context "ディレクトリ作成のテスト" do
|
|
61
|
+
let :workspace_name do
|
|
62
|
+
"test_dir_workspace_create"
|
|
63
|
+
end
|
|
64
|
+
before do
|
|
65
|
+
dir = workspace.directory("/foo")
|
|
66
|
+
if !dir.exists?
|
|
67
|
+
dir.create
|
|
68
|
+
workspace.file("/bar").create
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "既に同名のディレクトリがある場合、作成できない" do
|
|
73
|
+
expect do
|
|
74
|
+
workspace.directory("/foo").create
|
|
75
|
+
end.to raise_error
|
|
76
|
+
end
|
|
77
|
+
it "既に同名のファイルがある場合、作成できない" do
|
|
78
|
+
expect do
|
|
79
|
+
workspace.directory("/bar").create
|
|
80
|
+
end.to raise_error
|
|
81
|
+
end
|
|
82
|
+
it "ディレクトリ名がメタデータの拡張子で終わる場合、作成できない" do
|
|
83
|
+
expect do
|
|
84
|
+
workspace.directory("/hoge.meta").create
|
|
85
|
+
end.to raise_error
|
|
86
|
+
end
|
|
87
|
+
it "ディレクトリ名がパーミッションデータの拡張子で終わる場合、作成できない" do
|
|
88
|
+
expect do
|
|
89
|
+
workspace.directory("/hoge.perm").create
|
|
90
|
+
end.to raise_error
|
|
91
|
+
end
|
|
92
|
+
it "パスに問題が無ければディレクトリ作成できる" do
|
|
93
|
+
workspace.directory("hoge").create
|
|
94
|
+
expect(workspace.directory("hoge").exists?).to be true
|
|
95
|
+
workspace.directory("fuga").create
|
|
96
|
+
expect(workspace.directory("fuga").exists?).to be true
|
|
97
|
+
workspace.directory(".git").create
|
|
98
|
+
expect(workspace.directory(".git").exists?).to be true
|
|
99
|
+
workspace.directory(".keep").create
|
|
100
|
+
expect(workspace.directory(".keep").exists?).to be true
|
|
101
|
+
end
|
|
102
|
+
it "引数にブロックを渡してdirectory_bytes_limitを初期化できる" do
|
|
103
|
+
pending
|
|
104
|
+
|
|
105
|
+
workspace.directory("limit").create do |d|
|
|
106
|
+
d..metadata["directory_bytes_limit"] = 12345678
|
|
107
|
+
end
|
|
108
|
+
expect(workspace.directory("limit").metadata["directory_bytes_limit"]).to eq 12345678
|
|
109
|
+
end
|
|
110
|
+
it "引数にブロックを渡してオーナーを初期化できる" do
|
|
111
|
+
skip "とりあえず保留"
|
|
112
|
+
|
|
113
|
+
StoreAgent::Superuser.new.workspace(workspace_name).directory("chown").create do |d|
|
|
114
|
+
d.initial_owner = "initial_owner"
|
|
115
|
+
end
|
|
116
|
+
expect(workspace.directory("chown").metadata["owner"]).to eq "initial_owner"
|
|
117
|
+
end
|
|
118
|
+
it "引数にブロックを渡して権限を初期化できる" do
|
|
119
|
+
pending
|
|
120
|
+
|
|
121
|
+
workspace.directory("chmod").create do |d|
|
|
122
|
+
d.initial_permission = {"readwrite" => true}
|
|
123
|
+
end
|
|
124
|
+
expect(workspace.directory("chmod").permission).to eq ({"readwrite" => true})
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
context "ディレクトリ削除のテスト" do
|
|
129
|
+
let :workspace_name do
|
|
130
|
+
"test_dir_workspace_delete"
|
|
131
|
+
end
|
|
132
|
+
before do
|
|
133
|
+
dir = workspace.directory("/delete_test")
|
|
134
|
+
if dir.exists?
|
|
135
|
+
StoreAgent::Superuser.new.workspace(workspace_name).directory("/delete_test").delete
|
|
136
|
+
end
|
|
137
|
+
workspace.directory("/delete_test").create
|
|
138
|
+
workspace.directory("/delete_test/foo").create
|
|
139
|
+
workspace.file("/delete_test/hoge.txt").create
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
context "配下の全オブジェクトに対して削除権限がある場合" do
|
|
143
|
+
before do
|
|
144
|
+
workspace.directory("/delete_test").delete
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it "ルートノードは削除できない" do
|
|
148
|
+
expect do
|
|
149
|
+
workspace.directory("/").delete
|
|
150
|
+
end.to raise_error
|
|
151
|
+
end
|
|
152
|
+
it "ディレクトリが丸ごと削除される" do
|
|
153
|
+
expect(workspace.directory("/delete_test").exists?).to be false
|
|
154
|
+
end
|
|
155
|
+
it "メタデータ側のディレクトリは削除される" do
|
|
156
|
+
metadata_dir_path = "/tmp/store_agent/test_dir_workspace_delete/metadata/delete_test"
|
|
157
|
+
expect(File.exists?(metadata_dir_path)).to be false
|
|
158
|
+
end
|
|
159
|
+
it "パーミッション側のディレクトリは削除される" do
|
|
160
|
+
permission_dir_path = "/tmp/store_agent/test_dir_workspace_delete/permission/delete_test"
|
|
161
|
+
expect(File.exists?(permission_dir_path)).to be false
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
context "配下に削除権限が無いオブジェクトがある場合" do
|
|
165
|
+
let :workspace_name do
|
|
166
|
+
"test_dir_workspace_delete_with_no_permission"
|
|
167
|
+
end
|
|
168
|
+
before do
|
|
169
|
+
workspace.directory("/delete_test/bar").create
|
|
170
|
+
workspace.file("/delete_test/bar/hoge.txt").create("1234567890")
|
|
171
|
+
workspace.file("/delete_test/bar/hoge.txt").unset_permission(identifier: "foo", permission_names: "write")
|
|
172
|
+
workspace.directory("/delete_test/foobar").create
|
|
173
|
+
workspace.file("/delete_test/foobar/fuga.txt").create("12345678901234567890")
|
|
174
|
+
workspace.directory("/delete_test/foobar").unset_permission(identifier: "foo", permission_names: "write")
|
|
175
|
+
begin
|
|
176
|
+
workspace.directory("/delete_test").delete
|
|
177
|
+
rescue
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
context "メタデータの中身" do
|
|
182
|
+
context "ルートディレクトリ" do
|
|
183
|
+
let :root_node do
|
|
184
|
+
workspace.directory("/")
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
it "ディスク使用量は 4096 * 4 + 30 バイト" do
|
|
188
|
+
expect(root_node.metadata.disk_usage).to eq ((4096 * 4) + 30)
|
|
189
|
+
end
|
|
190
|
+
it "直下のファイル数は 1" do
|
|
191
|
+
expect(root_node.directory_file_count).to eq 1
|
|
192
|
+
end
|
|
193
|
+
it "サブツリー全体の配下ファイル数は 5" do
|
|
194
|
+
expect(root_node.tree_file_count).to eq 5
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
context "中間ディレクトリ" do
|
|
198
|
+
let :dir do
|
|
199
|
+
workspace.directory("/delete_test")
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
it "ディスク使用量は 4096 * 3 + 30 バイト" do
|
|
203
|
+
expect(dir.metadata.disk_usage).to eq ((4096 * 3) + 30)
|
|
204
|
+
end
|
|
205
|
+
it "直下のファイル数は 2" do
|
|
206
|
+
expect(dir.directory_file_count).to eq 2
|
|
207
|
+
end
|
|
208
|
+
it "サブツリー全体の配下ファイル数は 4" do
|
|
209
|
+
expect(dir.tree_file_count).to eq 4
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
context "配下ファイルに削除権限が無いディレクトリ" do
|
|
213
|
+
let :dir do
|
|
214
|
+
workspace.directory("/delete_test/bar")
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
it "ディスク使用量は 4096 + 10 バイト" do
|
|
218
|
+
expect(dir.metadata.disk_usage).to eq (4096 + 10)
|
|
219
|
+
end
|
|
220
|
+
it "直下のファイル数は 1" do
|
|
221
|
+
expect(dir.directory_file_count).to eq 1
|
|
222
|
+
end
|
|
223
|
+
it "サブツリー全体の配下ファイル数は 1" do
|
|
224
|
+
expect(dir.tree_file_count).to eq 1
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
context "削除権限が無いディレクトリ" do
|
|
228
|
+
let :dir do
|
|
229
|
+
workspace.directory("/delete_test/foobar")
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
it "ディスク使用量は 4096 + 20 バイト" do
|
|
233
|
+
expect(dir.metadata.disk_usage).to eq (4096 + 20)
|
|
234
|
+
end
|
|
235
|
+
it "直下のファイル数は 1" do
|
|
236
|
+
expect(dir.directory_file_count).to eq 1
|
|
237
|
+
end
|
|
238
|
+
it "サブツリー全体の配下ファイル数は 1" do
|
|
239
|
+
expect(dir.tree_file_count).to eq 1
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
context "削除権限があるノード" do
|
|
244
|
+
it "ディレクトリが丸ごと削除される" do
|
|
245
|
+
expect(workspace.directory("/delete_test/foo").exists?).to be false
|
|
246
|
+
end
|
|
247
|
+
it "メタデータ側のディレクトリは削除される" do
|
|
248
|
+
metadata_dir_path = "/tmp/store_agent/test_dir_workspace_delete_with_no_permission/metadata/delete_test/foo"
|
|
249
|
+
expect(File.exists?(metadata_dir_path)).to be false
|
|
250
|
+
end
|
|
251
|
+
it "パーミッション側のディレクトリは削除される" do
|
|
252
|
+
permission_dir_path = "/tmp/store_agent/test_dir_workspace_delete_with_no_permission/permission/delete_test/foo"
|
|
253
|
+
expect(File.exists?(permission_dir_path)).to be false
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
context "サブツリー内に削除権限が無いファイルがある場合" do
|
|
257
|
+
it "ファイルと親ディレクトリは削除されずに残る" do
|
|
258
|
+
expect(workspace.directory("/delete_test/bar").exists?).to be true
|
|
259
|
+
expect(workspace.file("/delete_test/bar/hoge.txt").exists?).to be true
|
|
260
|
+
end
|
|
261
|
+
it "ファイルと親ディレクトリのメタデータは削除されない" do
|
|
262
|
+
dir_metadata_path = "/tmp/store_agent/test_dir_workspace_delete_with_no_permission/metadata/delete_test/bar/.meta"
|
|
263
|
+
file_metadata_path = "/tmp/store_agent/test_dir_workspace_delete_with_no_permission/metadata/delete_test/bar/hoge.txt.meta"
|
|
264
|
+
expect(File.exists?(dir_metadata_path)).to be true
|
|
265
|
+
expect(File.exists?(file_metadata_path)).to be true
|
|
266
|
+
end
|
|
267
|
+
it "ファイルと親ディレクトリのパーミッションは削除されない" do
|
|
268
|
+
dir_permission_path = "/tmp/store_agent/test_dir_workspace_delete_with_no_permission/permission/delete_test/bar/.perm"
|
|
269
|
+
file_permission_path = "/tmp/store_agent/test_dir_workspace_delete_with_no_permission/permission/delete_test/bar/hoge.txt.perm"
|
|
270
|
+
expect(File.exists?(dir_permission_path)).to be true
|
|
271
|
+
expect(File.exists?(file_permission_path)).to be true
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
context "サブツリー内に削除権限が無いディレクトリがある場合" do
|
|
275
|
+
it "ディレクトリと配下ファイルは削除されずに残る" do
|
|
276
|
+
expect(workspace.directory("/delete_test/foobar").exists?).to be true
|
|
277
|
+
expect(workspace.file("/delete_test/foobar/fuga.txt").exists?).to be true
|
|
278
|
+
end
|
|
279
|
+
it "ディレクトリと配下ファイルのメタデータは削除されない" do
|
|
280
|
+
dir_metadata_path = "/tmp/store_agent/test_dir_workspace_delete_with_no_permission/metadata/delete_test/foobar/.meta"
|
|
281
|
+
file_metadata_path = "/tmp/store_agent/test_dir_workspace_delete_with_no_permission/metadata/delete_test/foobar/fuga.txt.meta"
|
|
282
|
+
expect(File.exists?(dir_metadata_path)).to be true
|
|
283
|
+
expect(File.exists?(file_metadata_path)).to be true
|
|
284
|
+
end
|
|
285
|
+
it "ディレクトリと配下ファイルのパーミッションは削除されない" do
|
|
286
|
+
dir_permission_path = "/tmp/store_agent/test_dir_workspace_delete_with_no_permission/permission/delete_test/foobar/.perm"
|
|
287
|
+
file_permission_path = "/tmp/store_agent/test_dir_workspace_delete_with_no_permission/permission/delete_test/foobar/fuga.txt.perm"
|
|
288
|
+
expect(File.exists?(dir_permission_path)).to be true
|
|
289
|
+
expect(File.exists?(file_permission_path)).to be true
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
context "ディレクトリのコピー" do
|
|
296
|
+
let :workspace_name do
|
|
297
|
+
"test_dir_workspace_copy"
|
|
298
|
+
end
|
|
299
|
+
let :src_dir do
|
|
300
|
+
workspace.directory("copy/src")
|
|
301
|
+
end
|
|
302
|
+
before do
|
|
303
|
+
dir = workspace.directory("copy")
|
|
304
|
+
if !dir.exists?
|
|
305
|
+
dir.create
|
|
306
|
+
src_dir.create
|
|
307
|
+
src_dir.file("foo.txt").create("copy")
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
context "コピー先にオブジェクトが無い場合" do
|
|
312
|
+
it "ディレクトリが中身ごとコピーされ、メタデータが更新される" do
|
|
313
|
+
dest_path = "copy/dest"
|
|
314
|
+
|
|
315
|
+
prev_count = workspace.directory("copy").tree_file_count
|
|
316
|
+
src_dir.copy(dest_path)
|
|
317
|
+
expect(workspace.file("copy/dest/foo.txt").read).to eq "copy"
|
|
318
|
+
expect(workspace.directory("copy").tree_file_count).to eq prev_count + 2
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
context "コピー先にファイルが存在する場合" do
|
|
322
|
+
it "例外 InvalidNodeTypeError が発生する" do
|
|
323
|
+
dest_file_path = "copy/dest_file.txt"
|
|
324
|
+
workspace.file(dest_file_path).create("dest file")
|
|
325
|
+
|
|
326
|
+
expect do
|
|
327
|
+
src_dir.copy(dest_file_path)
|
|
328
|
+
end.to raise_error StoreAgent::InvalidNodeTypeError
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
context "コピー先にディレクトリが存在する場合" do
|
|
332
|
+
it "コピー先のディレクトリ内に同名のオブジェクトが存在しない場合、ディレクトリがコピーされる" do
|
|
333
|
+
dest_directory_path = "copy/dest_dir"
|
|
334
|
+
workspace.directory(dest_directory_path).create
|
|
335
|
+
|
|
336
|
+
prev_count = workspace.directory("copy").tree_file_count
|
|
337
|
+
prev_bytesize = workspace.directory("copy").metadata["directory_bytes"]
|
|
338
|
+
src_dir.copy(dest_directory_path)
|
|
339
|
+
expect(workspace.directory(dest_directory_path).file("src/foo.txt").read).to eq "copy"
|
|
340
|
+
expect(workspace.directory("copy").metadata["directory_bytes"]).to eq prev_bytesize + 4096 + 4
|
|
341
|
+
expect(workspace.directory("copy").tree_file_count).to eq prev_count + 2
|
|
342
|
+
end
|
|
343
|
+
it "コピー先のディレクトリ内に同名のファイルが存在する場合、例外が発生する" do
|
|
344
|
+
dest_directory_path = "copy/dest_exists_file"
|
|
345
|
+
workspace.directory(dest_directory_path).create
|
|
346
|
+
workspace.directory(dest_directory_path).file("src").create("file already exists")
|
|
347
|
+
|
|
348
|
+
expect do
|
|
349
|
+
src_dir.copy(dest_directory_path)
|
|
350
|
+
end.to raise_error StoreAgent::InvalidPathError
|
|
351
|
+
end
|
|
352
|
+
it "コピー先のディレクトリ内に同名のディレクトリが存在する場合、例外が発生する" do
|
|
353
|
+
dest_directory_path = "copy/dest_exists_dir"
|
|
354
|
+
workspace.directory(dest_directory_path).create
|
|
355
|
+
workspace.directory(dest_directory_path).directory("src").create
|
|
356
|
+
|
|
357
|
+
expect do
|
|
358
|
+
src_dir.copy(dest_directory_path)
|
|
359
|
+
end.to raise_error StoreAgent::InvalidPathError
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
context "ディレクトリの移動" do
|
|
365
|
+
let :workspace_name do
|
|
366
|
+
"test_dir_workspace_move"
|
|
367
|
+
end
|
|
368
|
+
let :directory do
|
|
369
|
+
workspace.directory("move")
|
|
370
|
+
end
|
|
371
|
+
let :src_dir do
|
|
372
|
+
workspace.directory("move/src")
|
|
373
|
+
end
|
|
374
|
+
before do
|
|
375
|
+
if !directory.exists?
|
|
376
|
+
directory.create
|
|
377
|
+
end
|
|
378
|
+
if !src_dir.exists?
|
|
379
|
+
src_dir.create
|
|
380
|
+
workspace.file("move/src/bar.txt").create("move")
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
context "移動先にオブジェクトが無い場合" do
|
|
385
|
+
it "ディレクトリが中身ごと移動され、メタデータが更新される" do
|
|
386
|
+
dest_path = "move/dest"
|
|
387
|
+
|
|
388
|
+
prev_count = workspace.directory("move").tree_file_count
|
|
389
|
+
src_dir.move(dest_path)
|
|
390
|
+
expect(workspace.file("move/dest/bar.txt").read).to eq "move"
|
|
391
|
+
expect(workspace.directory("move").tree_file_count).to eq prev_count
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
context "移動先にファイルが存在する場合" do
|
|
395
|
+
it "例外 InvalidNodeTypeError が発生する" do
|
|
396
|
+
dest_file_path = "move/dest_file.txt"
|
|
397
|
+
workspace.file(dest_file_path).create("dest file")
|
|
398
|
+
|
|
399
|
+
expect do
|
|
400
|
+
src_dir.move(dest_file_path)
|
|
401
|
+
end.to raise_error StoreAgent::InvalidNodeTypeError
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
context "移動先にディレクトリが存在する場合" do
|
|
405
|
+
it "移動先のディレクトリ内に同名のオブジェクトが存在しない場合、ディレクトリが移動される" do
|
|
406
|
+
dest_directory_path = "move/dest_dir"
|
|
407
|
+
workspace.directory(dest_directory_path).create
|
|
408
|
+
|
|
409
|
+
prev_count = workspace.directory("move").tree_file_count
|
|
410
|
+
prev_bytesize = workspace.directory("move").metadata["directory_bytes"]
|
|
411
|
+
src_dir.move(dest_directory_path)
|
|
412
|
+
expect(workspace.directory(dest_directory_path).file("src/bar.txt").read).to eq "move"
|
|
413
|
+
expect(workspace.directory("move").metadata["directory_bytes"]).to eq prev_bytesize
|
|
414
|
+
expect(workspace.directory("move").tree_file_count).to eq prev_count
|
|
415
|
+
end
|
|
416
|
+
it "移動先のディレクトリ内に同名のファイルが存在する場合、例外が発生する" do
|
|
417
|
+
dest_directory_path = "move/dest_exists_file"
|
|
418
|
+
workspace.directory(dest_directory_path).create
|
|
419
|
+
workspace.directory(dest_directory_path).file("src").create("file already exists")
|
|
420
|
+
|
|
421
|
+
expect do
|
|
422
|
+
src_dir.move(dest_directory_path)
|
|
423
|
+
end.to raise_error StoreAgent::InvalidPathError
|
|
424
|
+
end
|
|
425
|
+
it "移動先のディレクトリ内に同名のディレクトリが存在する場合、例外が発生する" do
|
|
426
|
+
dest_directory_path = "move/dest_exists_dir"
|
|
427
|
+
workspace.directory(dest_directory_path).create
|
|
428
|
+
workspace.directory(dest_directory_path).directory("src").create
|
|
429
|
+
|
|
430
|
+
expect do
|
|
431
|
+
src_dir.move(dest_directory_path)
|
|
432
|
+
end.to raise_error StoreAgent::InvalidPathError
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
context "メタデータ取得のテスト" do
|
|
438
|
+
let :workspace_name do
|
|
439
|
+
"test_dir_workspace_get_metadata"
|
|
440
|
+
end
|
|
441
|
+
it "get_metadata でメタデータをハッシュ形式で取得できる" do
|
|
442
|
+
expect(workspace.directory("/").get_metadata.class).to eq Hash
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
context "パーミッション情報取得のテスト" do
|
|
447
|
+
let :workspace_name do
|
|
448
|
+
"test_dir_workspace_get_permissions"
|
|
449
|
+
end
|
|
450
|
+
it "get_permissions でパーミッション情報をハッシュ形式で取得できる" do
|
|
451
|
+
expect(workspace.directory("/").get_permissions.class).to eq Hash
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
context "オーナー変更のテスト" do
|
|
456
|
+
let :workspace_name do
|
|
457
|
+
"test_dir_workspace_chown"
|
|
458
|
+
end
|
|
459
|
+
before do
|
|
460
|
+
if !(dir = workspace.directory("chown")).exists?
|
|
461
|
+
dir.create
|
|
462
|
+
workspace.file("chown/hoge.txt").create
|
|
463
|
+
workspace.directory("chown_r").create
|
|
464
|
+
workspace.file("chown_r/fuga.txt").create
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
it "userは権限がないので、オーナー変更できない" do
|
|
468
|
+
expect do
|
|
469
|
+
workspace.directory("chown").chown(identifier: "hoge")
|
|
470
|
+
end.to raise_error
|
|
471
|
+
end
|
|
472
|
+
context "superuserはオーナー変更できる" do
|
|
473
|
+
it "recursive オプションが無いと、指定したディレクトリのみ変更される" do
|
|
474
|
+
superuser = StoreAgent::Superuser.new
|
|
475
|
+
superuser.workspace(workspace_name).directory("chown").chown(identifier: "hoge")
|
|
476
|
+
expect(workspace.directory("chown").metadata["owner"]).to eq "hoge"
|
|
477
|
+
expect(workspace.file("chown/hoge.txt").metadata["owner"]).to eq "foo"
|
|
478
|
+
end
|
|
479
|
+
it "recursive: true にすると、指定したディレクトリ以下の全ファイルが変更される" do
|
|
480
|
+
superuser = StoreAgent::Superuser.new
|
|
481
|
+
superuser.workspace(workspace_name).directory("chown_r").chown(identifier: "hoge", recursive: true)
|
|
482
|
+
expect(workspace.directory("chown_r").metadata["owner"]).to eq "hoge"
|
|
483
|
+
expect(workspace.file("chown_r/fuga.txt").metadata["owner"]).to eq "hoge"
|
|
484
|
+
end
|
|
485
|
+
end
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
context "配下オブジェクトを取得するテスト" do
|
|
489
|
+
let :workspace_name do
|
|
490
|
+
"test_dir_workspace_delete"
|
|
491
|
+
end
|
|
492
|
+
let :dir do
|
|
493
|
+
workspace.directory("search_children")
|
|
494
|
+
end
|
|
495
|
+
before do
|
|
496
|
+
if !dir.exists?
|
|
497
|
+
dir.create
|
|
498
|
+
workspace.file("search_children/foo.txt").create
|
|
499
|
+
workspace.directory("search_children/bar").create
|
|
500
|
+
workspace.directory("search_children/symlink_dir").create
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
context "ディレクトリを検索する" do
|
|
505
|
+
it "配下に存在するディレクトリを検索する" do
|
|
506
|
+
find_dir = dir.directory("bar")
|
|
507
|
+
expect(find_dir.path).to eq "/search_children/bar/"
|
|
508
|
+
expect(find_dir.exists?).to be true
|
|
509
|
+
end
|
|
510
|
+
it "配下に存在しないディレクトリを検索する" do
|
|
511
|
+
find_dir = dir.directory("foobar")
|
|
512
|
+
expect(find_dir.path).to eq "/search_children/foobar/"
|
|
513
|
+
expect(find_dir.exists?).to be false
|
|
514
|
+
end
|
|
515
|
+
it ". を検索すると、カレントディレクトリが返ってくる" do
|
|
516
|
+
expect(dir.directory(".").path).to eq "/search_children/"
|
|
517
|
+
end
|
|
518
|
+
it "/ を検索すると、カレントディレクトリが返ってくる" do
|
|
519
|
+
expect(dir.directory("/").path).to eq "/search_children/"
|
|
520
|
+
end
|
|
521
|
+
it ".. は / に変換されて検索される" do
|
|
522
|
+
expect(dir.directory("..").path).to eq "/search_children/"
|
|
523
|
+
end
|
|
524
|
+
end
|
|
525
|
+
context "ファイルを検索する" do
|
|
526
|
+
it "配下に存在するファイルを検索する" do
|
|
527
|
+
file = dir.file("foo.txt")
|
|
528
|
+
expect(file.path).to eq "/search_children/foo.txt"
|
|
529
|
+
expect(file.exists?).to be true
|
|
530
|
+
end
|
|
531
|
+
it "配下に存在しないファイルを検索する" do
|
|
532
|
+
file = dir.file("foobar.txt")
|
|
533
|
+
expect(file.path).to eq "/search_children/foobar.txt"
|
|
534
|
+
expect(file.exists?).to be false
|
|
535
|
+
end
|
|
536
|
+
it ".. は / に変換されて検索される" do
|
|
537
|
+
expect(dir.file("../foo.txt").path).to eq "/search_children/foo.txt"
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
context "タイプが不明なオブジェクトを検索する" do
|
|
541
|
+
it "パスがディレクトリなら、ディレクトリオブジェクトを返す" do
|
|
542
|
+
expect(dir.find_object("bar").class).to eq StoreAgent::Node::DirectoryObject
|
|
543
|
+
end
|
|
544
|
+
it "パスがファイルなら、ファイルオブジェクトを返す" do
|
|
545
|
+
expect(dir.find_object("foo.txt").class).to eq StoreAgent::Node::FileObject
|
|
546
|
+
end
|
|
547
|
+
it "パスに非対応形式のファイルが存在する場合、例外が発生する" do
|
|
548
|
+
File.symlink("/dev/null", "#{dir.storage_object_path}/symlink_dir/symlink")
|
|
549
|
+
expect do
|
|
550
|
+
dir.find_object("symlink_dir/symlink")
|
|
551
|
+
end.to raise_error
|
|
552
|
+
end
|
|
553
|
+
it "パスにファイルが存在しない場合、仮想オブジェクトを返す" do
|
|
554
|
+
expect(dir.find_object("foobar.txt").class).to eq StoreAgent::Node::VirtualObject
|
|
555
|
+
end
|
|
556
|
+
end
|
|
557
|
+
context "直下のファイル一覧を取得する" do
|
|
558
|
+
it "ディレクトリの直下にあるファイル一覧を返す" do
|
|
559
|
+
expect(dir.children.map(&:path).sort).to eq ["/search_children/bar/", "/search_children/foo.txt", "/search_children/symlink_dir/"].sort
|
|
560
|
+
end
|
|
561
|
+
end
|
|
562
|
+
end
|
|
563
|
+
end
|