thinking-sphinx 3.3.0 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +29 -20
  4. data/Appraisals +9 -5
  5. data/Gemfile +8 -3
  6. data/HISTORY +24 -0
  7. data/README.textile +5 -4
  8. data/bin/console +14 -0
  9. data/bin/literals +9 -0
  10. data/bin/loadsphinx +38 -0
  11. data/lib/thinking_sphinx.rb +15 -2
  12. data/lib/thinking_sphinx/active_record/callbacks/delta_callbacks.rb +2 -3
  13. data/lib/thinking_sphinx/active_record/callbacks/update_callbacks.rb +11 -1
  14. data/lib/thinking_sphinx/active_record/index.rb +1 -1
  15. data/lib/thinking_sphinx/active_record/join_association.rb +3 -1
  16. data/lib/thinking_sphinx/active_record/log_subscriber.rb +5 -0
  17. data/lib/thinking_sphinx/active_record/sql_source.rb +1 -1
  18. data/lib/thinking_sphinx/attribute_types.rb +70 -0
  19. data/lib/thinking_sphinx/commands/base.rb +41 -0
  20. data/lib/thinking_sphinx/commands/configure.rb +13 -0
  21. data/lib/thinking_sphinx/commands/index.rb +11 -0
  22. data/lib/thinking_sphinx/commands/start_attached.rb +20 -0
  23. data/lib/thinking_sphinx/commands/start_detached.rb +19 -0
  24. data/lib/thinking_sphinx/commands/stop.rb +22 -0
  25. data/lib/thinking_sphinx/configuration.rb +36 -28
  26. data/lib/thinking_sphinx/configuration/minimum_fields.rb +11 -8
  27. data/lib/thinking_sphinx/connection.rb +5 -122
  28. data/lib/thinking_sphinx/connection/client.rb +48 -0
  29. data/lib/thinking_sphinx/connection/jruby.rb +53 -0
  30. data/lib/thinking_sphinx/connection/mri.rb +28 -0
  31. data/lib/thinking_sphinx/core/index.rb +11 -0
  32. data/lib/thinking_sphinx/deletion.rb +6 -2
  33. data/lib/thinking_sphinx/deltas/default_delta.rb +1 -1
  34. data/lib/thinking_sphinx/deltas/delete_job.rb +14 -4
  35. data/lib/thinking_sphinx/distributed/index.rb +10 -0
  36. data/lib/thinking_sphinx/errors.rb +1 -1
  37. data/lib/thinking_sphinx/index_set.rb +14 -2
  38. data/lib/thinking_sphinx/interfaces/daemon.rb +32 -0
  39. data/lib/thinking_sphinx/interfaces/real_time.rb +41 -0
  40. data/lib/thinking_sphinx/interfaces/sql.rb +41 -0
  41. data/lib/thinking_sphinx/middlewares.rb +5 -3
  42. data/lib/thinking_sphinx/middlewares/active_record_translator.rb +13 -6
  43. data/lib/thinking_sphinx/middlewares/attribute_typer.rb +48 -0
  44. data/lib/thinking_sphinx/middlewares/valid_options.rb +23 -0
  45. data/lib/thinking_sphinx/rake_interface.rb +10 -124
  46. data/lib/thinking_sphinx/search.rb +11 -0
  47. data/lib/thinking_sphinx/search/query.rb +7 -1
  48. data/lib/thinking_sphinx/tasks.rb +80 -21
  49. data/lib/thinking_sphinx/with_output.rb +11 -0
  50. data/spec/acceptance/connection_spec.rb +4 -4
  51. data/spec/acceptance/searching_within_a_model_spec.rb +7 -0
  52. data/spec/acceptance/specifying_sql_spec.rb +26 -8
  53. data/spec/acceptance/sql_deltas_spec.rb +12 -0
  54. data/spec/internal/app/indices/album_index.rb +3 -0
  55. data/spec/internal/app/models/album.rb +19 -0
  56. data/spec/internal/db/schema.rb +8 -0
  57. data/spec/spec_helper.rb +4 -0
  58. data/spec/support/json_column.rb +5 -1
  59. data/spec/thinking_sphinx/active_record/callbacks/update_callbacks_spec.rb +5 -1
  60. data/spec/thinking_sphinx/active_record/sql_source_spec.rb +6 -0
  61. data/spec/thinking_sphinx/attribute_types_spec.rb +50 -0
  62. data/spec/thinking_sphinx/commands/configure_spec.rb +29 -0
  63. data/spec/thinking_sphinx/commands/index_spec.rb +26 -0
  64. data/spec/thinking_sphinx/commands/start_detached_spec.rb +55 -0
  65. data/spec/thinking_sphinx/commands/stop_spec.rb +54 -0
  66. data/spec/thinking_sphinx/configuration/minimum_fields_spec.rb +36 -0
  67. data/spec/thinking_sphinx/deletion_spec.rb +2 -5
  68. data/spec/thinking_sphinx/deltas/default_delta_spec.rb +1 -1
  69. data/spec/thinking_sphinx/errors_spec.rb +7 -0
  70. data/spec/thinking_sphinx/index_set_spec.rb +30 -7
  71. data/spec/thinking_sphinx/interfaces/daemon_spec.rb +52 -0
  72. data/spec/thinking_sphinx/interfaces/real_time_spec.rb +109 -0
  73. data/spec/thinking_sphinx/interfaces/sql_spec.rb +98 -0
  74. data/spec/thinking_sphinx/middlewares/attribute_typer_spec.rb +42 -0
  75. data/spec/thinking_sphinx/middlewares/valid_options_spec.rb +49 -0
  76. data/spec/thinking_sphinx/rake_interface_spec.rb +13 -246
  77. data/spec/thinking_sphinx/search/query_spec.rb +7 -0
  78. data/thinking-sphinx.gemspec +5 -4
  79. metadata +72 -16
  80. data/gemfiles/.gitignore +0 -1
  81. data/gemfiles/rails_3_2.gemfile +0 -13
  82. data/gemfiles/rails_4_0.gemfile +0 -13
  83. data/gemfiles/rails_4_1.gemfile +0 -13
  84. data/gemfiles/rails_4_2.gemfile +0 -13
  85. data/gemfiles/rails_5_0.gemfile +0 -12
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ThinkingSphinx::Interfaces::Daemon do
4
+ let(:configuration) { double 'configuration', :controller => controller }
5
+ let(:controller) { double 'controller', :running? => false }
6
+ let(:stream) { double 'stream', :puts => true }
7
+ let(:interface) {
8
+ ThinkingSphinx::Interfaces::Daemon.new(configuration, {}, stream)
9
+ }
10
+
11
+ describe '#start' do
12
+ let(:command) { double 'command', :call => true }
13
+
14
+ before :each do
15
+ stub_const 'ThinkingSphinx::Commands::StartDetached', command
16
+ end
17
+
18
+ it "starts the daemon" do
19
+ expect(command).to receive(:call)
20
+
21
+ interface.start
22
+ end
23
+
24
+ it "raises an error if the daemon is already running" do
25
+ allow(controller).to receive_messages :running? => true
26
+
27
+ expect {
28
+ interface.start
29
+ }.to raise_error(ThinkingSphinx::SphinxAlreadyRunning)
30
+ end
31
+ end
32
+
33
+ describe '#status' do
34
+ it "reports when the daemon is running" do
35
+ allow(controller).to receive_messages :running? => true
36
+
37
+ expect(stream).to receive(:puts).
38
+ with('The Sphinx daemon searchd is currently running.')
39
+
40
+ interface.status
41
+ end
42
+
43
+ it "reports when the daemon is not running" do
44
+ allow(controller).to receive_messages :running? => false
45
+
46
+ expect(stream).to receive(:puts).
47
+ with('The Sphinx daemon searchd is not currently running.')
48
+
49
+ interface.status
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,109 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ThinkingSphinx::Interfaces::SQL do
4
+ let(:interface) { ThinkingSphinx::Interfaces::RealTime.new(
5
+ configuration, {}, stream
6
+ ) }
7
+ let(:configuration) { double 'configuration', :controller => controller,
8
+ :render => true, :indices_location => '/path/to/indices',
9
+ :preload_indices => true }
10
+ let(:controller) { double 'controller', :running? => true }
11
+ let(:stream) { double :puts => nil }
12
+
13
+ describe '#clear' do
14
+ let(:plain_index) { double(:type => 'plain') }
15
+ let(:users_index) { double(:name => 'users', :type => 'rt', :render => true,
16
+ :path => '/path/to/my/index/users') }
17
+ let(:parts_index) { double(:name => 'parts', :type => 'rt', :render => true,
18
+ :path => '/path/to/my/index/parts') }
19
+
20
+ before :each do
21
+ allow(configuration).to receive_messages(
22
+ :indices => [plain_index, users_index, parts_index],
23
+ :searchd => double(:binlog_path => '/path/to/binlog')
24
+ )
25
+
26
+ allow(Dir).to receive(:[]).with('/path/to/my/index/users.*').
27
+ and_return(['users.a', 'users.b'])
28
+ allow(Dir).to receive(:[]).with('/path/to/my/index/parts.*').
29
+ and_return(['parts.a', 'parts.b'])
30
+
31
+ allow(FileUtils).to receive_messages :mkdir_p => true, :rm_r => true,
32
+ :rm => true
33
+ allow(File).to receive_messages :exists? => true
34
+ end
35
+
36
+ it 'finds each file for real-time indices' do
37
+ expect(Dir).to receive(:[]).with('/path/to/my/index/users.*').
38
+ and_return([])
39
+
40
+ interface.clear
41
+ end
42
+
43
+ it "removes the directory for the binlog files" do
44
+ expect(FileUtils).to receive(:rm_r).with('/path/to/binlog')
45
+
46
+ interface.clear
47
+ end
48
+
49
+ it "removes each file for real-time indices" do
50
+ expect(FileUtils).to receive(:rm).with('users.a')
51
+ expect(FileUtils).to receive(:rm).with('users.b')
52
+ expect(FileUtils).to receive(:rm).with('parts.a')
53
+ expect(FileUtils).to receive(:rm).with('parts.b')
54
+
55
+ interface.clear
56
+ end
57
+
58
+ context "with options[:index_filter]" do
59
+ let(:interface) { ThinkingSphinx::Interfaces::RealTime.new(
60
+ configuration, {:index_filter => 'users'}, stream
61
+ ) }
62
+
63
+ it "removes each file for real-time indices that match :index_filter" do
64
+ expect(FileUtils).to receive(:rm).with('users.a')
65
+ expect(FileUtils).to receive(:rm).with('users.b')
66
+ expect(FileUtils).not_to receive(:rm).with('parts.a')
67
+ expect(FileUtils).not_to receive(:rm).with('parts.b')
68
+
69
+ interface.clear
70
+ end
71
+ end
72
+ end
73
+
74
+ describe '#index' do
75
+ let(:plain_index) { double(:type => 'plain') }
76
+ let(:users_index) { double(name: 'users', :type => 'rt') }
77
+ let(:parts_index) { double(name: 'parts', :type => 'rt') }
78
+
79
+ before :each do
80
+ allow(configuration).to receive_messages(
81
+ :indices => [plain_index, users_index, parts_index]
82
+ )
83
+
84
+ allow(FileUtils).to receive_messages :mkdir_p => true
85
+ end
86
+
87
+ it 'populates each real-index' do
88
+ expect(ThinkingSphinx::RealTime::Populator).to receive(:populate).with(users_index)
89
+ expect(ThinkingSphinx::RealTime::Populator).to receive(:populate).with(parts_index)
90
+ expect(ThinkingSphinx::RealTime::Populator).not_to receive(:populate).with(plain_index)
91
+
92
+ interface.index
93
+ end
94
+
95
+ context "with options[:index_filter]" do
96
+ let(:interface) { ThinkingSphinx::Interfaces::RealTime.new(
97
+ configuration, {:index_filter => 'users'}, stream
98
+ ) }
99
+
100
+ it 'populates each real-index that matches :index_filter' do
101
+ expect(ThinkingSphinx::RealTime::Populator).to receive(:populate).with(users_index)
102
+ expect(ThinkingSphinx::RealTime::Populator).not_to receive(:populate).with(parts_index)
103
+ expect(ThinkingSphinx::RealTime::Populator).not_to receive(:populate).with(plain_index)
104
+
105
+ interface.index
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,98 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ThinkingSphinx::Interfaces::SQL do
4
+ let(:interface) { ThinkingSphinx::Interfaces::SQL.new(
5
+ configuration, {:verbose => true}, stream
6
+ ) }
7
+ let(:configuration) { double 'configuration', :preload_indices => true,
8
+ :render => true, :indices => [double(:index, :type => 'plain')],
9
+ :indices_location => '/path/to/indices' }
10
+ let(:stream) { double :puts => nil }
11
+
12
+ describe '#clear' do
13
+ let(:users_index) { double(:name => 'users', :type => 'plain',
14
+ :render => true, :path => '/path/to/my/index/users') }
15
+ let(:parts_index) { double(:name => 'users', :type => 'plain',
16
+ :render => true, :path => '/path/to/my/index/parts') }
17
+ let(:rt_index) { double(:type => 'rt') }
18
+
19
+ before :each do
20
+ allow(configuration).to receive_messages(
21
+ :indices => [users_index, parts_index, rt_index]
22
+ )
23
+
24
+ allow(Dir).to receive(:[]).with('/path/to/my/index/users.*').
25
+ and_return(['users.a', 'users.b'])
26
+ allow(Dir).to receive(:[]).with('/path/to/my/index/parts.*').
27
+ and_return(['parts.a', 'parts.b'])
28
+
29
+ allow(FileUtils).to receive_messages :mkdir_p => true, :rm_r => true,
30
+ :rm => true
31
+ allow(File).to receive_messages :exists? => true
32
+ end
33
+
34
+ it 'finds each file for sql-backed indices' do
35
+ expect(Dir).to receive(:[]).with('/path/to/my/index/users.*').
36
+ and_return([])
37
+
38
+ interface.clear
39
+ end
40
+
41
+ it "removes each file for real-time indices" do
42
+ expect(FileUtils).to receive(:rm).with('users.a')
43
+ expect(FileUtils).to receive(:rm).with('users.b')
44
+ expect(FileUtils).to receive(:rm).with('parts.a')
45
+ expect(FileUtils).to receive(:rm).with('parts.b')
46
+
47
+ interface.clear
48
+ end
49
+ end
50
+
51
+ describe '#index' do
52
+ let(:index_command) { double :call => true }
53
+ let(:configure_command) { double :call => true }
54
+
55
+ before :each do
56
+ stub_const 'ThinkingSphinx::Commands::Index', index_command
57
+ stub_const 'ThinkingSphinx::Commands::Configure', configure_command
58
+
59
+ allow(ThinkingSphinx).to receive_messages :before_index_hooks => []
60
+ allow(FileUtils).to receive_messages :mkdir_p => true
61
+ end
62
+
63
+ it "renders the configuration to a file by default" do
64
+ expect(configure_command).to receive(:call)
65
+
66
+ interface.index
67
+ end
68
+
69
+ it "does not render the configuration if requested" do
70
+ expect(configure_command).not_to receive(:call)
71
+
72
+ interface.index false
73
+ end
74
+
75
+ it "creates the directory for the index files" do
76
+ expect(FileUtils).to receive(:mkdir_p).with('/path/to/indices')
77
+
78
+ interface.index
79
+ end
80
+
81
+ it "calls all registered hooks" do
82
+ called = false
83
+ ThinkingSphinx.before_index_hooks << Proc.new { called = true }
84
+
85
+ interface.index
86
+
87
+ expect(called).to be_truthy
88
+ end
89
+
90
+ it "executes the index command" do
91
+ expect(index_command).to receive(:call).with(
92
+ configuration, {:verbose => true}, stream
93
+ )
94
+
95
+ interface.index
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ThinkingSphinx::Middlewares::AttributeTyper do
4
+ let(:app) { double('app', :call => true) }
5
+ let(:middleware) { ThinkingSphinx::Middlewares::AttributeTyper.new app }
6
+ let(:attributes) { {} }
7
+ let(:context) { double('context', :search => search) }
8
+ let(:search) { double('search', :options => {}) }
9
+
10
+ before :each do
11
+ allow(ThinkingSphinx::AttributeTypes).to receive(:call).
12
+ and_return(attributes)
13
+ allow(ActiveSupport::Deprecation).to receive(:warn)
14
+ end
15
+
16
+ it 'warns when providing a string value for an integer attribute' do
17
+ attributes['user_id'] = [:uint]
18
+ search.options[:with] = {:user_id => '1'}
19
+
20
+ expect(ActiveSupport::Deprecation).to receive(:warn)
21
+
22
+ middleware.call [context]
23
+ end
24
+
25
+ it 'warns when providing a string value for a float attribute' do
26
+ attributes['price'] = [:float]
27
+ search.options[:without] = {:price => '1.0'}
28
+
29
+ expect(ActiveSupport::Deprecation).to receive(:warn)
30
+
31
+ middleware.call [context]
32
+ end
33
+
34
+ it 'proceeds when providing a string value for a string attribute' do
35
+ attributes['status'] = [:string]
36
+ search.options[:with] = {:status => 'completed'}
37
+
38
+ expect(ActiveSupport::Deprecation).not_to receive(:warn)
39
+
40
+ middleware.call [context]
41
+ end
42
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ThinkingSphinx::Middlewares::ValidOptions do
4
+ let(:app) { double 'app', :call => true }
5
+ let(:middleware) { ThinkingSphinx::Middlewares::ValidOptions.new app }
6
+ let(:context) { double 'context', :search => search }
7
+ let(:search) { double 'search', :options => {} }
8
+
9
+ before :each do
10
+ allow(ThinkingSphinx::Logger).to receive(:log)
11
+ end
12
+
13
+ context 'with unknown options' do
14
+ before :each do
15
+ search.options[:foo] = :bar
16
+ end
17
+
18
+ it "adds a warning" do
19
+ expect(ThinkingSphinx::Logger).to receive(:log).
20
+ with(:warn, "Unexpected search options: [:foo]")
21
+
22
+ middleware.call [context]
23
+ end
24
+
25
+ it 'continues on' do
26
+ expect(app).to receive(:call).with([context])
27
+
28
+ middleware.call [context]
29
+ end
30
+ end
31
+
32
+ context "with known options" do
33
+ before :each do
34
+ search.options[:ids_only] = true
35
+ end
36
+
37
+ it "is silent" do
38
+ expect(ThinkingSphinx::Logger).to_not receive(:log)
39
+
40
+ middleware.call [context]
41
+ end
42
+
43
+ it 'continues on' do
44
+ expect(app).to receive(:call).with([context])
45
+
46
+ middleware.call [context]
47
+ end
48
+ end
49
+ end
@@ -1,270 +1,37 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ThinkingSphinx::RakeInterface do
4
- let(:configuration) { double('configuration', :controller => controller) }
5
4
  let(:interface) { ThinkingSphinx::RakeInterface.new }
