moar tests for native resolver paths

This commit is contained in:
HoneyryderChuck 2023-05-22 00:42:52 +02:00
parent 507339907c
commit 1433f35186
4 changed files with 136 additions and 1 deletions

View File

@ -11,7 +11,7 @@ Metrics/ModuleLength:
Max: 325
Metrics/BlockLength:
Max: 200
Max: 500
Metrics/BlockNesting:
Enabled: False

View File

@ -77,6 +77,51 @@ module Requests
verify_error_response(response, HTTPX::ResolveError)
end
when :native
define_method :"test_resolver_#{resolver_type}_tcp_request" do
tcp_socket = nil
resolver_class = Class.new(HTTPX::Resolver::Native) do
define_method :build_socket do
tcp_socket = super()
end
end
session = HTTPX.plugin(SessionWithPool)
uri = build_uri("/get")
response = session.head(uri, resolver_class: resolver_class, resolver_options: options.merge(socket_type: :tcp))
verify_status(response, 200)
response.close
assert !tcp_socket.nil?
assert tcp_socket.is_a?(HTTPX::TCP)
end
define_method :"test_resolver_#{resolver_type}_same_relative_name" do
addresses = nil
resolver_class = Class.new(HTTPX::Resolver::Native) do
define_method :parse_addresses do |addrs|
addresses = addrs
super(addrs)
end
end
start_test_servlet(DNSSameRelativeName, 0.2) do |slow_dns_server|
start_test_servlet(DNSSameRelativeName, 0.2) do |not_so_slow_dns_server|
nameservers = [slow_dns_server.nameserver, not_so_slow_dns_server.nameserver]
resolver_opts = options.merge(nameserver: nameservers)
session = HTTPX.plugin(SessionWithPool)
uri = URI(build_uri("/get"))
response = session.head(uri, resolver_class: resolver_class, resolver_options: resolver_opts)
verify_status(response, 200)
response.close
assert !addresses.nil?
addr = addresses.first
assert addr["name"] != uri.host
end
end
end
# this test mocks an unresponsive DNS server which doesn't return a DNS asnwer back.
define_method :"test_resolver_#{resolver_type}_timeout" do
@ -205,6 +250,23 @@ module Requests
assert resolver_class.ios.any?(HTTPX::TCP), "resolver did not upgrade to tcp"
end
define_method :"test_resolver_#{resolver_type}_no_addresses" do
start_test_servlet(DNSNoAddress, 0.2) do |slow_dns_server|
start_test_servlet(DNSNoAddress, 0.2) do |not_so_slow_dns_server|
nameservers = [slow_dns_server.nameserver, not_so_slow_dns_server.nameserver]
resolver_opts = options.merge(nameserver: nameservers)
HTTPX.plugin(SessionWithPool).wrap do |session|
uri = build_uri("/get")
response = session.get(uri, resolver_class: resolver_type, resolver_options: resolver_opts)
verify_error_response(response, /Can't resolve/)
end
end
end
end
end
end
end

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
require "resolv"
require_relative "test"
# from https://gist.github.com/peterc/1425383
class DNSNoAddress < TestDNSResolver
private
def dns_response(query)
domain = extract_domain(query)
ip = Resolv.getaddress(domain)
cname = ip =~ /[a-z]/
# Valid response header
response = "#{query[0, 2]}\x81\x00#{query[4, 2]}\x00\x00\x00\x00\x00\x00".b
# Append original question section
response << query[12..-1].b
# Use pointer to refer to domain name in question section
response << "\xc0\x0c".b
response
end
end

View File

@ -0,0 +1,47 @@
# frozen_string_literal: true
require "resolv"
require_relative "test"
# from https://gist.github.com/peterc/1425383
class DNSSameRelativeName < TestDNSResolver
private
def dns_response(query)
domain = extract_domain(query)
ip = Resolv.getaddress(domain)
cname = ip =~ /[a-z]/
# Valid response header
response = "#{query[0, 2]}\x81\x00#{query[4, 2] * 2}\x00\x00\x00\x00".b
# Append original question section
response << [domain.size].pack("C") << domain.b << query[-5..-1]
# Use pointer to refer to domain name in question section
response << "\xc0\x0c".b
# Set response type accordingly
response << (cname ? "\x00\x05".b : "\x00\x01".b)
# Set response class (IN)
response << "\x00\x01".b
# TTL in seconds
response << [120].pack("N").b
# Calculate RDATA - we need its length in advance
rdata = if cname
ip.split(".").map { |a| a.length.chr + a }.join << "\x00"
else
# Append IP address as four 8 bit unsigned bytes
ip.split(".").map(&:to_i).pack("C*")
end
# RDATA is 4 bytes
response << [rdata.length].pack("n").b
response << rdata.b
response
end
end