blob: 17dedc8195f8dc91507a40cd4848afb5c4ce97f8 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <string>
#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_base.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "net/nqe/effective_connection_type.h"
#include "services/network/test/test_network_quality_tracker.h"
namespace {
void VerifyDownlinkKbps(double expected_kbps, double got_kbps) {
// First verify that |got_kbps| is a multiple of 50.
int quotient = static_cast<int>(got_kbps / 50);
// |mod| is the remainder left after dividing |got_kbps| by 50 while
// restricting the quotient to integer. For example, if |got_kbps| is
// 1050, then mod will be 0. If |got_kbps| is 1030, mod will be 30.
double mod = got_kbps - 50 * quotient;
EXPECT_LE(0.0, mod);
EXPECT_GT(50.0, mod);
// It is possible that |mod| is not exactly 0 because of floating point
// computations. e.g., |got_kbps| may be 99.999999, in which case |mod|
// will be 49.999999.
EXPECT_TRUE(mod < (1e-5) || (50 - mod) < 1e-5) << " got_kbps=" << got_kbps;
if (expected_kbps > 10000)
expected_kbps = 10000;
// The difference between the actual and the estimate value should be within
// 10%. Add 50 (bucket size used in Blink) to account for the cases when the
// sample may spill over to the next bucket due to the added noise of 10%.
// For example, if sample is 300 kbps, after adding noise, it may become 330,
// and after rounding off, it would spill over to the next bucket of 350 kbps.
EXPECT_GE((expected_kbps * 0.1) + 50, std::abs(expected_kbps - got_kbps))
<< " expected_kbps=" << expected_kbps << " got_kbps=" << got_kbps;
}
} // namespace
class NetInfoBrowserTest : public InProcessBrowserTest {
public:
network::NetworkQualityTracker* GetNetworkQualityTracker() const {
return g_browser_process->network_quality_tracker();
}
protected:
void SetUpOnMainThread() override {}
// Runs |script| repeatedly until the |script| returns |expected_value|.
void RunScriptUntilExpectedStringValueMet(const std::string& script,
const std::string& expected_value) {
while (true) {
if (RunScriptExtractString(script) == expected_value)
return;
base::RunLoop().RunUntilIdle();
}
}
// Repeatedly runs NetInfo JavaScript API to get RTT until it returns
// |expected_rtt|.
void RunGetRttUntilExpectedValueReached(base::TimeDelta expected_rtt) {
if (expected_rtt > base::TimeDelta::FromMilliseconds(3000))
expected_rtt = base::TimeDelta::FromMilliseconds(3000);
while (true) {
int32_t got_rtt_milliseconds = RunScriptExtractInt("getRtt()");
EXPECT_EQ(0, got_rtt_milliseconds % 50)
<< " got_rtt_milliseconds=" << got_rtt_milliseconds;
// The difference between the actual and the estimate value should be
// within 10%. Add 50 (bucket size used in Blink) to account for the cases
// when the sample may spill over to the next bucket due to the added
// noise of 10%. For example, if sample is 300 msec, after adding noise,
// it may become 330, and after rounding off, it would spill over to the
// next bucket of 350 msec.
if (expected_rtt.InMilliseconds() * 0.1 + 50 >=
std::abs(expected_rtt.InMilliseconds() - got_rtt_milliseconds)) {
return;
}
}
}
double RunScriptExtractDouble(const std::string& script) {
double data = 0.0;
EXPECT_TRUE(ExecuteScriptAndExtractDouble(
browser()->tab_strip_model()->GetActiveWebContents(), script, &data));
return data;
}
private:
std::string RunScriptExtractString(const std::string& script) {
std::string data;
EXPECT_TRUE(ExecuteScriptAndExtractString(
browser()->tab_strip_model()->GetActiveWebContents(), script, &data));
return data;
}
int RunScriptExtractInt(const std::string& script) {
int data = 0;
EXPECT_TRUE(ExecuteScriptAndExtractInt(
browser()->tab_strip_model()->GetActiveWebContents(), script, &data));
return data;
}
};
// Make sure the changes in the effective connection type are notified to the
// render thread.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,
EffectiveConnectionTypeChangeNotfied) {
embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
EXPECT_TRUE(embedded_test_server()->Start());
ui_test_utils::NavigateToURL(
browser(), embedded_test_server()->GetURL("/net_info.html"));
// Change effective connection type so that the renderer process is notified.
// Changing the effective connection type from 2G to 3G is guaranteed to
// generate the notification to the renderers, irrespective of the current
// effective connection type.
GetNetworkQualityTracker()->ReportEffectiveConnectionTypeForTesting(
net::EFFECTIVE_CONNECTION_TYPE_2G);
RunScriptUntilExpectedStringValueMet("getEffectiveType()", "2g");
GetNetworkQualityTracker()->ReportEffectiveConnectionTypeForTesting(
net::EFFECTIVE_CONNECTION_TYPE_3G);
RunScriptUntilExpectedStringValueMet("getEffectiveType()", "3g");
}
// Make sure the changes in the network quality are notified to the render
// thread, and the changed network quality is accessible via Javascript API.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeNotified) {
GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
base::TimeDelta::FromSeconds(1), 300);
embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
EXPECT_TRUE(embedded_test_server()->Start());
ui_test_utils::NavigateToURL(
browser(), embedded_test_server()->GetURL("/net_info.html"));
RunGetRttUntilExpectedValueReached(base::TimeDelta::FromSeconds(1));
// If the updated RTT is available via JavaScript, then downlink must have
// been updated too.
VerifyDownlinkKbps(300, RunScriptExtractDouble("getDownlink()") * 1000);
// Verify that the network quality change is accessible via Javascript API.
GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
base::TimeDelta::FromSeconds(10), 3000);
RunGetRttUntilExpectedValueReached(base::TimeDelta::FromSeconds(10));
VerifyDownlinkKbps(3000, RunScriptExtractDouble("getDownlink()") * 1000);
}