oai 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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]) &&
|