sphinx 0.9.10.2122 → 2.1.1.3711

Sign up to get free protection for your applications and to get access to all the features.
Files changed (185) hide show
  1. data/.gitignore +5 -2
  2. data/.travis.yml +8 -0
  3. data/CHANGELOG.md +71 -0
  4. data/Gemfile +4 -0
  5. data/README.md +221 -0
  6. data/Rakefile +40 -35
  7. data/lib/sphinx.rb +3 -8
  8. data/lib/sphinx/client.rb +223 -70
  9. data/lib/sphinx/constants.rb +23 -8
  10. data/lib/sphinx/response.rb +6 -6
  11. data/lib/sphinx/timeout.rb +1 -2
  12. data/lib/sphinx/version.rb +3 -0
  13. data/spec/client_response_spec.rb +77 -64
  14. data/spec/client_spec.rb +68 -31
  15. data/spec/client_validations_spec.rb +61 -7
  16. data/spec/fixtures/requests/default_search.dat +0 -0
  17. data/spec/fixtures/requests/default_search_index.dat +0 -0
  18. data/spec/fixtures/requests/excerpt_custom.dat +0 -0
  19. data/spec/fixtures/requests/excerpt_default.dat +0 -0
  20. data/spec/fixtures/requests/excerpt_flags.dat +0 -0
  21. data/spec/fixtures/requests/field_weights.dat +0 -0
  22. data/spec/fixtures/requests/filter.dat +0 -0
  23. data/spec/fixtures/requests/filter_exclude.dat +0 -0
  24. data/spec/fixtures/requests/filter_float_range.dat +0 -0
  25. data/spec/fixtures/requests/filter_float_range_exclude.dat +0 -0
  26. data/spec/fixtures/requests/filter_range.dat +0 -0
  27. data/spec/fixtures/requests/filter_range_exclude.dat +0 -0
  28. data/spec/fixtures/requests/filter_range_int64.dat +0 -0
  29. data/spec/fixtures/requests/filter_ranges.dat +0 -0
  30. data/spec/fixtures/requests/filters.dat +0 -0
  31. data/spec/fixtures/requests/filters_different.dat +0 -0
  32. data/spec/fixtures/requests/geo_anchor.dat +0 -0
  33. data/spec/fixtures/requests/group_by_attr.dat +0 -0
  34. data/spec/fixtures/requests/group_by_attrpair.dat +0 -0
  35. data/spec/fixtures/requests/group_by_day.dat +0 -0
  36. data/spec/fixtures/requests/group_by_day_sort.dat +0 -0
  37. data/spec/fixtures/requests/group_by_month.dat +0 -0
  38. data/spec/fixtures/requests/group_by_week.dat +0 -0
  39. data/spec/fixtures/requests/group_by_year.dat +0 -0
  40. data/spec/fixtures/requests/group_distinct.dat +0 -0
  41. data/spec/fixtures/requests/id_range.dat +0 -0
  42. data/spec/fixtures/requests/id_range64.dat +0 -0
  43. data/spec/fixtures/requests/index_weights.dat +0 -0
  44. data/spec/fixtures/requests/keywords.dat +0 -0
  45. data/spec/fixtures/requests/limits.dat +0 -0
  46. data/spec/fixtures/requests/limits_cutoff.dat +0 -0
  47. data/spec/fixtures/requests/limits_max.dat +0 -0
  48. data/spec/fixtures/requests/limits_max_cutoff.dat +0 -0
  49. data/spec/fixtures/requests/match_all.dat +0 -0
  50. data/spec/fixtures/requests/match_any.dat +0 -0
  51. data/spec/fixtures/requests/match_boolean.dat +0 -0
  52. data/spec/fixtures/requests/match_extended.dat +0 -0
  53. data/spec/fixtures/requests/match_extended2.dat +0 -0
  54. data/spec/fixtures/requests/match_fullscan.dat +0 -0
  55. data/spec/fixtures/requests/match_phrase.dat +0 -0
  56. data/spec/fixtures/requests/max_query_time.dat +0 -0
  57. data/spec/fixtures/requests/miltiple_queries.dat +0 -0
  58. data/spec/fixtures/requests/outer_select.dat +0 -0
  59. data/spec/fixtures/requests/override.dat +0 -0
  60. data/spec/fixtures/{default_search.php → requests/php/default_search.php} +1 -1
  61. data/spec/fixtures/{default_search_index.php → requests/php/default_search_index.php} +1 -1
  62. data/spec/fixtures/{excerpt_custom.php → requests/php/excerpt_custom.php} +1 -1
  63. data/spec/fixtures/{excerpt_default.php → requests/php/excerpt_default.php} +1 -1
  64. data/spec/fixtures/{excerpt_flags.php → requests/php/excerpt_flags.php} +1 -1
  65. data/spec/fixtures/{field_weights.php → requests/php/field_weights.php} +1 -1
  66. data/spec/fixtures/{filter.php → requests/php/filter.php} +1 -1
  67. data/spec/fixtures/{filter_exclude.php → requests/php/filter_exclude.php} +1 -1
  68. data/spec/fixtures/{filter_float_range.php → requests/php/filter_float_range.php} +1 -1
  69. data/spec/fixtures/{filter_float_range_exclude.php → requests/php/filter_float_range_exclude.php} +1 -1
  70. data/spec/fixtures/{filter_range.php → requests/php/filter_range.php} +1 -1
  71. data/spec/fixtures/{filter_range_exclude.php → requests/php/filter_range_exclude.php} +1 -1
  72. data/spec/fixtures/{filter_range_int64.php → requests/php/filter_range_int64.php} +1 -1
  73. data/spec/fixtures/{filter_ranges.php → requests/php/filter_ranges.php} +1 -1
  74. data/spec/fixtures/{filters.php → requests/php/filters.php} +1 -1
  75. data/spec/fixtures/{filters_different.php → requests/php/filters_different.php} +1 -1
  76. data/spec/fixtures/{geo_anchor.php → requests/php/geo_anchor.php} +1 -1
  77. data/spec/fixtures/{group_by_attr.php → requests/php/group_by_attr.php} +1 -1
  78. data/spec/fixtures/{group_by_attrpair.php → requests/php/group_by_attrpair.php} +1 -1
  79. data/spec/fixtures/{group_by_day.php → requests/php/group_by_day.php} +1 -1
  80. data/spec/fixtures/{group_by_day_sort.php → requests/php/group_by_day_sort.php} +1 -1
  81. data/spec/fixtures/{group_by_month.php → requests/php/group_by_month.php} +1 -1
  82. data/spec/fixtures/{group_by_week.php → requests/php/group_by_week.php} +1 -1
  83. data/spec/fixtures/{group_by_year.php → requests/php/group_by_year.php} +1 -1
  84. data/spec/fixtures/{group_distinct.php → requests/php/group_distinct.php} +1 -1
  85. data/spec/fixtures/{id_range.php → requests/php/id_range.php} +1 -1
  86. data/spec/fixtures/{id_range64.php → requests/php/id_range64.php} +1 -1
  87. data/spec/fixtures/{index_weights.php → requests/php/index_weights.php} +1 -1
  88. data/spec/fixtures/{keywords.php → requests/php/keywords.php} +1 -1
  89. data/spec/fixtures/{limits.php → requests/php/limits.php} +1 -1
  90. data/spec/fixtures/{limits_cutoff.php → requests/php/limits_cutoff.php} +1 -1
  91. data/spec/fixtures/{limits_max.php → requests/php/limits_max.php} +1 -1
  92. data/spec/fixtures/{limits_max_cutoff.php → requests/php/limits_max_cutoff.php} +1 -1
  93. data/spec/fixtures/{match_all.php → requests/php/match_all.php} +1 -1
  94. data/spec/fixtures/{match_any.php → requests/php/match_any.php} +1 -1
  95. data/spec/fixtures/{match_boolean.php → requests/php/match_boolean.php} +1 -1
  96. data/spec/fixtures/{match_extended.php → requests/php/match_extended.php} +1 -1
  97. data/spec/fixtures/{match_extended2.php → requests/php/match_extended2.php} +1 -1
  98. data/spec/fixtures/{match_fullscan.php → requests/php/match_fullscan.php} +1 -1
  99. data/spec/fixtures/{match_phrase.php → requests/php/match_phrase.php} +1 -1
  100. data/spec/fixtures/{max_query_time.php → requests/php/max_query_time.php} +1 -1
  101. data/spec/fixtures/{miltiple_queries.php → requests/php/miltiple_queries.php} +1 -1
  102. data/spec/fixtures/requests/php/outer_select.php +9 -0
  103. data/spec/fixtures/{set_override.php → requests/php/override.php} +1 -1
  104. data/spec/fixtures/requests/php/query_flag.php +13 -0
  105. data/spec/fixtures/requests/php/query_flag_after_reset.php +19 -0
  106. data/spec/fixtures/{ranking_bm25.php → requests/php/ranking_bm25.php} +1 -1
  107. data/spec/fixtures/requests/php/ranking_expr.php +9 -0
  108. data/spec/fixtures/{ranking_fieldmask.php → requests/php/ranking_fieldmask.php} +1 -1
  109. data/spec/fixtures/{ranking_matchany.php → requests/php/ranking_matchany.php} +1 -1
  110. data/spec/fixtures/{ranking_none.php → requests/php/ranking_none.php} +1 -1
  111. data/spec/fixtures/{ranking_proximity.php → requests/php/ranking_proximity.php} +1 -1
  112. data/spec/fixtures/{ranking_proximity_bm25.php → requests/php/ranking_proximity_bm25.php} +1 -1
  113. data/spec/fixtures/{ranking_sph04.php → requests/php/ranking_sph04.php} +1 -1
  114. data/spec/fixtures/{ranking_wordcount.php → requests/php/ranking_wordcount.php} +1 -1
  115. data/spec/fixtures/{retries.php → requests/php/retries.php} +1 -1
  116. data/spec/fixtures/{retries_delay.php → requests/php/retries_delay.php} +1 -1
  117. data/spec/fixtures/{select.php → requests/php/select.php} +1 -1
  118. data/spec/fixtures/{sort_attr_asc.php → requests/php/sort_attr_asc.php} +1 -1
  119. data/spec/fixtures/{sort_attr_desc.php → requests/php/sort_attr_desc.php} +1 -1
  120. data/spec/fixtures/{sort_expr.php → requests/php/sort_expr.php} +1 -1
  121. data/spec/fixtures/{sort_extended.php → requests/php/sort_extended.php} +1 -1
  122. data/spec/fixtures/{sort_relevance.php → requests/php/sort_relevance.php} +1 -1
  123. data/spec/fixtures/{sort_time_segments.php → requests/php/sort_time_segments.php} +1 -1
  124. data/spec/fixtures/{update_attributes.php → requests/php/update_attributes.php} +1 -1
  125. data/spec/fixtures/{update_attributes_mva.php → requests/php/update_attributes_mva.php} +1 -1
  126. data/spec/fixtures/{weights.php → requests/php/weights.php} +1 -1
  127. data/spec/fixtures/requests/query_flag.dat +0 -0
  128. data/spec/fixtures/requests/query_flag_after_reset.dat +0 -0
  129. data/spec/fixtures/requests/ranking_bm25.dat +0 -0
  130. data/spec/fixtures/requests/ranking_expr.dat +0 -0
  131. data/spec/fixtures/requests/ranking_fieldmask.dat +0 -0
  132. data/spec/fixtures/requests/ranking_matchany.dat +0 -0
  133. data/spec/fixtures/requests/ranking_none.dat +0 -0
  134. data/spec/fixtures/requests/ranking_proximity.dat +0 -0
  135. data/spec/fixtures/requests/ranking_proximity_bm25.dat +0 -0
  136. data/spec/fixtures/requests/ranking_sph04.dat +0 -0
  137. data/spec/fixtures/requests/ranking_wordcount.dat +0 -0
  138. data/spec/fixtures/requests/retries.dat +0 -0
  139. data/spec/fixtures/requests/retries_delay.dat +0 -0
  140. data/spec/fixtures/requests/select.dat +0 -0
  141. data/spec/fixtures/requests/sort_attr_asc.dat +0 -0
  142. data/spec/fixtures/requests/sort_attr_desc.dat +0 -0
  143. data/spec/fixtures/requests/sort_expr.dat +0 -0
  144. data/spec/fixtures/requests/sort_extended.dat +0 -0
  145. data/spec/fixtures/requests/sort_relevance.dat +0 -0
  146. data/spec/fixtures/requests/sort_time_segments.dat +0 -0
  147. data/spec/fixtures/requests/update_attributes.dat +0 -0
  148. data/spec/fixtures/requests/update_attributes_mva.dat +0 -0
  149. data/spec/fixtures/requests/weights.dat +0 -0
  150. data/spec/fixtures/responses/build_excerpts.dat +0 -0
  151. data/spec/fixtures/responses/build_keywords.dat +0 -0
  152. data/spec/fixtures/responses/flush_attributes.dat +0 -0
  153. data/spec/fixtures/responses/flush_attrs.dat +2 -0
  154. data/spec/fixtures/responses/open.dat +0 -0
  155. data/spec/fixtures/responses/open_twice.dat +0 -0
  156. data/spec/fixtures/responses/php/build_excerpts.php +8 -0
  157. data/spec/fixtures/responses/php/build_keywords.php +8 -0
  158. data/spec/fixtures/responses/php/flush_attributes.php +8 -0
  159. data/spec/fixtures/responses/php/open.php +8 -0
  160. data/spec/fixtures/responses/php/open_twice.php +9 -0
  161. data/spec/fixtures/responses/php/query.php +8 -0
  162. data/spec/fixtures/responses/php/query_error.php +8 -0
  163. data/spec/fixtures/responses/php/query_id64.php +8 -0
  164. data/spec/fixtures/responses/php/run_queries.php +10 -0
  165. data/spec/fixtures/responses/php/run_queries_error.php +9 -0
  166. data/spec/fixtures/responses/php/status.php +8 -0
  167. data/spec/fixtures/responses/php/update_attributes.php +8 -0
  168. data/spec/fixtures/responses/php/update_attributes_mva.php +8 -0
  169. data/spec/fixtures/responses/query.dat +0 -0
  170. data/spec/fixtures/responses/query_error.dat +0 -0
  171. data/spec/fixtures/responses/query_id64.dat +0 -0
  172. data/spec/fixtures/responses/run_queries.dat +0 -0
  173. data/spec/fixtures/responses/run_queries_error.dat +0 -0
  174. data/spec/fixtures/responses/status.dat +0 -0
  175. data/spec/fixtures/responses/update_attributes.dat +0 -0
  176. data/spec/fixtures/responses/update_attributes_mva.dat +0 -0
  177. data/spec/fixtures/sphinxapi.php +217 -45
  178. data/spec/spec_helper.rb +18 -3
  179. data/spec/sphinx/sphinx-id64.conf +6 -6
  180. data/spec/sphinx/sphinx.conf +6 -6
  181. data/sphinx.gemspec +19 -121
  182. metadata +268 -105
  183. data/README.rdoc +0 -243
  184. data/VERSION.yml +0 -5
  185. data/init.rb +0 -1
