aesop 1.1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +19 -0
- data/.rspec +3 -0
- data/.travis.yml +21 -0
- data/Gemfile +13 -0
- data/LICENSE +0 -0
- data/README.md +8 -0
- data/Rakefile +20 -0
- data/aesop.gemspec +29 -0
- data/config/init.rb +24 -0
- data/lib/aesop.rb +27 -0
- data/lib/aesop/aesop.rb +135 -0
- data/lib/aesop/bootloader.rb +76 -0
- data/lib/aesop/configuration.rb +13 -0
- data/lib/aesop/dispatcher.rb +49 -0
- data/lib/aesop/dispatchers/log_dispatcher.rb +7 -0
- data/lib/aesop/exceptions.rb +7 -0
- data/lib/aesop/logger.rb +41 -0
- data/lib/aesop/merb/merb_boot_loader.rb +8 -0
- data/lib/aesop/rails/middleware.rb +18 -0
- data/lib/aesop/rails/railtie.rb +18 -0
- data/lib/aesop/recipes.rb +20 -0
- data/lib/aesop/version.rb +10 -0
- data/recipes/aesop.rb +6 -0
- data/spec/aesop/aesop_spec.rb +276 -0
- data/spec/aesop/bootloader_spec.rb +138 -0
- data/spec/aesop/dispatcher_spec.rb +76 -0
- data/spec/aesop/dispatchers/log_dispatcher_spec.rb +19 -0
- data/spec/aesop/hooks_spec.rb +79 -0
- data/spec/aesop/logger_spec.rb +72 -0
- data/spec/aesop/merb/merb_boot_loader_spec.rb +25 -0
- data/spec/aesop/rails/middleware_spec.rb +13 -0
- data/spec/aesop/rails/railtie_spec.rb +62 -0
- data/spec/aesop/recipes_spec.rb +47 -0
- data/spec/spec_helper.rb +47 -0
- metadata +188 -0
@@ -0,0 +1,76 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe Aesop::Dispatcher do
|
4
|
+
subject{ Aesop::Dispatcher.instance }
|
5
|
+
|
6
|
+
def clear_instance
|
7
|
+
#
|
8
|
+
# Hack to be able to test if methods are called during initialization
|
9
|
+
# We cannot just instantiate an instance, because #new is marked
|
10
|
+
# private by the Singleton module
|
11
|
+
#
|
12
|
+
Singleton.__init__(Aesop::Dispatcher)
|
13
|
+
end
|
14
|
+
|
15
|
+
before :all do
|
16
|
+
config.dispatchers = [:log_dispatcher]
|
17
|
+
end
|
18
|
+
|
19
|
+
before :each do
|
20
|
+
clear_instance
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'collects and registers dispatchers when initialized' do
|
24
|
+
Aesop::Dispatcher.any_instance.should_receive(:collect_dispatchers)
|
25
|
+
Aesop::Dispatcher.instance
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'knows how to get the configuration' do
|
29
|
+
subject.methods.map{|m| m.to_s}.should include "configuration"
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'uses the configuration to see which dispatchers should be created' do
|
33
|
+
subject.configuration.should_receive(:dispatchers).and_return([])
|
34
|
+
subject.collect_dispatchers
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'instantiates dispatchers from the configuration' do
|
38
|
+
subject.should_receive(:instantiate_dispatcher).with(:log_dispatcher)
|
39
|
+
subject.collect_dispatchers
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'registers dispatchers' do
|
43
|
+
subject.should_receive(:register_dispatcher)
|
44
|
+
subject.collect_dispatchers
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'adds dispatchers to its list when requested' do
|
48
|
+
dispatcher_double = double("TestDispatcher")
|
49
|
+
|
50
|
+
subject.register_dispatcher( dispatcher_double )
|
51
|
+
subject.dispatchers.should_not be_empty
|
52
|
+
subject.dispatchers.should include dispatcher_double
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'dispatches the exception to each registered dispatcher' do
|
56
|
+
exception = double()
|
57
|
+
5.times do |i|
|
58
|
+
dispatcher_double = double("Dispatcher #{i}")
|
59
|
+
dispatcher_double.should_receive(:dispatch_exception).with(exception)
|
60
|
+
|
61
|
+
subject.register_dispatcher( dispatcher_double )
|
62
|
+
end
|
63
|
+
subject.dispatch_exception( exception )
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'logs exceptions that might occur in a dispatcher' do
|
67
|
+
exception = Aesop::DispatchException.new
|
68
|
+
Aesop::Logger.should_receive(:error).with("Exception in Aesop::Dispatchers::LogDispatcher: Exception: Aesop::DispatchException. Trying to dispatch: RuntimeError: RuntimeError")
|
69
|
+
|
70
|
+
log_dispatcher = Aesop::Dispatchers::LogDispatcher.new
|
71
|
+
log_dispatcher.stub(:dispatch_exception){ raise RuntimeError.new }
|
72
|
+
|
73
|
+
subject.register_dispatcher(log_dispatcher)
|
74
|
+
subject.dispatch_exception( exception )
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), '..', '..', 'spec_helper')
|
2
|
+
require File.join( File.dirname(__FILE__), '..', '..', '..', 'lib', 'aesop', 'dispatchers', 'log_dispatcher')
|
3
|
+
|
4
|
+
describe Aesop::Dispatchers::LogDispatcher do
|
5
|
+
let(:file_stub){ double() }
|
6
|
+
|
7
|
+
it 'can dispatch exceptions' do
|
8
|
+
subject.methods.map{|m| m.to_s}.should include "dispatch_exception"
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'knows how to find the configuration' do
|
12
|
+
subject.methods.map{|m| m.to_s}.should include "configuration"
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'uses the aesop-logger to dispatch the messages at info level' do
|
16
|
+
Aesop::Logger.should_receive(:info).with( Exception.to_s )
|
17
|
+
subject.dispatch_exception( Exception.new )
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe 'Creating Hooks' do
|
4
|
+
let(:fake_class){ Class.new }
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
Aesop.send(:remove_const, :MerbBootLoader) if Aesop.const_defined?(:MerbBootLoader)
|
8
|
+
Aesop.send(:remove_const, :Railtie) if Aesop.const_defined?(:Railtie)
|
9
|
+
end
|
10
|
+
|
11
|
+
def load_file
|
12
|
+
load File.join( File.dirname(__FILE__), '..', '..', 'lib', 'aesop.rb')
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'Merb' do
|
16
|
+
def stub_merb_constants
|
17
|
+
stub_const('Merb', fake_class)
|
18
|
+
stub_const('Merb::BootLoader', fake_class)
|
19
|
+
stub_const('Merb::BootLoader::ChooseAdapter', fake_class)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'does not define a merb bootloader when merb does not exist' do
|
23
|
+
Aesop.should_not have_constant(:MerbBootLoader)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'defines a merb bootloader when Merb and a Merb::Bootloader exist' do
|
27
|
+
fake_class.stub(:after)
|
28
|
+
stub_merb_constants
|
29
|
+
load_file
|
30
|
+
Aesop.should have_constant(:MerbBootLoader)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'Rails' do
|
35
|
+
def stub_rails_constants
|
36
|
+
stub_const('Rails', fake_class)
|
37
|
+
stub_const('Rails::Railtie', fake_class)
|
38
|
+
end
|
39
|
+
|
40
|
+
before :each do
|
41
|
+
fake_class.stub(:initializer)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'does not define a railtie when rails does not exist' do
|
45
|
+
Aesop.should_not have_constant(:Railtie)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'defines a railtie when Rails exists and its version is > 3' do
|
49
|
+
stub_rails_constants
|
50
|
+
fake_class.stub(:version).and_return('3.1')
|
51
|
+
load_file
|
52
|
+
Aesop.should have_constant(:Railtie)
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'Rails < 3' do
|
56
|
+
before :each do
|
57
|
+
stub_rails_constants
|
58
|
+
fake_class.stub(:version).and_return('2.9')
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'does not define a railtie when Rails exists and its version < 3' do
|
62
|
+
load_file
|
63
|
+
Aesop.should_not have_constant(:Railtie)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'inits Aesop when Rails exists' do
|
67
|
+
Aesop::Aesop.instance.should_receive(:init)
|
68
|
+
load_file
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'Other' do
|
74
|
+
it 'inits' do
|
75
|
+
Aesop::Aesop.instance.should_receive(:init)
|
76
|
+
load_file
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), "..", "spec_helper" )
|
2
|
+
|
3
|
+
describe Aesop::Logger do
|
4
|
+
before :each do
|
5
|
+
@logger = Aesop::Logger
|
6
|
+
|
7
|
+
configatron.logger do |log|
|
8
|
+
log.name = 'aesop'
|
9
|
+
log.level = Aesop::Logger::WARN
|
10
|
+
log.outputters = 'stdout'
|
11
|
+
end
|
12
|
+
|
13
|
+
Aesop::Logger.reset
|
14
|
+
Aesop::Logger.stub(:configuration){ config.logger }
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'uses configuration to set logger name' do
|
18
|
+
config.logger.should_receive(:name).and_return('aesop')
|
19
|
+
@logger.log
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'uses configuration to set the outputter' do
|
23
|
+
config.logger.should_receive(:outputters).and_return('stdout')
|
24
|
+
@logger.log
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'uses configuration to set the lvel' do
|
28
|
+
config.logger.should_receive(:level).and_return(Aesop::Logger::WARN)
|
29
|
+
@logger.log
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'returns an object of Log4r::Logger class' do
|
33
|
+
@logger.log.should be_a Log4r::Logger
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'allows changing its settings' do
|
37
|
+
@logger.level.should_not == Log4r::DEBUG
|
38
|
+
@logger.level = Log4r::DEBUG
|
39
|
+
@logger.level.should == Log4r::DEBUG
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'can be reset' do
|
43
|
+
@logger.level = Log4r::FATAL
|
44
|
+
current_log = @logger.level
|
45
|
+
Aesop::Logger.reset
|
46
|
+
@logger.level.should_not == current_log
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'is able to use various log levels' do
|
50
|
+
@logger.level = Log4r::DEBUG
|
51
|
+
debug = @logger.debug("debug test message")
|
52
|
+
debug.should be_an Array
|
53
|
+
debug.select{|e| e.is_a?(Log4r::StdoutOutputter)}.should_not be_empty
|
54
|
+
|
55
|
+
info = @logger.info("info test message")
|
56
|
+
info.should be_an Array
|
57
|
+
info.select{|e| e.is_a?(Log4r::StdoutOutputter)}.should_not be_empty
|
58
|
+
|
59
|
+
warn = @logger.warn("warning test message")
|
60
|
+
warn.should be_an Array
|
61
|
+
warn.select{|e| e.is_a?(Log4r::StdoutOutputter)}.should_not be_empty
|
62
|
+
|
63
|
+
err = @logger.error("error test message")
|
64
|
+
err.should be_an Array
|
65
|
+
err.select{|e| e.is_a?(Log4r::StdoutOutputter)}.should_not be_empty
|
66
|
+
|
67
|
+
fatal = @logger.fatal("fatal test message")
|
68
|
+
fatal.should be_an Array
|
69
|
+
fatal.select{|e| e.is_a?(Log4r::StdoutOutputter)}.should_not be_empty
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), '..', '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe "Aesop::Merb::MerbBootLoader" do
|
4
|
+
let(:fake_class){ Class.new }
|
5
|
+
|
6
|
+
def load_class
|
7
|
+
load File.join( File.dirname(__FILE__), '..', '..', '..', 'lib', 'aesop', 'merb', 'merb_boot_loader.rb')
|
8
|
+
end
|
9
|
+
|
10
|
+
before :each do
|
11
|
+
stub_const('Merb', fake_class)
|
12
|
+
stub_const('Merb::BootLoader', fake_class)
|
13
|
+
stub_const('Merb::BootLoader::ChooseAdapter', fake_class)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'inserts after the choose adapter' do
|
17
|
+
fake_class.should_receive(:after).with(Merb::BootLoader::ChooseAdapter)
|
18
|
+
load_class
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'initializes aesop' do
|
22
|
+
Aesop::Aesop.instance.should_receive(:init)
|
23
|
+
Aesop::MerbBootLoader.run
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), '..', '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe Aesop::Rails::Middleware do
|
4
|
+
let(:fake_app){ double }
|
5
|
+
let(:exception){ Exception.new }
|
6
|
+
subject { Aesop::Rails::Middleware.new( fake_app ) }
|
7
|
+
|
8
|
+
it 'dispatches exceptions from the middleware stack to aesop' do
|
9
|
+
fake_app.stub(:call).with(anything()){ raise exception }
|
10
|
+
Aesop::Aesop.instance.should_receive(:catch_exception).with(exception)
|
11
|
+
subject.call(:production)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), '..', '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe "Aesop::Rails::Railtie" do
|
4
|
+
let(:fake_class){ Class.new }
|
5
|
+
let(:fake_app){ double }
|
6
|
+
|
7
|
+
def load_class
|
8
|
+
load File.join( File.dirname(__FILE__), '..', '..', '..', 'lib', 'aesop', 'rails', 'railtie.rb')
|
9
|
+
end
|
10
|
+
|
11
|
+
before :each do
|
12
|
+
stub_const('Rails', fake_class)
|
13
|
+
stub_const('Rails::Railtie', fake_class)
|
14
|
+
end
|
15
|
+
|
16
|
+
after :each do
|
17
|
+
Aesop.send(:remove_const, :Railtie) if Aesop.const_defined?(:Railtie)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'defines an initializer' do
|
21
|
+
fake_class.should_receive(:initializer)
|
22
|
+
load_class
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'initializes aesop in the railtie initializer' do
|
26
|
+
middleware = double
|
27
|
+
middleware.stub(:insert_after)
|
28
|
+
config = double
|
29
|
+
config.stub(:middleware).and_return(middleware)
|
30
|
+
fake_app.stub(:config).and_return(config)
|
31
|
+
Aesop::Aesop.instance.should_receive(:init)
|
32
|
+
fake_class.stub(:initializer) do |name, &blk|
|
33
|
+
blk.call(fake_app)
|
34
|
+
end
|
35
|
+
load_class
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'Inserting middleware' do
|
39
|
+
let(:middleware){ double }
|
40
|
+
|
41
|
+
before :each do
|
42
|
+
config = double
|
43
|
+
config.stub(:middleware).and_return(middleware)
|
44
|
+
fake_app.stub(:config).and_return(config)
|
45
|
+
fake_class.stub(:initializer) do |name, &blk|
|
46
|
+
blk.call(fake_app)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'inserts middleware after DebugExceptions if it exists' do
|
51
|
+
stub_const('ActionDispatch', fake_class)
|
52
|
+
stub_const('ActionDispatch::DebugExceptions', fake_class)
|
53
|
+
middleware.should_receive(:insert_after).with("ActionDispatch::DebugExceptions", "Aesop::Rails::Middleware")
|
54
|
+
load_class
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'inserts middleware after ShowExceptions if DebugExceptions does not exist' do
|
58
|
+
middleware.should_receive(:insert_after).with("ActionDispatch::ShowExceptions", "Aesop::Rails::Middleware")
|
59
|
+
load_class
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "capistrano"
|
2
|
+
require "capistrano-spec"
|
3
|
+
require File.join( File.dirname(__FILE__), '..', '..', 'recipes', 'aesop.rb')
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
config.include Capistrano::Spec::Matchers
|
7
|
+
config.include Capistrano::Spec::Helpers
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Aesop::Capistrano, "loaded into a configuration" do
|
11
|
+
let(:config){ Capistrano::Configuration.new }
|
12
|
+
let(:task_name){ "aesop:record_deployment" }
|
13
|
+
|
14
|
+
before :each do
|
15
|
+
config.extend(Capistrano::Spec::ConfigurationExtension)
|
16
|
+
config.load("deploy")
|
17
|
+
config.set(:application, 'aesop')
|
18
|
+
config.set(:repository, 'aesop')
|
19
|
+
Aesop::Capistrano.load_into(config)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'defines the record_deployment task' do
|
23
|
+
config.find_task(task_name).should_not be_nil
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'defines the task only for app server roles' do
|
27
|
+
task = config.find_task(task_name)
|
28
|
+
options = task.options
|
29
|
+
options.should have_key(:roles)
|
30
|
+
options[:roles].should == :app
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'sets the deployment_time variable' do
|
34
|
+
config.find_and_execute_task(task_name)
|
35
|
+
config.fetch(:deployment_time).should_not be_nil
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'uploads a file called defined in the configuration' do
|
39
|
+
config.set(:release_path, '/release_path')
|
40
|
+
config.find_and_execute_task(task_name)
|
41
|
+
config.should have_put(config.fetch(:deployment_time)).to("#{config.fetch(:release_path)}/DEPLOY_TIME")
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'executes after the deploy:finalize task' do
|
45
|
+
config.should callback(task_name).after("deploy:finalize_update")
|
46
|
+
end
|
47
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
|
11
|
+
unless RUBY_VERSION == "1.8.7"
|
12
|
+
require "codeclimate-test-reporter"
|
13
|
+
CodeClimate::TestReporter.start
|
14
|
+
|
15
|
+
require 'simplecov'
|
16
|
+
SimpleCov.start
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'rspec/core'
|
20
|
+
|
21
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
22
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
23
|
+
|
24
|
+
require 'aesop'
|
25
|
+
|
26
|
+
def config
|
27
|
+
configatron
|
28
|
+
end
|
29
|
+
|
30
|
+
def remove_deploy_file
|
31
|
+
if File.exist?(config.deployment_file)
|
32
|
+
File.delete(config.deployment_file)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def create_deploy_file(timestamp = Time.now)
|
37
|
+
remove_deploy_file
|
38
|
+
File.open(config.deployment_file, 'w') do |file|
|
39
|
+
file.write(timestamp.to_i)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
RSpec::Matchers.define :have_constant do |const|
|
44
|
+
match do |owner|
|
45
|
+
owner.const_defined?(const)
|
46
|
+
end
|
47
|
+
end
|