oai 1.1.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.
- checksums.yaml +4 -4
- data/README.md +19 -4
- data/Rakefile +7 -0
- data/bin/oai +0 -2
- data/examples/models/file_model.rb +2 -2
- data/lib/oai/client/response.rb +8 -8
- data/lib/oai/client.rb +34 -10
- data/lib/oai/exception.rb +46 -38
- data/lib/oai/harvester/config.rb +1 -1
- data/lib/oai/harvester/harvest.rb +37 -25
- data/lib/oai/harvester/logging.rb +3 -5
- data/lib/oai/harvester.rb +4 -1
- data/lib/oai/provider/model/activerecord_caching_wrapper.rb +5 -8
- data/lib/oai/provider/model/activerecord_wrapper.rb +38 -22
- data/lib/oai/provider/model.rb +1 -1
- data/lib/oai/provider/response/list_records.rb +12 -0
- data/lib/oai/provider/response.rb +7 -4
- data/lib/oai/provider/resumption_token.rb +18 -5
- data/test/activerecord_provider/database/0001_oaipmh_tables.rb +7 -1
- data/test/activerecord_provider/helpers/providers.rb +3 -1
- data/test/activerecord_provider/helpers/transactional_test_case.rb +2 -1
- data/test/activerecord_provider/models/dc_field.rb +8 -0
- data/test/activerecord_provider/models/dc_lang.rb +3 -0
- data/test/activerecord_provider/models/exclusive_set_dc_field.rb +6 -0
- data/test/activerecord_provider/tc_activerecord_wrapper.rb +63 -0
- data/test/activerecord_provider/tc_ar_provider.rb +54 -26
- data/test/activerecord_provider/tc_ar_sets_provider.rb +10 -9
- data/test/activerecord_provider/tc_caching_paging_provider.rb +9 -7
- data/test/activerecord_provider/tc_simple_paging_provider.rb +9 -7
- data/test/client/tc_exception.rb +1 -1
- data/test/client/tc_get_record.rb +1 -1
- data/test/client/tc_http_client.rb +2 -2
- data/test/client/tc_libxml.rb +1 -1
- data/test/client/tc_utf8_escaping.rb +8 -1
- data/test/harvester/tc_harvest.rb +42 -0
- data/test/harvester/test_helper_harvester.rb +6 -0
- data/test/provider/models.rb +3 -3
- data/test/provider/tc_functional_tokens.rb +17 -11
- data/test/provider/tc_provider.rb +26 -0
- metadata +27 -16
data/lib/oai/provider/model.rb
CHANGED
@@ -29,7 +29,7 @@ module OAI::Provider
|
|
29
29
|
# see the ResumptionToken class for more details.
|
30
30
|
#
|
31
31
|
class Model
|
32
|
-
attr_reader :timestamp_field, :identifier_field
|
32
|
+
attr_reader :timestamp_field, :identifier_field, :limit
|
33
33
|
|
34
34
|
def initialize(limit = nil, timestamp_field = 'updated_at', identifier_field = 'id')
|
35
35
|
@limit = limit
|
@@ -2,6 +2,18 @@ module OAI::Provider::Response
|
|
2
2
|
|
3
3
|
class ListRecords < RecordResponse
|
4
4
|
required_parameters :metadata_prefix
|
5
|
+
|
6
|
+
def valid?
|
7
|
+
super && matching_granularity?
|
8
|
+
end
|
9
|
+
|
10
|
+
def matching_granularity?
|
11
|
+
if options[:from].nil? == false && options[:until].nil? == false && options[:from].class.name != options[:until].class.name
|
12
|
+
raise OAI::ArgumentException.new, "The 'from' and 'until' options specified must have the same granularity"
|
13
|
+
else
|
14
|
+
true
|
15
|
+
end
|
16
|
+
end
|
5
17
|
|
6
18
|
def to_xml
|
7
19
|
result = provider.model.find(:all, options)
|
@@ -90,10 +90,13 @@ module OAI
|
|
90
90
|
|
91
91
|
def parse_date(value)
|
92
92
|
return value if value.respond_to?(:strftime)
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
93
|
+
|
94
|
+
if value[-1] == "Z"
|
95
|
+
Time.strptime(value, "%Y-%m-%dT%H:%M:%S%Z").utc
|
96
|
+
else
|
97
|
+
Date.strptime(value, "%Y-%m-%d")
|
98
|
+
end
|
99
|
+
rescue ArgumentError => e
|
97
100
|
raise OAI::ArgumentException.new, "unparsable date: '#{value}'"
|
98
101
|
end
|
99
102
|
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'time'
|
2
|
-
require 'enumerator'
|
3
2
|
require File.dirname(__FILE__) + "/partial_result"
|
4
3
|
|
5
4
|
module OAI::Provider
|
@@ -37,7 +36,7 @@ module OAI::Provider
|
|
37
36
|
attr_reader :prefix, :set, :from, :until, :last, :last_str, :expiration, :total
|
38
37
|
|
39
38
|
# parses a token string and returns a ResumptionToken
|
40
|
-
def self.parse(token_string)
|
39
|
+
def self.parse(token_string, expiration = nil, total = nil)
|
41
40
|
begin
|
42
41
|
options = {}
|
43
42
|
matches = /(.+):([^ :]+)$/.match(token_string)
|
@@ -55,7 +54,7 @@ module OAI::Provider
|
|
55
54
|
options[:until] = Time.parse(part.sub(/^u\(/, '').sub(/\)$/, '')).localtime
|
56
55
|
end
|
57
56
|
end
|
58
|
-
self.new(options)
|
57
|
+
self.new(options, expiration, total)
|
59
58
|
rescue => err
|
60
59
|
raise OAI::ResumptionTokenException.new
|
61
60
|
end
|
@@ -123,10 +122,24 @@ module OAI::Provider
|
|
123
122
|
end
|
124
123
|
|
125
124
|
def encode_conditions
|
125
|
+
return "" if last_str.nil? || last_str.to_s.strip.eql?("")
|
126
|
+
|
126
127
|
encoded_token = @prefix.to_s.dup
|
127
128
|
encoded_token << ".s(#{set})" if set
|
128
|
-
|
129
|
-
|
129
|
+
if self.from
|
130
|
+
if self.from.respond_to?(:utc)
|
131
|
+
encoded_token << ".f(#{self.from.utc.xmlschema})"
|
132
|
+
else
|
133
|
+
encoded_token << ".f(#{self.from.xmlschema})"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
if self.until
|
137
|
+
if self.until.respond_to?(:utc)
|
138
|
+
encoded_token << ".u(#{self.until.utc.xmlschema})"
|
139
|
+
else
|
140
|
+
encoded_token << ".u(#{self.until.xmlschema})"
|
141
|
+
end
|
142
|
+
end
|
130
143
|
encoded_token << ":#{last_str}"
|
131
144
|
end
|
132
145
|
|
@@ -10,6 +10,12 @@ class OaipmhTables < ActiveRecord::Migration[5.2]
|
|
10
10
|
t.column :oai_token_id, :integer, :null => false
|
11
11
|
end
|
12
12
|
|
13
|
+
create_table :dc_langs do |t|
|
14
|
+
t.column :name, :string
|
15
|
+
t.column :updated_at, :datetime
|
16
|
+
t.column :created_at, :datetime
|
17
|
+
end
|
18
|
+
|
13
19
|
dc_fields = proc do |t|
|
14
20
|
t.column :title, :string
|
15
21
|
t.column :creator, :string
|
@@ -21,7 +27,7 @@ class OaipmhTables < ActiveRecord::Migration[5.2]
|
|
21
27
|
t.column :type, :string
|
22
28
|
t.column :format, :string
|
23
29
|
t.column :source, :string
|
24
|
-
t.column :
|
30
|
+
t.column :dc_lang_id, :integer
|
25
31
|
t.column :relation, :string
|
26
32
|
t.column :coverage, :string
|
27
33
|
t.column :rights, :string
|
@@ -56,11 +56,13 @@ class ARLoader
|
|
56
56
|
File.join(File.dirname(__FILE__), '..', 'fixtures', 'dc.yml')
|
57
57
|
)
|
58
58
|
fixtures.keys.sort.each do |key|
|
59
|
-
|
59
|
+
lang = DCLang.create(name: fixtures[key].delete('language'))
|
60
|
+
DCField.create(fixtures[key].merge(dc_lang: lang))
|
60
61
|
end
|
61
62
|
end
|
62
63
|
|
63
64
|
def self.unload
|
64
65
|
DCField.delete_all
|
66
|
+
DCLang.delete_all
|
65
67
|
end
|
66
68
|
end
|
@@ -19,7 +19,8 @@ class TransactionalTestCase < Test::Unit::TestCase
|
|
19
19
|
)
|
20
20
|
disable_logging do
|
21
21
|
fixtures.keys.sort.each do |key|
|
22
|
-
|
22
|
+
lang = DCLang.create(name: fixtures[key].delete('language'))
|
23
|
+
DCField.create(fixtures[key].merge(dc_lang: lang))
|
23
24
|
end
|
24
25
|
end
|
25
26
|
end
|
@@ -4,4 +4,12 @@ class DCField < ActiveRecord::Base
|
|
4
4
|
:join_table => "dc_fields_dc_sets",
|
5
5
|
:foreign_key => "dc_field_id",
|
6
6
|
:class_name => "DCSet"
|
7
|
+
|
8
|
+
belongs_to :dc_lang, class_name: "DCLang", optional: true
|
9
|
+
|
10
|
+
default_scope -> { left_outer_joins(:dc_lang) }
|
11
|
+
|
12
|
+
def language
|
13
|
+
dc_lang&.name
|
14
|
+
end
|
7
15
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'test_helper_ar_provider'
|
2
|
+
|
3
|
+
class ActiveRecordWrapperTest < TransactionalTestCase
|
4
|
+
def test_sql_conditions_from_date
|
5
|
+
input = "2005-12-25"
|
6
|
+
expected = input.dup
|
7
|
+
sql_template, sql_opts = sql_conditions(from: input)
|
8
|
+
assert_equal "dc_fields.updated_at >= :from", sql_template
|
9
|
+
assert_equal expected, sql_opts[:from]
|
10
|
+
sql_template, sql_opts = sql_conditions(from: Date.strptime(input, "%Y-%m-%d"))
|
11
|
+
assert_equal "dc_fields.updated_at >= :from", sql_template
|
12
|
+
assert_equal expected, sql_opts[:from]
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_sql_conditions_from_time
|
16
|
+
input = "2005-12-25T00:00:00Z"
|
17
|
+
expected = "2005-12-25 00:00:00"
|
18
|
+
sql_template, sql_opts = sql_conditions(from: input)
|
19
|
+
assert_equal "dc_fields.updated_at >= :from", sql_template
|
20
|
+
assert_equal expected, sql_opts[:from]
|
21
|
+
sql_template, sql_opts = sql_conditions(from: Time.strptime(input, "%Y-%m-%dT%H:%M:%S%Z"))
|
22
|
+
assert_equal "dc_fields.updated_at >= :from", sql_template
|
23
|
+
assert_equal expected, sql_opts[:from]
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_sql_conditions_until_date
|
27
|
+
input = "2005-12-25"
|
28
|
+
expected = "2005-12-26"
|
29
|
+
sql_template, sql_opts = sql_conditions(until: input)
|
30
|
+
assert_equal "dc_fields.updated_at < :until", sql_template
|
31
|
+
assert_equal expected, sql_opts[:until]
|
32
|
+
sql_template, sql_opts = sql_conditions(until: Date.strptime(input, "%Y-%m-%d"))
|
33
|
+
assert_equal "dc_fields.updated_at < :until", sql_template
|
34
|
+
assert_equal expected, sql_opts[:until]
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_sql_conditions_until_time
|
38
|
+
input = "2005-12-25T00:00:00Z"
|
39
|
+
expected = "2005-12-25 00:00:01"
|
40
|
+
sql_template, sql_opts = sql_conditions(until: input)
|
41
|
+
assert_equal "dc_fields.updated_at < :until", sql_template
|
42
|
+
assert_equal expected, sql_opts[:until]
|
43
|
+
sql_template, sql_opts = sql_conditions(until: Time.strptime(input, "%Y-%m-%dT%H:%M:%S%Z"))
|
44
|
+
assert_equal "dc_fields.updated_at < :until", sql_template
|
45
|
+
assert_equal expected, sql_opts[:until]
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_sql_conditions_both
|
49
|
+
input = "2005-12-25"
|
50
|
+
sql_template, sql_opts = sql_conditions(from: input, until: input)
|
51
|
+
assert_equal "dc_fields.updated_at >= :from AND dc_fields.updated_at < :until", sql_template
|
52
|
+
end
|
53
|
+
|
54
|
+
def setup
|
55
|
+
@wrapper = OAI::Provider::ActiveRecordWrapper.new(DCField)
|
56
|
+
end
|
57
|
+
|
58
|
+
def sql_conditions(opts)
|
59
|
+
@wrapper.send :sql_conditions, opts
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
@@ -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(
|
107
|
-
DCField.where("id <
|
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(
|
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 <
|
120
|
-
DCField.where("id <
|
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(
|
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 >
|
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 >
|
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 >
|
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(
|
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 >
|
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 >
|
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 >
|
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
|
-
|
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
|
-
|
21
|
-
|
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(
|
26
|
-
DCField.where("id <=
|
27
|
-
DCField.where("id <
|
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
|
-
|
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
|
@@ -20,8 +20,9 @@ class SimpleResumptionProviderTest < TransactionalTestCase
|
|
20
20
|
assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
|
21
21
|
|
22
22
|
doc = Document.new(@provider.list_records(:resumption_token => token))
|
23
|
-
|
24
|
-
|
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
|
25
26
|
end
|
26
27
|
|
27
28
|
def test_non_integer_identifiers_resumption
|
@@ -42,10 +43,10 @@ class SimpleResumptionProviderTest < TransactionalTestCase
|
|
42
43
|
|
43
44
|
def test_from_and_until
|
44
45
|
first_id = DCField.order("id asc").first.id
|
45
|
-
DCField.where("id <
|
46
|
-
DCField.where("id <=
|
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"))
|
47
48
|
|
48
|
-
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
|
49
50
|
|
50
51
|
# Should return 50 records broken into 2 groups of 25.
|
51
52
|
doc = Document.new(
|
@@ -58,8 +59,9 @@ class SimpleResumptionProviderTest < TransactionalTestCase
|
|
58
59
|
assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
|
59
60
|
token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
|
60
61
|
doc = Document.new(@provider.list_records(:resumption_token => token))
|
61
|
-
|
62
|
-
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
|
63
65
|
end
|
64
66
|
|
65
67
|
def setup
|
data/test/client/tc_exception.rb
CHANGED
@@ -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::
|
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::
|
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 '
|
62
|
-
builder.use
|
61
|
+
require 'faraday/follow_redirects'
|
62
|
+
builder.use Faraday::FollowRedirects::Middleware
|
63
63
|
builder.adapter :test, stubs
|
64
64
|
end
|
65
65
|
|
data/test/client/tc_libxml.rb
CHANGED
@@ -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::
|
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>♥</character></test>'
|
16
|
+
expected = '<test>Frankie & Johnny <character>♥</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
|
+
|
data/test/provider/models.rb
CHANGED
@@ -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]) &&
|