@@ -24,9 +24,6 @@ module Sphinx
24
24
  # status command
25
25
  # @private
26
26
  SEARCHD_COMMAND_STATUS = 5
27
- # query command
28
- # @private
29
- SEARCHD_COMMAND_QUERY = 6
30
27
  # flushattrs command
31
28
  # @private
32
29
  SEARCHD_COMMAND_FLUSHATTRS = 7
@@ -37,13 +34,13 @@ module Sphinx
37
34
 
38
35
  # search command version
39
36
  # @private
40
- VER_COMMAND_SEARCH = 0x117
37
+ VER_COMMAND_SEARCH = 0x11D
41
38
  # excerpt command version
42
39
  # @private
43
- VER_COMMAND_EXCERPT = 0x100
40
+ VER_COMMAND_EXCERPT = 0x104
44
41
  # update command version
45
42
  # @private
46
- VER_COMMAND_UPDATE = 0x102
43
+ VER_COMMAND_UPDATE = 0x103
47
44
  # keywords command version
48
45
  # @private
49
46
  VER_COMMAND_KEYWORDS = 0x100
@@ -116,6 +113,8 @@ module Sphinx
116
113
  SPH_RANK_FIELDMASK = 6
117
114
  # codename SPH04, phrase proximity + bm25 + head/exact boost