6
5
 
7
- before :each do
8
- allow(ThinkingSphinx::Configuration).to receive_messages :instance => configuration
9
- allow(interface).to receive_messages(:puts => nil)
10
- end
11
-
12
- describe '#clear_all' do
13
- let(:controller) { double 'controller' }
14
-
15
- before :each do
16
- allow(configuration).to receive_messages(
17
- :indices_location => '/path/to/indices',
18
- :searchd => double(:binlog_path => '/path/to/binlog')
19
- )
20
-
21
- allow(FileUtils).to receive_messages :rm_r => true
22
- allow(File).to receive_messages :exists? => true
23
- end
24
-
25
- it "removes the directory for the index files" do
26
- expect(FileUtils).to receive(:rm_r).with('/path/to/indices')
27
-
28
- interface.clear_all
29
- end
30
-
31
- it "removes the directory for the binlog files" do
32
- expect(FileUtils).to receive(:rm_r).with('/path/to/binlog')
33
-
34
- interface.clear_all
35
- end
36
- end
37
-
38
- describe '#clear_real_time' do
39
- let(:controller) { double 'controller' }
40
- let(:index) {
41
- double(:type => 'rt', :render => true, :path => '/path/to/my/index')
42
- }
43
-
44
- before :each do
45
- allow(configuration).to receive_messages(
46
- :indices => [double(:type => 'plain'), index],
47
- :searchd => double(:binlog_path => '/path/to/binlog'),
48
- :preload_indices => true
49
- )
50
-
51
- allow(Dir).to receive_messages :[] => ['foo.a', 'foo.b']
52
- allow(FileUtils).to receive_messages :rm_r => true, :rm => true
53
- allow(File).to receive_messages :exists? => true
54
- end
55
-
56
- it 'finds each file for real-time indices' do
57
- expect(Dir).to receive(:[]).with('/path/to/my/index.*').and_return([])
58
-
59
- interface.clear_real_time
60
- end
61
-
62
- it "removes each file for real-time indices" do
63
- expect(FileUtils).to receive(:rm).with('foo.a')
64
- expect(FileUtils).to receive(:rm).with('foo.b')
65
-
66
- interface.clear_real_time
67
- end
68
-
69
- it "removes the directory for the binlog files" do
70
- expect(FileUtils).to receive(:rm_r).with('/path/to/binlog')
71
-
72
- interface.clear_real_time
73
- end
74
- end
75
-
76
6
  describe '#configure' do
