oai 1.0.0 → 1.2.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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +19 -4
  3. data/Rakefile +7 -0
  4. data/bin/oai +0 -2
  5. data/examples/models/file_model.rb +2 -2
  6. data/lib/oai/client/response.rb +8 -8
  7. data/lib/oai/client.rb +34 -10
  8. data/lib/oai/exception.rb +46 -38
  9. data/lib/oai/harvester/config.rb +1 -1
  10. data/lib/oai/harvester/harvest.rb +37 -25
  11. data/lib/oai/harvester/logging.rb +3 -5
  12. data/lib/oai/harvester.rb +4 -1
  13. data/lib/oai/provider/model/activerecord_caching_wrapper.rb +5 -8
  14. data/lib/oai/provider/model/activerecord_wrapper.rb +41 -25
  15. data/lib/oai/provider/model.rb +1 -1
  16. data/lib/oai/provider/response/list_records.rb +12 -0
  17. data/lib/oai/provider/response.rb +7 -4
  18. data/lib/oai/provider/resumption_token.rb +70 -21
  19. data/lib/oai/provider.rb +129 -7
  20. data/test/activerecord_provider/database/0001_oaipmh_tables.rb +7 -1
  21. data/test/activerecord_provider/helpers/providers.rb +10 -1
  22. data/test/activerecord_provider/helpers/transactional_test_case.rb +2 -1
  23. data/test/activerecord_provider/models/dc_field.rb +8 -0
  24. data/test/activerecord_provider/models/dc_lang.rb +3 -0
  25. data/test/activerecord_provider/models/exclusive_set_dc_field.rb +6 -0
  26. data/test/activerecord_provider/tc_activerecord_wrapper.rb +63 -0
  27. data/test/activerecord_provider/tc_ar_provider.rb +54 -26
  28. data/test/activerecord_provider/tc_ar_sets_provider.rb +10 -9
  29. data/test/activerecord_provider/tc_caching_paging_provider.rb +9 -7
  30. data/test/activerecord_provider/tc_simple_paging_provider.rb +28 -7
  31. data/test/client/tc_exception.rb +1 -1
  32. data/test/client/tc_get_record.rb +1 -1
  33. data/test/client/tc_http_client.rb +2 -2
  34. data/test/client/tc_libxml.rb +1 -1
  35. data/test/client/tc_utf8_escaping.rb +8 -1
  36. data/test/harvester/tc_harvest.rb +42 -0
  37. data/test/harvester/test_helper_harvester.rb +6 -0
  38. data/test/provider/models.rb +3 -3
  39. data/test/provider/tc_functional_tokens.rb +17 -11
  40. data/test/provider/tc_instance_provider.rb +41 -0
  41. data/test/provider/tc_provider.rb +26 -0
  42. data/test/provider/tc_resumption_tokens.rb +6 -0
  43. data/test/provider/test_helper_provider.rb +17 -0
  44. metadata +28 -17
@@ -81,30 +81,30 @@ class ActiveRecordProviderTest < TransactionalTestCase
81
81
 
82
82
  def test_from
83
83
  first_id = DCField.order("id asc").first.id
84
- DCField.where("id < #{first_id + 90}").update_all(updated_at: Time.parse("January 1 2005"))
84
+ DCField.where("dc_fields.id < #{first_id + 90}").update_all(updated_at: Time.parse("January 1 2005"))
85
85
 
86
- DCField.where("id < #{first_id + 10}").update_all(updated_at: Time.parse("June 1 2005"))
86
+ DCField.where("dc_fields.id < #{first_id + 10}").update_all(updated_at: Time.parse("June 1 2005"))
87
87
 
88
88
 
89
- from_param = Time.parse("January 1 2006")
89
+ from_param = Time.parse("January 1 2006").getutc.iso8601
90
90
 
91
91
  doc = REXML::Document.new(
92
92
  @provider.list_records(
93
93
  :metadata_prefix => 'oai_dc', :from => from_param)
94
94
  )
