Sam Roberts
1/31/2005 2:32:00 AM
Hi Tanaka,
I don't understand why DNS::Name#== requires both to be absolute if one
is.
Is this really necessary/useful? It surprises me.
Also, I have a set of comparison operations for Resolv::DNS::Name.
I copied the style (and docs) from Module/hierarchy comparisons, because
I think there is some similarity.
Comments?
If you will accept, I will send patch and changelog.
Thanks,
Sam
Below is implementation, followed by unit test so you can see behaviour.
# DNS names are hierarchical in a similar sense to ruby classes/modules, and the
# comparison operators are defined similarly to those of Module. A name is
# +<+ another if it is a subdomain.
# www.example.com < example.com # -> true
# example.com < example.com # -> false
# example.com <= example.com # -> true
# com < example.com # -> false
# bar.com < example.com # -> nil
#
# Note that #== does not consider two names equal if they differ in whether
# they are #absolute?, but #equal? considers only the label when comparing
# names.
class Name
def inspect
n = to_s
n << '.' if absolute?
return n
end
def equal?(name)
n = Name.create(name)
@labels == n.to_a
end
def related?(name)
n = Name.create(name)
l = length < n.length ? length : n.length
@labels[-l, l] == n.to_a[-l, l]
end
def lt?(name)
n = Name.create(name)
length > n.length && to_a[-n.length, n.length] == n.to_a
end
# Summary:
# name < other => true, false, or nil
#
# Returns true if +name+ is a subdomain of +other+. Returns
# <code>nil</code> if there's no relationship between the two.
def <(name)
n = Name.create(name)
return nil unless self.related?(n)
lt?(n)
end
# Summary:
# name > other => true, false, or nil
#
# Same as +other < name+, see #<.
def >(name)
n = Name.create(name)
n < self
end
# Summary:
# name <= other => true, false, or nil
#
# Returns true if +name+ is a subdomain of +other+ or is the same as
# +other+. Returns <code>nil</code> if there's no relationship between
# the two.
def <=(name)
n = Name.create(name)
self.equal?(n) || self < n
end
# Summary:
# name >= other => true, false, or nil
#
# Returns true if +name+ is an ancestor of +other+, or the two DNS names
# are the same. Returns <code>nil</code> if there's no relationship
# between the two.
def >=(name)
n = Name.create(name)
self.equal?(n) || self > n
end
# Summary:
# name <=> other => -1, 0, +1, nil
#
# Returns -1 if +name+ is a subdomain of +other+, 0 if
# +name+ is the same as +other+, and +1 if +other+ is a subdomain of
# +name+, or nil if +name+ has no relationship with +other+.
def <=>(name)
n = Name.create(name)
return nil unless self.related?(n)
return -1 if self.lt?(n)
return +1 if n.lt?(self)
# must be #equal?
return 0
end
end
require 'test/unit'
Name = Resolv::DNS::Name
class TestDnsName < Test::Unit::TestCase
def test_what_I_think_are_odd_behaviours
# Why can't test against strings?
assert_equal(false, Name.create("example.CoM") == "example.com")
assert_equal(false, Name.create("example.CoM").eql?("example.com"))
# Why does making it absolute mean they aren't equal?
assert_equal(false, Name.create("example.CoM").eql?(Name.create("example.com.")))
assert_equal(false, Name.create("example.CoM") == Name.create("example.com."))
end
def test_CoMparisons
assert_equal(true, Name.create("example.CoM").eql?(Name.create("example.com")))
assert_equal(true, Name.create("example.CoM") == Name.create("example.com"))
assert_equal(true, Name.create("example.CoM").equal?("example.com."))
assert_equal(true, Name.create("example.CoM").equal?("example.com"))
assert_equal(true, Name.create("www.example.CoM") < "example.com")
assert_equal(true, Name.create("www.example.CoM") <= "example.com")
assert_equal(-1, Name.create("www.example.CoM") <=> "example.com")
assert_equal(false, Name.create("www.example.CoM") >= "example.com")
assert_equal(false, Name.create("www.example.CoM") > "example.com")
assert_equal(false, Name.create("example.CoM") < "example.com")
assert_equal(true, Name.create("example.CoM") <= "example.com")
assert_equal(0, Name.create("example.CoM") <=> "example.com")
assert_equal(true, Name.create("example.CoM") >= "example.com")
assert_equal(false, Name.create("example.CoM") > "example.com")
assert_equal(false, Name.create("CoM") < "example.com")
assert_equal(false, Name.create("CoM") <= "example.com")
assert_equal(+1, Name.create("CoM") <=> "example.com")
assert_equal(true, Name.create("CoM") >= "example.com")
assert_equal(true, Name.create("CoM") > "example.com")
assert_equal(nil, Name.create("bar.CoM") < "example.com")
assert_equal(nil, Name.create("bar.CoM") <= "example.com")
assert_equal(nil, Name.create("bar.CoM") <=> "example.com")
assert_equal(nil, Name.create("bar.CoM") >= "example.com")
assert_equal(nil, Name.create("bar.CoM") > "example.com")
assert_equal(nil, Name.create("net.") < "com")
assert_equal(nil, Name.create("net.") <= "com")
assert_equal(nil, Name.create("net.") <=> "com")
assert_equal(nil, Name.create("net.") >= "com")
assert_equal(nil, Name.create("net.") > "com")
end
end