77
- let(:controller) { double('controller') }
7
+ let(:command) { double 'command', :call => true }
78
8
 
79
9
  before :each do
80
- allow(configuration).to receive_messages(
81
- :configuration_file => '/path/to/foo.conf',
82
- :render_to_file => true
83
- )
84
- end
85
-
86
- it "renders the configuration to a file" do
87
- expect(configuration).to receive(:render_to_file)
88
-
89
- interface.configure
10
+ stub_const 'ThinkingSphinx::Commands::Configure', command
90
11
  end
91
12
 
92
- it "prints a message stating the file is being generated" do
93
- expect(interface).to receive(:puts).
94
- with('Generating configuration to /path/to/foo.conf')
13
+ it 'sends the configure command' do
14
+ expect(command).to receive(:call)
95
15
 
96
16
  interface.configure
97
17
  end
98
18
  end
99
19
 
100
- describe '#index' do
101
- let(:controller) { double('controller', :index => true) }
102
-
103
- before :each do
104
- allow(ThinkingSphinx).to receive_messages :before_index_hooks => []
105
- allow(configuration).to receive_messages(
106
- :configuration_file => '/path/to/foo.conf',
107
- :render_to_file => true,
108
- :indices_location => '/path/to/indices'
109
- )
110
-
111
- allow(FileUtils).to receive_messages :mkdir_p => true
112
- end
113
-
114
- it "renders the configuration to a file by default" do
115
- expect(configuration).to receive(:render_to_file)
116
-
117
- interface.index
118
- end
119
-
120
- it "does not render the configuration if requested" do
121
- expect(configuration).not_to receive(:render_to_file)
122
-
123
- interface.index false
124
- end
125
-
126
- it "creates the directory for the index files" do
127
- expect(FileUtils).to receive(:mkdir_p).with('/path/to/indices')
128
-
129
- interface.index
130
- end
131
-
132
- it "calls all registered hooks" do
133
- called = false
134
- ThinkingSphinx.before_index_hooks << Proc.new { called = true }
135
-
136
- interface.index
137
-
138
- expect(called).to be_truthy
139
- end
140
-
141
- it "indexes all indices verbosely" do
142
- expect(controller).to receive(:index).with(:verbose => true)
143
-
144
- interface.index
145
- end
146
-
147
- it "does not index verbosely if requested" do
148
- expect(controller).to receive(:index).with(:verbose => false)
149
-
150
- interface.index true, false
151
- end
152
- end
153
-
154
- describe '#start' do
155
- let(:controller) { double('controller', :start => result, :pid => 101) }
156
- let(:result) { double 'result', :command => 'start', :status => 1,
157
- :output => '' }
158
-
159
- before :each do
160
- allow(controller).to receive(:running?).and_return(false, true)
161
- allow(configuration).to receive_messages(
162
- :indices_location => 'my/index/files',
163
- :searchd => double(:log => '/path/to/log')
164
- )
165
-
166
- allow(FileUtils).to receive_messages :mkdir_p => true
167
- end
168
-
169
- it "creates the index files directory" do
170
- expect(FileUtils).to receive(:mkdir_p).with('my/index/files')
171
-
172
- interface.start
173
- end
174
-
175
- it "starts the daemon" do
176
- expect(controller).to receive(:start)
177
-
178
- interface.start
179
- end
180
-
181
- it "raises an error if the daemon is already running" do
182
- allow(controller).to receive_messages :running? => true
183
-
184
- expect {
185
- interface.start
186
- }.to raise_error(ThinkingSphinx::SphinxAlreadyRunning)
187
- end
188
-
189
- it "prints a success message if the daemon has started" do
190
- allow(controller).to receive(:running?).and_return(false, true)
191
-
192
- expect(interface).to receive(:puts).
193
- with('Started searchd successfully (pid: 101).')
194
-
195
- interface.start
196
- end
197
-
198
- it "prints a failure message if the daemon does not start" do
199
- allow(controller).to receive(:running?).and_return(false, false)
200
- allow(interface).to receive(:exit)
201
-
202
- expect(interface).to receive(:puts) do |string|
203
- expect(string).to match('The Sphinx start command failed')
204
- end
205
-
206
- interface.start
20
+ describe '#daemon' do
21
+ it 'returns a daemon interface' do
22
+ expect(interface.daemon.class).to eq(ThinkingSphinx::Interfaces::Daemon)
207
23
  end