95
- assert_equal DCField.where(["updated_at >= ?", from_param]).size,
95
+ assert_equal DCField.where(["dc_fields.updated_at >= ?", from_param]).size,
96
96
  doc.elements['OAI-PMH/ListRecords'].size
97
97
 
98
98
  doc = REXML::Document.new(
99
99
  @provider.list_records(
100
- :metadata_prefix => 'oai_dc', :from => Time.parse("May 30 2005"))
100
+ :metadata_prefix => 'oai_dc', :from => Time.parse("May 30 2005").getutc.iso8601)
101
101
  )
102
102
  assert_equal 20, doc.elements['OAI-PMH/ListRecords'].to_a.size
103
103
  end
104
104
 
105
105
  def test_until
106
- first_id = DCField.order("id asc").first.id
107
- DCField.where("id < #{first_id + 10}").update_all(updated_at: Time.parse("June 1 2005"))
106
+ first_id = DCField.order(id: :asc).first.id
107
+ DCField.where("dc_fields.id < ?", first_id + 10).update_all(updated_at: Time.parse("June 1 2005"))
108
108
 
109
109
  doc = REXML::Document.new(
110
110
  @provider.list_records(
@@ -114,19 +114,46 @@ class ActiveRecordProviderTest < TransactionalTestCase
114
114
  end
115
115
 
116
116
  def test_from_and_until
117
- first_id = DCField.order("id asc").first.id
117
+ first_id = DCField.order(id: :asc).first.id
118
118
  DCField.update_all(updated_at: Time.parse("June 1 2005"))
119
- DCField.where("id < #{first_id + 50}").update_all(updated_at: Time.parse("June 15 2005"))
120
- DCField.where("id < #{first_id + 10}").update_all(updated_at: Time.parse("June 30 2005"))
119
+ DCField.where("dc_fields.id < ?", first_id + 50).update_all(updated_at: Time.parse("June 15 2005"))
120
+ DCField.where("dc_fields.id < ?", first_id + 10).update_all(updated_at: Time.parse("June 30 2005"))
121
121
 
122
122
  doc = REXML::Document.new(
123
123
  @provider.list_records(
124
124
  :metadata_prefix => 'oai_dc',
125
- :from => Time.parse("June 3 2005"),
126
- :until => Time.parse("June 16 2005"))
125
+ :from => Time.parse("June 3 2005").getutc.iso8601,
126
+ :until => Time.parse("June 16 2005").getutc.iso8601)
127
127
  )
128
128
  assert_equal 40, doc.elements['OAI-PMH/ListRecords'].to_a.size
129
129
  end
130
+
131
+ def test_bad_until_raises_exception
132
+ DCField.order(id: :asc).limit(10).update_all(updated_at: 1.year.ago)
133
+ DCField.order(id: :desc).limit(10).update_all(updated_at: 1.year.from_now)
134
+ badTimes = [
135
+ 'junk',
136
+ 'February 92nd, 2015']
137
+ badTimes.each do |time|
138
+ assert_raise(OAI::ArgumentException) do
139
+ @provider.list_records(:metadata_prefix => 'oai_dc', :until => time)
140
+ end
141
+ end
142
+ end
143
+
144
+ def test_bad_from_raises_exception
145
+ DCField.order(id: :asc).limit(10).update_all(updated_at: 1.year.ago)
146
+ DCField.order(id: :desc).limit(10).update_all(updated_at: 1.year.from_now)
147
+
148
+ badTimes = [
149
+ 'junk',
150
+ 'February 92nd, 2015']
151
+ badTimes.each do |time|
152
+ assert_raise(OAI::ArgumentException) do
153
+ @provider.list_records(:metadata_prefix => 'oai_dc', :from => time)
154
+ end
155
+ end
156
+ end
130
157
 
131
158
  def test_handles_empty_collections
132
159
  DCField.delete_all
@@ -142,6 +169,21 @@ class ActiveRecordProviderTest < TransactionalTestCase
142
169
  REXML::Document.new(@provider.list_records(:metadata_prefix => 'oai_dc'))
143
170
  end
144
171
  end
172
+
173
+ def test_bad_id_raises_exception
174
+ badIdentifiers = [
175
+ 'invalid"id',
176
+ 'oai:test/5000',
177
+ 'oai:test/-1',
178
+ 'oai:test/one',
179
+ 'oai:test/\\$1\1!']
180
+ badIdentifiers.each do |id|
181
+ assert_raise(OAI::IdException) do
182
+ @provider.get_record(:identifier => id, :metadata_prefix => 'oai_dc')
183
+ end
184
+ end
185
+ end
186
+
145
187
 
146
188
  def setup
147
189
  @provider = ARProvider.new
@@ -149,18 +191,4 @@ class ActiveRecordProviderTest < TransactionalTestCase
149
191
 
150
192
  end
151
193
 
152
- class ActiveRecordProviderTimezoneTest < ActiveRecordProviderTest
153
-
154
- def setup
155
- require 'active_record'
156
- ActiveRecord::Base.default_timezone = :utc
157
- super
158
- end
159
194
 
160
- def teardown
161
- require 'active_record'
162
- ActiveRecord::Base.default_timezone = :local
163
- super
164
- end
165
-
166
- end
@@ -51,22 +51,22 @@ class ActiveRecordSetProviderTest < TransactionalTestCase
51
51
  set_ab = DCSet.create(:name => "Set A:B", :spec => "A:B")
52
52
 
53
53
  next_id = 0
54
- DCField.limit(10).order("id asc").each do |record|
54
+ DCField.limit(10).order(id: :asc).each do |record|
55
55
  set_a.dc_fields << record
56
56
  next_id = record.id
57
57
  end
58
58
 
59
- DCField.where("id > #{next_id}").limit(10).order("id asc").each do |record|
59
+ DCField.where("dc_fields.id > ?", next_id).limit(10).order(id: :asc).each do |record|
60
60
  set_b.dc_fields << record
61
61
  next_id = record.id
62
62
  end
63
63
 
64
- DCField.where("id > #{next_id}").limit(10).order("id asc").each do |record|
64
+ DCField.where("dc_fields.id > ?", next_id).limit(10).order(id: :asc).each do |record|
65
65
  set_ab.dc_fields << record
66
66
  next_id = record.id
67
67
  end
68
68
 
69
- DCField.where("id > #{next_id}").limit(10).order("id asc").each do |record|
69
+ DCField.where("dc_fields.id > ?", next_id).limit(10).order(id: :asc).each do |record|
70
70
  set_a.dc_fields << record
71
71
  set_c.dc_fields << record
72
72
  next_id = record.id
@@ -117,25 +117,25 @@ class ActiveRecordExclusiveSetsProviderTest < TransactionalTestCase
117
117
  def define_sets
118
118
  next_id = 0
119
119
 
120
- ExclusiveSetDCField.limit(10).order("id asc").each do |record|
120
+ ExclusiveSetDCField.limit(10).order(id: :asc).each do |record|
121
121
  record.set = "A"
122
122
  record.save!
123
123
  next_id = record.id
124
124
  end
125
125
 
126
- ExclusiveSetDCField.where("id > #{next_id}").limit(10).order("id asc").each do |record|
126
+ ExclusiveSetDCField.where("id > ?", next_id).limit(10).order(id: :asc).each do |record|
127
127
  record.set = "B"
128
128
  record.save!
129
129
  next_id = record.id
130
130
  end
131
131
 
132
- ExclusiveSetDCField.where("id > #{next_id}").limit(10).order("id asc").each do |record|
132
+ ExclusiveSetDCField.where("id > ?", next_id).limit(10).order(id: :asc).each do |record|
133
133
  record.set = "A:B"
134
134
  record.save!
135
135
  next_id = record.id
136
136
  end
137
137
 
138
- ExclusiveSetDCField.where("id > #{next_id}").limit(10).order("id asc").each do |record|
138
+ ExclusiveSetDCField.where("id > ?", next_id).limit(10).order(id: :asc).each do |record|
139
139
  record.set = "A"
140
140
  record.save!
141
141
  next_id = record.id
@@ -150,7 +150,8 @@ class ActiveRecordExclusiveSetsProviderTest < TransactionalTestCase
150
150
  )
