From c12e2c8f65a59a075ad20424a03d137a62db7e48 Mon Sep 17 00:00:00 2001 From: Alex Young Date: Tue, 24 Feb 2015 11:34:38 +0000 Subject: Add some basic UDPServer tests. --- lib/mauve/sender.rb | 23 ++++++++++++------- lib/mauve/udp_server.rb | 23 ++++++++++--------- test/tc_mauve_udp_server.rb | 54 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 19 deletions(-) create mode 100644 test/tc_mauve_udp_server.rb 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,13 +144,20 @@ 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 -- cgit v1.2.1