duracloud-client 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,9 +1,13 @@
1
+ require 'support/shared_examples_for_tsv'
2
+
1
3
  module Duracloud
2
4
  RSpec.describe BitIntegrityReport do
3
5
 
6
+ subject { described_class.new("myspace") }
7
+
4
8
  let(:path) { File.expand_path('../../fixtures/bit_integrity_report.tsv', __FILE__) }
5
9
 
6
- subject { described_class.new("myspace") }
10
+ it_behaves_like "a TSV"
7
11
 
8
12
  describe "#csv" do
9
13
  before do
@@ -17,19 +21,5 @@ module Duracloud
17
21
  }
18
22
  end
19
23
 
20
- describe "#load_tsv" do
21
- it "loads a string" do
22
- tsv = File.read(path)
23
- subject.load_tsv(tsv)
24
- expect(subject.tsv).to eq(tsv)
25
- end
26
- it "loads an IO" do
27
- tsv = File.read(path)
28
- tsv_io = File.new(path, "rb")
29
- subject.load_tsv(tsv)
30
- expect(subject.tsv.to_s).to eq(tsv)
31
- end
32
- end
33
-
34
24
  end
35
25
  end
@@ -0,0 +1,17 @@
1
+ module Duracloud
2
+ RSpec.describe ContentManifest do
3
+
4
+ describe "source" do
5
+ let(:manifest) { described_class.new(space_id: 'foo', manifest_id: 'bar') }
6
+ subject { manifest.source }
7
+ before do
8
+ allow(manifest).to receive(:xml) { File.read(File.expand_path("../../fixtures/content_manifest.xml", __FILE__)) }
9
+ end
10
+ its(:md5) { is_expected.to eq "164e9aee34c0c42915716e11d5d539b5" }
11
+ its(:size) { is_expected.to eq 4227858432 }
12
+ its(:content_type) { is_expected.to eq "application/octet-stream" }
13
+ its(:content_id) { is_expected.to eq "datastreamStore/8/b/d4/info%3Afedora%2Fduke%3A447146%2Fcontent%2Fcontent.0" }
14
+ end
15
+
16
+ end
17
+ end
@@ -2,16 +2,32 @@ module Duracloud
2
2
  RSpec.describe Content do
3
3
 
4
4
  let(:url) { "https://example.com/durastore/foo/bar" }
5
+ let(:manifest_url) { "#{url}.dura-manifest" }
5
6
 
6
7
  describe ".find" do
7
8
  describe "when it exists" do
8
- before { stub_request(:head, url) }
9
- specify {
10
- expect(Content.find(space_id: "foo", content_id: "bar")).to be_a(Content)
11
- }
9
+ subject { described_class.find(space_id: "foo", content_id: "bar") }
10
+ describe "and it is not chunked" do
11
+ before { stub_request(:head, url) }
12
+ it { is_expected.to be_a described_class }
13
+ end
14
+ describe "and it is chunked" do
15
+ let(:manifest_xml) { File.read(File.expand_path("../../fixtures/content_manifest.xml", __FILE__)) }
16
+ before do
17
+ stub_request(:head, url).to_return(status: 404)
18
+ stub_request(:head, manifest_url)
19
+ stub_request(:get, manifest_url).to_return(body: manifest_xml)
20
+ end
21
+ it { is_expected.to be_a described_class }
22
+ its(:md5) { is_expected.to eq "164e9aee34c0c42915716e11d5d539b5" }
23
+ its(:content_type) { is_expected.to eq "application/octet-stream" }
24
+ end
12
25
  end
13
26
  describe "when it does not exist" do
14
- before { stub_request(:head, url).to_return(status: 404) }
27
+ before do
28
+ stub_request(:head, url).to_return(status: 404)
29
+ stub_request(:head, manifest_url).to_return(status: 404)
30
+ end
15
31
  specify {
16
32
  expect { Content.find(space_id: "foo", content_id: "bar") }.to raise_error(NotFoundError)
17
33
  }
@@ -35,13 +51,28 @@ module Duracloud
35
51
 
36
52
  describe ".exist?" do
37
53
  describe "when it exists" do
38
- before { stub_request(:head, url) }
39
- specify {
40
- expect(Content.exist?(space_id: "foo", content_id: "bar")).to be true
41
- }
54
+ describe "and it is not chunked" do
55
+ before { stub_request(:head, url) }
56
+ specify {
57
+ expect(Content.exist?(space_id: "foo", content_id: "bar")).to be true
58
+ }
59
+ end
60
+ describe "and it is chunked" do
61
+ before do
62
+ stub_request(:head, url).to_return(status: 404)
63
+ stub_request(:head, manifest_url)
64
+ stub_request(:get, manifest_url)
65
+ end
66
+ specify {
67
+ expect(Content.exist?(space_id: "foo", content_id: "bar")).to be true
68
+ }
69
+ end
42
70
  end