118
115
  SPH_RANK_SPH04 = 7
116
+ # lets you specify the ranking formula in run time
117
+ SPH_RANK_EXPR = 8
119
118
 
120
119
  #=================================================================
121
120
  # Known sort modes
@@ -164,8 +163,12 @@ module Sphinx
164
163
  SPH_ATTR_BIGINT = 6
165
164
  # string (binary; in-memory)
166
165
  SPH_ATTR_STRING = 7
166
+ # ???
167
+ SPH_ATTR_FACTORS = 1001
167
168
  # this attr has multiple values (0 or more)
168
- SPH_ATTR_MULTI = 0x40000000
169
+ SPH_ATTR_MULTI = 0x40000001
170
+ # this attr has multiple 64-bit values (0 or more)
171
+ SPH_ATTR_MULTI64 = 0x40000002
169
172
 
170
173
  #=================================================================
171
174
  # Known grouping functions
@@ -183,7 +186,19 @@ module Sphinx
183
186
  SPH_GROUPBY_ATTR = 4
184
187
  # group by sequential attrs pair
185
188
  SPH_GROUPBY_ATTRPAIR = 5
189
+
190
+ #=================================================================
191
+ # Known query flags
192
+ #=================================================================
193
+
194
+ QUERY_FLAGS = HashWithIndifferentAccess.new(
195
+ :reverse_scan => { :values => [ 0, 1 ], :index => 0 },
196
+ :sort_method => { :values => ['pq', 'kbuffer' ], :index => 1 },
197
+ :max_predicted_time => { :values => lambda { |x| x > 0 }, :index => 2 },
198
+ :boolean_simplify => { :values => [ false, true ], :index => 3 },
199
+ :idf => { :values => [ 'normalized', 'plain' ], :index => 4 }
200
+ )
186
201
  end
