| // Copyright (c) 2014 The Chromium Embedded Framework 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 <algorithm> |
| #include <cstdlib> |
| #include <string> |
| |
| #include "include/base/cef_bind.h" |
| #include "include/cef_stream.h" |
| #include "include/wrapper/cef_closure_task.h" |
| #include "include/wrapper/cef_stream_resource_handler.h" |
| #include "tests/ceftests/routing_test_handler.h" |
| #include "tests/gtest/include/gtest/gtest.h" |
| |
| namespace { |
| |
| const char kTestUrl[] = "http://tests-srh/test.html"; |
| const size_t kReadBlockSize = 1024U; // 1k. |
| |
| // The usual network buffer size is about 32k. Choose a value that's larger. |
| const size_t kReadDesiredSize = 100U * 1024U; // 100k |
| |
| class ReadHandler : public CefReadHandler { |
| public: |
| explicit ReadHandler(bool may_block) |
| : may_block_(may_block), offset_(0), expected_result_(0) {} |
| |
| void CreateContent() { |
| // To verify that the data transers successfully we're going to make a big |
| // math problem. |
| content_.reserve(kReadDesiredSize + 50U); |
| content_ = "<html><body><script>var myratherlongvariablename=0;"; |
| |
| while (content_.size() < kReadDesiredSize) { |
| content_ += "myratherlongvariablename=myratherlongvariablename+1;"; |
| expected_result_++; |
| } |
| |
| content_ += |
| "window.testQuery({request:myratherlongvariablename+''});" |
| "</script></body></html>"; |
| } |
| |
| int GetExpectedResult() const { return expected_result_; } |
| |
| size_t Read(void* ptr, size_t size, size_t n) override { |
| EXPECT_EQ(1U, size); |
| |
| // Read the minimum of requested size, remaining size or kReadBlockSize. |
| const size_t read_bytes = |
| std::min(std::min(size * n, content_.size() - offset_), kReadBlockSize); |
| if (read_bytes > 0) { |
| memcpy(ptr, content_.c_str() + offset_, read_bytes); |
| offset_ += read_bytes; |
| } |
| |
| return read_bytes; |
| } |
| |
| int Seek(int64 offset, int whence) override { |
| EXPECT_TRUE(false); // Not reached. |
| return 0; |
| } |
| |
| int64 Tell() override { |
| EXPECT_TRUE(false); // Not reached. |
| return 0; |
| } |
| |
| int Eof() override { |
| EXPECT_TRUE(false); // Not reached. |
| return 0; |
| } |
| |
| bool MayBlock() override { return may_block_; } |
| |
| private: |
| const bool may_block_; |
| std::string content_; |
| size_t offset_; |
| int expected_result_; |
| |
| IMPLEMENT_REFCOUNTING(ReadHandler); |
| }; |
| |
| class ReadTestHandler : public RoutingTestHandler { |
| public: |
| explicit ReadTestHandler(bool may_block) |
| : may_block_(may_block), expected_result_(0) {} |
| |
| void RunTest() override { |
| // Create the browser. |
| CreateBrowser(kTestUrl); |
| |
| // Time out the test after a reasonable period of time. |
| SetTestTimeout(); |
| } |
| |
| CefRefPtr<CefResourceHandler> GetResourceHandler( |
| CefRefPtr<CefBrowser> browser, |
| CefRefPtr<CefFrame> frame, |
| CefRefPtr<CefRequest> request) override { |
| got_resource_handler_.yes(); |
| |
| const std::string& url = request->GetURL(); |
| EXPECT_STREQ(kTestUrl, url.c_str()); |
| |
| CefRefPtr<ReadHandler> handler = new ReadHandler(may_block_); |
| handler->CreateContent(); |
| expected_result_ = handler->GetExpectedResult(); |
| |
| CefRefPtr<CefStreamReader> stream = |
| CefStreamReader::CreateForHandler(handler.get()); |
| return new CefStreamResourceHandler("text/html", stream); |
| } |
| |
| bool OnQuery(CefRefPtr<CefBrowser> browser, |
| CefRefPtr<CefFrame> frame, |
| int64 query_id, |
| const CefString& request, |
| bool persistent, |
| CefRefPtr<Callback> callback) override { |
| got_on_query_.yes(); |
| |
| const int actual_result = atoi(request.ToString().c_str()); |
| EXPECT_EQ(expected_result_, actual_result); |
| |
| DestroyTestIfDone(); |
| |
| return true; |
| } |
| |
| void OnLoadingStateChange(CefRefPtr<CefBrowser> browser, |
| bool isLoading, |
| bool canGoBack, |
| bool canGoForward) override { |
| if (!isLoading) { |
| got_on_loading_state_change_done_.yes(); |
| DestroyTestIfDone(); |
| } |
| } |
| |
| private: |
| void DestroyTestIfDone() { |
| if (got_on_query_ && got_on_loading_state_change_done_) |
| DestroyTest(); |
| } |
| |
| void DestroyTest() override { |
| EXPECT_TRUE(got_resource_handler_); |
| EXPECT_TRUE(got_on_query_); |
| EXPECT_TRUE(got_on_loading_state_change_done_); |
| RoutingTestHandler::DestroyTest(); |
| } |
| |
| const bool may_block_; |
| |
| int expected_result_; |
| TrackCallback got_resource_handler_; |
| TrackCallback got_on_query_; |
| TrackCallback got_on_loading_state_change_done_; |
| |
| IMPLEMENT_REFCOUNTING(ReadTestHandler); |
| }; |
| |
| } // namespace |
| |
| TEST(StreamResourceHandlerTest, ReadWillBlock) { |
| CefRefPtr<ReadTestHandler> handler = new ReadTestHandler(true); |
| handler->ExecuteTest(); |
| ReleaseAndWaitForDestructor(handler); |
| } |
| |
| TEST(StreamResourceHandlerTest, ReadWontBlock) { |
| CefRefPtr<ReadTestHandler> handler = new ReadTestHandler(false); |
| handler->ExecuteTest(); |
| ReleaseAndWaitForDestructor(handler); |
| } |