43
71
  describe "when it does not exist" do
44
- before { stub_request(:head, url).to_return(status: 404) }
72
+ before do
73
+ stub_request(:head, url).to_return(status: 404)
74
+ stub_request(:head, manifest_url).to_return(status: 404)
75
+ end
45
76
  specify {
46
77
  expect(Content.exist?(space_id: "foo", content_id: "bar")).to be false
47
78
  }
@@ -83,12 +114,12 @@ module Duracloud
83
114
  end
84
115
  end
85
116
  describe "and the space exists" do
86
- before {
117
+ before do
87
118
  stub_request(:put, url)
88
119
  .with(body: "Some file content",
89
120
  headers: {"Content-MD5"=>"92bbcf620ceb5f5bf38f08e9a1f31e7b"})
90
121
  .to_return(status: 201)
91
- }
122
+ end
92
123
  it "stores the content" do
93
124
  subject.save
94
125
  expect(subject).to be_persisted
@@ -115,7 +146,6 @@ module Duracloud
115
146
  end
116
147
  describe "and the body has not changed" do
117
148
  before {
118
- allow(subject).to receive(:body_changed?) { false }
119
149
  stub_request(:post, url)
120
150
  .with(headers: {'x-dura-meta-creator'=>'testuser'})
121
151
  }
@@ -173,33 +203,92 @@ module Duracloud
173
203
  end
174
204
 
175
205
  describe "#copy" do
176
- let(:target) { "https://example.com/durastore/spam/eggs" }
177
206
  subject { Content.new(space_id: "foo", content_id: "bar") }
207
+ let(:target) { "https://example.com/durastore/spam/eggs" }
208
+ before do
209
+ stub_request(:put, target)
210
+ .with(headers: {'x-dura-meta-copy-source'=>'foo/bar'})
211
+ stub_request(:head, target).to_return(status: 404)
212
+ stub_request(:head, "#{target}.dura-manifest").to_return(status: 404)
213
+ end
178
214
  specify {
215
+ copied = subject.copy(space_id: "spam", content_id: "eggs")
216
+ expect(copied).to be_a(Content)
217
+ }
218
+ it "defaults target space to current space" do
219
+ target = "https://example.com/durastore/foo/eggs"
179
220
  stub1 = stub_request(:put, target)
180
221
  .with(headers: {'x-dura-meta-copy-source'=>'foo/bar'})
181
- stub2 = stub_request(:head, target)
182
- copied = subject.copy(target_space_id: "spam", target_content_id: "eggs")
222
+ stub2 = stub_request(:head, target).to_return(status: 404)
223
+ stub3 = stub_request(:head, "#{target}.dura-manifest").to_return(status: 404)
224
+ copied = subject.copy(content_id: "eggs")
183
225
  expect(copied).to be_a(Content)
184
226
  expect(stub1).to have_been_requested
185
227
  expect(stub2).to have_been_requested
186
- }
228
+ expect(stub3).to have_been_requested
229
+ end
230
+ describe "when the target exists" do
231
+ before do
232
+ stub_request(:head, target).to_return(status: 200)
233
+ end
234
+ describe "and force argument is true" do
235
+ it "overwrites the target" do
236
+ expect { subject.copy(space_id: "spam", content_id: "eggs", force: true) }.not_to raise_error
237
+ end
238
+ end
239
+ describe "and force argument is false" do
240
+ it "raises an exception" do
241
+ expect { subject.copy(space_id: "spam", content_id: "eggs", force: false) }.to raise_error(Content::CopyError)
242
+ end
243
+ end
244
+ end
187
245
  end
188
246
 
189
247
  describe "#move" do
190
248
  let(:target) { "https://example.com/durastore/spam/eggs" }
191
249
  subject { Content.new(space_id: "foo", content_id: "bar") }