187
202
 
188
203
  include Constants
189
- end
204
+ end
@@ -10,17 +10,17 @@ module Sphinx
10
10
  @position = 0
11
11
  @size = response.length
12
12
  end
13
-
13
+
14
14
  # Gets current stream position.
15
15
  def position
16
16
  @position
17
17
  end
18
-
18
+
19
19
  # Gets response size.
20
20
  def size
21
21
  @size
22
22
  end
23
-
23
+
24
24
  # Returns <tt>true</tt> when response stream is out.
25
25
  def eof?
26
26
  @position >= @size
@@ -50,7 +50,7 @@ module Sphinx
50
50
  @position += length
51
51
  return values
52
52
  end
53
-
53
+
54
54
  # Get string from stream.
55
55
  def get_string
56
56
  length = get_int
@@ -59,7 +59,7 @@ module Sphinx
59
59
  @position += length
60
60
  return value
61
61
  end
62
-
62
+
63
63
  # Get float from stream.
64
64
  def get_float
65
65
  raise EOFError if @position + 4 > @size
@@ -68,4 +68,4 @@ module Sphinx
68
68
  return ([uval].pack('L')).unpack('f*').first
69
69
  end
70
70
  end
71
- end
71
+ end
@@ -12,8 +12,7 @@ module Sphinx
12
12
  require 'system_timer'
13
13
  Timeout = ::SystemTimer
14
14
  end
15
- rescue LoadError => e
16
- puts "[sphinx] Could not load SystemTimer gem, falling back to Ruby's slower/unsafe timeout library: #{e.message}"
15
+ rescue LoadError
17
16
  require 'timeout'
18
17
  Timeout = ::Timeout
19
18
  end
@@ -0,0 +1,3 @@
1
+ module Sphinx
2
+ VERSION = '2.1.1.3711'
3
+ end
@@ -6,30 +6,41 @@ describe Sphinx::Client, 'connected' do
6
6
  before :each do
7
7
  @sphinx = Sphinx::Client.new
8
8
  end
9
-
9
+
10
+ def mock_sphinx_response(fixture)
11
+ response = sphinx_fixture(fixture, :response)
12
+ @sock = SphinxFakeSocket.new(response, 'rb')
13
+ servers = @sphinx.instance_variable_get(:@servers)
14
+ servers.first.stub(:get_socket => @sock)
15
+ end
16
+
10
17
  context 'in Query method' do
11
18
  it 'should parse response' do
19
+ mock_sphinx_response('query')
12
20
  result = @sphinx.Query('wifi', 'test1')
13
21
  validate_results_wifi(result)
14
22
  end
15
23
 
16
24
  it 'should process 64-bit keys' do
25
+ mock_sphinx_response('query_id64')
17
26
  result = @sphinx.Query('wifi', 'test2')
18
- result['total_found'].should == 3
19
- result['matches'].length.should == 3
20
- result['matches'][0]['id'].should == 4294967298
21
- result['matches'][1]['id'].should == 4294967299
22
- result['matches'][2]['id'].should == 4294967297
27
+ result['total_found'].should eq(3)
28
+ result['matches'].length.should eq(3)
29
+ result['matches'][0]['id'].should eq(4294967298)
30
+ result['matches'][1]['id'].should eq(4294967299)
31
+ result['matches'][2]['id'].should eq(4294967297)
23
32
  end
24
33
 
25
34
  it 'should process errors in Query method' do
35
+ mock_sphinx_response('query_error')
26
36
  @sphinx.Query('wifi', 'fakeindex').should be_false
27
- @sphinx.GetLastError.should_not be_empty
37
+ @sphinx.GetLastError.should =~ /unknown local index/
28
38
  end
29
39
  end
30
-
40
+
31
41
  context 'in RunQueries method' do
32
42
  it 'should parse batch-query responce' do
43
+ mock_sphinx_response('run_queries')
33
44
  @sphinx.AddQuery('wifi', 'test1')
34
45
  @sphinx.AddQuery('gprs', 'test1')
35
46
  results = @sphinx.RunQueries
@@ -39,6 +50,7 @@ describe Sphinx::Client, 'connected' do
39
50
  end
40
51
 
41
52
  it 'should process errors in RunQueries method' do
53
+ mock_sphinx_response('run_queries_error')
42
54
  @sphinx.AddQuery('wifi', 'fakeindex')
43
55
  r = @sphinx.RunQueries
44
56
  r[0]['error'].should_not be_empty
@@ -47,132 +59,133 @@ describe Sphinx::Client, 'connected' do
47
59
 
48
60
  context 'in BuildExcerpts method' do
49
61
  it 'should parse response' do
62
+ mock_sphinx_response('build_excerpts')
50
63
  result = @sphinx.BuildExcerpts(['what the world', 'London is the capital of Great Britain'], 'test1', 'the')
