Index: chrome/browser/data_usage/tab_id_annotator_unittest.cc |
diff --git a/chrome/browser/data_usage/tab_id_annotator_unittest.cc b/chrome/browser/data_usage/tab_id_annotator_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..299d40032c9df39e1fd00c0b067b08915bd7146a |
--- /dev/null |
+++ b/chrome/browser/data_usage/tab_id_annotator_unittest.cc |
@@ -0,0 +1,171 @@ |
+// Copyright 2015 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 "chrome/browser/data_usage/tab_id_annotator.h" |
+ |
+#include <stdint.h> |
+ |
+#include <string> |
+ |
+#include "base/bind.h" |
+#include "base/callback.h" |
+#include "base/location.h" |
+#include "base/macros.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/run_loop.h" |
+#include "base/time/time.h" |
+#include "chrome/browser/sessions/session_tab_helper.h" |
+#include "chrome/test/base/chrome_render_view_host_test_harness.h" |
+#include "components/data_usage/core/data_use.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/render_frame_host.h" |
+#include "content/public/browser/render_process_host.h" |
+#include "content/public/browser/resource_request_info.h" |
+#include "content/public/browser/web_contents.h" |
+#include "net/base/network_change_notifier.h" |
+#include "net/base/request_priority.h" |
+#include "net/url_request/url_request.h" |
+#include "net/url_request/url_request_test_util.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "url/gurl.h" |
+ |
+using content::BrowserThread; |
+using data_usage::DataUse; |
+ |
+namespace chrome_browser_data_usage { |
+ |
+namespace { |
+ |
+class TabIdAnnotatorTest : public ChromeRenderViewHostTestHarness { |
+ public: |
+ TabIdAnnotatorTest() { |
+ // Cannot use IO_MAIN_LOOP with RenderViewHostTestHarness. |
+ SetThreadBundleOptions(content::TestBrowserThreadBundle::REAL_IO_THREAD); |
+ } |
+ |
+ ~TabIdAnnotatorTest() override {} |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(TabIdAnnotatorTest); |
+}; |
+ |
+// Synthesizes a DataUse object with the given |tab_id|. |
+scoped_ptr<DataUse> CreateDataUse(int32_t tab_id) { |
+ return scoped_ptr<DataUse>(new DataUse( |
+ GURL("http://foo.com"), base::TimeTicks(), GURL(), tab_id, |
+ net::NetworkChangeNotifier::CONNECTION_UNKNOWN, std::string(), 100, 100)); |
+} |
+ |
+// Expects that |expected| and |actual| are equal. |
+void ExpectDataUse(scoped_ptr<DataUse> expected, scoped_ptr<DataUse> actual) { |
+ // Single out the |tab_id| for better debug output in failure cases. |
+ EXPECT_EQ(expected->tab_id, actual->tab_id); |
+ EXPECT_EQ(*expected, *actual); |
+} |
+ |
+// Expects that |expected| and |actual| are equal, then quits |ui_run_loop| on |
+// the UI thread. |
+void ExpectDataUseAndQuit(base::RunLoop* ui_run_loop, |
+ scoped_ptr<DataUse> expected, |
+ scoped_ptr<DataUse> actual) { |
+ DCHECK(ui_run_loop); |
+ ExpectDataUse(expected.Pass(), actual.Pass()); |
+ |
+ // This can't use run_loop->QuitClosure here because that uses WeakPtrs, which |
+ // aren't thread safe. |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(&base::RunLoop::Quit, base::Unretained(ui_run_loop))); |
+} |
+ |
+// Tests that for a sample URLRequest, associated with the given |
+// |render_process_id| and |render_frame_id|, repeatedly annotating DataUse for |
+// that URLRequest yields the |expected_tab_id|. |ui_run_loop| is the RunLoop on |
+// the UI thread that should be quit after all the annotations are done. |
+// Passing in -1 for either or both of |render_process_id| or |render_frame_id| |
+// indicates that the URLRequest should have no associated ResourceRequestInfo. |
+void TestAnnotateOnIOThread(base::RunLoop* ui_run_loop, |
+ int render_process_id, |
+ int render_frame_id, |
+ int32_t expected_tab_id) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ DCHECK(ui_run_loop); |
+ |
+ TabIdAnnotator annotator; |
+ net::TestURLRequestContext context; |
+ net::TestDelegate test_delegate; |
+ scoped_ptr<net::URLRequest> request = |
+ context.CreateRequest(GURL("http://foo.com"), net::IDLE, &test_delegate); |
+ |
+ if (render_process_id != -1 && render_frame_id != -1) { |
+ // The only args that matter here for the ResourceRequestInfo are the |
+ // |request|, the |render_process_id|, and the |render_frame_id|; arbitrary |
+ // values are used for all the other args. |
+ content::ResourceRequestInfo::AllocateForTesting( |
+ request.get(), content::RESOURCE_TYPE_MAIN_FRAME, nullptr, |
+ render_process_id, -1, render_frame_id, true, false, true, true, false); |
+ } |
+ |
+ // An invalid tab ID to check that the annotator always sets the tab ID. -2 is |
+ // used because a tab ID of -1 is a valid value that means "no tab was found". |
+ const int32_t kInvalidTabId = -2; |
+ |
+ // Annotate two separate DataUse objects to ensure that repeated annotations |
+ // for the same URLRequest work properly. |
+ scoped_ptr<DataUse> first_expected_data_use = CreateDataUse(expected_tab_id); |
+ annotator.Annotate( |
+ request.get(), CreateDataUse(kInvalidTabId), |
+ base::Bind(&ExpectDataUse, base::Passed(&first_expected_data_use))); |
+ |
+ // Quit the |ui_run_loop| after the second annotation. |
+ scoped_ptr<DataUse> second_expected_data_use = CreateDataUse(expected_tab_id); |
+ annotator.Annotate(request.get(), CreateDataUse(kInvalidTabId), |
+ base::Bind(&ExpectDataUseAndQuit, ui_run_loop, |
+ base::Passed(&second_expected_data_use))); |
+} |
+ |
+TEST_F(TabIdAnnotatorTest, AnnotateWithNoRenderFrame) { |
+ base::RunLoop ui_run_loop; |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind(&TestAnnotateOnIOThread, &ui_run_loop, |
+ -1 /* render_process_id */, -1 /* render_frame_id */, |
+ -1 /* expected_tab_id */)); |
+ ui_run_loop.Run(); |
+} |
+ |
+TEST_F(TabIdAnnotatorTest, AnnotateWithRenderFrameAndNoTab) { |
+ base::RunLoop ui_run_loop; |
+ // |web_contents()| isn't a tab, so it shouldn't have a tab ID. |
+ EXPECT_EQ(-1, SessionTabHelper::IdForTab(web_contents())); |
+ |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind(&TestAnnotateOnIOThread, &ui_run_loop, |
+ web_contents()->GetMainFrame()->GetProcess()->GetID(), |
+ web_contents()->GetMainFrame()->GetRoutingID(), |
+ -1 /* expected_tab_id */)); |
+ ui_run_loop.Run(); |
+} |
+ |
+TEST_F(TabIdAnnotatorTest, AnnotateWithRenderFrameAndTab) { |
+ base::RunLoop ui_run_loop; |
+ // Make |web_contents()| into a tab. |
+ SessionTabHelper::CreateForWebContents(web_contents()); |
+ int32_t expected_tab_id = SessionTabHelper::IdForTab(web_contents()); |
+ // |web_contents()| is a tab, so it should have a tab ID. |
+ EXPECT_NE(-1, expected_tab_id); |
+ |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind(&TestAnnotateOnIOThread, &ui_run_loop, |
+ web_contents()->GetMainFrame()->GetProcess()->GetID(), |
+ web_contents()->GetMainFrame()->GetRoutingID(), |
+ expected_tab_id)); |
+ ui_run_loop.Run(); |
+} |
+ |
+} // namespace |
+ |
+} // namespace chrome_browser_data_usage |