aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Young <alex@bytemark.co.uk>2015-02-24 11:34:38 +0000
committerAlex Young <alex@bytemark.co.uk>2015-02-24 11:34:38 +0000
commitc12e2c8f65a59a075ad20424a03d137a62db7e48 (patch)
treecea2ad83471c161aa099a8279ef60f7a04a83d92
parent16ba9f08109ddb911e9aba8518a93d3df710a46b (diff)
Add some basic UDPServer tests.
-rw-r--r--lib/mauve/sender.rb23
-rw-r--r--lib/mauve/udp_server.rb23
-rw-r--r--test/tc_mauve_udp_server.rb54
3 files changed, 81 insertions, 19 deletions
diff --git a/lib/mauve/sender.rb b/lib/mauve/sender.rb
index c54cb0b..fe22471 100644
--- a/lib/mauve/sender.rb
+++ b/lib/mauve/sender.rb
@@ -53,17 +53,17 @@ module Mauve
#
def initialize(*destinations)
destinations = destinations.flatten
-
+
destinations = begin
File.read("/etc/mauvealert/mauvesend.destination").split(/\s+/)
rescue Errno::ENOENT => notfound
[]
end if destinations.empty?
-
+
if !destinations || destinations.empty?
raise ArgumentError.new("No destinations specified, and could not read any destinations from /etc/mauvealert/mauvesend.destination")
end
-
+
#
# Resolv results
#
@@ -105,7 +105,7 @@ module Mauve
# domain is an underscore, assume that it is a SRV record
#
srv_domain = (domain[0] == ?_ ? domain : "_mauvealert._udp.#{domain}")
-
+
list += dns.getresources(srv_domain, SRV).map do |srv|
[srv.target.to_s, srv.port]
end
@@ -144,14 +144,21 @@ module Mauve
# Sanitise all fields in an update, such that when we send, they are
# normal.
- #
+ #
#
def sanitize(update)
#
- # Must have a source, so default to hostname if user doesn't care
+ # Must have a source, so default to hostname if user doesn't care
update.source ||= Socket.gethostname
#
+ # Must have a `replace`. We supply a default, but it doesn't
+ # get used so if we want to use Sender outside of bin/mauvesend,
+ # we have to manually add it here with an explicit `false`.
+ # `nil` doesn't work.
+ update.replace ||= false
+
+ #
# Check the locale charset. This is to maximise the amout of information
# mauve receives, rather than provide proper sanitized data for the server.
#
@@ -159,7 +166,7 @@ module Mauve
from_charset ||= "UTF-8"
#
- #
+ #
#
update.each_field do |field, value|
#
@@ -171,7 +178,7 @@ module Mauve
elsif defined? Iconv
value = Iconv.conv("UTF-8//IGNORE", from_charset, value)
end
-
+
update.__send__("#{field.name}=", value)
end
diff --git a/lib/mauve/udp_server.rb b/lib/mauve/udp_server.rb
index 9dafdd0..09afa01 100644
--- a/lib/mauve/udp_server.rb
+++ b/lib/mauve/udp_server.rb
@@ -4,6 +4,7 @@ require 'socket'
require 'mauve/datamapper'
require 'mauve/proto'
require 'mauve/alert'
+require 'mauve/mauve_thread'
require 'ipaddr'
module Mauve
@@ -33,18 +34,18 @@ module Mauve
super
end
-
+
#
# This sets the IP which the server will listen on.
- #
- # @param [String] i The new IP
+ #
+ # @param [String] i The new IP
# @return [IPAddr]
#
def ip=(i)
raise ArgumentError, "ip must be a string" unless i.is_a?(String)
@ip = IPAddr.new(i)
end
-
+
# Sets the listening port
#
# @param [Integer] pr The new port
@@ -54,7 +55,7 @@ module Mauve
raise ArgumentError, "port must be an integer between 0 and #{2**16-1}" unless pr.is_a?(Integer) and pr < 2**16 and pr > 0
@port = pr
end
-
+
# This stops the UDP server, by signalling to the thread to stop, and
# sending a zero-length packet to the socket.
#
@@ -83,14 +84,14 @@ module Mauve
# Specify the family when opening the socket.
#
@socket = UDPSocket.new(@ip.family)
-
+
logger.debug("Trying to increase Socket::SO_RCVBUF to 10M.")
old = @socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_RCVBUF).unpack("i").first
@socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVBUF, 10*1024*1024)
new = @socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_RCVBUF).unpack("i").first
- logger.warn "Could not increase Socket::SO_RCVBUF. Had #{old} ended up with #{new}!" if old > new
+ logger.warn "Could not increase Socket::SO_RCVBUF. Had #{old} ended up with #{new}!" if old > new
logger.debug("Successfully increased Socket::SO_RCVBUF from #{old} to #{new}.")
@@ -105,9 +106,9 @@ module Mauve
return if @socket.nil? or @socket.closed?
begin
- @socket.close
+ @socket.close
rescue IOError => ex
- # Just in case there is some sort of explosion!
+ # Just in case there is some sort of explosion!
logger.error "Caught IOError #{ex.to_s}"
logger.debug ex.backtrace.join("\n")
end
@@ -127,7 +128,7 @@ module Mauve
open_socket if @socket.nil? or @socket.closed?
- return if self.should_stop?
+ return if self.should_stop?
#
# TODO: why is/isn't this non-block?
@@ -150,7 +151,7 @@ module Mauve
# If we get a zero length packet, and we've been flagged to stop, we stop!
#
if packet.first.length == 0 and self.should_stop?
- close_socket
+ close_socket
return
end
diff --git a/test/tc_mauve_udp_server.rb b/test/tc_mauve_udp_server.rb
new file mode 100644
index 0000000..9a82de8
--- /dev/null
+++ b/test/tc_mauve_udp_server.rb
@@ -0,0 +1,54 @@
+# encoding: utf-8
+
+$:.unshift "../lib"
+
+require 'th_mauve'
+require 'th_mauve_resolv'
+require 'mauve/udp_server'
+require 'mauve/server'
+
+class TcMauveUdpServer < Mauve::UnitTest
+ # Note: this test fires up the UDP socket. It *will* fail if more
+ # than one instance runs at the same time on the same machine.
+ include Mauve
+
+ def setup
+ super
+ Server.instance.packet_buffer.clear # blarg!
+ @server = UDPServer.instance # blarg!
+ end
+
+ def test_listens
+ update = generic_update()
+ t = Thread.new do @server.__send__(:main_loop) end
+ sleep(0.2)
+ sender.send(update)
+ Timeout.timeout(2) do t.join end
+ assert_equal update, Proto::AlertUpdate.new.parse_from_string(Server.packet_pop[0])
+ end
+
+ def test_closes
+ update = generic_update()
+ t = @server.run
+ sleep(0.2)
+ @server.stop
+ sleep(0.2)
+ sender.send(update)
+ Timeout.timeout(2) do t.join end
+ assert_nil Server.packet_pop
+ end
+
+
+ def sender
+ Sender.new(["#{@server.ip}:#{@server.port}"])
+ end
+
+ def generic_update
+ update = Proto::AlertUpdate.new
+ alert = Proto::Alert.new
+ alert.id = "alertid"
+ update.alert << alert
+ update
+ end
+
+end