51
- result.should == ['what <b>the</b> world', 'London is <b>the</b> capital of Great Britain']
64
+ result.should eq(['what <b>the</b> world', 'London is <b>the</b> capital of Great Britain'])
52
65
  end
53
66
  end
54
67
 
55
68
  context 'in BuildKeywords method' do
56
69
  it 'should parse response' do
70
+ mock_sphinx_response('build_keywords')
57
71
  result = @sphinx.BuildKeywords('wifi gprs', 'test1', true)
58
- result.should == [
72
+ result.should eq([
59
73
  { 'normalized' => 'wifi', 'tokenized' => 'wifi', 'hits' => 6, 'docs' => 3 },
60
74
  { 'normalized' => 'gprs', 'tokenized' => 'gprs', 'hits' => 1, 'docs' => 1 }
61
- ]
75
+ ])
62
76
  end
63
77
  end
64
78
 
65
79
  context 'in UpdateAttributes method' do
66
80
  it 'should parse response' do
67
- @sphinx.UpdateAttributes('test1', ['group_id'], { 2 => [1] }).should == 1
68
- result = @sphinx.Query('wifi', 'test1')
69
- result['matches'][0]['attrs']['group_id'].should == 1
70
- @sphinx.UpdateAttributes('test1', ['group_id'], { 2 => [2] }).should == 1
71
- result = @sphinx.Query('wifi', 'test1')
72
- result['matches'][0]['attrs']['group_id'].should == 2
81
+ mock_sphinx_response('update_attributes')
82
+ @sphinx.UpdateAttributes('test1', ['group_id'], { 2 => [1] }).should eq(1)
73
83
  end
74
84
 
75
85
  it 'should parse response with MVA' do
76
- @sphinx.UpdateAttributes('test1', ['tags'], { 2 => [[1, 2, 3, 4, 5, 6, 7, 8, 9]] }, true).should == 1
77
- result = @sphinx.Query('wifi', 'test1')
78
- result['matches'][0]['attrs']['tags'].should == [1, 2, 3, 4, 5, 6, 7, 8, 9]
79
- @sphinx.UpdateAttributes('test1', ['tags'], { 2 => [[5, 6, 7, 8]] }, true).should == 1
80
- result = @sphinx.Query('wifi', 'test1')
81
- result['matches'][0]['attrs']['tags'].should == [5, 6, 7, 8]
86
+ mock_sphinx_response('update_attributes_mva')
87
+ @sphinx.UpdateAttributes('test1', ['tags'], { 2 => [[1, 2, 3, 4, 5, 6, 7, 8, 9]] }, true).should eq(1)
82
88
  end
83
89
  end
84
90
 
85
91
  context 'in Open method' do
86
92
  it 'should open socket' do
93
+ mock_sphinx_response('open')
87
94
  @sphinx.Open.should be_true
88
95
  socket = @sphinx.servers.first.instance_variable_get(:@socket)
89
- socket.should_not be_nil
90
- socket.should be_kind_of(Sphinx::BufferedIO)
96
+ socket.should eq(@sock)
91
97
  socket.close
92
98
  end
93
-
99
+
94
100
  it 'should produce an error when opened twice' do
101
+ mock_sphinx_response('open')
102
+ sock = @sock
95
103
  @sphinx.Open.should be_true
104
+ mock_sphinx_response('open_twice')
96
105
  @sphinx.Open.should be_false
97
- @sphinx.GetLastError.should == 'already connected'
98
-
106
+ @sphinx.GetLastError.should eq('already connected')
107
+
99
108
  socket = @sphinx.servers.first.instance_variable_get(:@socket)
100
- socket.should be_kind_of(Sphinx::BufferedIO)
109
+ socket.should eq(sock)
101
110
  socket.close
102
111
  end
103
112
  end
104
-
113
+
105
114
  context 'in Close method' do
106
115
  it 'should open socket' do
116
+ mock_sphinx_response('open')
107
117
  @sphinx.Open.should be_true
108
118
  @sphinx.Close.should be_true
109
119
  @sphinx.servers.first.instance_variable_get(:@socket).should be_nil
110
120
  end
111
-
121
+
112
122
  it 'should produce socket is closed' do
113
123
  @sphinx.Close.should be_false
114
- @sphinx.GetLastError.should == 'not connected'
124
+ @sphinx.GetLastError.should eq('not connected')
115
125
  @sphinx.servers.first.instance_variable_get(:@socket).should be_nil
116
-
126
+
127
+ mock_sphinx_response('open')
117
128
  @sphinx.Open.should be_true
118
129
  @sphinx.Close.should be_true
119
130
  @sphinx.Close.should be_false
120
- @sphinx.GetLastError.should == 'not connected'
131
+ @sphinx.GetLastError.should eq('not connected')
121
132
  @sphinx.servers.first.instance_variable_get(:@socket).should be_nil
122
133
  end
123
134
  end
124
135
 
125
136
  context 'in Status method' do
126
137
  it 'should parse response' do
138
+ mock_sphinx_response('status')
127
139
  response = @sphinx.Status
128
140
  response.should be_an(Array)
129
141
  response.size.should be > 10
130
142
  end
131
143
  end
132
144
 
133
- context 'in FlushAttrs method' do
145
+ context 'in FlushAttributes method' do
134
146
  it 'should not raise an error' do
147
+ mock_sphinx_response('flush_attributes')
135
148
  expect {
136
- @sphinx.FlushAttrs
149
+ @sphinx.FlushAttributes
137
150
  }.to_not raise_error
138
151
  end
139
152
  end
140
153
 
141
154
  def validate_results_wifi(result)
142
- result['total_found'].should == 3
143
- result['matches'].length.should == 3
155
+ result['total_found'].should eq(3)
156
+ result['matches'].length.should eq(3)
144
157
  result['time'].should_not be_nil
