aesop 1.1.0.1
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.
- 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
|