diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..55acae1 --- /dev/null +++ b/Rakefile @@ -0,0 +1,6 @@ +ROOT = File.dirname(__FILE__) + +task :test do + $:.unshift File.join(ROOT, "lib") + $:.unshift File.join(ROOT, "test") +end diff --git a/test/LICENSE-contest b/test/LICENSE-contest new file mode 100644 index 0000000..9247f9e --- /dev/null +++ b/test/LICENSE-contest @@ -0,0 +1,19 @@ +Copyright (c) 2009 Damian Janowski and Michel Martens for Citrusbyte + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/test/contest.rb b/test/contest.rb new file mode 100644 index 0000000..f822d3b --- /dev/null +++ b/test/contest.rb @@ -0,0 +1,94 @@ +# Downloaded from https://github.com/citrusbyte/contest/ + +=begin +############################################################################ +Copyright (c) 2009 Damian Janowski and Michel Martens for Citrusbyte + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +############################################################################ +=end + +require "test/unit" + +# Test::Unit loads a default test if the suite is empty, whose purpose is to +# fail. Since having empty contexts is a common practice, we decided to +# overwrite TestSuite#empty? in order to allow them. Having a failure when no +# tests have been defined seems counter-intuitive. +class Test::Unit::TestSuite + def empty? + false + end +end + +# Contest adds +teardown+, +test+ and +context+ as class methods, and the +# instance methods +setup+ and +teardown+ now iterate on the corresponding +# blocks. Note that all setup and teardown blocks must be defined with the +# block syntax. Adding setup or teardown instance methods defeats the purpose +# of this library. +class Test::Unit::TestCase + def self.setup(&block) + define_method :setup do + super(&block) + instance_eval(&block) + end + end + + def self.teardown(&block) + define_method :teardown do + instance_eval(&block) + super(&block) + end + end + + def self.context(*name, &block) + subclass = Class.new(self) + remove_tests(subclass) + subclass.class_eval(&block) if block_given? + const_set(context_name(name.join(" ")), subclass) + end + + def self.test(name, &block) + define_method(test_name(name), &block) + end + + class << self + alias_method :should, :test + alias_method :describe, :context + end + +private + + def self.context_name(name) + "Test#{sanitize_name(name).gsub(/(^| )(\w)/) { $2.upcase }}".to_sym + end + + def self.test_name(name) + "test_#{sanitize_name(name).gsub(/\s+/,'_')}".to_sym + end + + def self.sanitize_name(name) + name.gsub(/\W+/, ' ').strip + end + + def self.remove_tests(subclass) + subclass.public_instance_methods.grep(/^test_/).each do |meth| + subclass.send(:undef_method, meth.to_sym) + end + end +end diff --git a/test/t_route.rb b/test/t_route.rb new file mode 100644 index 0000000..4196762 --- /dev/null +++ b/test/t_route.rb @@ -0,0 +1,127 @@ +require File.join(File.dirname(__FILE__), 'test_helper') +require 'linux/netlink/route' + +# Note: multiple sockets bound to the same PID seem to cause timeout problems. +# (Should we use different algorithm for generating the PID? PID + seq?) +$ip ||= Linux::Netlink::Route::Socket.new + +class TestAddr < Test::Unit::TestCase + context "With netlink route socket" do + setup do + @ip = $ip + end + + test "Read link type" do + assert_equal Linux::ARPHRD_LOOPBACK, @ip.link["lo"].type + end + + def addrlist(opt = {:index=>"lo"}) + res = @ip.addr.list(opt).map { |x| x.address.to_s }.sort + end + + def add_and_remove_addr(testaddr, pfx) + begin + @ip.addr.delete(:index=>"lo", :local=>testaddr, :prefixlen=>pfx) + rescue Errno::EADDRNOTAVAIL + end + + addrs1 = addrlist + assert !addrs1.include?(testaddr) + + @ip.addr.add(:index=>"lo", :local=>testaddr, :prefixlen=>pfx) + assert_raises(Errno::EEXIST) { + @ip.addr.add(:index=>"lo", :local=>testaddr, :prefixlen=>pfx) + } + + addrs2 = addrlist + assert addrs2.include?(testaddr), "#{addrs2.inspect} doesn't include #{testaddr}" + + @ip.addr.delete(:index=>"lo", :local=>testaddr, :prefixlen=>pfx) + + addrs3 = addrlist + assert_equal addrs1, addrs3 + end + + test "Read all addresses" do + a = addrlist + assert a.include?("127.0.0.1") + assert a.include?("::1") + end + + test "Read v4 addresses only" do + a = addrlist(:index=>"lo", :family=>Socket::AF_INET) + assert a.include?("127.0.0.1") + assert !a.include?("::1") + end + + test "Read v6 addresses only" do + a = addrlist(:index=>"lo", :family=>Socket::AF_INET6) + assert !a.include?("127.0.0.1") + assert a.include?("::1") + end + + test "Add and remove V4 address" do + add_and_remove_addr("1.2.3.4", 32) + end + + test "Add and remove V6 address" do + add_and_remove_addr("2001:dead:beef::1", 64) + end + + def vlanlist + @ip.vlan.list(:link=>"lo").map { |x| x.linkinfo.data.id } + end + + test "Add and remove vlan" do + begin + @ip.vlan.delete(:link=>"lo", :vlan_id=>1234) + rescue Errno::ENODEV + end + + vlans1 = vlanlist + assert !vlans1.include?(1234) + + @ip.vlan.add(:link=>"lo", :vlan_id=>1234) + + vlans2 = vlanlist + assert vlans2.include?(1234) + + @ip.vlan.delete(:link=>"lo", :vlan_id=>1234) + + vlans3 = vlanlist + assert_equal vlans1, vlans3 + end + + def routes + @ip.route.list(:table=>Linux::RT_TABLE_MAIN).map { |x| [x.dst.to_s, x.dst_len] } + end + + test "We have a V4 default route" do + # note that kernel doesn't send us rtattr dst 0.0.0.0, so it shows as nil + assert_equal [["",0]], routes.select { |x| x == ["",0] } + end + + def add_and_remove_route(info) + begin + @ip.route.delete(info) + rescue Errno::ESRCH + end + + assert_equal 0, routes.select { |x| x == [info[:dst], info[:dst_len]] }.size + + @ip.route.add(info) + assert_equal 1, routes.select { |x| x == [info[:dst], info[:dst_len]] }.size + + @ip.route.delete(info) + assert_equal 0, routes.select { |x| x == [info[:dst], info[:dst_len]] }.size + end + + test "Add and remove V4 route" do + add_and_remove_route(:oif=>"lo", :dst=>"1.2.3.4", :dst_len=>32, :gateway=>"127.0.0.1") + end + + test "Add and remove V6 route" do + add_and_remove_route(:oif=>"lo", :dst=>"2001:f000:baaa::", :dst_len=>64) + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000..ddb801b --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,6 @@ +ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')) +$:.unshift File.join(ROOT, "lib") +$:.unshift File.join(ROOT, "test") +require 'contest' +require 'test/unit' + \ No newline at end of file