diff options
author | Patrick J Cherry <patrick@bytemark.co.uk> | 2011-08-17 11:08:07 +0100 |
---|---|---|
committer | Patrick J Cherry <patrick@bytemark.co.uk> | 2011-08-17 11:08:07 +0100 |
commit | 8c8e5ae926e0009743fe92dccb588783640a6022 (patch) | |
tree | e23eea583beac0caf5fb3e45a33b4d2ac7796abf | |
parent | 79dcf16ec6d229d6c31e055ed8e6a98327526a3a (diff) |
* Reminder notifications now take the same path to notify as initial alerts
* Threading tidied -- processor will not do anything unless the timer has frozen
* Person#send_alert now tidied and merged with alert_changed
* POP3 server only shows alerts relevant to the user
* Server now defaults to using an in-memory SQLite database (good for testing)
* Server initializes a blank mauve config.
* Tests tidied up
25 files changed, 522 insertions, 286 deletions
diff --git a/lib/mauve/alert.rb b/lib/mauve/alert.rb index 07421d5..28dfcf1 100644 --- a/lib/mauve/alert.rb +++ b/lib/mauve/alert.rb @@ -235,7 +235,11 @@ module Mauve public def notify - self.alert_group.notify(self) + if self.alert_group.nil? + logger.warn "Could not notify for #{self} since there are no matching alert groups" + else + self.alert_group.notify(self) + end end def acknowledge!(person, ack_until = Time.now+3600) @@ -531,7 +535,8 @@ module Mauve alert_db.clear! end end - + + return nil end def logger diff --git a/lib/mauve/alert_changed.rb b/lib/mauve/alert_changed.rb index 9840b84..9b74396 100644 --- a/lib/mauve/alert_changed.rb +++ b/lib/mauve/alert_changed.rb @@ -19,7 +19,6 @@ module Mauve property :remind_at, Time # property :updated_at, Time, :required => true - def inspect "#<AlertChanged #{id}: alert_id #{alert_id}, for #{person}, update_type #{update_type}>" end @@ -44,35 +43,6 @@ module Mauve Log4r::Logger.new self.class.to_s end - ## Checks to see if a raise was send to the person. - # - # @TODO: Recurence is broken in ruby, change this so that it does not - # use it. - # - # @author Matthew Bloch - # @return [Boolean] true if it was relevant, false otherwise. - def was_relevant_when_raised? - - if "acknowledged" == update_type and true == was_relevant - return true - end - - return was_relevant if update_type == "raised" - - previous = AlertChanged.first(:id.lt => id, - :alert_id => alert_id, - :person => person) - if previous - previous.was_relevant_when_raised? - else - # a bug, but hardly inconceivable :) - logger.info("Could not see that #{alert} was raised with #{person} "+ - "but further updates exist (e.g. #{self}) "+ - "- you may see spurious notifications as a result") - true - end - end - # Sends a reminder about this alert state change, or forget about it if # the alert has been acknowledged # @@ -82,69 +52,31 @@ module Mauve destroy! return false end - - - alert_group = AlertGroup.matches(alert)[0] - - if !alert_group || alert.acknowledged? - logger.info((alert_group ? - "Alert already acknowledged" : - "No alert group matches any more" - ) + " => no reminder due for #{self.alert.inspect}" - ) + if !alert_group + logger.info("No alert group matches any more. Clearing reminder for #{self.alert}.") self.remind_at = nil - save - else - logger.info "Sending a reminder for #{self.alert.inspect}" - - saved = false - unless alert_group.notifications.nil? + return save + end - alert_group.notifications.each do |notification| - # - # Build an array of people that could/should be notified. - # - notification_people = [] + if alert.acknowledged? + logger.info("Alert already acknowledged. Clearing reminder due for #{self.alert}.") + self.remind_at = nil + return save + end - notification.people.each do |np| - case np - when Person - notification_people << np.username - when PeopleList - notification_people += np.list - end - end + alert_group.notify(alert) + # + # Need to make sure this reminder is cleared. + # + self.remind_at = nil - # - # For each person, send a notification - # - notification_people.sort.uniq.each do |np| - if np == self.person - # - # Only remind if the time is right. - # - if DuringRunner.new(Time.now, alert, ¬ification.during).now? - Configuration.current.people[np].send_alert(level, alert) - end - self.remind_at = notification.remind_at_next(alert) - save - saved = true - end - end - end - end - - if !saved - logger.warn("#{self.inspect} did not match any people, maybe configuration has changed but I'm going to delete this and not try to remind anyone again") - destroy! - end - end + save end def due_at # mimic interface from Alert - remind_at ? remind_at.to_time : nil + remind_at ? remind_at : nil end def poll # mimic interface from Alert diff --git a/lib/mauve/alert_group.rb b/lib/mauve/alert_group.rb index 6cff33b..114c39b 100644 --- a/lib/mauve/alert_group.rb +++ b/lib/mauve/alert_group.rb @@ -26,38 +26,13 @@ module Mauve grps end - # If there is any significant change to a set of alerts, the Alert - # class sends the list here so that appropriate action can be taken - # for each one. We scan the list of alert groups to find out which - # alerts match which groups, then send a notification to each group - # object in turn. - # - def notify(alerts) - alerts.each do |alert| - groups = matches(alert) - - # - # Make sure we've got a matching group - # - if groups.empty? - logger.warn "no groups found for #{alert}!" - next - end - - # - # Notify just the first group - # - this_group = groups.first - logger.info("notifying group #{this_group} of #{alert}") - this_group.notify(alert) - end - end - def logger Log4r::Logger.new self.to_s end def all + return [] if Configuration.current.nil? + Configuration.current.alert_groups end @@ -83,7 +58,7 @@ module Mauve self.includes = Proc.new { true } end - def to_s + def inspect "#<AlertGroup:#{name} (level #{level})>" end @@ -129,7 +104,7 @@ module Mauve # The notifications are specified in the config file. # notifications.each do |notification| - notification.alert_changed(alert) + notification.notify(alert) end end diff --git a/lib/mauve/mauve_thread.rb b/lib/mauve/mauve_thread.rb index 52c2801..77df95e 100644 --- a/lib/mauve/mauve_thread.rb +++ b/lib/mauve/mauve_thread.rb @@ -18,10 +18,18 @@ module Mauve def poll_every=(i) raise ArgumentError.new("poll_every must be numeric") unless i.is_a?(Numeric) + # + # Set the minimum poll frequency. + # + if i.to_f < 0.2 + logger.debug "Increasing thread polling interval to 0.2s from #{i}" + i = 0.2 + end + @poll_every = i end - def run_thread(interval = 0.1) + def run_thread(interval = 1.0) # # Good to go. # @@ -70,18 +78,21 @@ module Mauve def state=(s) raise "Bad state for mauve_thread #{s.inspect}" unless [:stopped, :starting, :started, :freezing, :frozen, :stopping, :killing, :killed].include?(s) + unless @state == s @state = s logger.debug(s.to_s.capitalize) end + + @state end def freeze self.state = :freezing - 20.times { Kernel.sleep 0.1 ; break if @thread.stop? } + 20.times { Kernel.sleep 0.2 ; break if @thread.stop? } - logger.debug("Thread has not frozen!") unless @thread.stop? + logger.warn("Thread has not frozen!") unless @thread.stop? end def frozen? diff --git a/lib/mauve/notification.rb b/lib/mauve/notification.rb index dea07a3..8e125be 100644 --- a/lib/mauve/notification.rb +++ b/lib/mauve/notification.rb @@ -149,20 +149,6 @@ module Mauve def logger ; Log4r::Logger.new self.class.to_s ; end - # Updated code, now takes account of lists of people. - # - # @TODO refactor so we can test this more easily. - # - # @TODO Make sure that if no notifications is send at all, we log this - # as an error so that an email is send to the developers. Hum, we - # could have person.alert_changed return true if a notification was - # send (false otherwise) and add it to a queue. Then, dequeue till - # we see a "true" and abort. However, this needs a timeout loop - # around it and we will slow down the whole notificatin since it - # will have to wait untill such a time as it gets a true or timeout. - # Not ideal. A quick fix is to make sure that the clause in the - # configuration has a fall back that will send an alert in all cases. - # def notify(alert) if people.nil? or people.empty? @@ -173,6 +159,8 @@ module Mauve # Should we notify at all? is_relevant = DuringRunner.new(Time.now, alert, &during).now? + n_sent = 0 + people.collect do |person| case person when Person @@ -184,14 +172,13 @@ module Mauve [] end end.flatten.uniq.each do |person| - person.send_alert(level, alert, is_relevant, remind_at_next(alert)) + n_sent += 1 if person.send_alert(self.level, alert, is_relevant, remind_at_next(alert)) end - return nil + return n_sent end def remind_at_next(alert) - return DuringRunner.new(Time.now, alert, &during).find_next(every) if alert.raised? return nil diff --git a/lib/mauve/notifier.rb b/lib/mauve/notifier.rb index 1c3bf9b..d660a54 100644 --- a/lib/mauve/notifier.rb +++ b/lib/mauve/notifier.rb @@ -14,9 +14,8 @@ module Mauve # sz = Server.notification_buffer_size - return if sz == 0 - my_threads = [] + sz.times do person, *args = Server.notification_pop diff --git a/lib/mauve/person.rb b/lib/mauve/person.rb index 76b52e0..3831529 100644 --- a/lib/mauve/person.rb +++ b/lib/mauve/person.rb @@ -5,7 +5,7 @@ require 'log4r' module Mauve class Person < Struct.new(:username, :password, :holiday_url, :urgent, :normal, :low, :email, :xmpp, :sms) - attr_reader :notification_thresholds + attr_reader :notification_thresholds, :last_pop3_login def initialize(*args) # @@ -13,6 +13,10 @@ module Mauve # @notification_thresholds = { 60 => Array.new(10) } @suppressed = false + # + # TODO fix up web login so pop3 can be used as a proxy. + # + @last_pop3_login = {:from => nil, :at => nil} super(*args) end @@ -37,10 +41,11 @@ module Mauve def logger ; @logger ||= Log4r::Logger.new self.class.to_s ; end # - # This method makes sure things liek + # This method makes sure things like + # + # xmpp # - # xmpp - # works + # works # def method_missing(name, *args) # @@ -79,83 +84,65 @@ module Mauve end end - - ## Deals with changes in an alert. - # - # == Old comments by Matthew. - # - # An AlertGroup tells a Person that an alert has changed. Within - # this alert group, the alert may or may not be "relevant" to this - # person, but it is ultimately up to the Person to decide whether to - # send a notification. (i.e. notification of acks/clears should - # always go out to a Person who was notified of the original alert, - # even if the alert is no longer relevant to them). - # - # == New comment - # - # The old code works like this: An alert arrives, with a relevance. An - # AlertChanged is created and the alert may or may not be send. The - # problem is that alerts can be relevant AFTER the initial raise and this - # code (due to AlertChange.was_relevant_when_raised?()) will ignore it. - # This is wrong. - # + # - # The Thread.exclusive wrapper around the AlertChanged creation makes - # sure that two AlertChanged are not created at the same time. This - # caused both instances to set the remind_at time of the other to nil. - # Thus reminders were never seen which is clearly wrong. This bug was - # only showing on jruby due to green threads in MRI. + # Sends the alert, and updates when the AlertChanged database to set the next reminder. # - # - # @author Matthew Bloch, Yann Golanski - # @param [symb] level Level of the alert. - # @param [Alert] alert An alert object. - # @param [Boolean] Whether the alert is relevant as defined by notification - # class. - # @param [MauveTime] When to send remind. - # @return [NULL] nada - def alert_changed(level, alert, is_relevant=true, remind_at=nil) - # User should get notified but will not since on holiday. - str = String.new -# if is_on_holiday? -# is_relevant = false -# str = ' (user on holiday)' -# end - - # Deals with AlertChange database entry. - last_change = AlertChanged.first(:alert_id => alert.id, :person => username) - - if not last_change.nil? - if not last_change.remind_at.nil? and not remind_at.nil? - if last_change.remind_at.to_time < remind_at - remind_at = last_change.remind_at.to_time - end + def send_alert(level, alert, is_relevant=true, remind_at=nil) + # + # First check that we've not just sent an notification to this person for + # this alert + # + last_reminder = AlertChanged.first(:alert => alert, :person => username, :update_type => alert.update_type, :at.gte => (Time.now - 1.minute) ) + + if last_reminder and last_reminder.at >= (Time.now - 1.minute) + # + # + logger.info("Not sending notification to #{username} for #{alert} because one has just been sent.") + return false + end + + + this_reminder = AlertChanged.new( + :level => level.to_s, + :alert_id => alert.id, + :person => username, + :at => Time.now, + :update_type => alert.update_type, + :remind_at => remind_at, + :was_relevant => is_relevant) + + # + # Check to make sure that we've not got a sooner reminder set. + # + unless remind_at.nil? + next_reminder = AlertChanged.first(:alert => alert, :remind_at.gt => Time.now, :person => username, :update_type => alert.update_type) + + if next_reminder + # + # If the reminder is further in the future than the one we're about + # to put on, then just update it. + # + # Otherwise if it is sooner, we don't need to create a new one. + # + if next_reminder.remind_at > remind_at + next_reminder.remind_at = remind_at + logger.info("Not inserting a new reminder, as there is already one in place sooner") + this_reminder = next_reminder + else + this_reminder = nil end end + end - new_change = AlertChanged.create( - :level => level.to_s, - :alert_id => alert.id, - :at => MauveTime.now, - :person => username, - :update_type => alert.update_type, - :remind_at => remind_at, - :was_relevant => is_relevant) - - # We need to look at the AlertChanged objects to reset them to - # the right value. What is the right value? Well... - if true == is_relevant - last_change.was_relevant = true if false == last_change.nil? - end + this_reminder.save unless this_reminder.nil? - send_alert(level, alert) if is_relevant # last_change.was_relevant_when_raised? - end - - # - # This just wraps send_alert by sending the job to a queue. - # - def send_alert(level, alert) - Server.notification_push([self, level, alert]) + if is_relevant + Server.notification_push([self, level, alert]) + return true + end + + return false end def do_send_alert(level, alert) @@ -214,12 +201,11 @@ module Mauve @notification_thresholds[period].push Time.now @notification_thresholds[period].shift end - true - - else - false + return true end + + return false end # Returns the subset of current alerts that are relevant to this Person. diff --git a/lib/mauve/pop3_server.rb b/lib/mauve/pop3_server.rb index ef307d5..f4dbf3a 100644 --- a/lib/mauve/pop3_server.rb +++ b/lib/mauve/pop3_server.rb @@ -283,7 +283,7 @@ module Mauve # # A maximum of the 100 most recent alerts. # - AlertChanged.first(100, :person => self.user).each do |a| + AlertChanged.first(100, :person => self.user, :was_relevant => true).each do |a| # # Not interested in alerts # diff --git a/lib/mauve/processor.rb b/lib/mauve/processor.rb index 86ed5dd..d68c551 100644 --- a/lib/mauve/processor.rb +++ b/lib/mauve/processor.rb @@ -34,6 +34,13 @@ module Mauve sz = Server.packet_buffer_size sz.times do + Timer.instance.freeze if Timer.instance.alive? and !Timer.instance.frozen? + + # + # Hmm.. timer not frozen. + # + break unless Timer.instance.frozen? + data, client, received_at = Server.packet_pop # @@ -41,7 +48,6 @@ module Mauve # break if data.nil? - Timer.instance.freeze if Timer.instance.alive? and !Timer.instance.frozen? # logger.debug("Got #{data.inspect} from #{client.inspect}") diff --git a/lib/mauve/server.rb b/lib/mauve/server.rb index 5cc8484..27157a5 100644 --- a/lib/mauve/server.rb +++ b/lib/mauve/server.rb @@ -32,7 +32,7 @@ module Mauve def initialize super @hostname = "localhost" - @database = "sqlite3:///./mauvealert.db" + @database = "sqlite3::memory:" @started_at = Time.now @initial_sleep = 300 @@ -65,6 +65,12 @@ module Mauve end def setup + # + # + # + @packet_buffer = [] + @notification_buffer = [] + DataMapper.setup(:default, @database) # DataObjects::Sqlite3.logger = Log4r::Logger.new("Mauve::DataMapper") @@ -75,6 +81,10 @@ module Mauve AlertChanged.auto_upgrade! History.auto_upgrade! Mauve::AlertEarliestDate.create_view! + + Mauve::Configuration.current = Mauve::Configuration.new if Mauve::Configuration.current.nil? + + return nil end def start diff --git a/test/tc_mauve_alert.rb b/test/tc_mauve_alert.rb index ef80424..f79859f 100644 --- a/test/tc_mauve_alert.rb +++ b/test/tc_mauve_alert.rb @@ -1,16 +1,30 @@ $:.unshift "../lib" -require 'test/unit' + +require 'th_mauve' +require 'th_mauve_resolv' + require 'mauve/alert' +require 'mauve/proto' +require 'mauve/server' require 'mauve/configuration' require 'mauve/configuration_builder' -require 'th_mauve_resolv' -require 'pp' +require 'mauve/configuration_builders' -class TcMauveAlert < Test::Unit::TestCase +class TcMauveAlert < Mauve::UnitTest + include Mauve - def test_source_list + def setup + super + setup_database + end + + def teardown + teardown_database + super + end + def test_source_list config=<<EOF source_list "test", %w(test-1.example.com) @@ -19,9 +33,9 @@ source_list "has_ipv4", "0.0.0.0/0" source_list "has_ipv6", "2000::/3" EOF - Mauve::Configuration.current = Mauve::ConfigurationBuilder.parse(config) + Configuration.current = ConfigurationBuilder.parse(config) - a = Mauve::Alert.new + a = Alert.new a.subject = "www.example.com" assert( a.in_source_list?("test") ) @@ -35,7 +49,7 @@ EOF def test_summary - a = Mauve::Alert.new + a = Alert.new a.summary = "Free swap memory (MB) (memory_swap) is too low" assert_match(/memory_swap/, a.summary) @@ -43,5 +57,85 @@ EOF end + def test_raise + + config=<<EOF + +alert_group("test") { + +} + +EOF + + Configuration.current = ConfigurationBuilder.parse(config) + + Server.instance.setup + + a= Alert.new(:source => "test-host", + :alert_id => "test" ) + + a.raise! + end + + def test_alert_reception + Server.instance.setup + + update = Proto::AlertUpdate.new + update.source = "test-host" + message = Proto::Alert.new + update.alert << message + message.id = "test1" + message.summary = "test summary" + message.detail = "test detail" + message.raise_time = Time.now.to_i + message.clear_time = Time.now.to_i+5.minutes + + Alert.receive_update(update, Time.now, "127.0.0.1") + + a = Alert.first(:alert_id => 'test1') + + assert(a.raised?) + assert_equal("test-host", a.subject) + assert_equal("test-host", a.source) + assert_equal("test detail", a.detail) + assert_equal("test summary", a.summary) + + end + + def test_alert_ackowledgement + person = Mauve::Person.new + person.username = "test-user" + + Server.instance.setup + + Mauve::Configuration.current.people[person.username] = person + + alert = Alert.new( + :alert_id => "test-acknowledge", + :source => "test", + :subject => "test" + ) + alert.raise! + assert(alert.raised?) + + alert.acknowledge!(person, Time.now + 3.minutes) + assert(alert.acknowledged?) + + next_alert = Alert.find_next_with_event + assert_equal(next_alert.id, alert.id) + assert_equal(Time.now+3.minutes, next_alert.due_at) + + Timecop.freeze(next_alert.due_at) + + alert.poll + + # + # The alert should unacknowledge itself. + # + assert(!alert.acknowledged?) + + + end + end diff --git a/test/tc_mauve_alert_changed.rb b/test/tc_mauve_alert_changed.rb new file mode 100644 index 0000000..52f1f25 --- /dev/null +++ b/test/tc_mauve_alert_changed.rb @@ -0,0 +1,76 @@ +$:.unshift "../lib" + +require 'mauve/alert' +require 'mauve/alert_changed' +require 'mauve/configuration' +require 'mauve/configuration_builder' +require 'mauve/configuration_builders' +require 'th_mauve' + +class TcMauveAlertChanged < Mauve::UnitTest + include Mauve + + def setup + super + setup_database + end + + def teardown + teardown_database + super + end + + def test_reminder + + config=<<EOF +server { + database "sqlite::memory:" +} + +person("test_person") { + all { true } +} + +alert_group("test_group") { + + notify("test_person") { + every 5.minutes + } + +} +EOF + + Mauve::Configuration.current = Mauve::ConfigurationBuilder.parse(config) + + Server.instance.setup + + alert = Mauve::Alert.new(:source => "test", :alert_id => "test_alert", :summary => "test alert") + alert.raise! + + reminders = 1 + notifications = 1 + + mins = 0 + 121.times do + mins += 1 + + assert_equal(notifications, Server.instance.notification_buffer.length) + assert_equal(reminders, AlertChanged.count) + + Timecop.freeze(Time.now+1.minutes) + + if mins % 5 == 0 + notifications += 1 + reminders += 1 + end + + AlertChanged.all.each{|ac| ac.poll} + end + + end + + +end + + + diff --git a/test/tc_mauve_alert_group.rb b/test/tc_mauve_alert_group.rb index 12f25ef..d6416a2 100644 --- a/test/tc_mauve_alert_group.rb +++ b/test/tc_mauve_alert_group.rb @@ -1,11 +1,11 @@ $:.unshift "../lib" -require 'test/unit' +require 'th_mauve' require 'mauve/alert_group' require 'th_mauve_resolv' require 'pp' -class TcMauveAlert < Test::Unit::TestCase +class TcMauveAlert < Mauve::UnitTest def test_matches_alert diff --git a/test/tc_mauve_configuration_builder.rb b/test/tc_mauve_configuration_builder.rb index 03b86ca..faa0bfa 100644 --- a/test/tc_mauve_configuration_builder.rb +++ b/test/tc_mauve_configuration_builder.rb @@ -1,13 +1,16 @@ $:.unshift "../lib/" -require 'test/unit' -require 'pp' +require 'th_mauve' require 'mauve/configuration_builder' -class TcMauveConfigurationBuildersPeopleAndSourceLists < Test::Unit::TestCase +class TcMauveConfigurationBuildersPeopleAndSourceLists < Mauve::UnitTest def setup - Log4r::Logger.new("Mauve").outputters = Log4r::Outputter.stdout + setup_logger + end + + def teardown + teardown_logger end def test_people_list @@ -48,7 +51,16 @@ people_list "htc-highroad", EOF x = nil + # + # This should generate two warnings: + # * duplicate list + # * Lars already being on a list + # assert_nothing_raised { x = Mauve::ConfigurationBuilder.parse(config) } + + assert_match(/Lars/, logger_pop()) + assert_match(/Duplicate/, logger_pop()) + assert_equal(1, x.people_lists.keys.length) assert_equal(["mark c","mark r","Lars","Bernie","Danny"].sort, x.people_lists["htc-highroad"].list.sort) end diff --git a/test/tc_mauve_configuration_builders_alert_group.rb b/test/tc_mauve_configuration_builders_alert_group.rb index a4104bb..77d16b5 100644 --- a/test/tc_mauve_configuration_builders_alert_group.rb +++ b/test/tc_mauve_configuration_builders_alert_group.rb @@ -1,10 +1,10 @@ $:.unshift "../lib/" -require 'test/unit' +require 'th_mauve' require 'pp' require 'mauve/configuration_builders/alert_group' -class TcMauveConfigurationBuildersNotificationMethod < Test::Unit::TestCase +class TcMauveConfigurationBuildersNotificationMethod < Mauve::UnitTest def test_load diff --git a/test/tc_mauve_configuration_builders_logger.rb b/test/tc_mauve_configuration_builders_logger.rb index 8a4bc4e..2d2bb80 100644 --- a/test/tc_mauve_configuration_builders_logger.rb +++ b/test/tc_mauve_configuration_builders_logger.rb @@ -1,10 +1,12 @@ $:.unshift "../lib/" -require 'test/unit' -require 'pp' +require 'th_mauve' require 'mauve/configuration_builders/logger' -class TcMauveConfigurationBuildersLogger < Test::Unit::TestCase +class TcMauveConfigurationBuildersLogger < Mauve::UnitTest + + def setup + end def test_load diff --git a/test/tc_mauve_configuration_builders_notification_method.rb b/test/tc_mauve_configuration_builders_notification_method.rb index 1ea1e08..e5e8475 100644 --- a/test/tc_mauve_configuration_builders_notification_method.rb +++ b/test/tc_mauve_configuration_builders_notification_method.rb @@ -1,10 +1,10 @@ $:.unshift "../lib/" -require 'test/unit' +require 'th_mauve' require 'pp' require 'mauve/configuration_builders/notification_method' -class TcMauveConfigurationBuildersNotificationMethod < Test::Unit::TestCase +class TcMauveConfigurationBuildersNotificationMethod < Mauve::UnitTest def test_load diff --git a/test/tc_mauve_configuration_builders_person.rb b/test/tc_mauve_configuration_builders_person.rb index cb0b100..b4fbd4f 100644 --- a/test/tc_mauve_configuration_builders_person.rb +++ b/test/tc_mauve_configuration_builders_person.rb @@ -1,10 +1,10 @@ $:.unshift "../lib/" -require 'test/unit' +require 'th_mauve' require 'pp' require 'mauve/configuration_builders/person' -class TcMauveConfigurationBuildersNotificationMethod < Test::Unit::TestCase +class TcMauveConfigurationBuildersNotificationMethod < Mauve::UnitTest def test_load diff --git a/test/tc_mauve_configuration_builders_server.rb b/test/tc_mauve_configuration_builders_server.rb index 6f4255f..213ff68 100644 --- a/test/tc_mauve_configuration_builders_server.rb +++ b/test/tc_mauve_configuration_builders_server.rb @@ -1,9 +1,9 @@ $:.unshift "../lib/" -require 'test/unit' +require 'th_mauve' require 'mauve/configuration_builders/server' -class TcMauveConfigurationBuildersServer < Test::Unit::TestCase +class TcMauveConfigurationBuildersServer < Mauve::UnitTest def test_server_params hostname = "test.example.com" diff --git a/test/tc_mauve_notification.rb b/test/tc_mauve_notification.rb index 03e6b96..435d5da 100644 --- a/test/tc_mauve_notification.rb +++ b/test/tc_mauve_notification.rb @@ -1,28 +1,34 @@ $:.unshift "../lib" -require 'test/unit' +require 'th_mauve' require 'mauve/alert' require 'mauve/notification' require 'mauve/configuration' require 'mauve/configuration_builder' require 'mauve/configuration_builders' require 'mauve/mauve_time' -require 'th_mauve_resolv' -require 'th_mauve_time' -require 'th_logger' -require 'pp' +class TcMauveDuringRunner < Mauve::UnitTest + include Mauve -class TcMauveDuringRunner < Test::Unit::TestCase + def setup + super + setup_database + end + + def teardown + teardown_database + super + end def test_initialize - alert = Mauve::Alert.new + alert = Alert.new time = Time.now during = Proc.new { false } - dr = Mauve::DuringRunner.new(time, alert, &during) + dr = DuringRunner.new(time, alert, &during) assert_equal(dr.alert, alert) assert_equal(dr.time, time) @@ -31,11 +37,12 @@ class TcMauveDuringRunner < Test::Unit::TestCase end def test_now? - alert = Mauve::Alert.new + alert = Alert.new time = Time.now during = Proc.new { @test_time } - dr = Mauve::DuringRunner.new(time, alert, &during) + dr = DuringRunner.new(time, alert, &during) + assert_equal(time, dr.now?) assert_equal(time+3600, dr.now?(time+3600)) assert_equal(time, dr.time) @@ -57,36 +64,37 @@ class TcMauveDuringRunner < Test::Unit::TestCase # This should give us midnight last sunday night. # now = Time.now - midnight_sunday = now - (now.hour.hours + now.min.minutes + now.sec.seconds + now.wday.days) # # first working hour on Monday - monday_morning = midnight_sunday.in_x_hours(0,"working") + workday_morning = now.in_x_hours(0,"working") + + assert(workday_morning != now, "booo") # # This should alert at exactly first thing on Monday morning. # - dr = Mauve::DuringRunner.new(midnight_sunday, nil){ working_hours? } - assert_equal(dr.find_next(6.hours), monday_morning) + dr = DuringRunner.new(now, nil){ working_hours? } + assert_equal(dr.find_next(6.hours), workday_morning) # # This should alert six hours later than the last one. # - dr = Mauve::DuringRunner.new(monday_morning, nil){ working_hours? } - assert_equal(dr.find_next(6.hours), monday_morning + 6.hours) + dr = DuringRunner.new(workday_morning, nil){ working_hours? } + assert_equal(dr.find_next(6.hours), workday_morning + 6.hours) # # Now assuming the working day is not 12 hours long, if we progress to 6 # hours in the future then the next alert should be first thing on Tuesday. # - dr = Mauve::DuringRunner.new(monday_morning + 6.hours, nil){ working_hours? } - tuesday_morning = monday_morning+24.hours + dr = DuringRunner.new(workday_morning + 6.hours, nil){ working_hours? } + tuesday_morning = workday_morning+24.hours assert_equal(dr.find_next(6.hours), tuesday_morning) # # If an alert is too far in the future (a week) return nil. # - dr = Mauve::DuringRunner.new(monday_morning, nil){ @test_time > (@time + 12.days) } + dr = DuringRunner.new(workday_morning, nil){ @test_time > (@time + 12.days) } assert_nil(dr.find_next) end @@ -101,7 +109,20 @@ class TcMauveDuringRunner < Test::Unit::TestCase end -class TcMauveNotification < Test::Unit::TestCase +class TcMauveNotification < Mauve::UnitTest + + include Mauve + + def setup + @logger = setup_logger + Timecop.freeze(Time.local(2011,8,1,0,0,0,0)) + end + + def teardown + teardown_logger + Timecop.return + DataObjects::Pooling.pools.each{|pool| pool.dispose} + end def test_notify t = Time.now @@ -141,7 +162,7 @@ alert_group("default") { } notify("test2") { - during { @test_time.to_i >= #{(t + 1.hour).to_i} } + during { hours_in_day 1..23 } every 10.minutes } @@ -153,19 +174,28 @@ alert_group("default") { } EOF - - assert_nothing_raised { - Mauve::Configuration.current = Mauve::ConfigurationBuilder.parse(config) - Mauve::Server.instance.setup - alert = Mauve::Alert.new( - :alert_id => "test", - :source => "test", - :subject => "test" - ) - alert.raise! - } + Configuration.current = ConfigurationBuilder.parse(config) + Server.instance.setup + alert = Alert.new( + :alert_id => "test", + :source => "test", + :subject => "test" + ) + alert.raise! + + assert_equal(1, Alert.count, "Wrong number of alerts saved") - assert_equal(1, Mauve::Alert.count) + # + # Although there are four clauses above for notifications, test1 should be + # alerted in 10 minutes time, and the 15 minutes clause is ignored, since + # 10 minutes is sooner. + # + assert_equal(3, AlertChanged.count, "Wrong number of reminders inserted") + + # + # Also make sure that only 1 notification has been sent.. + # + assert_equal(1, Server.instance.notification_buffer.size, "Wrong number of notifications sent") reminder_times = { "test1" => t + 10.minutes, @@ -173,12 +203,12 @@ EOF "test3" => t + 2.hours } - Mauve::AlertChanged.all.each do |a| - pp a - assert_equal("urgent", a.level, "Level is wrong") - assert_equal("raised", a.update_type, "Update type is wrong") - assert_in_delta(reminder_times[a.person].to_f, a.remind_at.to_time.to_f, 10.0, "reminder time is wrong for #{a.person}") + AlertChanged.all.each do |a| + assert_equal("urgent", a.level, "Level is wrong for #{a.person}") + assert_equal("raised", a.update_type, "Update type is wrong for #{a.person}") + assert_equal(reminder_times[a.person], a.remind_at,"reminder time is wrong for #{a.person}") end + end end diff --git a/test/tc_mauve_person.rb b/test/tc_mauve_person.rb new file mode 100644 index 0000000..8ac3141 --- /dev/null +++ b/test/tc_mauve_person.rb @@ -0,0 +1,17 @@ +$:.unshift "../lib" + +require 'th_mauve' +require 'mauve/person' +require 'mauve/configuration' +require 'mauve/configuration_builder' +require 'mauve/configuration_builders' +require 'pp' + +class TcMauvePerson < Mauve::UnitTest + + + +end + + + diff --git a/test/tc_mauve_source_list.rb b/test/tc_mauve_source_list.rb index d07791f..bc68094 100644 --- a/test/tc_mauve_source_list.rb +++ b/test/tc_mauve_source_list.rb @@ -1,11 +1,11 @@ $:.unshift "../lib/" -require 'test/unit' +require 'th_mauve' require 'mauve/source_list' require 'th_mauve_resolv' require 'pp' -class TcMauveSourceList < Test::Unit::TestCase +class TcMauveSourceList < Mauve::UnitTest def test_hostname_match sl = Mauve::SourceList.new("test") diff --git a/test/tc_mauve_time.rb b/test/tc_mauve_time.rb index 0749fef..7a8fefa 100644 --- a/test/tc_mauve_time.rb +++ b/test/tc_mauve_time.rb @@ -1,10 +1,10 @@ $: << "../lib/" -require 'test/unit' +require 'th_mauve' require 'mauve/mauve_time' require 'pp' -class TestMauveTime < Test::Unit::TestCase +class TestMauveTime < Mauve::UnitTest def test_in_x_hours diff --git a/test/test_mauve.rb b/test/test_mauve.rb index a8dba9b..87aa188 100644 --- a/test/test_mauve.rb +++ b/test/test_mauve.rb @@ -4,6 +4,7 @@ $:.unshift libdir if File.directory?(libdir) end +require 'pp' require 'test/unit' %w( @@ -15,8 +16,10 @@ tc_mauve_configuration_builders_person.rb tc_mauve_configuration_builders_server.rb tc_mauve_source_list.rb tc_mauve_people_list.rb +tc_mauve_person.rb tc_mauve_alert.rb tc_mauve_alert_group.rb +tc_mauve_alert_changed.rb tc_mauve_notification.rb tc_mauve_time.rb ).each do |s| diff --git a/test/th_mauve.rb b/test/th_mauve.rb new file mode 100644 index 0000000..a113ad0 --- /dev/null +++ b/test/th_mauve.rb @@ -0,0 +1,91 @@ +require 'test/unit' +require 'mauve/datamapper' +require 'timecop' +require 'log4r' +require 'pp' + +module Mauve + class TestOutputter < Log4r::Outputter + def initialize( _name, hash={}) + @buffer = [] + super + end + + def pop ; @buffer.pop ; end + def shift ; @buffer.shift ; end + + def write(data) + @buffer << data + end + + def flush + print "\n" if @buffer.length > 0 + while d = @buffer.shift + print d + end + end + + end +end + + +module Mauve + class UnitTest < Test::Unit::TestCase + + def setup + setup_logger + setup_time + end + + def teardown + teardown_logger + teardown_time + end + + def setup_logger + @logger = Log4r::Logger.new 'Mauve' + @outputter = Mauve::TestOutputter.new("test") + @outputter.formatter = Log4r::PatternFormatter.new( :pattern => "%d %l %m" ) + @outputter.level = Log4r::DEBUG + @logger.outputters << @outputter + return @logger + end + + def logger_pop + @outputter.pop + end + + def teardown_logger + logger = Log4r::Logger['Mauve'] + return if logger.nil? + + o = logger.outputters.find{|o| o.name == "test"} + o.flush if o.respond_to?("flush") + # Delete the logger. + Log4r::Logger::Repository.instance.loggers.delete('Mauve') + end + + def setup_database + DataMapper::Model.raise_on_save_failure = true + end + + def teardown_database + DataObjects::Pooling.pools.each{|pool| pool.dispose} + end + + def setup_time + Timecop.freeze(Time.local(2011,8,1,0,0,0,0)) + end + + def teardown_time + Timecop.return + end + + def default_test + # + # + flunk("No tests specified") unless self.class == Mauve::UnitTest + end + + end +end |