151
151
  disable_logging do
152
152
  fixtures.keys.sort.each do |key|
153
- ExclusiveSetDCField.create(fixtures[key])
153
+ lang = DCLang.create(name: fixtures[key].delete('language'))
154
+ ExclusiveSetDCField.create(fixtures[key].merge(dc_lang: lang))
154
155
  end
155
156
  end
156
157
  end
@@ -17,14 +17,15 @@ class CachingPagingProviderTest < TransactionalTestCase
17
17
  token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
18
18
  assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].size
19
19
  doc = Document.new(@provider.list_records(:resumption_token => token))
20
- assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
21
- assert_equal 25, doc.elements["/OAI-PMH/ListRecords"].size
20
+ assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
21
+ assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
22
+ assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
22
23
  end
23
24
 
24
25
  def test_from_and_until
25
- first_id = DCField.order("id asc").first.id
26
- DCField.where("id <= #{first_id + 25}").update_all(updated_at: Time.parse("September 15 2005"))
27
- DCField.where("id < #{first_id + 50} and id > #{first_id + 25}").update_all(updated_at: Time.parse("November 1 2005"))
26
+ first_id = DCField.order(id: :asc).first.id
27
+ DCField.where("dc_fields.id <= ?", first_id + 25).update_all(updated_at: Time.parse("September 15 2005"))
28
+ DCField.where(["dc_fields.id < ? and dc_fields.id > ?", first_id + 50, first_id + 25]).update_all(updated_at: Time.parse("November 1 2005"))
28
29
 
