15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Single threaded tests of UrlInfo functionality. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <time.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h" 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/net/url_info.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta; 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UrlHostInfoTest : public testing::Test { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef chrome_browser_net::UrlInfo UrlInfo; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Cycle throught the states held by a UrlInfo instance, and check to see that 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// states look reasonable as time ticks away. If the test bots are too slow, 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we'll just give up on this test and exit from it. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(UrlHostInfoTest, StateChangeTest) { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo info_practice, info; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url1("http://domain1.com:80"), url2("https://domain2.com:443"); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First load DLL, so that their load time won't interfere with tests. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some tests involve timing function performance, and DLL time can overwhelm 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // test durations (which are considering network vs cache response times). 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info_practice.SetUrl(url2); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info_practice.SetQueuedState(UrlInfo::UNIT_TEST_MOTIVATED); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info_practice.SetAssignedState(); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info_practice.SetFoundState(); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start test with actual (long/default) expiration time intact. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Complete the construction of real test object. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.SetUrl(url1); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(info.NeedsDnsUpdate()) << "error in construction state"; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.SetQueuedState(UrlInfo::UNIT_TEST_MOTIVATED); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(info.NeedsDnsUpdate()) << "update needed after being queued"; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.SetAssignedState(); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(info.NeedsDnsUpdate()) << "update needed during resolution"; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks before_resolution_complete = TimeTicks::Now(); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.SetFoundState(); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "Immediately" check to see if we need an update yet (we shouldn't). 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (info.NeedsDnsUpdate()) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The test bot must be really slow, so we can verify that. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GT((TimeTicks::Now() - before_resolution_complete).InMilliseconds(), 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo::get_cache_expiration().InMilliseconds()); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // Lets punt here, the test bot is too slow. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run similar test with a shortened expiration, so we can trigger it. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TimeDelta kMockExpirationTime = TimeDelta::FromMilliseconds(300); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.set_cache_expiration(kMockExpirationTime); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // That was a nice life when the object was found.... but next time it won't 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be found. We'll sleep for a while, and then come back with not-found. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.SetQueuedState(UrlInfo::UNIT_TEST_MOTIVATED); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(info.NeedsDnsUpdate()); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.SetAssignedState(); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(info.NeedsDnsUpdate()); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Greater than minimal expected network latency on DNS lookup. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(25)); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) before_resolution_complete = TimeTicks::Now(); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.SetNoSuchNameState(); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "Immediately" check to see if we need an update yet (we shouldn't). 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (info.NeedsDnsUpdate()) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The test bot must be really slow, so we can verify that. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GT((TimeTicks::Now() - before_resolution_complete), 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMockExpirationTime); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait over 300ms, so it should definately be considered out of cache. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PlatformThread::Sleep(kMockExpirationTime + 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromMilliseconds(20)); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(info.NeedsDnsUpdate()) << "expiration time not honored"; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When a system gets "congested" relative to DNS, it means it is doing too many 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DNS resolutions, and bogging down the system. When we detect such a 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// situation, we divert the sequence of states a UrlInfo instance moves 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// through. Rather than proceeding from QUEUED (waiting in a name queue for a 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// worker thread that can resolve the name) to ASSIGNED (where a worker thread 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// actively resolves the name), we enter the ASSIGNED state (without actually 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// getting sent to a resolver thread) and reset our state to what it was before 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the corresponding name was put in the work_queue_. This test drives through 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the state transitions used in such congestion handling. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(UrlHostInfoTest, CongestionResetStateTest) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo info; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url("http://domain1.com:80"); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.SetUrl(url); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.SetQueuedState(UrlInfo::UNIT_TEST_MOTIVATED); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.SetAssignedState(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(info.is_assigned()); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.RemoveFromQueue(); // Do the reset. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(info.is_assigned()); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since this was a new info instance, and it never got resolved, we land back 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in a PENDING state rather than FOUND or NO_SUCH_NAME. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(info.was_found()); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(info.was_nonexistent()); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we're completely re-usable, by going throug a normal flow. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.SetQueuedState(UrlInfo::UNIT_TEST_MOTIVATED); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.SetAssignedState(); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.SetFoundState(); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(info.was_found()); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use the congestion flow, and check that we end up in the found state. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.SetQueuedState(UrlInfo::UNIT_TEST_MOTIVATED); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.SetAssignedState(); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.RemoveFromQueue(); // Do the reset. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(info.is_assigned()); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(info.was_found()); // Back to what it was before being queued. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(jar): Add death test for illegal state changes, and also for setting 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// hostname when already set. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 131