145
- result['attrs'].should == {
158
+ result['attrs'].should eq({
146
159
  'group_id' => Sphinx::SPH_ATTR_INTEGER,
147
160
  'created_at' => Sphinx::SPH_ATTR_TIMESTAMP,
148
161
  'rating' => Sphinx::SPH_ATTR_FLOAT,
149
162
  'tags' => Sphinx::SPH_ATTR_MULTI | Sphinx::SPH_ATTR_INTEGER
150
- }
151
- result['fields'].should == [ 'name', 'description' ]
152
- result['total'].should == 3
163
+ })
164
+ result['fields'].should eq([ 'name', 'description' ])
165
+ result['total'].should eq(3)
153
166
  result['matches'].should be_an_instance_of(Array)
154
167
 
155
- result['matches'][0]['id'].should == 2
156
- result['matches'][0]['weight'].should == 2
157
- result['matches'][0]['attrs']['group_id'].should == 2
158
- result['matches'][0]['attrs']['created_at'].should == 1175658555
159
- result['matches'][0]['attrs']['tags'].should == [5, 6, 7, 8]
160
- ('%0.2f' % result['matches'][0]['attrs']['rating']).should == '54.85'
161
-
162
- result['matches'][1]['id'].should == 3
163
- result['matches'][1]['weight'].should == 2
164
- result['matches'][1]['attrs']['group_id'].should == 1
165
- result['matches'][1]['attrs']['created_at'].should == 1175658647
166
- result['matches'][1]['attrs']['tags'].should == [1, 7, 9, 10]
167
- ('%0.2f' % result['matches'][1]['attrs']['rating']).should == '16.25'
168
-
169
- result['matches'][2]['id'].should == 1
170
- result['matches'][2]['weight'].should == 1
171
- result['matches'][2]['attrs']['group_id'].should == 1
172
- result['matches'][2]['attrs']['created_at'].should == 1175658490
173
- result['matches'][2]['attrs']['tags'].should == [1, 2, 3, 4]
174
- ('%0.2f' % result['matches'][2]['attrs']['rating']).should == '13.32'
175
-
176
- result['words'].should == { 'wifi' => { 'hits' => 6, 'docs' => 3 } }
168
+ result['matches'][0]['id'].should eq(2)
169
+ result['matches'][0]['weight'].should eq(2)
170
+ result['matches'][0]['attrs']['group_id'].should eq(2)
171
+ result['matches'][0]['attrs']['created_at'].should eq(1175683755)
172
+ result['matches'][0]['attrs']['tags'].should eq([5, 6, 7, 8])
173
+ ('%0.2f' % result['matches'][0]['attrs']['rating']).should eq('54.85')
174
+
175
+ result['matches'][1]['id'].should eq(3)
176
+ result['matches'][1]['weight'].should eq(2)
177
+ result['matches'][1]['attrs']['group_id'].should eq(1)
178
+ result['matches'][1]['attrs']['created_at'].should eq(1175683847)
179
+ result['matches'][1]['attrs']['tags'].should eq([1, 7, 9, 10])
180
+ ('%0.2f' % result['matches'][1]['attrs']['rating']).should eq('16.25')
181
+
182
+ result['matches'][2]['id'].should eq(1)
183
+ result['matches'][2]['weight'].should eq(1)
184
+ result['matches'][2]['attrs']['group_id'].should eq(1)
185
+ result['matches'][2]['attrs']['created_at'].should eq(1175683690)
186
+ result['matches'][2]['attrs']['tags'].should eq([1, 2, 3, 4])
187
+ ('%0.2f' % result['matches'][2]['attrs']['rating']).should eq('13.32')
188
+
189
+ result['words'].should eq({ 'wifi' => { 'hits' => 6, 'docs' => 3 } })
177
190
  end
178
191
  end
@@ -20,7 +20,7 @@ describe Sphinx::Client, 'disconnected' do
20
20
  2.times do
21
21
  cnt = 0
22
22
  expect {
23
- @sphinx.send(:with_server) { |server| cnt += 1; server.should == @sphinx.servers[0]; raise Sphinx::SphinxConnectError }
23
+ @sphinx.send(:with_server) { |server| cnt += 1; server.should eq(@sphinx.servers[0]); raise Sphinx::SphinxConnectError }
24
24
  }.to raise_error(Sphinx::SphinxConnectError)
25
25
  cnt.should == 1
26
26
  end
@@ -29,24 +29,24 @@ describe Sphinx::Client, 'disconnected' do
29
29
  it 'should select server based on index' do
30
30
  @sphinx.SetServers(@servers)
31
31
  cnt = 0
32
- @sphinx.send(:with_server, 0) { |server| cnt += 1; server.should == @sphinx.servers[0] }
33
- cnt.should == 1
32
+ @sphinx.send(:with_server, 0) { |server| cnt += 1; server.should eq(@sphinx.servers[0]) }
33
+ cnt.should eq(1)
34
34
  cnt = 0
35
- @sphinx.send(:with_server, 1) { |server| cnt += 1; server.should == @sphinx.servers[1] }
36
- cnt.should == 1
35
+ @sphinx.send(:with_server, 1) { |server| cnt += 1; server.should eq(@sphinx.servers[1]) }
36
+ cnt.should eq(1)
37
37
  cnt = 0
38
- @sphinx.send(:with_server, 2) { |server| cnt += 1; server.should == @sphinx.servers[0] }
39
- cnt.should == 1
38
+ @sphinx.send(:with_server, 2) { |server| cnt += 1; server.should eq(@sphinx.servers[0]) }
39
+ cnt.should eq(1)
40
40
  end
41
41
 
42
42
  it 'should select given server' do
43
43
  @sphinx.SetServers(@servers)
44
44
  cnt = 0
45
45
  @sphinx.send(:with_server, @sphinx.servers[0]) { |server| cnt += 1; server.should == @sphinx.servers[0] }