29
30
  # Should return 50 records broken into 2 groups of 25.
30
31
  doc = Document.new(
@@ -37,8 +38,9 @@ class CachingPagingProviderTest < TransactionalTestCase
37
38
  token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
38
39
  assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
39
40
  doc = Document.new(@provider.list_records(:resumption_token => token))
40
- assert_equal 25, doc.elements["/OAI-PMH/ListRecords"].size
41
- assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
41
+ assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
42
+ assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
43
+ assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
42
44
  end
43
45
 
44
46
  def setup
@@ -8,25 +8,45 @@ class SimpleResumptionProviderTest < TransactionalTestCase
8
8
  assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
9
9
  assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
10
10
  token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
11
+
11
12
  doc = Document.new(@provider.list_records(:resumption_token => token))
12
13
  assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
13
14
  token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
14
15
  assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
16
+
15
17
  doc = Document.new(@provider.list_records(:resumption_token => token))
16
18
  assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
17
19
  token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
18
20
  assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
21
+
19
22
  doc = Document.new(@provider.list_records(:resumption_token => token))
20
- assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
21
- assert_equal 25, doc.elements["/OAI-PMH/ListRecords"].to_a.size
23
+ assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
24
+ assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
25
+ assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
26
+ end
27
+
28
+ def test_non_integer_identifiers_resumption
29
+ @provider = SimpleResumptionProviderWithNonIntegerID.new
30
+
31
+ doc = Document.new(@provider.list_records(:metadata_prefix => 'oai_dc'))
32
+ assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
33
+ assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
34
+ token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
35
+
36
+ next_doc = Document.new(@provider.list_records(:resumption_token => token))
37
+ assert_not_nil next_doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
38
+ next_token = next_doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
39
+ assert_equal 26, next_doc.elements["/OAI-PMH/ListRecords"].to_a.size
40
+
41
+ assert_not_equal token, next_token
22
42
  end
23
43
 
24
44
  def test_from_and_until
25
45
  first_id = DCField.order("id asc").first.id
26
- DCField.where("id < #{first_id + 25}").update_all(updated_at: Time.parse("September 15 2005"))
27
- DCField.where("id <= #{first_id + 50} and id > #{first_id + 25}").update_all(updated_at: Time.parse("November 1 2005"))
46
+ DCField.where("dc_fields.id < ?", first_id + 25).update_all(updated_at: Time.parse("September 15 2005"))
47
+ DCField.where(["dc_fields.id <= ? and dc_fields.id > ?", first_id + 50, first_id + 25]).update_all(updated_at: Time.parse("November 1 2005"))
28
48
 
29
- total = DCField.where(["updated_at >= ? AND updated_at <= ?", Time.parse("September 1 2005"), Time.parse("November 30 2005")]).count
49
+ total = DCField.where(["dc_fields.updated_at >= ? AND dc_fields.updated_at <= ?", Time.parse("September 1 2005"), Time.parse("November 30 2005")]).count
30
50
 
31
51
  # Should return 50 records broken into 2 groups of 25.
32
52
  doc = Document.new(
@@ -39,8 +59,9 @@ class SimpleResumptionProviderTest < TransactionalTestCase
39
59
  assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
40
60
  token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
41
61
  doc = Document.new(@provider.list_records(:resumption_token => token))
42
- assert_equal 25, doc.elements["/OAI-PMH/ListRecords"].to_a.size
43
- assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
62
+ assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
63
+ assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
64
+ assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
44
65
  end
45
66
 
46
67
  def setup
@@ -18,7 +18,7 @@ class ExceptionTest < Test::Unit::TestCase
18
18
 
19
19
  def test_oai_error
20
20
  client = OAI::Client.new 'http://localhost:3333/oai'
21
- assert_raises(OAI::Exception) do
21
+ assert_raises(OAI::ResumptionTokenException) do
22
22
  client.list_identifiers :resumption_token => 'bogus'
23
23
  end
24
24
  end
@@ -25,7 +25,7 @@ class GetRecordTest < Test::Unit::TestCase
25
25
  begin
26
26
  client.get_record :metadata_prefix => 'oai_dc'
27
27
  flunk 'invalid get_record did not throw OAI::Exception'
28
- rescue OAI::Exception => e
28
+ rescue OAI::ArgumentException => e
29
29
  assert_match /The request includes illegal arguments/, e.to_s
30
30
  end
31
31
  end
@@ -58,8 +58,8 @@ eos
58
58
  end
59
59
 
60
60
  faraday_stub = Faraday.new do |builder|
61
- require 'faraday_middleware'
62
- builder.use FaradayMiddleware::FollowRedirects
61
+ require 'faraday/follow_redirects'
62
+ builder.use Faraday::FollowRedirects::Middleware
63
63
  builder.adapter :test, stubs
64
64
  end
65
65
 
@@ -7,7 +7,7 @@ class LibXMLTest < Test::Unit::TestCase
7
7
 
8
8
  uri = 'http://localhost:3333/oai'
9
9
  client = OAI::Client.new uri, :parser => 'libxml'
10
- assert_raises(OAI::Exception) {client.get_record(:identifier => 'nosuchid')}
10
+ assert_raises(OAI::IdException) {client.get_record(:identifier => 'nosuchid')}
11
11
  end
12
12
 
13
13
  def test_list_records
@@ -1,12 +1,19 @@
1
1
  require 'test_helper_client'
2
2
 
3
3
  class UTF8Test < Test::Unit::TestCase
4
+ def client
5
+ @client ||= OAI::Client.new 'http://localhost:3333/oai'
6
+ end
4
7
 
5
8
  def test_escaping_invalid_utf_8_characters
6
- client = OAI::Client.new 'http://localhost:3333/oai' #, :parser => 'libxml'
7
9
  invalid_utf_8 = [2, 3, 4, 104, 5, 101, 6, 108, 66897, 108, 66535, 111, 1114112, 33, 55234123, 33].pack("U*")
8
10
  invalid_utf_8 = invalid_utf_8.force_encoding("binary") if invalid_utf_8.respond_to? :force_encoding
9
11
  assert_equal("hello!!", client.send(:strip_invalid_utf_8_chars, invalid_utf_8).gsub(/\?/, ''))
10
12
  end
11
13
 
14
+ def test_unescaped_ampersand_content_correction
15
+ src = '<test>Frankie & Johnny <character>&#9829;</character></test>'
16
+ expected = '<test>Frankie &amp; Johnny <character>&#9829;</character></test>'
17
+ assert_equal(expected, client.sanitize_xml(src))
18
+ end
12
19
  end
@@ -0,0 +1,42 @@
1
+ require 'test_helper_harvester'
2
+
3
+ class HarvestTest < Test::Unit::TestCase
4
+ ONE_HOUR = 3600
5
+ EARLIEST_FIXTURE = "1998-05-02T04:00:00Z"
6
+ LATEST_FIXTURE = "2005-12-25T05:00:00Z"
7
+ def test_harvest
8
+ until_value = Time.now.utc - ONE_HOUR
9
+ config = OpenStruct.new(sites: { 'test' => { 'url' => 'http://localhost:3333/oai' }})
10
+ OAI::Harvester::Harvest.new(config).start
11
+ last = config.sites.dig('test', 'last')
12
+ assert_kind_of Time, last
13
+ assert last >= (until_value + ONE_HOUR), "#{last} < #{(until_value + ONE_HOUR)}"
14
+ end
15
+
16
+ def test_harvest_from_last
17
+ from_value = Time.parse(LATEST_FIXTURE).utc
18
+ now = Time.now.utc
19
+ config = OpenStruct.new(sites: { 'test' => { 'url' => 'http://localhost:3333/oai' }})
20
+ OAI::Harvester::Harvest.new(config, nil, from_value).start
21
+ last = config.sites.dig('test', 'last')
22
+ assert last >= now, "#{last} < #{now}"
23
+ end
24
+
25
+ def test_harvest_after_last
26
+ from_value = Time.parse(LATEST_FIXTURE).utc + 1
27
+ config = OpenStruct.new(sites: { 'test' => { 'url' => 'http://localhost:3333/oai' }})
28
+ OAI::Harvester::Harvest.new(config, nil, from_value).start
29
+ last = config.sites.dig('test', 'last')
30
+ assert_kind_of NilClass, last
31
+ end
32
+
33
+ def test_harvest_with_until
34
+ until_value = Time.parse(EARLIEST_FIXTURE).utc + ONE_HOUR
35
+ config = OpenStruct.new(sites: { 'test' => { 'url' => 'http://localhost:3333/oai' }})
36
+ OAI::Harvester::Harvest.new(config, nil, nil, until_value).start
37
+ last = config.sites.dig('test', 'last')
38
+ assert_kind_of Time, last
39
+ assert_equal last, until_value
40
+ end
41
+ end
42
+
@@ -0,0 +1,6 @@
1
+ require 'oai'
2
+ require 'oai/harvester'
3
+ require 'test/unit'
4
+
5
+ require File.dirname(__FILE__) + '/../client/helpers/provider'
6
+ require File.dirname(__FILE__) + '/../client/helpers/test_wrapper'
@@ -68,7 +68,7 @@ class TestModel < OAI::Provider::Model
68
68
  if token.last < @groups.size - 1
69
69
  PartialResult.new(@groups[token.last], token.next(token.last + 1))
70
70
  else
71
- @groups[token.last]
71
+ PartialResult.new(@groups[token.last], token.next(nil))
72
72
  end
73
73
  rescue
74
74
  raise OAI::ResumptionTokenException.new
@@ -76,8 +76,8 @@ class TestModel < OAI::Provider::Model
76
76
  else
77
77
  records = @records.select do |rec|
78
78
  ((opts[:set].nil? || rec.in_set(opts[:set])) &&
79
- (opts[:from].nil? || rec.updated_at >= opts[:from]) &&
80
- (opts[:until].nil? || rec.updated_at <= opts[:until]))
79
+ (opts[:from].nil? || rec.updated_at >= opts[:from].to_time) &&
80
+ (opts[:until].nil? || rec.updated_at <= opts[:until].to_time))
81
81
  #else
82
82
  # ((opts[:set].nil? || rec.in_set(opts[:set])) &&
83
83
  # (opts[:from].nil? || rec.updated_at >= opts[:from]) &&
@@ -13,15 +13,16 @@ class ResumptionTokenFunctionalTest < Test::Unit::TestCase
13
13
  end
14
14
  doc = Document.new(@provider.list_records(:metadata_prefix => 'oai_dc'))
15
15
  assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
16
- assert_equal 101, doc.elements["/OAI-PMH/ListRecords"].to_a.size
16
+ assert_equal (@provider.model.limit + 1), doc.elements["/OAI-PMH/ListRecords"].to_a.size
17
17
  token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
18
18
  doc = Document.new(@provider.list_records(:resumption_token => token))
19
19
  assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
20
- assert_equal 101, doc.elements["/OAI-PMH/ListRecords"].to_a.size
20
+ assert_equal (@provider.model.limit + 1), doc.elements["/OAI-PMH/ListRecords"].to_a.size
21
21
  end
22
22
 
23
23
  def test_from_and_until_with_resumption_tokens
24
- # Should return 300 records broken into 3 groups of 100.
24
+ # Should return 550 records broken into 5 groups of 100, and a final group of 50.
25
+ # checked elements under ListRecords are limit + 1, accounting for the resumptionToken element
25
26
  assert_nothing_raised do
26
27
  Document.new(@provider.list_records(:metadata_prefix => 'oai_dc'))
27
28
  end
@@ -29,19 +30,24 @@ class ResumptionTokenFunctionalTest < Test::Unit::TestCase
29
30
  @provider.list_records(
30
31
  :metadata_prefix => 'oai_dc',
31
32
  :from => Time.parse("September 1 2004"),
32
- :until => Time.parse("November 30 2004"))
33
+ :until => Time.parse("December 25 2005"))
33
34
  )
