1 // Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4
5 #include <algorithm>
6 #include <cstdlib>
7 #include <string>
8
9 #include "include/base/cef_callback.h"
10 #include "include/cef_stream.h"
11 #include "include/wrapper/cef_closure_task.h"
12 #include "include/wrapper/cef_stream_resource_handler.h"
13 #include "tests/ceftests/routing_test_handler.h"
14 #include "tests/gtest/include/gtest/gtest.h"
15
16 namespace {
17
18 const char kTestUrl[] = "http://tests-srh/test.html";
19 const size_t kReadBlockSize = 1024U; // 1k.
20
21 // The usual network buffer size is about 32k. Choose a value that's larger.
22 const size_t kReadDesiredSize = 100U * 1024U; // 100k
23
24 class ReadHandler : public CefReadHandler {
25 public:
ReadHandler(bool may_block)26 explicit ReadHandler(bool may_block)
27 : may_block_(may_block), offset_(0), expected_result_(0) {}
28
CreateContent()29 void CreateContent() {
30 // To verify that the data transers successfully we're going to make a big
31 // math problem.
32 content_.reserve(kReadDesiredSize + 50U);
33 content_ = "<html><body><script>var myratherlongvariablename=0;";
34
35 while (content_.size() < kReadDesiredSize) {
36 content_ += "myratherlongvariablename=myratherlongvariablename+1;";
37 expected_result_++;
38 }
39
40 content_ +=
41 "window.testQuery({request:myratherlongvariablename+''});"
42 "</script></body></html>";
43 }
44
GetExpectedResult() const45 int GetExpectedResult() const { return expected_result_; }
46
Read(void * ptr,size_t size,size_t n)47 size_t Read(void* ptr, size_t size, size_t n) override {
48 EXPECT_EQ(1U, size);
49
50 // Read the minimum of requested size, remaining size or kReadBlockSize.
51 const size_t read_bytes =
52 std::min(std::min(size * n, content_.size() - offset_), kReadBlockSize);
53 if (read_bytes > 0) {
54 memcpy(ptr, content_.c_str() + offset_, read_bytes);
55 offset_ += read_bytes;
56 }
57
58 return read_bytes;
59 }
60
Seek(int64 offset,int whence)61 int Seek(int64 offset, int whence) override {
62 EXPECT_TRUE(false); // Not reached.
63 return 0;
64 }
65
Tell()66 int64 Tell() override {
67 EXPECT_TRUE(false); // Not reached.
68 return 0;
69 }
70
Eof()71 int Eof() override {
72 EXPECT_TRUE(false); // Not reached.
73 return 0;
74 }
75
MayBlock()76 bool MayBlock() override { return may_block_; }
77
78 private:
79 const bool may_block_;
80 std::string content_;
81 size_t offset_;
82 int expected_result_;
83
84 IMPLEMENT_REFCOUNTING(ReadHandler);
85 };
86
87 class ReadTestHandler : public RoutingTestHandler {
88 public:
ReadTestHandler(bool may_block)89 explicit ReadTestHandler(bool may_block)
90 : may_block_(may_block), expected_result_(0) {}
91
RunTest()92 void RunTest() override {
93 // Create the browser.
94 CreateBrowser(kTestUrl);
95
96 // Time out the test after a reasonable period of time.
97 SetTestTimeout();
98 }
99
GetResourceHandler(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request)100 CefRefPtr<CefResourceHandler> GetResourceHandler(
101 CefRefPtr<CefBrowser> browser,
102 CefRefPtr<CefFrame> frame,
103 CefRefPtr<CefRequest> request) override {
104 got_resource_handler_.yes();
105
106 const std::string& url = request->GetURL();
107 EXPECT_STREQ(kTestUrl, url.c_str());
108
109 CefRefPtr<ReadHandler> handler = new ReadHandler(may_block_);
110 handler->CreateContent();
111 expected_result_ = handler->GetExpectedResult();
112
113 CefRefPtr<CefStreamReader> stream =
114 CefStreamReader::CreateForHandler(handler.get());
115 return new CefStreamResourceHandler("text/html", stream);
116 }
117
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)118 bool OnQuery(CefRefPtr<CefBrowser> browser,
119 CefRefPtr<CefFrame> frame,
120 int64 query_id,
121 const CefString& request,
122 bool persistent,
123 CefRefPtr<Callback> callback) override {
124 got_on_query_.yes();
125
126 const int actual_result = atoi(request.ToString().c_str());
127 EXPECT_EQ(expected_result_, actual_result);
128
129 DestroyTestIfDone();
130
131 return true;
132 }
133
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading,bool canGoBack,bool canGoForward)134 void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
135 bool isLoading,
136 bool canGoBack,
137 bool canGoForward) override {
138 if (!isLoading) {
139 got_on_loading_state_change_done_.yes();
140 DestroyTestIfDone();
141 }
142 }
143
144 private:
DestroyTestIfDone()145 void DestroyTestIfDone() {
146 if (got_on_query_ && got_on_loading_state_change_done_)
147 DestroyTest();
148 }
149
DestroyTest()150 void DestroyTest() override {
151 EXPECT_TRUE(got_resource_handler_);
152 EXPECT_TRUE(got_on_query_);
153 EXPECT_TRUE(got_on_loading_state_change_done_);
154 RoutingTestHandler::DestroyTest();
155 }
156
157 const bool may_block_;
158
159 int expected_result_;
160 TrackCallback got_resource_handler_;
161 TrackCallback got_on_query_;
162 TrackCallback got_on_loading_state_change_done_;
163
164 IMPLEMENT_REFCOUNTING(ReadTestHandler);
165 };
166
167 } // namespace
168
TEST(StreamResourceHandlerTest,ReadWillBlock)169 TEST(StreamResourceHandlerTest, ReadWillBlock) {
170 CefRefPtr<ReadTestHandler> handler = new ReadTestHandler(true);
171 handler->ExecuteTest();
172 ReleaseAndWaitForDestructor(handler);
173 }
174
TEST(StreamResourceHandlerTest,ReadWontBlock)175 TEST(StreamResourceHandlerTest, ReadWontBlock) {
176 CefRefPtr<ReadTestHandler> handler = new ReadTestHandler(false);
177 handler->ExecuteTest();
178 ReleaseAndWaitForDestructor(handler);
179 }
180