46
- cnt.should == 1
46
+ cnt.should eq(1)
47
47
  cnt = 0
48
48
  @sphinx.send(:with_server, @sphinx.servers[1]) { |server| cnt += 1; server.should == @sphinx.servers[1] }
49
- cnt.should == 1
49
+ cnt.should eq(1)
50
50
  end
51
51
  end
52
52
 
@@ -58,36 +58,36 @@ describe Sphinx::Client, 'disconnected' do
58
58
  it 'should raise an exception on error' do
59
59
  cnt = 0
60
60
  expect {
61
- @sphinx.send(:with_server) { |server| cnt += 1; server.should == @sphinx.servers[0]; raise Sphinx::SphinxConnectError }
61
+ @sphinx.send(:with_server) { |server| cnt += 1; server.should eq(@sphinx.servers[0]); raise Sphinx::SphinxConnectError }
62
62
  }.to raise_error(Sphinx::SphinxConnectError)
63
- cnt.should == 3
63
+ cnt.should eq(3)
64
64
  end
65
65
 
66
66
  it 'should round-robin servers and raise an exception on error' do
67
67
  @sphinx.SetServers(@servers)
68
68
  cnt = 0
69
69
  expect {
70
- @sphinx.send(:with_server) { |server| cnt += 1; server.should == @sphinx.servers[(cnt - 1) % 2]; raise Sphinx::SphinxConnectError }
70
+ @sphinx.send(:with_server) { |server| cnt += 1; server.should eq(@sphinx.servers[(cnt - 1) % 2]); raise Sphinx::SphinxConnectError }
71
71
  }.to raise_error(Sphinx::SphinxConnectError)
72
- cnt.should == 3
72
+ cnt.should eq(3)
73
73
  end
74
74
 
75
75
  it 'should round-robin servers with respect to passed index and raise an exception on error' do
76
76
  @sphinx.SetServers(@servers)
77
77
  cnt = 0
78
78
  expect {
79
- @sphinx.send(:with_server, 1) { |server| cnt += 1; server.should == @sphinx.servers[cnt % 2]; raise Sphinx::SphinxConnectError }
79
+ @sphinx.send(:with_server, 1) { |server| cnt += 1; server.should eq(@sphinx.servers[cnt % 2]); raise Sphinx::SphinxConnectError }
80
80
  }.to raise_error(Sphinx::SphinxConnectError)
81
- cnt.should == 3
81
+ cnt.should eq(3)
82
82
  end
83
83
 
84
84
  it 'should round-robin with respect to attempts number passed' do
85
85
  @sphinx.SetServers(@servers)
86
86
  cnt = 0
87
87
  expect {
88
- @sphinx.send(:with_server, 0, 5) { |server| cnt += 1; server.should == @sphinx.servers[(cnt - 1) % 2]; raise Sphinx::SphinxConnectError }
88
+ @sphinx.send(:with_server, 0, 5) { |server| cnt += 1; server.should eq(@sphinx.servers[(cnt - 1) % 2]); raise Sphinx::SphinxConnectError }
89
89
  }.to raise_error(Sphinx::SphinxConnectError)
90
- cnt.should == 5
90
+ cnt.should eq(5)
91
91
  end
92
92
  end
93
93
  end
@@ -110,7 +110,7 @@ describe Sphinx::Client, 'disconnected' do
110
110
  @socket.should_receive(:read).with(4).and_return([1].pack('N'))
111
111
  cnt = 0
112
112
  @sphinx.send(:with_socket, @server) { |socket| cnt += 1; socket.should == @socket }
113
- cnt.should == 1
113
+ cnt.should eq(1)
114
114
  end
115
115
 
116
116
  it 'should raise exception when searchd protocol is not 1+' do
@@ -120,7 +120,7 @@ describe Sphinx::Client, 'disconnected' do
120
120
  expect {
121
121
  @sphinx.send(:with_socket, @server) { cnt += 1; }
122
122
  }.to raise_error(Sphinx::SphinxConnectError, 'expected searchd protocol version 1+, got version \'0\'')
123
- cnt.should == 0
123
+ cnt.should eq(0)
124
124
  end
125
125
 
126
126
  it 'should handle request timeouts' do
@@ -130,10 +130,10 @@ describe Sphinx::Client, 'disconnected' do
130
130
  cnt = 0
131
131
  expect {
132
132
  @sphinx.send(:with_socket, @server) { cnt += 1; sleep 2 }
133
- }.to raise_error(Sphinx::SphinxResponseError, 'failed to read searchd response (msg=time\'s up!)')
134
- cnt.should == 1
133
+ }.to raise_error(Sphinx::SphinxResponseError, 'failed to read searchd response (msg=execution expired)')
134
+ cnt.should eq(1)
135
135
 
136
- @sphinx.GetLastError.should == 'failed to read searchd response (msg=time\'s up!)'
136
+ @sphinx.GetLastError.should eq('failed to read searchd response (msg=execution expired)')
137
137
  @sphinx.IsConnectError.should be_false
138
138
  end
139
139
 
@@ -144,9 +144,9 @@ describe Sphinx::Client, 'disconnected' do
144
144
  expect {
145
145
  @sphinx.send(:with_socket, @server) { cnt += 1; raise Sphinx::SphinxInternalError, 'hello' }
146
146
  }.to raise_error(Sphinx::SphinxInternalError, 'hello')
147
- cnt.should == 1
147
+ cnt.should eq(1)
148
148
 
149
- @sphinx.GetLastError.should == 'hello'
149
+ @sphinx.GetLastError.should eq('hello')
150
150
  @sphinx.IsConnectError.should be_false
151
151
  end
152
152
  end
@@ -167,9 +167,9 @@ describe Sphinx::Client, 'disconnected' do
167
167
  expect {
168
168
  @sphinx.send(:with_socket, @server) { cnt += 1; raise Sphinx::SphinxInternalError, 'hello' }
169
169
  }.to raise_error(Sphinx::SphinxInternalError, 'hello')
