rsolr 0.9.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +228 -0
- data/LICENSE +13 -0
- data/README.rdoc +148 -0
- data/Rakefile +76 -0
- data/examples/direct.rb +29 -0
- data/examples/http.rb +25 -0
- data/lib/rsolr.rb +66 -0
- data/lib/rsolr/connection.rb +124 -0
- data/lib/rsolr/connection/adapter/direct.rb +88 -0
- data/lib/rsolr/connection/adapter/http.rb +42 -0
- data/lib/rsolr/http_client.rb +149 -0
- data/lib/rsolr/http_client/adapter/curb.rb +51 -0
- data/lib/rsolr/http_client/adapter/net_http.rb +48 -0
- data/lib/rsolr/message.rb +153 -0
- data/lib/rsolr/message/adapter/builder.rb +85 -0
- data/lib/rsolr/message/adapter/libxml.rb +59 -0
- data/rsolr.gemspec +46 -0
- data/test/connection/direct_test.rb +37 -0
- data/test/connection/http_test.rb +29 -0
- data/test/connection/test_methods.rb +97 -0
- data/test/helper.rb +61 -0
- data/test/http_client/curb_test.rb +18 -0
- data/test/http_client/net_http_test.rb +12 -0
- data/test/http_client/test_methods.rb +40 -0
- data/test/http_client/util_test.rb +83 -0
- data/test/message_test.rb +167 -0
- data/test/rsolr_test.rb +21 -0
- metadata +92 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
if defined?(JRUBY_VERSION)
|
2
|
+
|
3
|
+
require 'helper'
|
4
|
+
require 'connection/test_methods'
|
5
|
+
|
6
|
+
class ConnectionDirectTest < RSolrBaseTest
|
7
|
+
|
8
|
+
include ConnectionTestMethods
|
9
|
+
|
10
|
+
attr :dist
|
11
|
+
attr :home
|
12
|
+
|
13
|
+
def setup
|
14
|
+
base = File.expand_path( File.dirname(__FILE__) )
|
15
|
+
@dist = File.join(base, '..', '..', 'apache-solr')
|
16
|
+
@home = File.join(dist, 'example', 'solr')
|
17
|
+
@solr = RSolr.connect(:direct, :home_dir=>@home, :dist_dir=>@dist)
|
18
|
+
@solr.delete_by_query('*:*')
|
19
|
+
@solr.commit
|
20
|
+
end
|
21
|
+
|
22
|
+
def teardown
|
23
|
+
@solr.adapter.close
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_new_connection_with_existing_core
|
27
|
+
Dir["#{@dist}/dist/*.jar"].each { |p| require p }
|
28
|
+
dc = org.apache.solr.servlet.DirectSolrConnection.new(@home, "#{@home}/data", nil)
|
29
|
+
adapter = RSolr::Connection::Adapter::Direct.new dc
|
30
|
+
s = RSolr::Connection::Base.new(adapter)
|
31
|
+
assert_equal Hash, s.request('/admin/ping').class
|
32
|
+
adapter.close
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
unless defined?(JRUBY_VERSION)
|
2
|
+
|
3
|
+
require 'helper'
|
4
|
+
require 'connection/test_methods'
|
5
|
+
|
6
|
+
class AdapterHTTPTest < RSolrBaseTest
|
7
|
+
|
8
|
+
include ConnectionTestMethods
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@solr = RSolr.connect(:http)
|
12
|
+
@solr.delete_by_query('*:*')
|
13
|
+
@solr.commit
|
14
|
+
end
|
15
|
+
|
16
|
+
# http://www.w3.org/TR/html4/interact/forms.html#submit-format
|
17
|
+
|
18
|
+
# due to the way some servers implement their query string parsing,
|
19
|
+
# POST is sometimes needed for large query strings.
|
20
|
+
# This test simply shows that a large q value will not blow up solr.
|
21
|
+
def test_post_for_select
|
22
|
+
big_honkin_q = (['ipod']*1000).join(' OR ')
|
23
|
+
response = @solr.adapter.request '/select', {:q=>big_honkin_q}, :method=>:post
|
24
|
+
assert response
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# These are all of the test methods used by the various connection + adapter tests
|
2
|
+
# Currently: Direct and HTTP
|
3
|
+
# By sharing these tests, we can make sure the adapters are doing what they're suppossed to
|
4
|
+
# while staying "dry"
|
5
|
+
|
6
|
+
module ConnectionTestMethods
|
7
|
+
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
@solr.delete_by_query('id:[* TO *]')
|
11
|
+
@solr.commit
|
12
|
+
assert_equal 0, @solr.select(:q=>'*:*')['response']['docs'].size
|
13
|
+
end
|
14
|
+
|
15
|
+
# If :wt is NOT :ruby, the format doesn't get converted into a Mash (special Hash; see lib/mash.rb)
|
16
|
+
# Raw ruby can be returned by using :wt=>'ruby', not :ruby
|
17
|
+
def test_raw_response_formats
|
18
|
+
ruby_response = @solr.select(:q=>'*:*', :wt=>'ruby')
|
19
|
+
assert ruby_response.is_a?(String)
|
20
|
+
assert ruby_response =~ %r('wt'=>'ruby')
|
21
|
+
# xml?
|
22
|
+
xml_response = @solr.select(:q=>'*:*', :wt=>'xml')
|
23
|
+
assert xml_response.is_a?(String)
|
24
|
+
assert xml_response =~ %r(<str name="wt">xml</str>)
|
25
|
+
# json?
|
26
|
+
json_response = @solr.select(:q=>'*:*', :wt=>'json')
|
27
|
+
assert json_response.is_a?(String)
|
28
|
+
assert json_response =~ %r("wt":"json")
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_raise_on_invalid_query
|
32
|
+
assert_raise RSolr::RequestError do
|
33
|
+
@solr.select(:q=>'!')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_select_response_docs
|
38
|
+
@solr.add(:id=>1, :price=>1.00, :cat=>['electronics', 'something else'])
|
39
|
+
@solr.commit
|
40
|
+
r = @solr.select(:q=>'*:*')
|
41
|
+
assert r.is_a?(Hash)
|
42
|
+
|
43
|
+
docs = r['response']['docs']
|
44
|
+
assert_equal Array, docs.class
|
45
|
+
first = docs.first
|
46
|
+
|
47
|
+
# test the has? method
|
48
|
+
assert_equal 1.00, first['price']
|
49
|
+
|
50
|
+
assert_equal Array, first['cat'].class
|
51
|
+
assert first['cat'].include?('electronics')
|
52
|
+
assert first['cat'].include?('something else')
|
53
|
+
assert first['cat'].include?('something else')
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_add
|
58
|
+
assert_equal 0, @solr.select(:q=>'*:*')['response']['numFound']
|
59
|
+
update_response = @solr.add({:id=>100})
|
60
|
+
assert update_response.is_a?(Hash)
|
61
|
+
#
|
62
|
+
@solr.commit
|
63
|
+
assert_equal 1, @solr.select(:q=>'*:*')['response']['numFound']
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_delete_by_id
|
67
|
+
@solr.add(:id=>100)
|
68
|
+
@solr.commit
|
69
|
+
total = @solr.select(:q=>'*:*')['response']['numFound']
|
70
|
+
assert_equal 1, total
|
71
|
+
delete_response = @solr.delete_by_id(100)
|
72
|
+
@solr.commit
|
73
|
+
assert delete_response.is_a?(Hash)
|
74
|
+
total = @solr.select(:q=>'*:*')['response']['numFound']
|
75
|
+
assert_equal 0, total
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_delete_by_query
|
79
|
+
@solr.add(:id=>1, :name=>'BLAH BLAH BLAH')
|
80
|
+
@solr.commit
|
81
|
+
assert_equal 1, @solr.select(:q=>'*:*')['response']['numFound']
|
82
|
+
response = @solr.delete_by_query('name:"BLAH BLAH BLAH"')
|
83
|
+
@solr.commit
|
84
|
+
assert response.is_a?(Hash)
|
85
|
+
assert_equal 0, @solr.select(:q=>'*:*')['response']['numFound']
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_admin_luke_index_info
|
89
|
+
response = @solr.request('/admin/luke', :numTerms=>0)
|
90
|
+
assert response.is_a?(Hash)
|
91
|
+
# make sure the ? methods are true/false
|
92
|
+
assert [true, false].include?(response['index']['current'])
|
93
|
+
assert [true, false].include?(response['index']['optimized'])
|
94
|
+
assert [true, false].include?(response['index']['hasDeletions'])
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
|
2
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'rsolr')
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
#
|
6
|
+
class Test::Unit::TestCase
|
7
|
+
|
8
|
+
def self.test(name, &block)
|
9
|
+
test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
|
10
|
+
defined = instance_method(test_name) rescue false
|
11
|
+
raise "#{test_name} is already defined in #{self}" if defined
|
12
|
+
if block_given?
|
13
|
+
define_method(test_name, &block)
|
14
|
+
else
|
15
|
+
define_method(test_name) do
|
16
|
+
flunk "No implementation provided for #{name}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
class RSolrBaseTest < Test::Unit::TestCase
|
24
|
+
|
25
|
+
def assert_class(expected, instance)
|
26
|
+
assert_equal expected, instance.class
|
27
|
+
end
|
28
|
+
|
29
|
+
def default_test
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
begin
|
36
|
+
require 'rubygems'
|
37
|
+
require 'redgreen'
|
38
|
+
rescue LoadError
|
39
|
+
end
|
40
|
+
|
41
|
+
def mock_query_response
|
42
|
+
%({'responseHeader'=>{
|
43
|
+
'status'=>0,'QTime'=>43,'params'=>{
|
44
|
+
'q'=>'*:*','wt'=>'ruby','echoParams'=>'EXPLICIT'
|
45
|
+
}
|
46
|
+
},
|
47
|
+
'response'=>{
|
48
|
+
'numFound'=>26,'start'=>0,'docs'=>[
|
49
|
+
{'id'=>'SP2514N','inStock'=>true,'manu'=>'Samsung Electronics Co. Ltd.','name'=>'Samsung SpinPoint P120 SP2514N - hard drive - 250 GB - ATA-133','popularity'=>6,'price'=>92.0,'sku'=>'SP2514N','timestamp'=>'2008-11-21T17:21:55.601Z','cat'=>['electronics','hard drive'],'spell'=>['Samsung SpinPoint P120 SP2514N - hard drive - 250 GB - ATA-133'],'features'=>['7200RPM, 8MB cache, IDE Ultra ATA-133','NoiseGuard, SilentSeek technology, Fluid Dynamic Bearing (FDB) motor']},
|
50
|
+
{'id'=>'6H500F0','inStock'=>true,'manu'=>'Maxtor Corp.','name'=>'Maxtor DiamondMax 11 - hard drive - 500 GB - SATA-300','popularity'=>6,'price'=>350.0,'sku'=>'6H500F0','timestamp'=>'2008-11-21T17:21:55.617Z','cat'=>['electronics','hard drive'],'spell'=>['Maxtor DiamondMax 11 - hard drive - 500 GB - SATA-300'],'features'=>['SATA 3.0Gb/s, NCQ','8.5ms seek','16MB cache']},
|
51
|
+
{'id'=>'F8V7067-APL-KIT','inStock'=>false,'manu'=>'Belkin','name'=>'Belkin Mobile Power Cord for iPod w/ Dock','popularity'=>1,'price'=>19.95,'sku'=>'F8V7067-APL-KIT','timestamp'=>'2008-11-21T17:21:55.652Z','weight'=>4.0,'cat'=>['electronics','connector'],'spell'=>['Belkin Mobile Power Cord for iPod w/ Dock'],'features'=>['car power adapter, white']},
|
52
|
+
{'id'=>'IW-02','inStock'=>false,'manu'=>'Belkin','name'=>'iPod & iPod Mini USB 2.0 Cable','popularity'=>1,'price'=>11.5,'sku'=>'IW-02','timestamp'=>'2008-11-21T17:21:55.657Z','weight'=>2.0,'cat'=>['electronics','connector'],'spell'=>['iPod & iPod Mini USB 2.0 Cable'],'features'=>['car power adapter for iPod, white']},
|
53
|
+
{'id'=>'MA147LL/A','inStock'=>true,'includes'=>'earbud headphones, USB cable','manu'=>'Apple Computer Inc.','name'=>'Apple 60 GB iPod with Video Playback Black','popularity'=>10,'price'=>399.0,'sku'=>'MA147LL/A','timestamp'=>'2008-11-21T17:21:55.681Z','weight'=>5.5,'cat'=>['electronics','music'],'spell'=>['Apple 60 GB iPod with Video Playback Black'],'features'=>['iTunes, Podcasts, Audiobooks','Stores up to 15,000 songs, 25,000 photos, or 150 hours of video','2.5-inch, 320x240 color TFT LCD display with LED backlight','Up to 20 hours of battery life','Plays AAC, MP3, WAV, AIFF, Audible, Apple Lossless, H.264 video','Notes, Calendar, Phone book, Hold button, Date display, Photo wallet, Built-in games, JPEG photo playback, Upgradeable firmware, USB 2.0 compatibility, Playback speed control, Rechargeable capability, Battery level indication']},
|
54
|
+
{'id'=>'TWINX2048-3200PRO','inStock'=>true,'manu'=>'Corsair Microsystems Inc.','name'=>'CORSAIR XMS 2GB (2 x 1GB) 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) Dual Channel Kit System Memory - Retail','popularity'=>5,'price'=>185.0,'sku'=>'TWINX2048-3200PRO','timestamp'=>'2008-11-21T17:21:55.706Z','cat'=>['electronics','memory'],'spell'=>['CORSAIR XMS 2GB (2 x 1GB) 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) Dual Channel Kit System Memory - Retail'],'features'=>['CAS latency 2, 2-3-3-6 timing, 2.75v, unbuffered, heat-spreader']},
|
55
|
+
{'id'=>'VS1GB400C3','inStock'=>true,'manu'=>'Corsair Microsystems Inc.','name'=>'CORSAIR ValueSelect 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - Retail','popularity'=>7,'price'=>74.99,'sku'=>'VS1GB400C3','timestamp'=>'2008-11-21T17:21:55.71Z','cat'=>['electronics','memory'],'spell'=>['CORSAIR ValueSelect 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - Retail']},
|
56
|
+
{'id'=>'VDBDB1A16','inStock'=>true,'manu'=>'A-DATA Technology Inc.','name'=>'A-DATA V-Series 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - OEM','popularity'=>5,'sku'=>'VDBDB1A16','timestamp'=>'2008-11-21T17:21:55.712Z','cat'=>['electronics','memory'],'spell'=>['A-DATA V-Series 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - OEM'],'features'=>['CAS latency 3, 2.7v']},
|
57
|
+
{'id'=>'3007WFP','inStock'=>true,'includes'=>'USB cable','manu'=>'Dell, Inc.','name'=>'Dell Widescreen UltraSharp 3007WFP','popularity'=>6,'price'=>2199.0,'sku'=>'3007WFP','timestamp'=>'2008-11-21T17:21:55.724Z','weight'=>401.6,'cat'=>['electronics','monitor'],'spell'=>['Dell Widescreen UltraSharp 3007WFP'],'features'=>['30" TFT active matrix LCD, 2560 x 1600, .25mm dot pitch, 700:1 contrast']},
|
58
|
+
{'id'=>'VA902B','inStock'=>true,'manu'=>'ViewSonic Corp.','name'=>'ViewSonic VA902B - flat panel display - TFT - 19"','popularity'=>6,'price'=>279.95,'sku'=>'VA902B','timestamp'=>'2008-11-21T17:21:55.734Z','weight'=>190.4,'cat'=>['electronics','monitor'],'spell'=>['ViewSonic VA902B - flat panel display - TFT - 19"'],'features'=>['19" TFT active matrix LCD, 8ms response time, 1280 x 1024 native resolution']}]
|
59
|
+
}
|
60
|
+
})
|
61
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# don't run this test in jruby,
|
2
|
+
# the curb gem is a c extension based gem, jruby has no support for this
|
3
|
+
unless defined?(JRUBY_VERSION)
|
4
|
+
|
5
|
+
require 'helper'
|
6
|
+
require 'http_client/test_methods'
|
7
|
+
|
8
|
+
class CurbTest < RSolrBaseTest
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@c ||= RSolr::HTTPClient::connect(:curb, :url=>URL)
|
12
|
+
end
|
13
|
+
|
14
|
+
include HTTPClientTestMethods
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module HTTPClientTestMethods
|
2
|
+
|
3
|
+
URL = 'http://localhost:8983/solr/'
|
4
|
+
|
5
|
+
def test_raise_unknown_adapter
|
6
|
+
assert_raise RSolr::HTTPClient::UnkownAdapterError do
|
7
|
+
c = RSolr::HTTPClient.connect(:blah, URL)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# the responses from the HTTPClient adapter should return the same hash structure
|
12
|
+
def test_get_response
|
13
|
+
headers = {}
|
14
|
+
data = nil
|
15
|
+
response = @c.get('select', :q=>'*:*')
|
16
|
+
assert_equal data, response[:data]
|
17
|
+
assert_equal 200, response[:status_code]
|
18
|
+
expected_params = {:q=>'*:*'}
|
19
|
+
assert_equal expected_params, response[:params]
|
20
|
+
assert_equal 'select', response[:path]
|
21
|
+
assert response[:body] =~ /name="responseHeader"/
|
22
|
+
assert_equal 'http://localhost:8983/solr/select?q=%2A%3A%2A', response[:url]
|
23
|
+
assert_equal headers, response[:headers]
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_post_response
|
27
|
+
headers = {"Content-Type" => 'text/xml; charset=utf-8'}
|
28
|
+
data = '<add><doc><field name="id">1</field></doc></add>'
|
29
|
+
response = @c.post('update', data, {}, headers)
|
30
|
+
assert_equal data, response[:data]
|
31
|
+
assert_equal 200, response[:status_code]
|
32
|
+
expected_params = {}
|
33
|
+
assert_equal expected_params, response[:params]
|
34
|
+
assert_equal 'update', response[:path]
|
35
|
+
assert response[:body] =~ /name="responseHeader"/
|
36
|
+
assert_equal 'http://localhost:8983/solr/update', response[:url]
|
37
|
+
assert_equal headers, response[:headers]
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class HTTPUtilTest < RSolrBaseTest
|
4
|
+
|
5
|
+
class DummyClass
|
6
|
+
include RSolr::HTTPClient::Util
|
7
|
+
end
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@c = DummyClass.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_build_url
|
14
|
+
assert_equal '/something', @c.build_url('/something')
|
15
|
+
assert_equal '/something?q=Testing', @c.build_url('/something', :q=>'Testing')
|
16
|
+
assert_equal '/something?array=1&array=2&array=3', @c.build_url('/something', :array=>[1, 2, 3])
|
17
|
+
result = @c.build_url('/something', :q=>'A', :array=>[1, 2, 3])
|
18
|
+
assert result=~/^\/something\?/
|
19
|
+
assert result=~/q=A/
|
20
|
+
assert result=~/array=1/
|
21
|
+
assert result=~/array=2/
|
22
|
+
assert result=~/array=3/
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_escape
|
26
|
+
assert_equal '%2B', @c.escape('+')
|
27
|
+
assert_equal 'This+is+a+test', @c.escape('This is a test')
|
28
|
+
assert_equal '%3C%3E%2F%5C', @c.escape('<>/\\')
|
29
|
+
assert_equal '%22', @c.escape('"')
|
30
|
+
assert_equal '%3A', @c.escape(':')
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_hash_to_query
|
34
|
+
my_params = {
|
35
|
+
:z=>'should be whatever',
|
36
|
+
:q=>'test',
|
37
|
+
:d=>[1, 2, 3, 4],
|
38
|
+
:b=>:zxcv,
|
39
|
+
:x=>['!', '*', nil]
|
40
|
+
}
|
41
|
+
result = @c.hash_to_query(my_params)
|
42
|
+
assert result=~/z=should\+be\+whatever/
|
43
|
+
assert result=~/q=test/
|
44
|
+
assert result=~/d=1/
|
45
|
+
assert result=~/d=2/
|
46
|
+
assert result=~/d=3/
|
47
|
+
assert result=~/d=4/
|
48
|
+
assert result=~/b=zxcv/
|
49
|
+
assert result=~/x=%21/
|
50
|
+
assert result=~/x=*/
|
51
|
+
assert result=~/x=&?/
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_ampersand_within_query_value
|
55
|
+
my_params = {
|
56
|
+
"fq" => "building_facet:\"Green (Humanities & Social Sciences)\""
|
57
|
+
}
|
58
|
+
expected = 'fq=building_facet%3A%22Green+%28Humanities+%26+Social+Sciences%29%22'
|
59
|
+
assert_equal expected, @c.hash_to_query(my_params)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_brackets
|
63
|
+
assert_equal '%7B', @c.escape('{')
|
64
|
+
assert_equal '%7D', @c.escape('}')
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_exclamation
|
68
|
+
assert_equal '%21', @c.escape('!')
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_complex_solr_query1
|
72
|
+
my_params = {'fq' => '{!raw f=field_name}crazy+\"field+value'}
|
73
|
+
expected = 'fq=%7B%21raw+f%3Dfield_name%7Dcrazy%2B%5C%22field%2Bvalue'
|
74
|
+
assert_equal expected, @c.hash_to_query(my_params)
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_complex_solr_query2
|
78
|
+
my_params = {'q' => '+popularity:[10 TO *] +section:0'}
|
79
|
+
expected = 'q=%2Bpopularity%3A%5B10+TO+%2A%5D+%2Bsection%3A0'
|
80
|
+
assert_equal expected, @c.hash_to_query(my_params)
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
module MessageTestMethods
|
5
|
+
|
6
|
+
def builder
|
7
|
+
@builder ||= RSolr::Message::Builder.new
|
8
|
+
end
|
9
|
+
|
10
|
+
# call all of the simple methods...
|
11
|
+
# make sure the xml string is valid
|
12
|
+
# ensure the class is actually Solr::XML
|
13
|
+
def test_simple_methods
|
14
|
+
[:optimize, :rollback, :commit].each do |meth|
|
15
|
+
result = self.builder.send(meth)
|
16
|
+
assert_equal "<#{meth}/>", result.to_s
|
17
|
+
assert_equal String, result.class
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_add_yields_doc_objects_if_block_given
|
22
|
+
documents = [{:id=>1, :name=>'sam', :cat=>['cat 1', 'cat 2']}]
|
23
|
+
add_attrs = {:boost=>200.00}
|
24
|
+
result = self.builder.add(documents, add_attrs) do |doc|
|
25
|
+
doc.field_by_name(:name).attrs[:boost] = 10
|
26
|
+
assert_equal 4, doc.fields.size
|
27
|
+
assert_equal 2, doc.fields_by_name(:cat).size
|
28
|
+
end
|
29
|
+
#<add boost="200.0">
|
30
|
+
#<doc>
|
31
|
+
#<field name="cat">cat 1</field>
|
32
|
+
#<field name="cat">cat 2</field>
|
33
|
+
#<field name="name" boost="10">sam</field>
|
34
|
+
#<field name="id">1</field>
|
35
|
+
#</doc>
|
36
|
+
#</add>
|
37
|
+
assert result =~ %r(name="cat">cat 1</field>)
|
38
|
+
assert result =~ %r(name="cat">cat 2</field>)
|
39
|
+
assert result =~ %r(<add boost="200.0">)
|
40
|
+
assert result =~ %r(boost="10")
|
41
|
+
assert result =~ %r(<field name="id">1</field>)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_delete_by_id
|
45
|
+
result = self.builder.delete_by_id(10)
|
46
|
+
assert_equal String, result.class
|
47
|
+
assert_equal '<delete><id>10</id></delete>', result.to_s
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_delete_by_multiple_ids
|
51
|
+
result = self.builder.delete_by_id([1, 2, 3])
|
52
|
+
assert_equal String, result.class
|
53
|
+
assert_equal '<delete><id>1</id><id>2</id><id>3</id></delete>', result.to_s
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_delete_by_query
|
57
|
+
result = self.builder.delete_by_query('status:"LOST"')
|
58
|
+
assert_equal String, result.class
|
59
|
+
assert_equal '<delete><query>status:"LOST"</query></delete>', result.to_s
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_delete_by_multiple_queries
|
63
|
+
result = self.builder.delete_by_query(['status:"LOST"', 'quantity:0'])
|
64
|
+
assert_equal String, result.class
|
65
|
+
assert_equal '<delete><query>status:"LOST"</query><query>quantity:0</query></delete>', result.to_s
|
66
|
+
end
|
67
|
+
|
68
|
+
# add a single hash ("doc")
|
69
|
+
def test_add_hash
|
70
|
+
data = {
|
71
|
+
:id=>1,
|
72
|
+
:name=>'matt'
|
73
|
+
}
|
74
|
+
assert self.builder.add(data).to_s =~ /<field name="name">matt<\/field>/
|
75
|
+
assert self.builder.add(data).to_s =~ /<field name="id">1<\/field>/
|
76
|
+
end
|
77
|
+
|
78
|
+
# add an array of hashes
|
79
|
+
def test_add_array
|
80
|
+
data = [
|
81
|
+
{
|
82
|
+
:id=>1,
|
83
|
+
:name=>'matt'
|
84
|
+
},
|
85
|
+
{
|
86
|
+
:id=>2,
|
87
|
+
:name=>'sam'
|
88
|
+
}
|
89
|
+
]
|
90
|
+
|
91
|
+
message = self.builder.add(data)
|
92
|
+
expected = '<add><doc><field name="id">1</field><field name="name">matt</field></doc><doc><field name="id">2</field><field name="name">sam</field></doc></add>'
|
93
|
+
|
94
|
+
assert message.to_s=~/<field name="name">matt<\/field>/
|
95
|
+
assert message.to_s=~/<field name="name">sam<\/field>/
|
96
|
+
end
|
97
|
+
|
98
|
+
# multiValue field support test, thanks to Fouad Mardini!
|
99
|
+
def test_add_multi_valued_field
|
100
|
+
data = {
|
101
|
+
:id => 1,
|
102
|
+
:name => ['matt1', 'matt2']
|
103
|
+
}
|
104
|
+
|
105
|
+
result = self.builder.add(data)
|
106
|
+
|
107
|
+
assert result.to_s =~ /<field name="name">matt1<\/field>/
|
108
|
+
assert result.to_s =~ /<field name="name">matt2<\/field>/
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_add_single_document
|
112
|
+
document = RSolr::Message::Document.new
|
113
|
+
document.add_field('id', 1)
|
114
|
+
document.add_field('name', 'matt', :boost => 2.0)
|
115
|
+
result = self.builder.add(document)
|
116
|
+
|
117
|
+
assert result.to_s =~ /<field name="id">1<\/field>/
|
118
|
+
|
119
|
+
# depending on which ruby version, the attributes can be out of place
|
120
|
+
# so we need to test both... there's gotta be a better way to do this?
|
121
|
+
assert(
|
122
|
+
result.to_s =~ /<field name="name" boost="2.0">matt<\/field>/ ||
|
123
|
+
result.to_s =~ /<field boost="2.0" name="name">matt<\/field>/
|
124
|
+
)
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_add_multiple_documents
|
128
|
+
documents = (1..2).map do |i|
|
129
|
+
doc = RSolr::Message::Document.new
|
130
|
+
doc.add_field('id', i)
|
131
|
+
doc.add_field('name', "matt#{i}")
|
132
|
+
doc
|
133
|
+
end
|
134
|
+
result = self.builder.add(documents)
|
135
|
+
|
136
|
+
assert result.to_s =~ /<field name="name">matt1<\/field>/
|
137
|
+
assert result.to_s =~ /<field name="name">matt2<\/field>/
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
#####
|
143
|
+
|
144
|
+
unless defined?(JRUBY_VERSION)
|
145
|
+
class LibxmlMessageTest < RSolrBaseTest
|
146
|
+
|
147
|
+
include MessageTestMethods
|
148
|
+
|
149
|
+
def setup
|
150
|
+
self.builder.adapter = RSolr::Message::Adapter::Libxml.new
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
#####
|
158
|
+
|
159
|
+
class BuilderMessageTest < RSolrBaseTest
|
160
|
+
|
161
|
+
include MessageTestMethods
|
162
|
+
|
163
|
+
def setup
|
164
|
+
self.builder.adapter = RSolr::Message::Adapter::Builder.new
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|