# -*- coding: utf-8 -*- require 'spec_helper' require 'amqp' require 'eventmachine' require 'tengine/mq' require 'tengine/event' describe "Tengine::Core::Bootstrap" do describe "bootメソッドでは" do context "config[:action] => load の場合" do it "load_dslがよばれること" do options = { :action => "load" } bootstrap = Tengine::Core::Bootstrap.new(options) bootstrap.should_receive(:load_dsl) bootstrap.boot end end context "config[:action] => start かつ skipオプションが設定されている場合" do it "load_dslはよばれず、start_kernelのみよばれること" do options = { :action => "start", :tengined => { :skip_load => true, :skip_enablement => true, :wait_activation => false } } bootstrap = Tengine::Core::Bootstrap.new(options) bootstrap.should_receive(:start_kernel) # skip_loadオプションを指定してもtengine_core-0.5系の再設計により無視するように変更しました。 # bootstrap.should_not_receive(:load_dsl) bootstrap.should_receive(:load_dsl) bootstrap.boot end end context "config[:action] => enable の場合" do it "enable_driversがよばれること" do options = { :action => "enable" } bootstrap = Tengine::Core::Bootstrap.new(options) bootstrap.should_receive(:enable_drivers) bootstrap.boot end end context "config[:action] => startで、skipオプションの指定がない場合" do it "load_dslとstart_kernelがよばれること" do options = { :action => "start" } bootstrap = Tengine::Core::Bootstrap.new(options) bootstrap.should_receive(:load_dsl) bootstrap.should_receive(:start_kernel) bootstrap.boot end end context "config[:action] => test の場合" do it "load_dsl, start_kernel, start_connection_test, stop_kernelがよばれること" do bootstrap = Tengine::Core::Bootstrap.new(:action => "test") bootstrap.should_receive(:load_dsl) bootstrap.should_receive(:start_kernel) # #stop_kernel は、#start_kernel に渡されるブロックから呼び出されます # bootstrap.should_receive(:stop_kernel) Tengine::Core.stdout_logger.should_receive(:info).with("Connection test success.") bootstrap.boot end it "start_kernelに渡されたブロックを実行する" do bootstrap = Tengine::Core::Bootstrap.new(:action => "test") bootstrap.should_receive(:load_dsl) mock_mq = mock(:mq) bootstrap.should_receive(:start_kernel).and_yield(mock_mq) EM.should_receive(:defer).with(an_instance_of(Proc), an_instance_of(Proc)) Tengine::Core.stdout_logger.should_receive(:info).with("Connection test success.") bootstrap.boot end it "start_kernelに失敗するとstdout_loggerに出力する" do bootstrap = Tengine::Core::Bootstrap.new(:action => "test") bootstrap.should_receive(:load_dsl) bootstrap.should_receive(:start_kernel).and_raise(IOError.new("Something wrong.")) Tengine::Core.stderr_logger.should_receive(:error).with("Connection test failure: [IOError] Something wrong.") bootstrap.boot end end context "config[:action]に想定外の値が設定された場合" do it "ArgumentErrorをraiseする" do options = { :action => 1 } bootstrap = Tengine::Core::Bootstrap.new(options) expect { bootstrap.boot }.to raise_error(ArgumentError, /config[:action] must be test|load|start|enable|stop|force-stop but was/) end end end describe :prepare_trap do it "シグナルハンドラが定義される" do mock_kernel = mock(:kernel) Signal.should_receive(:trap).with(:HUP) # Signal.should_receive(:trap).with(:QUIT) bootstrap = Tengine::Core::Bootstrap.new({}) end end describe :load_dsl do it "Tengine::Core::DslLoaderのevaluateがよばれる" do options = { :action => "load" } bootstrap = Tengine::Core::Bootstrap.new(options) mock_config = mock(:config) mock_config.should_receive(:dsl_version).and_return("test2011102623595999") bootstrap.should_receive(:config).twice.and_return(mock_config) bootstrap.kernel.context.tap do |context| context.should_receive(:__evaluate__) end bootstrap.load_dsl end context "拡張モジュールあり" do before(:all) do @ext_mod1 = Module.new{} @ext_mod1.instance_eval do def dsl_loader; self; end end Tengine.plugins.add(@ext_mod1) end it "拡張モジュールがextendされ、Tengine::Core::DslLoaderとのevaluateがよばれる" do options = { :action => "load" } bootstrap = Tengine::Core::Bootstrap.new(options) mock_config = mock(:config) mock_config.should_receive(:dsl_version).and_return("test2011102623595999") bootstrap.should_receive(:config).twice.and_return(mock_config) bootstrap.kernel.context.tap do |context| context.is_a?(@ext_mod1).should be_true context.should_receive(:__evaluate__) end bootstrap.load_dsl end end context "Tengine::Core::Settingとしてdsl_versionが保存される" do shared_examples_for "dsl_versionに値が設定される" do it do Tengine::Core::Driver.delete_all Tengine::Core::Session.delete_all config = Tengine::Core::Config::Core.new({ :tengined => { :load_path => File.expand_path('../../../examples/uc08_if_both_a_and_b_occurs.rb', File.dirname(__FILE__)), }, }) @bootstrap = Tengine::Core::Bootstrap.new(config) @bootstrap.load_dsl dsl_version_document = Tengine::Core::Setting.first(:conditions => {:name => "dsl_version"}) dsl_version_document.should_not be_nil dsl_version_document.value.should == "20110902213500" # examples/VERSION の中身 end end context "Tengine::Core::Settingにname=dsl_versionのドキュメントが存在しない" do before do Tengine::Core::Setting.delete_all end it_should_behave_like "dsl_versionに値が設定される" end context "Tengine::Core::Settingにname=dsl_versionのドキュメントが存在する場合" do before do Tengine::Core::Setting.delete_all Tengine::Core::Setting.create!(:name => "dsl_version", :value => "fooo") end it_should_behave_like "dsl_versionに値が設定される" end end end describe :start_kernel do it "Tengine::Core::Kernel#start がよばれる" do options = { :action => "start" } bootstrap = Tengine::Core::Bootstrap.new(options) mock_config = mock(:config) bootstrap.should_receive(:config).and_return(mock_config) mock_kernel = mock(:kernel) Tengine::Core::Kernel.should_receive(:new).with(mock_config).and_return(mock_kernel) mock_kernel.should_receive(:start) bootstrap.start_kernel end end describe :enable_drivers do before do # capistranoのデフォルトのデプロイ先を想定しています # see "BACK TO CONFIGURATION" in https://github.com/capistrano/capistrano/wiki/2.x-From-The-Beginning # http://www.slideshare.net/T2J/capistrano-tips-tips Dir.stub!(:pwd).and_return("/u/apps/app1/current") end before do Tengine::Core::Driver.delete_all t = Time.utc(2011,9,5,17,28,30) Time.stub!(:now).and_return(t) @time_str = "20110905172830" @d1 = Tengine::Core::Driver.create!(:name=>"driver1", :version=>@time_str, :enabled=>false, :enabled_on_activation=>true) @d2 = Tengine::Core::Driver.create!(:name=>"driver2", :version=>@time_str, :enabled=>false, :enabled_on_activation=>true) @d3 = Tengine::Core::Driver.create!(:name=>"driver3", :version=>@time_str, :enabled=>false, :enabled_on_activation=>true) end it "enabled=true に更新される" do Dir.stub!(:exist?).with("/u/apps/app1/current/examples").and_return(true) File.stub!(:exist?).with("/u/apps/app1/current/examples/VERSION").and_return(false) options = { :action => "enable", :tengined => { :load_path => "examples" } } bootstrap = Tengine::Core::Bootstrap.new(options) bootstrap.config.dsl_version.should == @time_str bootstrap.boot Tengine::Core::Driver.where(:version => @time_str).each do |d| d.enabled.should be_true end end end describe :start_connection_test do before do class << Tengine attr_accessor :callback_for_test end end after do class << Tengine remove_method :callback_for_test, :callback_for_test= end end it "イベント:fooを発火して、テスト用のDSLが受信後にbarを発火、それを受け取るイベントハンドラから通知が来るまで待つ" do bootstrap = Tengine::Core::Bootstrap.new(:action => "test") mock_mq = mock(:mq) Tengine::Event.should_receive(:fire).with(:foo, :level_key => :info, :keep_connection => true) bootstrap.should_receive(:loop).and_yield bootstrap.start_connection_test(mock_mq) # Tengine::Core.stdout_logger.should_receive(:info).with("handing :foo successfully.") Tengine.callback_for_test.call(:foo) Tengine::Core.stdout_logger.should_receive(:info).with("handing :bar successfully.") Tengine.callback_for_test.call(:bar) Tengine::Core.stderr_logger.should_receive(:error).with("Unexpected event: baz") Tengine.callback_for_test.call(:baz) end end describe :stop_kernel do it "Tengine::Core::Kernel#stop がよばれること" do options = { :action => "stop" } bootstrap = Tengine::Core::Bootstrap.new(options) mock_config = mock(:config) bootstrap.should_receive(:config).and_return(mock_config) mock_kernel = mock(:kernel) Tengine::Core::Kernel.should_receive(:new).with(mock_config).and_return(mock_kernel) mock_kernel.should_receive(:start) bootstrap.start_kernel mock_kernel.should_receive(:stop) bootstrap.stop_kernel end end end