34
- assert_equal 101, doc.elements["/OAI-PMH/ListRecords"].to_a.size
35
- token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
36
-
37
- doc = Document.new(@provider.list_records(:resumption_token => token))
35
+ assert_equal (@provider.model.limit + 1), doc.elements["/OAI-PMH/ListRecords"].to_a.size
38
36
  assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
39
- assert_equal 101, doc.elements["/OAI-PMH/ListRecords"].to_a.size
40
37
  token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
41
38
 
39
+ 4.times do
40
+ doc = Document.new(@provider.list_records(:resumption_token => token))
41
+ assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
42
+ assert_equal (@provider.model.limit + 1), doc.elements["/OAI-PMH/ListRecords"].to_a.size
43
+ token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
44
+ end
45
+
42
46
  doc = Document.new(@provider.list_records(:resumption_token => token))
43
- assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
44
- assert_equal 100, doc.elements["/OAI-PMH/ListRecords"].to_a.size
47
+ # assert that ListRecords includes remaining records and an empty resumption token
48
+ assert_equal (551 % @provider.model.limit), doc.elements["/OAI-PMH/ListRecords"].to_a.size
49
+ assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
50
+ assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
45
51
  end
46
52
 
47
53
  end
@@ -0,0 +1,41 @@
1
+ require 'test_helper_provider'
2
+
3
+ class TestInstanceProvider < Test::Unit::TestCase
4
+
5
+ # Prior to the commit introducing this code, the InstanceProvider#identify
6
+ # method would instantiate a Response::Identify object, passing the
7
+ # InstanceProvider class as the provider for the Response::Identify
8
+ # instance. With the commit introducing this test, the
9
+ # InstanceProvider#identify now passes the instance of InstanceProvider
10
+ # to the instantiation of Response::Identify.
11
+ #
12
+ # Thus we can override, on an instance by instance basis, the behavior of a
13
+ # response object.
14
+ def test_instance_used_in_responses
15
+ @url_path = "/stringy-mc-string-face"
16
+ @instance_provider = InstanceProvider.new({ :provider_context => :instance_based, :url_path => @url_path })
17
+
18
+ xml = @instance_provider.identify
19
+ doc = REXML::Document.new(xml)
20
+ assert_equal "http://localhost#{@url_path}", doc.elements["OAI-PMH/Identify/baseURL"].text
21
+ end
22
+
23
+ def test_class_used_in_responses
24
+ @url_path = "/stringy-mc-string-face"
25
+ @instance_provider = InstanceProvider.new({ :provider_context => :class_based, :url_path => @url_path })
26
+
27
+ xml = @instance_provider.identify
28
+ doc = REXML::Document.new(xml)
29
+ assert_equal "http://localhost", doc.elements["OAI-PMH/Identify/baseURL"].text
30
+ end
31
+
32
+ def test_by_default_class_used_in_responses
33
+ @url_path = "/stringy-mc-string-face"
34
+ @instance_provider = InstanceProvider.new({ :url_path => @url_path })
35
+
36
+ xml = @instance_provider.identify
37
+ doc = REXML::Document.new(xml)
38
+ assert_equal "http://localhost", doc.elements["OAI-PMH/Identify/baseURL"].text
39
+ end
40
+
41
+ end
@@ -78,6 +78,32 @@ class OaiTest < Test::Unit::TestCase
78
78
  )
