1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <string> 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/values.h" 10 #include "chrome/common/url_constants.h" 11 #include "chrome/test/base/ui_test_utils.h" 12 #include "chrome/test/base/web_ui_browser_test.h" 13 #include "content/public/browser/web_ui.h" 14 #include "content/public/browser/web_ui_message_handler.h" 15 #include "testing/gmock/include/gmock/gmock.h" 16 #include "testing/gtest/include/gtest/gtest-spi.h" 17 18 using content::WebUIMessageHandler; 19 20 // According to the interface for EXPECT_FATAL_FAILURE 21 // (http://code.google.com/p/googletest/wiki/AdvancedGuide#Catching_Failures) 22 // the statement must be statically available. Therefore, we make a static 23 // global s_test_ which should point to |this| for the duration of the test run 24 // and be cleared afterward. 25 class WebUIBrowserExpectFailTest : public WebUIBrowserTest { 26 public: 27 WebUIBrowserExpectFailTest() { 28 EXPECT_FALSE(s_test_); 29 s_test_ = this; 30 } 31 32 protected: 33 virtual ~WebUIBrowserExpectFailTest() { 34 EXPECT_TRUE(s_test_); 35 s_test_ = NULL; 36 } 37 38 static void RunJavascriptTestNoReturn(const std::string& testname) { 39 EXPECT_TRUE(s_test_); 40 s_test_->RunJavascriptTest(testname); 41 } 42 43 static void RunJavascriptAsyncTestNoReturn(const std::string& testname) { 44 EXPECT_TRUE(s_test_); 45 s_test_->RunJavascriptAsyncTest(testname); 46 } 47 48 private: 49 static WebUIBrowserTest* s_test_; 50 }; 51 52 WebUIBrowserTest* WebUIBrowserExpectFailTest::s_test_ = NULL; 53 54 // Test that bogus javascript fails fast - no timeout waiting for result. 55 IN_PROC_BROWSER_TEST_F(WebUIBrowserExpectFailTest, TestFailsFast) { 56 AddLibrary(base::FilePath(FILE_PATH_LITERAL("sample_downloads.js"))); 57 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); 58 EXPECT_FATAL_FAILURE(RunJavascriptTestNoReturn("DISABLED_BogusFunctionName"), 59 "WebUITestHandler::JavaScriptComplete"); 60 } 61 62 // Test that bogus javascript fails fast - no timeout waiting for result. 63 IN_PROC_BROWSER_TEST_F(WebUIBrowserExpectFailTest, TestRuntimeErrorFailsFast) { 64 AddLibrary(base::FilePath(FILE_PATH_LITERAL("runtime_error.js"))); 65 ui_test_utils::NavigateToURL(browser(), GURL(kDummyURL)); 66 EXPECT_FATAL_FAILURE(RunJavascriptTestNoReturn("TestRuntimeErrorFailsFast"), 67 "WebUITestHandler::JavaScriptComplete"); 68 } 69 70 // Test that bogus javascript fails async test fast as well - no timeout waiting 71 // for result. 72 IN_PROC_BROWSER_TEST_F(WebUIBrowserExpectFailTest, TestFailsAsyncFast) { 73 AddLibrary(base::FilePath(FILE_PATH_LITERAL("sample_downloads.js"))); 74 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); 75 EXPECT_FATAL_FAILURE( 76 RunJavascriptAsyncTestNoReturn("DISABLED_BogusFunctionName"), 77 "WebUITestHandler::JavaScriptComplete"); 78 } 79 80 // Tests that the async framework works. 81 class WebUIBrowserAsyncTest : public WebUIBrowserTest { 82 public: 83 // Calls the testDone() function from test_api.js 84 void TestDone() { 85 RunJavascriptFunction("testDone"); 86 } 87 88 // Starts a failing test. 89 void RunTestFailsAssert() { 90 RunJavascriptFunction("runAsync", new base::StringValue("testFailsAssert")); 91 } 92 93 // Starts a passing test. 94 void RunTestPasses() { 95 RunJavascriptFunction("runAsync", new base::StringValue("testPasses")); 96 } 97 98 protected: 99 WebUIBrowserAsyncTest() {} 100 101 // Class to synchronize asynchronous javascript activity with the tests. 102 class AsyncWebUIMessageHandler : public WebUIMessageHandler { 103 public: 104 AsyncWebUIMessageHandler() {} 105 106 MOCK_METHOD1(HandleTestContinues, void(const base::ListValue*)); 107 MOCK_METHOD1(HandleTestFails, void(const base::ListValue*)); 108 MOCK_METHOD1(HandleTestPasses, void(const base::ListValue*)); 109 110 private: 111 virtual void RegisterMessages() OVERRIDE { 112 web_ui()->RegisterMessageCallback("startAsyncTest", 113 base::Bind(&AsyncWebUIMessageHandler::HandleStartAsyncTest, 114 base::Unretained(this))); 115 web_ui()->RegisterMessageCallback("testContinues", 116 base::Bind(&AsyncWebUIMessageHandler::HandleTestContinues, 117 base::Unretained(this))); 118 web_ui()->RegisterMessageCallback("testFails", 119 base::Bind(&AsyncWebUIMessageHandler::HandleTestFails, 120 base::Unretained(this))); 121 web_ui()->RegisterMessageCallback("testPasses", 122 base::Bind(&AsyncWebUIMessageHandler::HandleTestPasses, 123 base::Unretained(this))); 124 } 125 126 // Starts the test in |list_value|[0] with the runAsync wrapper. 127 void HandleStartAsyncTest(const base::ListValue* list_value) { 128 const base::Value* test_name; 129 ASSERT_TRUE(list_value->Get(0, &test_name)); 130 web_ui()->CallJavascriptFunction("runAsync", *test_name); 131 } 132 133 DISALLOW_COPY_AND_ASSIGN(AsyncWebUIMessageHandler); 134 }; 135 136 // Handler for this object. 137 ::testing::StrictMock<AsyncWebUIMessageHandler> message_handler_; 138 139 private: 140 // Provide this object's handler. 141 virtual WebUIMessageHandler* GetMockMessageHandler() OVERRIDE { 142 return &message_handler_; 143 } 144 145 // Set up and browse to kDummyURL for all tests. 146 virtual void SetUpOnMainThread() OVERRIDE { 147 WebUIBrowserTest::SetUpOnMainThread(); 148 AddLibrary(base::FilePath(FILE_PATH_LITERAL("async.js"))); 149 ui_test_utils::NavigateToURL(browser(), GURL(kDummyURL)); 150 } 151 152 DISALLOW_COPY_AND_ASSIGN(WebUIBrowserAsyncTest); 153 }; 154 155 // Test that assertions fail immediately after assertion fails (no testContinues 156 // message). (Sync version). 157 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestSyncOkTestFail) { 158 ASSERT_FALSE(RunJavascriptTest("testFailsAssert")); 159 } 160 161 // Test that assertions fail immediately after assertion fails (no testContinues 162 // message). (Async version). 163 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestAsyncFailsAssert) { 164 EXPECT_CALL(message_handler_, HandleTestFails(::testing::_)); 165 ASSERT_FALSE(RunJavascriptAsyncTest( 166 "startAsyncTest", new base::StringValue("testFailsAssert"))); 167 } 168 169 // Test that expectations continue the function, but fail the test. 170 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestAsyncFailsExpect) { 171 ::testing::InSequence s; 172 EXPECT_CALL(message_handler_, HandleTestContinues(::testing::_)); 173 EXPECT_CALL(message_handler_, HandleTestFails(::testing::_)); 174 ASSERT_FALSE(RunJavascriptAsyncTest( 175 "startAsyncTest", new base::StringValue("testFailsExpect"))); 176 } 177 178 // Test that test continues and passes. (Sync version). 179 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestSyncPasses) { 180 EXPECT_CALL(message_handler_, HandleTestContinues(::testing::_)); 181 ASSERT_TRUE(RunJavascriptTest("testPasses")); 182 } 183 184 // Test that test continues and passes. (Async version). 185 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestAsyncPasses) { 186 ::testing::InSequence s; 187 EXPECT_CALL(message_handler_, HandleTestContinues(::testing::_)); 188 EXPECT_CALL(message_handler_, HandleTestPasses(::testing::_)) 189 .WillOnce(::testing::InvokeWithoutArgs( 190 this, &WebUIBrowserAsyncTest::TestDone)); 191 ASSERT_TRUE(RunJavascriptAsyncTest( 192 "startAsyncTest", new base::StringValue("testPasses"))); 193 } 194 195 // Test that two tests pass. 196 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestAsyncPassPass) { 197 ::testing::InSequence s; 198 EXPECT_CALL(message_handler_, HandleTestContinues(::testing::_)); 199 EXPECT_CALL(message_handler_, HandleTestPasses(::testing::_)) 200 .WillOnce(::testing::InvokeWithoutArgs( 201 this, &WebUIBrowserAsyncTest::RunTestPasses)); 202 EXPECT_CALL(message_handler_, HandleTestContinues(::testing::_)); 203 EXPECT_CALL(message_handler_, HandleTestPasses(::testing::_)) 204 .WillOnce(::testing::InvokeWithoutArgs( 205 this, &WebUIBrowserAsyncTest::TestDone)); 206 ASSERT_TRUE(RunJavascriptAsyncTest( 207 "startAsyncTest", new base::StringValue("testPasses"))); 208 } 209 210 // Test that first test passes; second fails. 211 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestAsyncPassThenFail) { 212 ::testing::InSequence s; 213 EXPECT_CALL(message_handler_, HandleTestContinues(::testing::_)); 214 EXPECT_CALL(message_handler_, HandleTestPasses(::testing::_)) 215 .WillOnce(::testing::InvokeWithoutArgs( 216 this, &WebUIBrowserAsyncTest::RunTestFailsAssert)); 217 EXPECT_CALL(message_handler_, HandleTestFails(::testing::_)); 218 ASSERT_FALSE(RunJavascriptAsyncTest( 219 "startAsyncTest", new base::StringValue("testPasses"))); 220 } 221 222 // Test that testDone() with failure first then sync pass still fails. 223 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestAsyncDoneFailFirstSyncPass) { 224 ::testing::InSequence s; 225 EXPECT_CALL(message_handler_, HandleTestContinues(::testing::_)); 226 EXPECT_CALL(message_handler_, HandleTestFails(::testing::_)); 227 228 // Call runAsync directly instead of deferring through startAsyncTest. It will 229 // call testDone() on failure, then return. 230 ASSERT_FALSE(RunJavascriptAsyncTest( 231 "runAsync", new base::StringValue("testAsyncDoneFailFirstSyncPass"))); 232 } 233 234 // Test that calling testDone during RunJavascriptAsyncTest still completes 235 // when waiting for async result. This is similar to the previous test, but call 236 // testDone directly and expect pass result. 237 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestTestDoneEarlyPassesAsync) { 238 ASSERT_TRUE(RunJavascriptAsyncTest("testDone")); 239 } 240 241 // Test that calling testDone during RunJavascriptTest still completes when 242 // waiting for async result. 243 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestTestDoneEarlyPasses) { 244 ASSERT_TRUE(RunJavascriptTest("testDone")); 245 } 246