From 3e44b1a8d51a844688a51d880831ae89d1bf0690 Mon Sep 17 00:00:00 2001 From: Nick Muerdter Date: Mon, 21 May 2018 22:10:25 -0600 Subject: [PATCH] Improve negative TTL caching tests. To better clarify usage and add a second test to ensure the negative TTL setting is actually being used, rather than the timing just happening to work for the default TTL (which we saw in a separate branch working on this with Trafficserver's DNS). --- test/proxy/dns/test_negative_caching.rb | 64 +++++++++++++++---- .../api_umbrella_test_helpers/setup.rb | 24 +++++++ 2 files changed, 75 insertions(+), 13 deletions(-) diff --git a/test/proxy/dns/test_negative_caching.rb b/test/proxy/dns/test_negative_caching.rb index 482941080..146e28159 100644 --- a/test/proxy/dns/test_negative_caching.rb +++ b/test/proxy/dns/test_negative_caching.rb @@ -26,33 +26,71 @@ def after_all override_config_reset("--router") end - def test_failed_host_down_after_ttl_expires + def test_caches_failed_lookups_before_retrying + assert_negative_ttl(NEGATIVE_TTL) + end + + def test_negative_ttl_can_be_configured + negative_ttl = 3 + + # Ensure this negative TTL is different enough than the default that we can + # distinguish the results in tests. + assert_operator(negative_ttl, :<=, (NEGATIVE_TTL - TTL_BUFFER_POS).floor) + + override_config({ + "dns_resolver" => { + "nameservers" => ["[127.0.0.1]:#{$config["unbound"]["port"]}"], + "max_stale" => 0, + "negative_ttl" => negative_ttl, + }, + }, "--router") do + assert_negative_ttl(negative_ttl) + end + end + + private + + def assert_negative_ttl(negative_ttl) prepend_api_backends([ { :frontend_host => "127.0.0.1", - :backend_host => "negative-caching-invalid-hostname-begins-resolving.ooga", - :servers => [{ :host => "negative-caching-invalid-hostname-begins-resolving.ooga", :port => 9444 }], - :url_matches => [{ :frontend_prefix => "/#{unique_test_id}/negative-caching-invalid-hostname-begins-resolving/", :backend_prefix => "/info/" }], + :backend_host => unique_test_hostname, + :servers => [{ :host => unique_test_hostname, :port => 9444 }], + :url_matches => [{ :frontend_prefix => "/#{unique_test_id}/", :backend_prefix => "/info/" }], }, ]) do - # The negative TTL caching really begins as soon as the initial - # configuration is put into place by runServer (since that's when the - # hostname is first seen and the unresolvable status is cached). So start - # our timer here. + # Make an initial request, which we expect to not succeed, since the + # hostname is bad. + wait_for_response("/#{unique_test_id}/", { + :code => 502, + }) + + # The negative TTL caching begins after TrafficServer sees the first + # request and tries to resolve it. So start our timer after the first + # request. start_time = Time.now.utc - wait_for_response("/#{unique_test_id}/negative-caching-invalid-hostname-begins-resolving/", { + # Add the DNS record for the previously invalid domain. + set_dns_records(["#{unique_test_hostname} 60 A 127.0.0.1"]) + + # Ensure that negative caching is in place and the hostname is still not + # resolving (despite the DNS being installed now). + wait_for_response("/#{unique_test_id}/", { :code => 502, }) - set_dns_records(["negative-caching-invalid-hostname-begins-resolving.ooga 60 A 127.0.0.1"]) - wait_for_response("/#{unique_test_id}/negative-caching-invalid-hostname-begins-resolving/", { + # Wait for the successful response to resolve once the negative TTL has + # expired. + wait_for_response("/#{unique_test_id}/", { :code => 200, :local_interface_ip => "127.0.0.1", }) + + # Sanity check the results to ensure the results fit within the expected + # negative TTL values. duration = Time.now.utc - start_time - min_duration = NEGATIVE_TTL - TTL_BUFFER_NEG - max_duration = NEGATIVE_TTL + TTL_BUFFER_POS + min_duration = negative_ttl - TTL_BUFFER_NEG + max_duration = negative_ttl + TTL_BUFFER_POS assert_operator(min_duration, :>, 0) assert_operator(duration, :>=, min_duration) assert_operator(duration, :<, max_duration) diff --git a/test/support/api_umbrella_test_helpers/setup.rb b/test/support/api_umbrella_test_helpers/setup.rb index 48e07bb63..33d80de6c 100644 --- a/test/support/api_umbrella_test_helpers/setup.rb +++ b/test/support/api_umbrella_test_helpers/setup.rb @@ -279,6 +279,30 @@ def unique_test_id @unique_test_id ||= self.location.gsub(/[^\w]+/, "-") end + def unique_test_hostname + unless @unique_test_hostname + # Replace all non alpha-numeric chars (namely underscores that might be + # in the ID) with dashes (since underscores aren't valid for + # hostnames). + hostname = unique_test_id.downcase.gsub(/[^a-z0-9]+/, "-") + + # Truncate the hostname so the label will fit in unbound's 63 char + # limit. + hostname = hostname[-56..-1] || hostname + + # Strip first char if it happens to be a dash. + hostname.gsub!(/^-/, "") + + # Since we've truncated the test ID, it's possible it's no longer + # unique, so append some random chars (but still, fitting within the 63 + # char limit). + hostname = "#{hostname}-#{SecureRandom.hex(3)}" + + @unique_test_hostname = "#{hostname}.test" + end + @unique_test_hostname + end + def next_unique_ip_addr @@incrementing_unique_ip_addr = @@incrementing_unique_ip_addr.succ @@incrementing_unique_ip_addr.to_s