170
- cnt.should == 3
170
+ cnt.should eq(3)
171
171
 
172
- @sphinx.GetLastError.should == 'hello'
172
+ @sphinx.GetLastError.should eq('hello')
173
173
  @sphinx.IsConnectError.should be_false
174
174
  end
175
175
  end
@@ -206,7 +206,7 @@ describe Sphinx::Client, 'disconnected' do
206
206
  @socket.should_receive(:read).with(8).and_return([Sphinx::SEARCHD_WARNING, 1, 14].pack('n2N'))
207
207
  @socket.should_receive(:read).with(14).and_return([5].pack('N') + 'helloworld')
208
208
  @sphinx.send(:parse_response, @socket, 1).should == 'world'
209
- @sphinx.GetLastWarning.should == 'hello'
209
+ @sphinx.GetLastWarning.should eq('hello')
210
210
  end
211
211
 
212
212
  it 'should raise exception when SEARCHD_ERROR received' do
@@ -313,24 +313,26 @@ describe Sphinx::Client, 'disconnected' do
313
313
 
314
314
  describe 'with rank' do
315
315
  [ :proximity_bm25, :bm25, :none, :wordcount, :proximity, :matchany, :fieldmask, :sph04 ].each do |rank|
316
+ expr = rank == :expr ? '' : 'sum(lcs*user_weight)*1000+bm25'
317
+
316
318
  it "should generate valid request for SPH_RANK_#{rank.to_s.upcase}" do
317
319
  expected = sphinx_fixture("ranking_#{rank}")
318
320
  @sock.should_receive(:write).with(expected)
319
- @sphinx.SetRankingMode(Sphinx::Client.const_get("SPH_RANK_#{rank.to_s.upcase}"))
321
+ @sphinx.SetRankingMode(Sphinx::Client.const_get("SPH_RANK_#{rank.to_s.upcase}"), expr)
320
322
  sphinx_safe_call { @sphinx.Query('query') }
321
323
  end
322
324
 
323
325
  it "should generate valid request for \"#{rank}\"" do
324
326
  expected = sphinx_fixture("ranking_#{rank}")
325
327
  @sock.should_receive(:write).with(expected)
326
- @sphinx.SetRankingMode(rank.to_s)
328
+ @sphinx.SetRankingMode(rank.to_s, expr)
327
329
  sphinx_safe_call { @sphinx.Query('query') }
328
330
  end
329
331
 
330
332
  it "should generate valid request for :#{rank}" do
331
333
  expected = sphinx_fixture("ranking_#{rank}")
332
334
  @sock.should_receive(:write).with(expected)
333
- @sphinx.SetRankingMode(rank)
335
+ @sphinx.SetRankingMode(rank, expr)
334
336
  sphinx_safe_call { @sphinx.Query('query') }
335
337
  end
336
338
  end
@@ -535,7 +537,7 @@ describe Sphinx::Client, 'disconnected' do
535
537
  end
536
538
 
537
539
  it 'should generate valid request for SetOverride' do
538
- expected = sphinx_fixture('set_override')
540
+ expected = sphinx_fixture('override')
539
541
  @sock.should_receive(:write).with(expected)
540
542
  @sphinx.SetOverride('attr1', Sphinx::SPH_ATTR_INTEGER, { 10 => 20 })
541
543
  @sphinx.SetOverride('attr2', Sphinx::SPH_ATTR_FLOAT, { 11 => 30.3 })
@@ -549,6 +551,41 @@ describe Sphinx::Client, 'disconnected' do
549
551
  @sphinx.SetSelect('attr1, attr2')
550
552
  sphinx_safe_call { @sphinx.Query('query') }
551
553
  end
554
+
555
+ it 'should generate valid request for SetOuterSelect' do
556
+ expected = sphinx_fixture('outer_select')
557
+ @sock.should_receive(:write).with(expected)
558
+ @sphinx.SetOuterSelect('attr', 10, 100)
559
+ sphinx_safe_call { @sphinx.Query('query') }
560
+ end
561
+
562
+ it 'should generate valid request for SetQueryFlag' do
563
+ expected = sphinx_fixture('query_flag')
564
+ @sock.should_receive(:write).with(expected)
565
+ @sphinx.SetQueryFlag('reverse_scan', 1)
566
+ @sphinx.SetQueryFlag('sort_method', 'kbuffer')
567
+ @sphinx.SetQueryFlag('max_predicted_time', 15)
568
+ @sphinx.SetQueryFlag('boolean_simplify', true)
569
+ @sphinx.SetQueryFlag('idf', 'plain')
570
+ sphinx_safe_call { @sphinx.Query('query') }
571
+ end
572
+
573
+ it 'should generate valid request for SetQueryFlag after flag reset' do
574
+ expected = sphinx_fixture('query_flag_after_reset')
575
+ @sock.should_receive(:write).with(expected)
576
+ @sphinx.SetQueryFlag('reverse_scan', 1)
577
+ @sphinx.SetQueryFlag('sort_method', 'kbuffer')
578
+ @sphinx.SetQueryFlag('max_predicted_time', 15)
579
+ @sphinx.SetQueryFlag('boolean_simplify', true)
580
+ @sphinx.SetQueryFlag('idf', 'plain')
581
+
582
+ @sphinx.SetQueryFlag('reverse_scan', 0)
583
+ @sphinx.SetQueryFlag('sort_method', 'pq')
584
+ @sphinx.SetQueryFlag('max_predicted_time', 0)
585
+ @sphinx.SetQueryFlag('boolean_simplify', false)
586
+ @sphinx.SetQueryFlag('idf', 'normalized')
587
+ sphinx_safe_call { @sphinx.Query('query') }
588
+ end
552
589
  end
553
590
 
554
591
  context 'in RunQueries method' do