rsolr 1.0.8 → 1.1.2

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.
@@ -2,73 +2,137 @@ require 'spec_helper'
2
2
  require 'base64'
3
3
 
4
4
  describe "RSolr::Connection" do
5
-
5
+
6
6
  context "setup_raw_request" do
7
- c = RSolr::Connection.new
8
- base_url = "http://localhost:8983/solr"
9
- client = RSolr::Client.new c, :url => base_url
10
- req = c.send :setup_raw_request, {:headers => {"content-type" => "text/xml"}, :method => :get, :uri => URI.parse(base_url + "/select?q=*:*")}
11
- req.path.should == "/solr/select?q=*:*"
12
- headers = {}
13
- req.each_header{|k,v| headers[k] = v}
14
- headers.should == {"content-type"=>"text/xml"}
7
+ it "should set the correct request parameters" do
8
+ c = RSolr::Connection.new
9
+ base_url = "http://localhost:8983/solr"
10
+ client = RSolr::Client.new c, :url => base_url
11
+ req = c.send :setup_raw_request, {:headers => {"content-type" => "text/xml"}, :method => :get, :uri => URI.parse(base_url + "/select?q=*:*")}
12
+ expect(req.path).to eq("/solr/select?q=*:*")
13
+ headers = {}
14
+ req.each_header{|k,v| headers[k] = v}
15
+ expect(headers).to eq({"content-type"=>"text/xml"})
16
+ end
17
+ end
18
+
19
+ context "when the connection is refused" do
20
+ subject { RSolr::Connection.new }
21
+
22
+ it "raises a custom exception" do
23
+ http_stub = double("Net:HTTP")
24
+ allow(http_stub).to receive(:request).and_raise(Errno::ECONNREFUSED)
25
+
26
+ allow(subject).to receive(:setup_raw_request) { http_stub }
27
+ allow(subject).to receive(:http) { Net::HTTP.new("localhost", 80) }
28
+
29
+ expect { subject.execute(nil, {}) }.to raise_error(RSolr::Error::ConnectionRefused)
30
+ end
15
31
  end
16
32
 
17
33
  context "read timeout configuration" do
18
- let(:client) { mock.as_null_object }
34
+ let(:client) { double.as_null_object }
19
35
 
20
- let(:http) { mock(Net::HTTP).as_null_object }
36
+ let(:http) { double(Net::HTTP).as_null_object }
21
37
 
22
- subject { RSolr::Connection.new }
38
+ subject { RSolr::Connection.new }
23
39
 
24
40
  before do
25
- Net::HTTP.stub(:new) { http }
41
+ allow(Net::HTTP).to receive(:new) { http }
26
42
  end
27
43
 
28
44
  it "should configure Net:HTTP read_timeout" do
29
- http.should_receive(:read_timeout=).with(42)
45
+ expect(http).to receive(:read_timeout=).with(42)
30
46
  subject.execute client, {:uri => URI.parse("http://localhost/some_uri"), :method => :get, :read_timeout => 42}
31
47
  end
32
48
 
33
49
  it "should use Net:HTTP default read_timeout if not specified" do
34
- http.should_not_receive(:read_timeout=)
50
+ expect(http).not_to receive(:read_timeout=)
35
51
  subject.execute client, {:uri => URI.parse("http://localhost/some_uri"), :method => :get}
36
52
  end
37
53
  end
38
54
 
39
55
  context "open timeout configuration" do
40
- let(:client) { mock.as_null_object }
56
+ let(:client) { double.as_null_object }
41
57
 
42
- let(:http) { mock(Net::HTTP).as_null_object }
58
+ let(:http) { double(Net::HTTP).as_null_object }
43
59
 
44
- subject { RSolr::Connection.new }
60
+ subject { RSolr::Connection.new }
45
61
 
46
62
  before do
47
- Net::HTTP.stub(:new) { http }
63
+ allow(Net::HTTP).to receive(:new) { http }
48
64
  end
49
65
 
50
66
  it "should configure Net:HTTP open_timeout" do
51
- http.should_receive(:open_timeout=).with(42)
67
+ expect(http).to receive(:open_timeout=).with(42)
52
68
  subject.execute client, {:uri => URI.parse("http://localhost/some_uri"), :method => :get, :open_timeout => 42}
53
69
  end
54
70
 
55
71
  it "should use Net:HTTP default open_timeout if not specified" do
