PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/test/mri/resolv/test_dns.rb

http://github.com/jruby/jruby
Ruby | 218 lines | 198 code | 15 blank | 5 comment | 1 complexity | 74e0b7be41555aefd029a02b5fb9dda6 MD5 | raw file
Possible License(s): GPL-3.0, BSD-3-Clause, GPL-2.0, JSON, LGPL-2.1
  1. # frozen_string_literal: false
  2. require 'test/unit'
  3. require 'resolv'
  4. require 'socket'
  5. require 'tempfile'
  6. class TestResolvDNS < Test::Unit::TestCase
  7. def setup
  8. @save_do_not_reverse_lookup = BasicSocket.do_not_reverse_lookup
  9. BasicSocket.do_not_reverse_lookup = true
  10. end
  11. def teardown
  12. BasicSocket.do_not_reverse_lookup = @save_do_not_reverse_lookup
  13. end
  14. def with_udp(host, port)
  15. u = UDPSocket.new
  16. begin
  17. u.bind(host, port)
  18. yield u
  19. ensure
  20. u.close
  21. end
  22. end
  23. # [ruby-core:65836]
  24. def test_resolve_with_2_ndots
  25. conf = Resolv::DNS::Config.new :nameserver => ['127.0.0.1'], :ndots => 2
  26. assert conf.single?
  27. candidates = []
  28. conf.resolv('example.com') { |candidate, *args|
  29. candidates << candidate
  30. raise Resolv::DNS::Config::NXDomain
  31. }
  32. n = Resolv::DNS::Name.create 'example.com.'
  33. assert_equal n, candidates.last
  34. end
  35. def test_query_ipv4_address
  36. begin
  37. OpenSSL
  38. rescue LoadError
  39. skip 'autoload problem. see [ruby-dev:45021][Bug #5786]'
  40. end if defined?(OpenSSL)
  41. with_udp('127.0.0.1', 0) {|u|
  42. _, server_port, _, server_address = u.addr
  43. begin
  44. client_thread = Thread.new {
  45. Resolv::DNS.open(:nameserver_port => [[server_address, server_port]]) {|dns|
  46. dns.getresources("foo.example.org", Resolv::DNS::Resource::IN::A)
  47. }
  48. }
  49. server_thread = Thread.new {
  50. msg, (_, client_port, _, client_address) = Timeout.timeout(5) {u.recvfrom(4096)}
  51. id, word2, qdcount, ancount, nscount, arcount = msg.unpack("nnnnnn")
  52. qr = (word2 & 0x8000) >> 15
  53. opcode = (word2 & 0x7800) >> 11
  54. aa = (word2 & 0x0400) >> 10
  55. tc = (word2 & 0x0200) >> 9
  56. rd = (word2 & 0x0100) >> 8
  57. ra = (word2 & 0x0080) >> 7
  58. z = (word2 & 0x0070) >> 4
  59. rcode = word2 & 0x000f
  60. rest = msg[12..-1]
  61. assert_equal(0, qr) # 0:query 1:response
  62. assert_equal(0, opcode) # 0:QUERY 1:IQUERY 2:STATUS
  63. assert_equal(0, aa) # Authoritative Answer
  64. assert_equal(0, tc) # TrunCation
  65. assert_equal(1, rd) # Recursion Desired
  66. assert_equal(0, ra) # Recursion Available
  67. assert_equal(0, z) # Reserved for future use
  68. assert_equal(0, rcode) # 0:No-error 1:Format-error 2:Server-failure 3:Name-Error 4:Not-Implemented 5:Refused
  69. assert_equal(1, qdcount) # number of entries in the question section.
  70. assert_equal(0, ancount) # number of entries in the answer section.
  71. assert_equal(0, nscount) # number of entries in the authority records section.
  72. assert_equal(0, arcount) # number of entries in the additional records section.
  73. name = [3, "foo", 7, "example", 3, "org", 0].pack("Ca*Ca*Ca*C")
  74. assert_operator(rest, :start_with?, name)
  75. rest = rest[name.length..-1]
  76. assert_equal(4, rest.length)
  77. qtype, _ = rest.unpack("nn")
  78. assert_equal(1, qtype) # A
  79. assert_equal(1, qtype) # IN
  80. id = id
  81. qr = 1
  82. opcode = opcode
  83. aa = 0
  84. tc = 0
  85. rd = rd
  86. ra = 1
  87. z = 0
  88. rcode = 0
  89. qdcount = 0
  90. ancount = 1
  91. nscount = 0
  92. arcount = 0
  93. word2 = (qr << 15) |
  94. (opcode << 11) |
  95. (aa << 10) |
  96. (tc << 9) |
  97. (rd << 8) |
  98. (ra << 7) |
  99. (z << 4) |
  100. rcode
  101. msg = [id, word2, qdcount, ancount, nscount, arcount].pack("nnnnnn")
  102. type = 1
  103. klass = 1
  104. ttl = 3600
  105. rdlength = 4
  106. rdata = [192,0,2,1].pack("CCCC") # 192.0.2.1 (TEST-NET address) RFC 3330
  107. rr = [name, type, klass, ttl, rdlength, rdata].pack("a*nnNna*")
  108. msg << rr
  109. u.send(msg, 0, client_address, client_port)
  110. }
  111. result, _ = assert_join_threads([client_thread, server_thread])
  112. assert_instance_of(Array, result)
  113. assert_equal(1, result.length)
  114. rr = result[0]
  115. assert_instance_of(Resolv::DNS::Resource::IN::A, rr)
  116. assert_instance_of(Resolv::IPv4, rr.address)
  117. assert_equal("192.0.2.1", rr.address.to_s)
  118. assert_equal(3600, rr.ttl)
  119. end
  120. }
  121. end
  122. def test_query_ipv4_address_timeout
  123. with_udp('127.0.0.1', 0) {|u|
  124. _, port , _, host = u.addr
  125. start = nil
  126. rv = Resolv::DNS.open(:nameserver_port => [[host, port]]) {|dns|
  127. dns.timeouts = 0.1
  128. start = Time.now
  129. dns.getresources("foo.example.org", Resolv::DNS::Resource::IN::A)
  130. }
  131. t2 = Time.now
  132. diff = t2 - start
  133. assert rv.empty?, "unexpected: #{rv.inspect} (expected empty)"
  134. assert_operator 0.1, :<=, diff
  135. rv = Resolv::DNS.open(:nameserver_port => [[host, port]]) {|dns|
  136. dns.timeouts = [ 0.1, 0.2 ]
  137. start = Time.now
  138. dns.getresources("foo.example.org", Resolv::DNS::Resource::IN::A)
  139. }
  140. t2 = Time.now
  141. diff = t2 - start
  142. assert rv.empty?, "unexpected: #{rv.inspect} (expected empty)"
  143. assert_operator 0.3, :<=, diff
  144. }
  145. end
  146. def test_no_server
  147. u = UDPSocket.new
  148. u.bind("127.0.0.1", 0)
  149. _, port, _, host = u.addr
  150. u.close
  151. # A rase condition here.
  152. # Another program may use the port.
  153. # But no way to prevent it.
  154. Timeout.timeout(5) do
  155. Resolv::DNS.open(:nameserver_port => [[host, port]]) {|dns|
  156. assert_equal([], dns.getresources("test-no-server.example.org", Resolv::DNS::Resource::IN::A))
  157. }
  158. end
  159. end
  160. def test_invalid_byte_comment
  161. bug9273 = '[ruby-core:59239] [Bug #9273]'
  162. Tempfile.create('resolv_test_dns_') do |tmpfile|
  163. tmpfile.print("\xff\x00\x40")
  164. tmpfile.close
  165. assert_nothing_raised(ArgumentError, bug9273) do
  166. Resolv::DNS::Config.parse_resolv_conf(tmpfile.path)
  167. end
  168. end
  169. end
  170. def test_dots_diffences
  171. name1 = Resolv::DNS::Name.create("example.org")
  172. name2 = Resolv::DNS::Name.create("ex.ampl.eo.rg")
  173. assert_not_equal(name1, name2, "different dots")
  174. end
  175. def test_case_insensitive_name
  176. bug10550 = '[ruby-core:66498] [Bug #10550]'
  177. lower = Resolv::DNS::Name.create("ruby-lang.org")
  178. upper = Resolv::DNS::Name.create("Ruby-Lang.org")
  179. assert_equal(lower, upper, bug10550)
  180. end
  181. def test_ipv6_name
  182. addr = Resolv::IPv6.new("\0"*16)
  183. labels = addr.to_name.to_a
  184. expected = (['0'] * 32 + ['ip6', 'arpa']).map {|label| Resolv::DNS::Label::Str.new(label) }
  185. assert_equal(expected, labels)
  186. end
  187. def test_too_big_label_address
  188. n = 2000
  189. m = Resolv::DNS::Message::MessageEncoder.new {|msg|
  190. 2.times {
  191. n.times {|i| msg.put_labels(["foo#{i}"]) }
  192. }
  193. }
  194. Resolv::DNS::Message::MessageDecoder.new(m.to_s) {|msg|
  195. 2.times {
  196. n.times {|i|
  197. assert_equal(["foo#{i}"], msg.get_labels.map {|label| label.to_s })
  198. }
  199. }
  200. }
  201. assert_operator(2**14, :<, m.to_s.length)
  202. end
  203. end