79
79
  assert_equal 100, doc.elements['OAI-PMH/ListRecords'].to_a.size
80
80
  end
81
+
82
+ def test_from_and_until_match
83
+ assert_nothing_raised do
84
+ @big_provider.list_records(
85
+ :metadata_prefix => 'oai_dc',
86
+ :from => "2000-11-01T05:00:00Z",
87
+ :until => "2000-11-30T05:00:00Z"
88
+ )
89
+ end
90
+
91
+ assert_nothing_raised do
92
+ @big_provider.list_records(
93
+ :metadata_prefix => 'oai_dc',
94
+ :from => "2000-11-01",
95
+ :until => "2000-11-30"
96
+ )
97
+ end
98
+
99
+ assert_raise(OAI::ArgumentException) do
100
+ @big_provider.list_records(
101
+ :metadata_prefix => 'oai_dc',
102
+ :from => "2000-11-01T05:00:00Z",
103
+ :until => "2000-11-30"
104
+ )
105
+ end
106
+ end
81
107
 
82
108
  def test_from_and_until
83
109
  assert_nothing_raised do
@@ -43,4 +43,10 @@ class ResumptionTokenTest < Test::Unit::TestCase
43
43
  assert_equal "#{@token.to_s}:#{@token.last}", doc.elements['/resumptionToken'].text
44
44
  end
45
45
 
46
+ def test_resumption_token_id_does_not_need_to_be_numeric
47
+ serialized = "oai_dc.s(A).f(2005-01-01T17:00:00Z).u(2005-01-31T17:00:00Z):FA129C"
48
+
49
+ token = ResumptionToken.parse(serialized)
50
+ assert_equal serialized, token.send(:encode_conditions)
51
+ end
46
52
  end
@@ -43,3 +43,20 @@ class DescribedProvider < Provider::Base
43
43
  sample_id '13900'
44
44
  extra_description "<my_custom_xml />"
45
45
  end
46
+
47
+ class InstanceProvider < Provider::Base
48
+ repository_name 'Instance Provider'
49
+ record_prefix 'oai:test'
50
+ repository_url 'http://localhost'
51
+ source_model SimpleModel.new
52
+
53
+ def initialize(options = {})
54
+ super
55
+ @url_path = options.fetch(:url_path)
56
+ end
57
+ attr_reader :url_path
58
+
59
+ def url
60
+ File.join(super, url_path)
61
+ end
62
+ end