56
- http.should_not_receive(:open_timeout=)
72
+ expect(http).not_to receive(:open_timeout=)
57
73
  subject.execute client, {:uri => URI.parse("http://localhost/some_uri"), :method => :get}
58
74
  end
59
75
  end
60
-
76
+
77
+ context "proxy configuration" do
78
+ let(:client) { double.as_null_object }
79
+
80
+ let(:http) { double(Net::HTTP).as_null_object }
81
+
82
+ let(:uri) { URI.parse("http://localhost/some_url") }
83
+ let(:proxy) { URI.parse("http://my.proxy/") }
84
+
85
+ subject { RSolr::Connection.new }
86
+
87
+ it "should use the default if no proxy is provided" do
88
+ expect(Net::HTTP).to receive(:new).with(uri.host, uri.port) { http }
89
+ subject.execute client, { :uri => uri, :method => :get }
90
+ end
91
+
92
+ it "should use the proxy if one is provided" do
93
+ expect(Net::HTTP).to receive(:Proxy).with(proxy.host, proxy.port, nil, nil) { http }
94
+ subject.execute client, { :uri => uri, :proxy => proxy, :method => :get }
95
+ end
96
+
97
+ it "should not use a proxy if proxy setting is false" do
98
+ expect(Net::HTTP).to receive(:new).with(uri.host, uri.port, nil) { http }
99
+ subject.execute client, { :uri => uri, :proxy => false, :method => :get }
100
+ end
101
+ end
102
+
103
+ context "connection refused" do
104
+ let(:client) { double.as_null_object }
105
+
106
+ let(:http) { double(Net::HTTP).as_null_object }
107
+ let(:request_context) {
108
+ {:uri => URI.parse("http://localhost/some_uri"), :method => :get, :open_timeout => 42}
109
+ }
110
+ subject { RSolr::Connection.new }
111
+
112
+ before do
113
+ allow(Net::HTTP).to receive(:new) { http }
114
+ end
115
+
116
+ it "should configure Net:HTTP open_timeout" do
117
+ skip "doesn't work with ruby 1.8" if RUBY_VERSION < "1.9"
118
+ expect(http).to receive(:request).and_raise(Errno::ECONNREFUSED)
119
+ expect {
120
+ subject.execute client, request_context
121
+ }.to raise_error(Errno::ECONNREFUSED, /#{request_context}/)
122
+ end
123
+ end
124
+
61
125
  describe "basic auth support" do
62
- let(:http) { mock(Net::HTTP).as_null_object }
63
-
126
+ let(:http) { double(Net::HTTP).as_null_object }
127
+
64
128
  before do
65
- Net::HTTP.stub(:new) { http }
129
+ allow(Net::HTTP).to receive(:new) { http }
66
130
  end
67
-
131
+
68
132
  it "sets the authorization header" do
69
- http.should_receive(:request) do |request|
70
- request.fetch('authorization').should == "Basic #{Base64.encode64("joe:pass")}".strip
71
- mock(Net::HTTPResponse).as_null_object
133
+ expect(http).to receive(:request) do |request|
134
+ expect(request.fetch('authorization')).to eq("Basic #{Base64.encode64("joe:pass")}".strip)
135
+ double(Net::HTTPResponse).as_null_object
72
136
  end
73
137
  RSolr::Connection.new.execute nil, :uri => URI.parse("http://joe:pass@localhost:8983/solr"), :method => :get
74
138
  end
@@ -5,52 +5,42 @@ describe "RSolr::Error" do
5
5
  rescue RSolr::Error::Http => exception
6
6
  exception
7
7
  end
8
+ let (:response_lines) { (1..15).to_a.map { |i| "line #{i}" } }
9
+ let(:request) { double :[] => "mocked" }
10
+ let(:response_body) { response_lines.join("\n") }
11
+ let(:response) {{
12
+ :body => response_body,
13
+ :status => 400
14
+ }}
15
+ subject { generate_error_with_backtrace(request, response).to_s }
8
16
 
9
17
  context "when the response body is wrapped in a <pre> element" do
10
- before do
11
- response_lines = (1..15).to_a.map { |i| "line #{i}" }
12
-
13
- @request = mock :[] => "mocked"
14
- @response = {
15
- :body => "<pre>" + response_lines.join("\n") + "</pre>",
16
- :status => 400
17
- }
18
- end
18
+ let(:response_body) { "<pre>" + response_lines.join("\n") + "</pre>" }
19
19
 
20
20
  it "only shows the first eleven lines of the response" do
21
- error = generate_error_with_backtrace @request, @response
22
- error.to_s.should match(/line 1\n.+line 11\n\n/m)
21
+ expect(subject).to match(/line 1\n.+line 11\n\n/m)
23
22
  end
24
23
 
25
- it "shows only one line when the response is one line long" do
26
- @response[:body] = "<pre>failed</pre>"
27
-
28
- error = generate_error_with_backtrace @request, @response
29
- error.to_s.should match(/Error: failed/)
24
+ context "when the response is one line long" do
25
+ let(:response_body) { "<pre>failed</pre>" }
26
+ it { should match(/Error: failed/) }
30
27
  end
31
28
  end
32
29
 
33
30
  context "when the response body is not wrapped in a <pre> element" do
34
- before do
35
- response_lines = (1..15).to_a.map { |i| "line #{i}" }
36
-
37
- @request = mock :[] => "mocked"
38
- @response = {
39
- :body => response_lines.join("\n"),
40
- :status => 400
41
- }
42
- end
43
31
 
44
32
  it "only shows the first eleven lines of the response" do
45
- error = generate_error_with_backtrace @request, @response
46
- error.to_s.should match(/line 1\n.+line 11\n\n/m)
33
+ expect(subject).to match(/line 1\n.+line 11\n\n/m)
47
34
  end
48
35
 
49
- it "shows only one line when the response is one line long" do
50
- @response[:body] = "failed"
51
-
52
- error = generate_error_with_backtrace @request, @response
53
- error.to_s.should match(/Error: failed/)
36
+ context "when the response is one line long" do
37
+ let(:response_body) { 'failed' }
38
+ it { should match(/Error: failed/) }
39
+ end
40
+ context "when the response body contains a msg key" do
41
+ let(:msg) { "'org.apache.solr.search.SyntaxError: Cannot parse \\':false\\': Encountered \" \":\" \": \"\" at line 1, column 0.'" }
42
+ let(:response_body) { (response_lines << "'error'=>{'msg'=> #{msg}").join("\n") }
43
+ it { should include msg }
54
44
  end
55
45
  end
56
46
  end
@@ -6,16 +6,23 @@ describe "RSolr::Pagination" do
6
6
  r = c.build_paginated_request 3, 25, "select", {:params => {:q => "test"}}
7
7
  #r[:page].should == 3
8
8
  #r[:per_page].should == 25
9
- r[:params]["start"].should == 50
10
- r[:params]["rows"].should == 25
11
- r[:uri].query.should =~ /rows=25/
12
- r[:uri].query.should =~ /start=50/
9
+ expect(r[:params]["start"]).to eq(50)
10
+ expect(r[:params]["rows"]).to eq(25)
11
+ expect(r[:uri].query).to match(/rows=25/)
12
+ expect(r[:uri].query).to match(/start=50/)
13
+ end
14
+
15
+ it 'passes through client options' do
16
+ c = RSolr::Client.new(nil, open_timeout: 5, read_timeout: 7)
17
+ r = c.build_paginated_request 3, 25, "select", {:params => {:q => "test"}}
18
+ expect(r[:open_timeout]).to eq(5)
19
+ expect(r[:read_timeout]).to eq(7)
13
20
  end
14
21
  end
15
22
  context "paginate" do
16
23
  it "should build a paginated request context and call execute" do
17
24
  c = RSolr::Client.new(nil, {})#.extend(RSolr::Pagination::Client)
18
- c.should_receive(:execute).with(hash_including({
25
+ expect(c).to receive(:execute).with(hash_including({
19
26
  #:page => 1,
20
27
  #:per_page => 10,
21
28
  :params => {
@@ -2,18 +2,38 @@ require 'spec_helper'
2
2
  describe "RSolr" do
3
3
 
4
4
  it "has a version that can be read via #version or VERSION" do
5
- RSolr.version.should == RSolr::VERSION
5
+ expect(RSolr.version).to eq(RSolr::VERSION)
6
6
  end
7
-
8
- it "can escape" do
9
- RSolr.should be_a(RSolr::Char)
10
- RSolr.escape("this string").should == "this\\ string"
11
- end
12
-
7
+
13
8
  context "connect" do
14
9
  it "should return a RSolr::Client instance" do
15
- RSolr.connect.should be_a(RSolr::Client)
10
+ expect(RSolr.connect).to be_a(RSolr::Client)
11
+ end
12
+ end
13
+
14
+ context '.solr_escape' do
15
+ it "adds backslash to Solr query syntax chars" do
16
+ # per http://lucene.apache.org/core/4_0_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Escaping_Special_Characters
17
+ special_chars = [ "+", "-", "&", "|", "!", "(", ")", "{", "}", "[", "]", "^", '"', "~", "*", "?", ":", "\\", "/" ]
18
+ escaped_str = RSolr.solr_escape("aa#{special_chars.join('aa')}aa")
19
+ special_chars.each { |c|
20
+ # note that the ruby code sending the query to Solr will un-escape the backslashes
21
+ # so the result sent to Solr is ultimately a single backslash in front of the particular character
22
+ expect(escaped_str).to match "\\#{c}"
23
+ }
24
+ end
25
+ it "leaves other chars alone" do
26
+ str = "nothing to see here; let's move along people."
27
+ expect(RSolr.solr_escape(str)).to eq str
16
28
  end
17
29
  end
30
+
31
+ # deprecated as of 2015-02
32
+ =begin
33
+ it "can escape" do
34
+ expect(RSolr).to be_a(RSolr::Char)
35
+ expect(RSolr.escape("this string")).to eq("this\\ string")
36
+ end
37
+ =end
18
38
 
19
39
  end
data/spec/api/uri_spec.rb CHANGED
@@ -1,70 +1,128 @@
1
1
  require 'spec_helper'
2
2
  describe "RSolr::Uri" do
3
3
 
4
- context "class-level methods" do
5
-
6
- let(:uri){ RSolr::Uri }
7
-
8
- it "should return a URI object with a trailing slash" do
4
+ let(:uri) { RSolr::Uri }
5
+
6
+ context '.create' do
7
+ it "returns a URI object" do
9
8
  u = uri.create 'http://apache.org'
10
- u.path[0].should == ?/
9
+ expect(u).to be_a_kind_of URI
11
10
  end
12
-
13
- it "should return the bytesize of a string" do
14
- uri.bytesize("test").should == 4
11
+ it "calls URI.parse" do
12
+ expect(URI).to receive(:parse).twice.and_call_original
13
+ u = uri.create 'http://apache.org'
15
14
  end
16
-
17
- it "should convert a solr query string from a hash w/o a starting ?" do
15
+ it "adds a trailing slash after host if there is none" do
16
+ u = uri.create 'http://apache.org'
17
+ u_str = u.to_s
18
+ size = u_str.size
19
+ expect(u_str[size - 1]).to eq '/'
20
+ end
21
+ it "does not add trailing slash after host if there already is one" do
22
+ u = uri.create 'http://apache.org/'
23
+ u_str = u.to_s
24
+ size = u_str.size
25
+ expect(u_str[size - 2, 2]).to eq 'g/'
26
+ end
27
+ it "adds a trailing slash after path if there is none" do
28
+ u = uri.create 'http://apache.org/lucene'
29
+ u_str = u.to_s
30
+ size = u_str.size
31
+ expect(u_str[size - 1]).to eq '/'
32
+ end
33
+ it "does not add trailing slash after path if there already is one" do
34
+ u = uri.create 'http://apache.org/lucene/'
35
+ u_str = u.to_s
36
+ size = u_str.size
37
+ expect(u_str[size - 2, 2]).to eq 'e/'
38
+ end
39
+ it "does not add trailing slash if there are query params" do
40
+ u = uri.create 'http://apache.org?foo=bar'
41
+ u_str = u.to_s
42
+ size = u_str.size
43
+ expect(u_str[size - 1]).not_to eq '/'
44
+ end
45
+ end
46
+
47
+ context '.params_to_solr' do
48
+ it "converts Hash to Solr query string w/o a starting ?" do
18
49
  hash = {:q => "gold", :fq => ["mode:one", "level:2"]}
19
50
  query = uri.params_to_solr hash
20
- query[0].should_not == ??
51
+ expect(query[0]).not_to eq(??)
21
52
  [/q=gold/, /fq=mode%3Aone/, /fq=level%3A2/].each do |p|
22
- query.should match p
53
+ expect(query).to match p
23
54
  end
24
- query.split('&').size.should == 3
55
+ expect(query.split('&').size).to eq(3)
56
+ end
57
+ it 'should URL escape &' do
58
+ expect(uri.params_to_solr(:fq => "&")).to eq('fq=%26')
25
59
  end
26
-
27
- context "escape_query_value" do
28
-
29
- it 'should escape &' do
30
- uri.params_to_solr(:fq => "&").should == 'fq=%26'
31
- end
32
60
 
33
- it 'should convert spaces to +' do
34
- uri.params_to_solr(:fq => "me and you").should == 'fq=me+and+you'
35
- end
61
+ it 'should convert spaces to +' do
62
+ expect(uri.params_to_solr(:fq => "me and you")).to eq('fq=me+and+you')
63
+ end
36
64
 
37
- it 'should escape comlex queries, part 1' do
38
- my_params = {'fq' => '{!raw f=field_name}crazy+\"field+value'}
39
- expected = 'fq=%7B%21raw+f%3Dfield_name%7Dcrazy%2B%5C%22field%2Bvalue'
40
- uri.params_to_solr(my_params).should == expected
41
- end
65
+ it 'should URL escape complex queries, part 1' do
66
+ my_params = {'fq' => '{!raw f=field_name}crazy+\"field+value'}
67
+ expected = 'fq=%7B%21raw+f%3Dfield_name%7Dcrazy%2B%5C%22field%2Bvalue'
68
+ expect(uri.params_to_solr(my_params)).to eq(expected)
69
+ end
42
70
 
43
- it 'should escape complex queries, part 2' do
44
- my_params = {'q' => '+popularity:[10 TO *] +section:0'}
45
- expected = 'q=%2Bpopularity%3A%5B10+TO+%2A%5D+%2Bsection%3A0'
46
- uri.params_to_solr(my_params).should == expected
47
- end
48
-
49
- it 'should escape properly' do
50
- uri.escape_query_value('+').should == '%2B'
51
- uri.escape_query_value('This is a test').should == 'This+is+a+test'
52
- uri.escape_query_value('<>/\\').should == '%3C%3E%2F%5C'
53
- uri.escape_query_value('"').should == '%22'
54
- uri.escape_query_value(':').should == '%3A'
55
- end
71
+ it 'should URL escape complex queries, part 2' do
72
+ my_params = {'q' => '+popularity:[10 TO *] +section:0'}
73
+ expected = 'q=%2Bpopularity%3A%5B10+TO+*%5D+%2Bsection%3A0'
74
+ expect(uri.params_to_solr(my_params)).to eq(expected)
75
+ end
76
+ end
77
+
78
+ =begin
79
+ # deprecated
80
+ context '.build_param' do
81
+ it "calls URI.encode_www_form_component by default" do
82
+ expect(URI).to receive(:encode_www_form_component).twice
83
+ uri.build_param("foo", "bar")
84
+ end
85
+ it "calls URI.encode_www_form_component if escape arg = true" do
86
+ expect(URI).to receive(:encode_www_form_component).twice
87
+ uri.build_param("foo", "bar", true)
88
+ end
89
+ it "doesn't call URI.encode_www_form_component if escape arg = false" do
90
+ expect(URI).not_to receive(:encode_www_form_component)
91
+ uri.build_param("foo", "bar", false)
92
+ end
93
+ end
56
94
 
57
- it 'should escape brackets' do
58
- uri.escape_query_value('{').should == '%7B'
59
- uri.escape_query_value('}').should == '%7D'
60
- end
95
+ # deprecated
96
+ context ".escape_query_value" do
97
+ it 'should escape properly' do
98
+ expect(uri.escape_query_value('+')).to eq('%2B')
99
+ expect(uri.escape_query_value('This is a test')).to eq('This+is+a+test')
100
+ expect(uri.escape_query_value('<>/\\')).to eq('%3C%3E%2F%5C')
101
+ expect(uri.escape_query_value('"')).to eq('%22')
102
+ expect(uri.escape_query_value(':')).to eq('%3A')
103
+ end
61
104
 
62
- it 'should escape exclamation marks!' do
63
- uri.escape_query_value('!').should == '%21'
64
- end
65
-
105
+ it 'should escape brackets' do
106
+ expect(uri.escape_query_value('{')).to eq('%7B')
107
+ expect(uri.escape_query_value('}')).to eq('%7D')
108
+ end
109
+
110
+ it 'should escape exclamation marks!' do
111
+ expect(uri.escape_query_value('!')).to eq('%21')
66
112
  end
67
-
68
113
  end
69
114
 
115
+ # deprecated
116
+ context '.bytesize' do
117
+ it "calls .bytesize for String" do
118
+ str = "testing"
119
+ expect(str).to receive(:bytesize)
120
+ uri.bytesize(str)
121
+ end
122
+ it "returns the size of a String" do
123
+ expect(uri.bytesize("test")).to eq(4)
124
+ end
125
+ end
126
+ =end
127
+
70
128
  end