require 'spec_helper' describe ThinkingSphinx::Configuration do let(:config) { ThinkingSphinx::Configuration.instance } after :each do ThinkingSphinx::Configuration.reset end describe '.instance' do it "returns an instance of ThinkingSphinx::Configuration" do ThinkingSphinx::Configuration.instance. should be_a(ThinkingSphinx::Configuration) end it "memoizes the instance" do config = double('configuration') ThinkingSphinx::Configuration.should_receive(:new).once.and_return(config) ThinkingSphinx::Configuration.instance ThinkingSphinx::Configuration.instance end end describe '.reset' do after :each do config.framework = ThinkingSphinx::Frameworks.current end it 'does not cache settings after reset' do File.stub :exists? => true File.stub :read => { 'test' => {'foo' => 'bugs'}, 'production' => {'foo' => 'bar'} }.to_yaml ThinkingSphinx::Configuration.reset # Grab a new copy of the instance. config = ThinkingSphinx::Configuration.instance config.settings['foo'].should == 'bugs' config.framework = double :environment => 'production', :root => Pathname.new(__FILE__).join('..', '..', 'internal') config.settings['foo'].should == 'bar' end end describe '#configuration_file' do it "uses the Rails environment in the configuration file name" do config.configuration_file. should == File.join(Rails.root, 'config', 'test.sphinx.conf') end it "respects provided settings" do write_configuration 'configuration_file' => '/path/to/foo.conf' config.configuration_file.should == '/path/to/foo.conf' end end describe '#controller' do it "returns an instance of Riddle::Controller" do config.controller.should be_a(Riddle::Controller) end it "memoizes the instance" do Riddle::Controller.should_receive(:new).once. and_return(double('controller')) config.controller config.controller end it "sets the bin path from the thinking_sphinx.yml file" do write_configuration('bin_path' => '/foo/bar/bin/') config.controller.bin_path.should == '/foo/bar/bin/' end it "appends a backslash to the bin_path if appropriate" do write_configuration('bin_path' => '/foo/bar/bin') config.controller.bin_path.should == '/foo/bar/bin/' end end describe '#index_paths' do it "uses app/indices in the Rails app by default" do config.index_paths.should include(File.join(Rails.root, 'app', 'indices')) end it "uses app/indices in the Rails engines" do engine = double :engine, { :paths => { 'app/indices' => double(:path, { :existent => '/engine/app/indices' } ) } } engine_class = double :instance => engine Rails::Engine.should_receive(:subclasses).and_return([ engine_class ]) config.index_paths.should include('/engine/app/indices') end end describe '#indices_location' do it "stores index files in db/sphinx/ENVIRONMENT" do config.indices_location. should == File.join(Rails.root, 'db', 'sphinx', 'test') end it "respects provided settings" do write_configuration 'indices_location' => '/my/index/files' config.indices_location.should == '/my/index/files' end end describe '#initialize' do before :each do FileUtils.rm_rf Rails.root.join('log') end it "sets the daemon pid file within log for the Rails app" do config.searchd.pid_file. should == File.join(Rails.root, 'log', 'test.sphinx.pid') end it "sets the daemon log within log for the Rails app" do config.searchd.log. should == File.join(Rails.root, 'log', 'test.searchd.log') end it "sets the query log within log for the Rails app" do config.searchd.query_log. should == File.join(Rails.root, 'log', 'test.searchd.query.log') end it "sets indexer settings if within thinking_sphinx.yml" do write_configuration 'mem_limit' => '128M' config.indexer.mem_limit.should == '128M' end it "sets searchd settings if within thinking_sphinx.yml" do write_configuration 'workers' => 'none' config.searchd.workers.should == 'none' end it 'adds settings to indexer without common section' do write_configuration 'lemmatizer_base' => 'foo' expect(config.indexer.lemmatizer_base).to eq('foo') end it 'adds settings to common section if requested' do write_configuration 'lemmatizer_base' => 'foo', 'common_sphinx_configuration' => true expect(config.common.lemmatizer_base).to eq('foo') end end describe '#next_offset' do let(:reference) { double('reference') } it "starts at 0" do config.next_offset(reference).should == 0 end it "increments for each new reference" do config.next_offset(double('reference')).should == 0 config.next_offset(double('reference')).should == 1 config.next_offset(double('reference')).should == 2 end it "doesn't increment for recorded references" do config.next_offset(reference).should == 0 config.next_offset(reference).should == 0 end end describe '#preload_indices' do let(:distributor) { double :reconcile => true } before :each do stub_const 'ThinkingSphinx::Configuration::DistributedIndices', double(:new => distributor) end it "searches each index path for ruby files" do config.index_paths.replace ['/path/to/indices', '/path/to/other/indices'] Dir.should_receive(:[]).with('/path/to/indices/**/*.rb').once. and_return([]) Dir.should_receive(:[]).with('/path/to/other/indices/**/*.rb').once. and_return([]) config.preload_indices end it "loads each file returned" do config.index_paths.replace ['/path/to/indices'] Dir.stub! :[] => [ '/path/to/indices/foo_index.rb', '/path/to/indices/bar_index.rb' ] ActiveSupport::Dependencies.should_receive(:require_or_load). with('/path/to/indices/foo_index.rb').once ActiveSupport::Dependencies.should_receive(:require_or_load). with('/path/to/indices/bar_index.rb').once config.preload_indices end it "does not double-load indices" do config.index_paths.replace ['/path/to/indices'] Dir.stub! :[] => [ '/path/to/indices/foo_index.rb', '/path/to/indices/bar_index.rb' ] ActiveSupport::Dependencies.should_receive(:require_or_load). with('/path/to/indices/foo_index.rb').once ActiveSupport::Dependencies.should_receive(:require_or_load). with('/path/to/indices/bar_index.rb').once config.preload_indices config.preload_indices end it 'adds distributed indices' do distributor.should_receive(:reconcile) config.preload_indices end it 'does not add distributed indices if disabled' do write_configuration('distributed_indices' => false) distributor.should_not_receive(:reconcile) config.preload_indices end end describe '#render' do before :each do config.searchd.stub! :render => 'searchd { }' end it "searches each index path for ruby files" do config.index_paths.replace ['/path/to/indices', '/path/to/other/indices'] Dir.should_receive(:[]).with('/path/to/indices/**/*.rb').once. and_return([]) Dir.should_receive(:[]).with('/path/to/other/indices/**/*.rb').once. and_return([]) config.render end it "loads each file returned" do config.index_paths.replace ['/path/to/indices'] Dir.stub! :[] => [ '/path/to/indices/foo_index.rb', '/path/to/indices/bar_index.rb' ] ActiveSupport::Dependencies.should_receive(:require_or_load). with('/path/to/indices/foo_index.rb').once ActiveSupport::Dependencies.should_receive(:require_or_load). with('/path/to/indices/bar_index.rb').once config.render end it "does not double-load indices" do config.index_paths.replace ['/path/to/indices'] Dir.stub! :[] => [ '/path/to/indices/foo_index.rb', '/path/to/indices/bar_index.rb' ] ActiveSupport::Dependencies.should_receive(:require_or_load). with('/path/to/indices/foo_index.rb').once ActiveSupport::Dependencies.should_receive(:require_or_load). with('/path/to/indices/bar_index.rb').once config.preload_indices config.preload_indices end end describe '#render_to_file' do let(:file) { double('file') } let(:output) { config.render } before :each do config.searchd.stub! :render => 'searchd { }' end it "writes the rendered configuration to the file" do config.configuration_file = '/path/to/file.config' config.should_receive(:open).with('/path/to/file.config', 'w'). and_yield(file) file.should_receive(:write).with(output) config.render_to_file end it "creates a directory at the binlog_path" do FileUtils.stub :mkdir_p => true config.stub :searchd => double(:binlog_path => '/path/to/binlog') FileUtils.should_receive(:mkdir_p).with('/path/to/binlog') config.render_to_file end it "skips creating a directory when the binlog_path is blank" do FileUtils.stub :mkdir_p => true config.stub :searchd => double(:binlog_path => '') FileUtils.should_not_receive(:mkdir_p) config.render_to_file end end describe '#searchd' do describe '#address' do it "defaults to 127.0.0.1" do config.searchd.address.should == '127.0.0.1' end it "respects the address setting" do write_configuration('address' => '10.11.12.13') config.searchd.address.should == '10.11.12.13' end end describe '#mysql41' do it "defaults to 9306" do config.searchd.mysql41.should == 9306 end it "respects the port setting" do write_configuration('port' => 9313) config.searchd.mysql41.should == 9313 end it "respects the mysql41 setting" do write_configuration('mysql41' => 9307) config.searchd.mysql41.should == 9307 end end end describe '#settings' do context 'YAML file exists' do before :each do File.stub :exists? => true end it "reads from the YAML file" do File.should_receive(:read).and_return('') config.settings end it "uses the settings for the given environment" do File.stub :read => { 'test' => {'foo' => 'bar'}, 'staging' => {'baz' => 'qux'} }.to_yaml Rails.stub :env => 'staging' config.settings['baz'].should == 'qux' end it "remembers the file contents" do File.should_receive(:read).and_return('') config.settings config.settings end it "returns an empty hash when no settings for the environment exist" do File.stub :read => {'test' => {'foo' => 'bar'}}.to_yaml Rails.stub :env => 'staging' config.settings.should == {} end end context 'YAML file does not exist' do before :each do File.stub :exists? => false end it "does not read the file" do File.should_not_receive(:read) config.settings end it "returns an empty hash" do config.settings.should == {} end end end describe '#version' do it "defaults to 2.1.4" do config.version.should == '2.1.4' end it "respects supplied YAML versions" do write_configuration 'version' => '2.0.4' config.version.should == '2.0.4' end end end