208
24
  end
209
25
 
210
- describe '#stop' do
211
- let(:controller) { double('controller', :stop => true, :pid => 101) }
212
- let(:result) { double 'result', :command => 'start', :status => 1,
213
- :output => '' }
214
-
215
- before :each do
216
- allow(controller).to receive(:running?).and_return(true, true, false)
217
- end
218
-
219
- it "prints a message if the daemon is not already running" do
220
- allow(controller).to receive_messages :running? => false
221
-
222
- expect(interface).to receive(:puts).with('searchd is not currently running.')
223
-
224
- interface.stop
225
- end
226
-
227
- it "stops the daemon" do
228
- expect(controller).to receive(:stop)
229
-
230
- interface.stop
231
- end
232
-
233
- it "prints a message informing the daemon has stopped" do
234
- expect(interface).to receive(:puts).with('Stopped searchd daemon (pid: 101).')
235
-
236
- interface.stop
237
- end
238
-
239
- it "should retry stopping the daemon until it stops" do
240
- allow(controller).to receive(:running?).
241
- and_return(true, true, true, false)
242
-
243
- expect(controller).to receive(:stop).twice
244
-
245
- interface.stop
26
+ describe '#rt' do
27
+ it 'returns a real-time interface' do
28
+ expect(interface.rt.class).to eq(ThinkingSphinx::Interfaces::RealTime)
246
29
  end
247
30
  end
248
31
 
249
- describe '#status' do
250
- let(:controller) { double('controller') }
251
-
252
- it "reports when the daemon is running" do
253
- allow(controller).to receive_messages :running? => true
254
-
255
- expect(interface).to receive(:puts).
256
- with('The Sphinx daemon searchd is currently running.')
257
-
258
- interface.status
259
- end
260
-
261
- it "reports when the daemon is not running" do
262
- allow(controller).to receive_messages :running? => false
263
-
264
- expect(interface).to receive(:puts).
265
- with('The Sphinx daemon searchd is not currently running.')
266
-
267
- interface.status
32
+ describe '#sql' do
33
+ it 'returns an SQL interface' do
34
+ expect(interface.sql.class).to eq(ThinkingSphinx::Interfaces::SQL)
268
35
  end
269
36
  end
270
37
  end