192
- specify {
193
- stub1 = stub_request(:put, target)
194
- .with(headers: {'x-dura-meta-copy-source'=>'foo/bar'})
195
- stub2 = stub_request(:head, target)
196
- stub3 = stub_request(:delete, "https://example.com/durastore/foo/bar")
197
- moved = subject.move(target_space_id: "spam", target_content_id: "eggs")
198
- expect(moved).to be_a(Content)
199
- expect(stub1).to have_been_requested
200
- expect(stub2).to have_been_requested
201
- expect(stub3).to have_been_requested
202
- }
250
+ describe "when copy succeeds" do
251
+ it "deletes the source" do
252
+ stub1 = stub_request(:put, target)
253
+ .with(headers: {'x-dura-meta-copy-source'=>'foo/bar'})
254
+ stub2 = stub_request(:head, target).to_return(status: 404)
255
+ stub2a = stub_request(:head, "#{target}.dura-manifest").to_return(status: 404)
256
+ stub3 = stub_request(:delete, "https://example.com/durastore/foo/bar")
257
+ moved = subject.move(space_id: "spam", content_id: "eggs")
258
+ expect(moved).to be_a(Content)
259
+ expect(stub1).to have_been_requested
260
+ expect(stub2).to have_been_requested
261
+ expect(stub2a).to have_been_requested
262
+ expect(stub3).to have_been_requested
263
+ end
264
+ end
265
+ describe "when copy fails" do
266
+ it "does not delete the source" do
267
+ allow(subject).to receive(:copy).with(space_id: "spam", content_id: "eggs").and_raise(Content::CopyError)
268
+ expect(subject).not_to receive(:delete)
269
+ expect { subject.move(space_id: "spam", content_id: "eggs") }.to raise_error(Content::CopyError)
270
+ end
271
+ end
272
+ describe "when target exists" do
273
+ before do
274
+ stub_request(:put, target)
275
+ .with(headers: {'x-dura-meta-copy-source'=>'foo/bar'})
276
+ stub_request(:delete, "https://example.com/durastore/foo/bar")
277
+ stub_request(:head, target).to_return(status: 200)
278
+ allow(Content).to receive(:exist?).with(space_id: "spam", content_id: "eggs") { true }
279
+ end
280
+ describe "and force argument is true" do
281
+ it "overwrites the target" do
282
+ expect(subject).to receive(:copy).and_call_original
283
+ subject.move(space_id: "spam", content_id: "eggs", force: true)
284
+ end
285
+ end
286
+ describe "and force argument is false" do
287
+ it "raises an exception" do
288
+ expect { subject.move(space_id: "spam", content_id: "eggs", force: false) }.to raise_error(Content::CopyError)
289
+ end
290
+ end
291
+ end
203
292
  end
204
293
 
205
294
  end
@@ -1,9 +1,14 @@
1
+ require 'support/shared_examples_for_tsv'
2
+
1
3
  module Duracloud
2
4
  RSpec.describe Manifest do
3
5
 
4
6
  subject { described_class.new("myspace") }
7
+
5
8
  let(:path) { File.expand_path('../../fixtures/manifest.tsv', __FILE__) }
6
9
 
10
+ it_behaves_like "a TSV"
11
+
7
12
  describe "#csv" do
8
13
  before do
9
14
  allow(subject).to receive(:tsv) { File.read(path) }
@@ -16,19 +21,5 @@ module Duracloud
16
21
  }
17
22
  end
18
23
 
19
- describe "#load_tsv" do
20
- it "loads a string" do
21
- tsv = File.read(path)
22
- subject.load_tsv(tsv)
23
- expect(subject.tsv).to eq(tsv)
24
- end
25
- it "loads an IO" do
26
- tsv = File.read(path)
27
- tsv_io = File.new(path, "rb")
28
- subject.load_tsv(tsv)
29
- expect(subject.tsv.to_s).to eq(tsv)
30
- end
31
- end
32
-
33
24
  end
34
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: duracloud-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Chandek-Stark
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-27 00:00:00.000000000 Z
11
+ date: 2017-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashie
@@ -161,19 +161,20 @@ files:
161
161
  - gemfiles/Gemfile.activemodel-5.0
162
162
  - lib/duracloud-client.rb
163
163
  - lib/duracloud.rb
164
+ - lib/duracloud/abstract_entity.rb
164
165
  - lib/duracloud/audit_log.rb
165
166
  - lib/duracloud/bit_integrity_report.rb
167
+ - lib/duracloud/chunked_content.rb
166
168
  - lib/duracloud/client.rb
167
169
  - lib/duracloud/configuration.rb
168
170
  - lib/duracloud/connection.rb
169
171
  - lib/duracloud/content.rb
172
+ - lib/duracloud/content_manifest.rb
170
173
  - lib/duracloud/content_properties.rb
171
174
  - lib/duracloud/durastore_request.rb
172
175
  - lib/duracloud/error.rb
173
176
  - lib/duracloud/error_handler.rb
174
- - lib/duracloud/has_properties.rb
175
177
  - lib/duracloud/manifest.rb
176
- - lib/duracloud/persistence.rb
177
178
  - lib/duracloud/properties.rb
