aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick J Cherry <patrick@bytemark.co.uk>2011-08-17 11:08:07 +0100
committerPatrick J Cherry <patrick@bytemark.co.uk>2011-08-17 11:08:07 +0100
commit8c8e5ae926e0009743fe92dccb588783640a6022 (patch)
treee23eea583beac0caf5fb3e45a33b4d2ac7796abf
parent79dcf16ec6d229d6c31e055ed8e6a98327526a3a (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
-rw-r--r--lib/mauve/alert.rb9
-rw-r--r--lib/mauve/alert_changed.rb100
-rw-r--r--lib/mauve/alert_group.rb33
-rw-r--r--lib/mauve/mauve_thread.rb17
-rw-r--r--lib/mauve/notification.rb21
-rw-r--r--lib/mauve/notifier.rb3
-rw-r--r--lib/mauve/person.rb144
-rw-r--r--lib/mauve/pop3_server.rb2
-rw-r--r--lib/mauve/processor.rb8
-rw-r--r--lib/mauve/server.rb12
-rw-r--r--test/tc_mauve_alert.rb110
-rw-r--r--test/tc_mauve_alert_changed.rb76
-rw-r--r--test/tc_mauve_alert_group.rb4
-rw-r--r--test/tc_mauve_configuration_builder.rb20
-rw-r--r--test/tc_mauve_configuration_builders_alert_group.rb4
-rw-r--r--test/tc_mauve_configuration_builders_logger.rb8
-rw-r--r--test/tc_mauve_configuration_builders_notification_method.rb4
-rw-r--r--test/tc_mauve_configuration_builders_person.rb4
-rw-r--r--test/tc_mauve_configuration_builders_server.rb4
-rw-r--r--test/tc_mauve_notification.rb106
-rw-r--r--test/tc_mauve_person.rb17
-rw-r--r--test/tc_mauve_source_list.rb4
-rw-r--r--test/tc_mauve_time.rb4
-rw-r--r--test/test_mauve.rb3
-rw-r--r--test/th_mauve.rb91
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, &notification.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