mole 0.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.
- data/History.txt +4 -0
- data/Manifest.txt +45 -0
- data/README.txt +140 -0
- data/Rakefile +47 -0
- data/bin/mole +8 -0
- data/bin/molify +64 -0
- data/config/database.yml +21 -0
- data/config/test_database.yml +69 -0
- data/lib/mole/db/migrate.rb +90 -0
- data/lib/mole/e_mole.rb +74 -0
- data/lib/mole/logger.rb +131 -0
- data/lib/mole/models/mole_feature.rb +45 -0
- data/lib/mole/models/mole_log.rb +56 -0
- data/lib/mole/module.rb +274 -0
- data/lib/mole/moler.rb +51 -0
- data/lib/mole/utils/frameworks.rb +22 -0
- data/lib/mole/version.rb +15 -0
- data/lib/mole.rb +175 -0
- data/spec/data/blee.rb +53 -0
- data/spec/db/migrate_spec.rb +19 -0
- data/spec/emole_spec.rb +43 -0
- data/spec/logger_spec.rb +56 -0
- data/spec/models/mole_feature_spec.rb +37 -0
- data/spec/models/mole_log_spec.rb +73 -0
- data/spec/module_spec.rb +171 -0
- data/spec/mole_spec.rb +38 -0
- data/spec/moler_spec.rb +65 -0
- data/spec/spec_helper.rb +59 -0
- data/spec/utils/framework_spec.rb +46 -0
- data/tasks/ann.rake +76 -0
- data/tasks/annotations.rake +22 -0
- data/tasks/doc.rake +48 -0
- data/tasks/gem.rake +110 -0
- data/tasks/manifest.rake +49 -0
- data/tasks/mole.rake +115 -0
- data/tasks/post_load.rake +26 -0
- data/tasks/rubyforge.rake +57 -0
- data/tasks/setup.rb +227 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +44 -0
- data/tasks/test.rake +38 -0
- data/templates/mole/e_mole/exception_alerts.rhtml +14 -0
- data/templates/mole/e_mole/feature_alerts.rhtml +11 -0
- data/templates/mole/e_mole/perf_alerts.rhtml +12 -0
- data/test/test_mole.rb +0 -0
- metadata +120 -0
data/lib/mole.rb
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
# $Id$
|
2
|
+
|
3
|
+
# Equivalent to a header guard in C/C++
|
4
|
+
# Used to prevent the class/module from being loaded more than once
|
5
|
+
unless defined? Mole
|
6
|
+
require 'activerecord'
|
7
|
+
module Mole
|
8
|
+
# :stopdoc:
|
9
|
+
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
10
|
+
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
11
|
+
|
12
|
+
# :startdoc:
|
13
|
+
# The MOle can be ran in a couple of modes: Transient and Persistent
|
14
|
+
# Transient mode will log the output to the specified log file
|
15
|
+
# Persistent mode will log the mole output to your db
|
16
|
+
# The default is :transient
|
17
|
+
def self.run_modes #:nodoc:
|
18
|
+
[:transient, :persistent]
|
19
|
+
end
|
20
|
+
|
21
|
+
# MOle Default settings
|
22
|
+
def self.defaults #:nodoc:
|
23
|
+
@defaults ||= {
|
24
|
+
:moleable => false,
|
25
|
+
:application => "Default",
|
26
|
+
:perf_threshold => 5,
|
27
|
+
:mode => :transient,
|
28
|
+
:emole_from => "MOleBeatch",
|
29
|
+
:mole_config => nil,
|
30
|
+
:emole_recipients => [],
|
31
|
+
|
32
|
+
# logging options
|
33
|
+
:log_file => $stdout,
|
34
|
+
:log_level => :info,
|
35
|
+
:email_alerts_to => "MOleBeatch",
|
36
|
+
:email_alert_level => :error }
|
37
|
+
end
|
38
|
+
|
39
|
+
# Reset the configuration to what it would be when the class is parsed
|
40
|
+
# this is needed mainly for running specs. This resets the class to the
|
41
|
+
# state it was before initialize is called. initialize MUST be called
|
42
|
+
# after reset_configuration! is invoked
|
43
|
+
def self.reset_configuration! #:nodoc:
|
44
|
+
@logger.clear_appenders if @logger
|
45
|
+
@logger = nil
|
46
|
+
@config = nil
|
47
|
+
end
|
48
|
+
|
49
|
+
# Initialize the MOle
|
50
|
+
# Valid options are
|
51
|
+
# <tt>moleable</tt>:: specify if this application is moleable.
|
52
|
+
# Defaults to false.
|
53
|
+
# <tt>application</tt>:: the name of the application to be moled.
|
54
|
+
# <tt>perf_threshold</tt>:: the performance threshold over which a Mole condition will be issued.
|
55
|
+
# Defaults to 5 seconds
|
56
|
+
# <tt>mode</tt>:: the MOle logging mole. The mole can either log information to a db via
|
57
|
+
# the :persistent option or to a log file via the :transient flag.
|
58
|
+
# Defaults to transient
|
59
|
+
# <tt>emole_from</tt>:: the EMole originator when sending eMOle alerts.
|
60
|
+
# <tt>emole_recipients</tt>:: a collection of EMOle recipients
|
61
|
+
# <tt>mole_config</tt>:: the location of the MOle configuration file where the interceptors will
|
62
|
+
# be defined.
|
63
|
+
# <tt>log_file</tt>:: The log file to be used to log MOle interceptions
|
64
|
+
# <tt>log_level</tt>:: logging level ie :info, :debug, :error, :warn...
|
65
|
+
# <tt>email_alerts_to</tt>:: log level email alert recipients.
|
66
|
+
# <tt>email_alert_level</tt>:: specifies which log level will trigger email alerts to be sent
|
67
|
+
def self.initialize( opts={} )
|
68
|
+
@config = defaults.merge( opts )
|
69
|
+
@config[:email_alerts_to] = @config[:emole_recipients] if @config[:emole_recipients] and !@config[:emole_recipients].empty?
|
70
|
+
# dump
|
71
|
+
# Add the mode to the ruby lib path...
|
72
|
+
$: << libpath
|
73
|
+
Mole.require_all_libs_relative_to __FILE__
|
74
|
+
|
75
|
+
raise "Unable to find the MOle configuration file #{conf_file}" if conf_file and !File.exists? conf_file
|
76
|
+
load conf_file if conf_file and moleable?
|
77
|
+
end
|
78
|
+
|
79
|
+
# Fetch the MOle configuration file
|
80
|
+
def self.conf_file #:nodoc:
|
81
|
+
config[:mole_config]
|
82
|
+
end
|
83
|
+
|
84
|
+
# EMole alert sender
|
85
|
+
def self.emole_from #:nodoc:
|
86
|
+
config[:emole_from]
|
87
|
+
end
|
88
|
+
|
89
|
+
# EMole alert recipients
|
90
|
+
def self.emole_recipients #:nodoc:
|
91
|
+
config[:emole_recipients]
|
92
|
+
end
|
93
|
+
|
94
|
+
# Fetch the MOle configuration
|
95
|
+
def self.config #:nodoc:
|
96
|
+
@config
|
97
|
+
end
|
98
|
+
|
99
|
+
# Debug
|
100
|
+
def self.dump #:nodoc:
|
101
|
+
puts ""
|
102
|
+
puts "Mole Configuration Landscape"
|
103
|
+
config.keys.sort{ |a,b| a.to_s <=> b.to_s }.each do |k|
|
104
|
+
key = k.to_s.rjust(20)
|
105
|
+
value = config[k].to_s.rjust(97,".")
|
106
|
+
puts "#{key} : #{value}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# get a hold of a logger. This is the global logger for sentiment.
|
111
|
+
def self.logger #:nodoc:
|
112
|
+
@logger ||= ::Mole::Logger.new( { :log_file => config[:log_file],
|
113
|
+
:logger_name => "MOle",
|
114
|
+
:log_level => config[:log_level],
|
115
|
+
:email_alerts_to => config[:email_alerts_to],
|
116
|
+
:email_alert_level => config[:email_alert_level],
|
117
|
+
:additive => false } )
|
118
|
+
end
|
119
|
+
|
120
|
+
# The name of the MOled application
|
121
|
+
def self.application #:nodoc:
|
122
|
+
config[:application]
|
123
|
+
end
|
124
|
+
|
125
|
+
# Is this application is MOleable
|
126
|
+
def self.moleable? #:nodoc:
|
127
|
+
config[:moleable]
|
128
|
+
end
|
129
|
+
|
130
|
+
# Returns the MOle perf threshold. If any MOled features takes longer
|
131
|
+
# than this time to complete, then an alarm will be triggered...
|
132
|
+
def self.perf_threshold #:nodoc:
|
133
|
+
config[:perf_threshold]
|
134
|
+
end
|
135
|
+
|
136
|
+
# Enable to toggle between different log modes ie :persistent/:transient
|
137
|
+
def self.switch_mode( mode )
|
138
|
+
config[:mode] = mode
|
139
|
+
end
|
140
|
+
|
141
|
+
# Check if the MOle is running in persistent mode
|
142
|
+
def self.persistent?
|
143
|
+
config[:mode] == :persistent
|
144
|
+
end
|
145
|
+
|
146
|
+
# Returns the library path for the module. If any arguments are given,
|
147
|
+
# they will be joined to the end of the libray path using
|
148
|
+
# <tt>File.join</tt>.
|
149
|
+
#
|
150
|
+
def self.libpath( *args ) #:nodoc:
|
151
|
+
args.empty? ? LIBPATH : ::File.join(LIBPATH, *args)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Returns the lpath for the module. If any arguments are given,
|
155
|
+
# they will be joined to the end of the path using
|
156
|
+
# <tt>File.join</tt>.
|
157
|
+
#
|
158
|
+
def self.path( *args ) #:nodoc:
|
159
|
+
args.empty? ? PATH : ::File.join(PATH, *args)
|
160
|
+
end
|
161
|
+
|
162
|
+
# Utility method used to rquire all files ending in .rb that lie in the
|
163
|
+
# directory below this file that has the same name as the filename passed
|
164
|
+
# in. Optionally, a specific _directory_ name can be passed in such that
|
165
|
+
# the _filename_ does not have to be equivalent to the directory.
|
166
|
+
#
|
167
|
+
def self.require_all_libs_relative_to( fname, dir = nil ) #:nodoc:
|
168
|
+
dir ||= ::File.basename(fname, '.*')
|
169
|
+
search_me = ::File.expand_path(
|
170
|
+
::File.join(::File.dirname(fname), dir, '**', '*.rb'))
|
171
|
+
|
172
|
+
Dir.glob(search_me).sort.each {|rb| require rb}
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
data/spec/data/blee.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'mole/module'
|
2
|
+
|
3
|
+
class Blee
|
4
|
+
def self.blee_static
|
5
|
+
end
|
6
|
+
|
7
|
+
def crap_out
|
8
|
+
end
|
9
|
+
|
10
|
+
def crap_out_too
|
11
|
+
end
|
12
|
+
|
13
|
+
def blee_no_args
|
14
|
+
# puts ">>> Blee_No_Args"
|
15
|
+
end
|
16
|
+
|
17
|
+
def blee_args( i, p )
|
18
|
+
# puts ">>> Blee_Args #{i} -- #{p}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def blee_args_ret( p )
|
22
|
+
"Hello #{p}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def blee_raise
|
26
|
+
raise "Blee exception"
|
27
|
+
end
|
28
|
+
|
29
|
+
def blee_raise_too
|
30
|
+
raise "Blee exception"
|
31
|
+
end
|
32
|
+
|
33
|
+
def blee_slow
|
34
|
+
sleep( 1 )
|
35
|
+
end
|
36
|
+
|
37
|
+
def blee_slow_too
|
38
|
+
sleep( 1 )
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def blee_private( arg )
|
44
|
+
arg
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
def blee_protected( arg )
|
50
|
+
arg
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "spec_helper" )
|
2
|
+
|
3
|
+
describe Mole::Db::Migrate do
|
4
|
+
before( :all ) do
|
5
|
+
::Mole.reset_configuration!
|
6
|
+
::Mole.initialize( :moleable => true )
|
7
|
+
@config = ::File.expand_path( ::File.join(::File.dirname(__FILE__), %w[.. .. config database.yml] ) )
|
8
|
+
end
|
9
|
+
|
10
|
+
it "migrates down correctly" do
|
11
|
+
mgt = Mole::Db::Migrate.new( OpenStruct.new( :direction => :down, :configuration => @config, :environment => 'test' ) )
|
12
|
+
mgt.apply
|
13
|
+
end
|
14
|
+
|
15
|
+
it "migrates up correctly" do
|
16
|
+
mgt = Mole::Db::Migrate.new( OpenStruct.new( :direction => :up, :configuration => @config, :environment => 'test' ) )
|
17
|
+
mgt.apply
|
18
|
+
end
|
19
|
+
end
|
data/spec/emole_spec.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper" )
|
2
|
+
|
3
|
+
require 'action_mailer'
|
4
|
+
ActionMailer::Base.delivery_method = :sendmail
|
5
|
+
ActionMailer::Base.raise_delivery_errors = true
|
6
|
+
|
7
|
+
# TODO Figure out how to auto check email was sent
|
8
|
+
describe Mole::EMole do
|
9
|
+
before( :each ) do
|
10
|
+
::Mole.reset_configuration!
|
11
|
+
::Mole.initialize( :moleable => true,
|
12
|
+
:emole_from => "MOleBeatch@liquidrail.com",
|
13
|
+
:emole_recipients => ['fernand@liquidrail.com'] )
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should send out a correct perf alert" do
|
17
|
+
Mole::EMole.deliver_perf_alerts(
|
18
|
+
self,
|
19
|
+
"fernand",
|
20
|
+
:feature => "test",
|
21
|
+
:elapsed_time => 10 )
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should send out a correct feature alert" do
|
25
|
+
Mole::EMole.deliver_feature_alerts(
|
26
|
+
self,
|
27
|
+
"fernand",
|
28
|
+
:feature => "test",
|
29
|
+
:fred => "blee" )
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should send out a correct exception alert" do
|
33
|
+
begin
|
34
|
+
raise "Something craped out"
|
35
|
+
rescue => boom
|
36
|
+
Mole::EMole.deliver_exception_alerts(
|
37
|
+
self,
|
38
|
+
"fernand",
|
39
|
+
:feature => "test",
|
40
|
+
:boom => boom )
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/spec/logger_spec.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper" )
|
2
|
+
|
3
|
+
require 'stringio'
|
4
|
+
require File.join(File.dirname(__FILE__), %w[.. lib mole logger] )
|
5
|
+
|
6
|
+
describe Mole::Logger do
|
7
|
+
it "raises an error if the email addresses passed in is empty" do
|
8
|
+
lambda { Mole::Logger.new( { :email_alerts_to => [] } ) }.should raise_error( Mole::Logger::ConfigurationError )
|
9
|
+
end
|
10
|
+
|
11
|
+
it "configures an email appender if :email_alerts is set" do
|
12
|
+
l = Mole::Logger.new( { :logger_name => "Test2", :email_alerts_to => "fernand@invalid.address", :email_alert_level => :off })
|
13
|
+
l.email_appender.should_not == nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it "does not configure an email appender if :email_alerts is not set" do
|
17
|
+
l = Mole::Logger.new( { :logger_name => "Test3" })
|
18
|
+
lambda { l.email_appender }.should raise_error( Mole::Logger::ConfigurationError )
|
19
|
+
end
|
20
|
+
|
21
|
+
it "raises an error if an invalid object is passed in for the :log_file" do
|
22
|
+
lambda { l = Mole::Logger.new( { :log_file => Object.new } ) }.should raise_error( Mole::Logger::ConfigurationError )
|
23
|
+
end
|
24
|
+
|
25
|
+
it "logs to an IO stream if given" do
|
26
|
+
io = StringIO.new
|
27
|
+
l = Mole::Logger.new( { :log_file => io, :logger_name => "Test4" })
|
28
|
+
l.info "This is a test io message"
|
29
|
+
io.string.split("\n").should have(1).item
|
30
|
+
io.string.should =~ /This is a test io message/
|
31
|
+
io.string.should =~ /INFO/
|
32
|
+
end
|
33
|
+
|
34
|
+
it "logs to a file if given a file name to log to" do
|
35
|
+
log_file = "/tmp/mole_logger_test.log"
|
36
|
+
FileUtils.rm( log_file ) if File.exists?( log_file )
|
37
|
+
l = Mole::Logger.new({ :log_file => log_file, :logger_name => "Test5" })
|
38
|
+
l.info "This is a test log file message"
|
39
|
+
|
40
|
+
log_lines = IO.readlines(log_file)
|
41
|
+
|
42
|
+
log_lines.should have(1).items
|
43
|
+
log_lines.first.should =~ /This is a test log file message/
|
44
|
+
log_lines.first.should =~ /INFO/
|
45
|
+
end
|
46
|
+
|
47
|
+
it "creates a logger from another logger" do
|
48
|
+
io = StringIO.new
|
49
|
+
l = Mole::Logger.new( { :log_file => io, :logger_name => ::Mole})
|
50
|
+
child_l = l.for(Mole)
|
51
|
+
|
52
|
+
child_l.info "This is a child log message"
|
53
|
+
io.string.should =~ /This is a child log message/
|
54
|
+
io.string.should =~ /INFO/
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "spec_helper" )
|
2
|
+
|
3
|
+
describe MoleFeature do
|
4
|
+
before( :each ) do
|
5
|
+
::Mole.reset_configuration!
|
6
|
+
::Mole.initialize( :mode => :persistent, :log_level => :debug, :moleable => true )
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should find or create known features correctly" do
|
10
|
+
%w[ all performance exception].each do |f|
|
11
|
+
feature = MoleFeature.send( "find_#{f}_feature".to_sym, ::Mole.application )
|
12
|
+
feature.should_not be_nil
|
13
|
+
feature.name.downcase.should == f
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should create a new feature" do
|
18
|
+
feature = MoleFeature.find_feature( "Fred", ::Mole.application, self.class.name )
|
19
|
+
feature.should_not be_nil
|
20
|
+
feature.name.should == "Fred"
|
21
|
+
feature.context.should == self.class.name
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should not create a feature with no name" do
|
25
|
+
feature = MoleFeature.find_feature( "", ::Mole.application, self.class.name )
|
26
|
+
feature.should be_nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should find all features for a given application correctly" do
|
30
|
+
%w[ all performance exception].each do |f|
|
31
|
+
MoleFeature.send( "find_#{f}_feature".to_sym, ::Mole.application )
|
32
|
+
end
|
33
|
+
MoleFeature.find_feature( "Fred", ::Mole.application, self.class.name )
|
34
|
+
features = MoleFeature.find_features( ::Mole.application )
|
35
|
+
features.should have(4).mole_features
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "spec_helper" )
|
2
|
+
|
3
|
+
describe MoleLog do
|
4
|
+
before( :each ) do
|
5
|
+
::Mole.reset_configuration!
|
6
|
+
::Mole.initialize( :mode => :persistent, :log_level => :info, :moleable => true )
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should log unchecked exceptions correctly" do
|
10
|
+
begin
|
11
|
+
raise "Something crapped out"
|
12
|
+
rescue => boom
|
13
|
+
MoleLog.check_it( self, 100, :blee => "Hello", :duh => "World", :boom => boom )
|
14
|
+
end
|
15
|
+
except_feature = MoleFeature.find_exception_feature( ::Mole.application )
|
16
|
+
except_feature.should_not be_nil
|
17
|
+
|
18
|
+
log = MoleLog.find( :all, :conditions => ['mole_feature_id = ?', except_feature.id] )
|
19
|
+
log.should_not be_nil
|
20
|
+
log.should have(1).mole_log
|
21
|
+
log.first.user_id.should == 100
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should log perf exception correctly" do
|
25
|
+
MoleLog.perf_it( self, 100, :blee => "Hello", :duh => "World" )
|
26
|
+
perf_feature = MoleFeature.find_performance_feature( ::Mole.application )
|
27
|
+
perf_feature.should_not be_nil
|
28
|
+
|
29
|
+
log = MoleLog.find( :all, :conditions => ['mole_feature_id = ?', perf_feature.id] )
|
30
|
+
log.should_not be_nil
|
31
|
+
log.should have(1).mole_log
|
32
|
+
log.first.user_id.should == 100
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should mole a feature correctly" do
|
36
|
+
MoleLog.mole_it( "Test", "fred", 100, :blee => "Hello", :duh => "World" )
|
37
|
+
feature = MoleFeature.find_feature( "fred", ::Mole.application, "Test".class.name )
|
38
|
+
feature.should_not be_nil
|
39
|
+
|
40
|
+
log = MoleLog.find( :all, :conditions => ['mole_feature_id = ?', feature.id] )
|
41
|
+
log.should_not be_nil
|
42
|
+
log.should have(1).mole_log
|
43
|
+
log.first.user_id.should == 100
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should log request info correctly" do
|
47
|
+
ctrl = Moled::Controller.new
|
48
|
+
MoleLog.mole_it( ctrl, "fred", 100, :blee => "Hello", :duh => "World" )
|
49
|
+
feature = MoleFeature.find_feature( "fred", ::Mole.application, ctrl.class.name )
|
50
|
+
feature.should_not be_nil
|
51
|
+
|
52
|
+
log = MoleLog.find( :all, :conditions => ['mole_feature_id = ?', feature.id] )
|
53
|
+
log.should_not be_nil
|
54
|
+
log.should have(1).mole_log
|
55
|
+
log.first.user_id.should == 100
|
56
|
+
log.first.ip_address.should == "1.1.1.1"
|
57
|
+
log.first.browser_type.should == "GodZilla"
|
58
|
+
end
|
59
|
+
|
60
|
+
module Moled
|
61
|
+
class Controller
|
62
|
+
class Request
|
63
|
+
def env
|
64
|
+
{'REMOTE_ADDR' => "1.1.1.1", 'HTTP_USER_AGENT' => 'GodZilla' }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def request
|
69
|
+
Request.new
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/spec/module_spec.rb
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper" )
|
2
|
+
|
3
|
+
|
4
|
+
describe Module do
|
5
|
+
before( :all ) do
|
6
|
+
::Mole.initialize( :perf_threshold => 1 )
|
7
|
+
require File.join( File.dirname(__FILE__), %w[data blee] )
|
8
|
+
end
|
9
|
+
|
10
|
+
before( :each ) do
|
11
|
+
@blee = Blee.new
|
12
|
+
CallStackChecker.reset
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should trap mole before handler exceptions" do
|
16
|
+
Blee.mole_before( :feature => :crap_out ) { |context, feature, *args|
|
17
|
+
raise "Before - Something did crap out"
|
18
|
+
CallStackChecker.called
|
19
|
+
}
|
20
|
+
@blee.crap_out
|
21
|
+
CallStackChecker.should_not be_called
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should trap mole after handler exceptions" do
|
25
|
+
Blee.mole_after( :feature => :crap_out ) { |context, feature, *args|
|
26
|
+
raise "After - Something did crap out"
|
27
|
+
CallStackChecker.called
|
28
|
+
}
|
29
|
+
@blee.crap_out
|
30
|
+
CallStackChecker.should_not be_called
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should trap mole handler exceptions" do
|
34
|
+
Blee.mole_unchecked( :features => [:blee_raise_too] ) { |context, feature, *args|
|
35
|
+
raise "Unchecked - Something did crap out"
|
36
|
+
CallStackChecker.called
|
37
|
+
}
|
38
|
+
@blee.blee_raise_too rescue nil
|
39
|
+
CallStackChecker.should_not be_called
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should trap a perf handler exception" do
|
43
|
+
Blee.mole_perf( :features => [:blee_slow_too] ) do |context, feature, elapsed_time, args, block|
|
44
|
+
raise "Perf - Something did crap out"
|
45
|
+
CallStackChecker.called
|
46
|
+
end
|
47
|
+
@blee.blee_slow_too
|
48
|
+
CallStackChecker.should_not be_called
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should trap mole handler exceptions" do
|
52
|
+
Blee.mole_before( :feature => :crap_out ) { |context, feature, *args|
|
53
|
+
raise "Something did crap out"
|
54
|
+
CallStackChecker.called
|
55
|
+
}
|
56
|
+
@blee.crap_out
|
57
|
+
CallStackChecker.should_not be_called
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should correctly setup a before call" do
|
61
|
+
Blee.mole_before( :feature => :blee_no_args ) { |context, feature, *args|
|
62
|
+
context.class.should == Blee
|
63
|
+
feature.should == "blee_no_args"
|
64
|
+
args.should have(0).items
|
65
|
+
CallStackChecker.called
|
66
|
+
}
|
67
|
+
@blee.blee_no_args
|
68
|
+
CallStackChecker.should be_called
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should correctly setup an after call" do
|
72
|
+
Blee.mole_after( :feature => :blee_no_args ) { |context, feature, *args|
|
73
|
+
context.class.should == Blee
|
74
|
+
feature.should == "blee_no_args"
|
75
|
+
args.should have(0).items
|
76
|
+
CallStackChecker.called
|
77
|
+
}
|
78
|
+
@blee.blee_no_args
|
79
|
+
CallStackChecker.should be_called
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should correctly trap an exception" do
|
83
|
+
Blee.mole_unchecked( :features => [:blee_raise] ) do |context, feature, boom, args, block|
|
84
|
+
context.class.should == Blee
|
85
|
+
feature.should == "blee_raise"
|
86
|
+
boom.to_s.should == "Blee exception"
|
87
|
+
CallStackChecker.called
|
88
|
+
end
|
89
|
+
@blee.blee_raise rescue nil
|
90
|
+
CallStackChecker.should be_called
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should not trap a before call" do
|
94
|
+
@blee.blee_args( "Hello", "World" )
|
95
|
+
CallStackChecker.should_not be_called
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should correctly trap the before call arguments" do
|
99
|
+
Blee.mole_before( :feature => :blee_args ) { |context, feature, *args|
|
100
|
+
context.class.should == Blee
|
101
|
+
feature.should == "blee_args"
|
102
|
+
args.should have(2).items
|
103
|
+
args[0].should == "Hello"
|
104
|
+
args[1].should == "World"
|
105
|
+
CallStackChecker.called
|
106
|
+
}
|
107
|
+
@blee.blee_args( "Hello", "World" )
|
108
|
+
CallStackChecker.should be_called
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should correctly trap the after call arguments" do
|
112
|
+
Blee.mole_after( :feature => :blee_args ) { |context, feature, *args|
|
113
|
+
context.class.should == Blee
|
114
|
+
feature.should == "blee_args"
|
115
|
+
args.size.should == 2
|
116
|
+
args[0].should == "Hello"
|
117
|
+
args[1].should == "World"
|
118
|
+
CallStackChecker.called
|
119
|
+
}
|
120
|
+
@blee.blee_args( "Hello", "World" )
|
121
|
+
CallStackChecker.should be_called
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should correctly trap a slow call" do
|
125
|
+
Blee.mole_perf( :features => [:blee_slow] ) do |context, feature, elapsed_time, args, block|
|
126
|
+
context.class.should == Blee
|
127
|
+
feature.should == "blee_slow"
|
128
|
+
elapsed_time.should > 1
|
129
|
+
CallStackChecker.called
|
130
|
+
end
|
131
|
+
@blee.blee_slow rescue nil
|
132
|
+
CallStackChecker.should be_called
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should trap a private method correctly" do
|
136
|
+
Blee.mole_after( :feature => :blee_private ) { |context, feature, *args|
|
137
|
+
context.class.should == Blee
|
138
|
+
feature.should == "blee_private"
|
139
|
+
args.size.should == 1
|
140
|
+
args[0].should == "Hello"
|
141
|
+
CallStackChecker.called
|
142
|
+
}
|
143
|
+
@blee.send( :blee_private, "Hello" )
|
144
|
+
CallStackChecker.should be_called
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should trap a protected method correctly" do
|
148
|
+
Blee.mole_after( :feature => :blee_protected ) { |context, feature, *args|
|
149
|
+
context.class.should == Blee
|
150
|
+
feature.should == "blee_protected"
|
151
|
+
args.size.should == 1
|
152
|
+
args[0].should == "Hello"
|
153
|
+
CallStackChecker.called
|
154
|
+
}
|
155
|
+
@blee.send( :blee_protected, "Hello" )
|
156
|
+
CallStackChecker.should be_called
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should mole a static method correctly" do
|
160
|
+
pending do
|
161
|
+
Blee.mole_after( :feature => :blee_static ) { |context, feature, *args|
|
162
|
+
context.class.should == Blee
|
163
|
+
feature.should == "blee_static"
|
164
|
+
args.size.should == 0
|
165
|
+
CallStackChecker.called
|
166
|
+
}
|
167
|
+
Blee.blee_static
|
168
|
+
CallStackChecker.should be_called
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
data/spec/mole_spec.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper" )
|
2
|
+
|
3
|
+
describe Mole do
|
4
|
+
before( :all ) do
|
5
|
+
::Mole.reset_configuration!
|
6
|
+
::Mole.initialize( :moleable => true )
|
7
|
+
@root = ::File.expand_path( ::File.join(::File.dirname(__FILE__), ".." ) )
|
8
|
+
end
|
9
|
+
|
10
|
+
it "is versioned" do
|
11
|
+
::Mole::Version.version.should =~ /\d+\.\d+\.\d+/
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should have the right defaults" do
|
15
|
+
Mole.should be_moleable
|
16
|
+
Mole.logger.should_not be_nil
|
17
|
+
Mole.perf_threshold.should == 5
|
18
|
+
Mole.should_not be_persistent
|
19
|
+
Mole.application.should == "Default"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "generates a correct path relative to root" do
|
23
|
+
Mole.path( "mole.rb" ).should == ::File.join(@root, "mole.rb" )
|
24
|
+
end
|
25
|
+
|
26
|
+
it "generates a correct path relative to lib" do
|
27
|
+
Mole.libpath(%w[ mole db_mole.rb]).should == ::File.join(@root, "lib", "mole", "db_mole.rb")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should define the correct run modes" do
|
31
|
+
Mole.run_modes.should == [:transient,:persistent]
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should dump config info to console" do
|
35
|
+
Mole.dump
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|