178
179
  - lib/duracloud/request.rb
179
180
  - lib/duracloud/response.rb
@@ -186,12 +187,15 @@ files:
186
187
  - lib/duracloud/version.rb
187
188
  - spec/fixtures/audit_log.tsv
188
189
  - spec/fixtures/bit_integrity_report.tsv
190
+ - spec/fixtures/content_manifest.xml
189
191
  - spec/fixtures/lorem_ipsum.txt
190
192
  - spec/fixtures/manifest.tsv
191
193
  - spec/spec_helper.rb
194
+ - spec/support/shared_examples_for_tsv.rb
192
195
  - spec/unit/audit_log_spec.rb
193
196
  - spec/unit/bit_integrity_report_spec.rb
194
197
  - spec/unit/client_spec.rb
198
+ - spec/unit/content_manifest_spec.rb
195
199
  - spec/unit/content_spec.rb
196
200
  - spec/unit/manifest_spec.rb
197
201
  - spec/unit/properties_spec.rb
@@ -225,12 +229,15 @@ summary: Ruby client for communicating with DuraCloud
225
229
  test_files:
226
230
  - spec/fixtures/audit_log.tsv
227
231
  - spec/fixtures/bit_integrity_report.tsv
232
+ - spec/fixtures/content_manifest.xml
228
233
  - spec/fixtures/lorem_ipsum.txt
229
234
  - spec/fixtures/manifest.tsv
230
235
  - spec/spec_helper.rb
236
+ - spec/support/shared_examples_for_tsv.rb
231
237
  - spec/unit/audit_log_spec.rb
232
238
  - spec/unit/bit_integrity_report_spec.rb
233
239
  - spec/unit/client_spec.rb
240
+ - spec/unit/content_manifest_spec.rb
234
241
  - spec/unit/content_spec.rb
235
242
  - spec/unit/manifest_spec.rb
236
243
  - spec/unit/properties_spec.rb
@@ -1,52 +0,0 @@
1
- module Duracloud
2
- module HasProperties
3
-
4
- def self.included(base)
5
- base.class_eval do
6
- include Persistence
7
-
8
- before_delete :reset_properties
9
- after_save :reset_properties
10
- end
11
- end
12
-
13
- # Return the properties associated with this resource,
14
- # loading from Duracloud if necessary.
15
- # @return [Duracloud::Properties] the properties
16
- # @raise [Duracloud::NotFoundError] if the resource is marked persisted
17
- # but does not exist in Duracloud
18
- def properties
19
- load_properties if persisted? && @properties.nil?
20
- @properties ||= properties_class.new
21
- end
22
-
23
- # @api private
24
- # @raise [Duracloud::NotFoundError] the resource does not exist in DuraCloud.
25
- def load_properties
26
- response = get_properties_response
27
- self.properties = response.headers
28
- yield response if block_given?
29
- persisted!
30
- end
31
-
32
- private
33
-
34
- def properties=(props)
35
- filtered = props ? properties_class.filter(props) : props
36
- @properties = properties_class.new(filtered)
37
- end
38
-
39
- def reset_properties
40
- @properties = nil
41
- end
42
-
43
- def properties_class
44
- Properties
45
- end
46
-
47
- def get_properties_response
48
- raise NotImplementedError, "Class must implement `get_properties_response`."
49
- end
50
-
51
- end
52
- end
@@ -1,59 +0,0 @@
1
- require "active_model"
2
-
3
- module Duracloud
4
- module Persistence
5
-
6
- def self.included(base)
7
- base.class_eval do
8
- extend ActiveModel::Callbacks
9
-
10
- define_model_callbacks :save, :delete
11
- end
12
- end
13
-
14
- def save
15
- raise Error, "Cannot save deleted #{self.class}." if deleted?
16
- run_callbacks :save do
17
- do_save
18
- persisted!
19
- end
20
- end
21
-
22
- def delete
23
- raise Error, "Cannot delete, already deleted." if deleted?
24
- run_callbacks :delete do
25
- do_delete
26
- deleted!
27
- freeze
28
- end
29
- end
30
-
31
- def persisted?
32
- !!@persisted
33
- end
34
-
35
- def deleted?
36
- !!@deleted
37
- end
38
-
39
- private
40
-
41
- def persisted!
42
- @persisted = true
43
- end
44
-
45
- def deleted!
46
- @deleted = true
47
- @persisted = false
48
- end
49
-
50
- def do_delete
51
- raise NotImplementedError, "Classes must implement `do_delete`."
52
- end
53
-
54
- def do_save
55
- raise NotImplementedError, "Classes must implement `do_save`."
56
- end
57
-
58
- end
59
- end