- add sources.
[platform/framework/web/crosswalk.git] / src / chrome_frame / test / urlmon_moniker_unittest.cc
1 // Copyright (c) 2011 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 <atlbase.h>
6 #include <atlcom.h>
7
8 #include "base/file_util.h"
9 #include "base/path_service.h"
10 #include "base/win/scoped_comptr.h"
11 #include "chrome_frame/test/chrome_frame_test_utils.h"
12 #include "chrome_frame/test/urlmon_moniker_tests.h"
13 #include "chrome_frame/urlmon_bind_status_callback.h"
14
15 using chrome_frame_test::ScopedVirtualizeHklmAndHkcu;
16 using testing::Return;
17 using testing::Eq;
18
19 class MonikerPatchTest : public testing::Test {
20  protected:
21   MonikerPatchTest() {
22   }
23
24   virtual void SetUp() {
25     DeleteAllSingletons();
26     PathService::Get(base::DIR_SOURCE_ROOT, &test_file_path_);
27     test_file_path_ = test_file_path_.Append(FILE_PATH_LITERAL("chrome_frame"))
28         .Append(FILE_PATH_LITERAL("test"))
29         .Append(FILE_PATH_LITERAL("data"));
30   }
31
32   bool ReadFileAsString(const wchar_t* file_name, std::string* file_contents) {
33     EXPECT_TRUE(file_name);
34     base::FilePath file_path = test_file_path_.Append(file_name);
35     return base::ReadFileToString(file_path, file_contents);
36   }
37
38   static bool StringToStream(const std::string& data, IStream** ret) {
39     EXPECT_TRUE(!data.empty());
40
41     base::win::ScopedComPtr<IStream> stream;
42     HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, stream.Receive());
43     EXPECT_HRESULT_SUCCEEDED(hr);
44     if (FAILED(hr)) {
45       return false;
46     }
47
48     DWORD written = 0;
49     hr = stream->Write(data.c_str(), data.size(), &written);
50     EXPECT_HRESULT_SUCCEEDED(hr);
51     EXPECT_EQ(data.size(), written);
52
53     bool result = false;
54     if (SUCCEEDED(hr)) {
55       RewindStream(stream);
56       *ret = stream.Detach();
57       result = true;
58     }
59
60     return result;
61   }
62
63   base::FilePath test_file_path_;
64   ScopedVirtualizeHklmAndHkcu virtualized_registry_;
65 };
66
67 // Tests the CacheStream class by writing content into a stream object
68 // and verify that reading that stream back
69 TEST_F(MonikerPatchTest, CacheStream) {
70   const char data[] = "ReadStreamCacheTest";
71   char ret[2 * sizeof(data)] = {0};
72   DWORD read = 0;
73
74   // Test 1: empty stream reads nothing
75   CComObjectStackEx<CacheStream> cache_stream1;
76   EXPECT_EQ(S_FALSE, cache_stream1.Read(ret, sizeof(ret), &read));
77   EXPECT_EQ(0, read);
78
79   // Test 2: Read from initialized cache
80   CComObjectStackEx<CacheStream> cache_stream2;
81   cache_stream2.Initialize(data, sizeof(data), false);
82   EXPECT_HRESULT_SUCCEEDED(cache_stream2.Read(ret, sizeof(ret), &read));
83   EXPECT_EQ(sizeof(data), read);
84   EXPECT_EQ(std::string(data), std::string(ret));
85
86   read = 0;
87   EXPECT_EQ(E_PENDING, cache_stream2.Read(ret, sizeof(ret), &read));
88   EXPECT_EQ(0, read);
89 }
90
91 ACTION_P3(ReadStream, buffer, size, ret) {
92   EXPECT_EQ(TYMED_ISTREAM, arg3->tymed);
93   *ret = arg3->pstm->Read(buffer, *size, size);
94 }
95
96 // Tests the implementation of BSCBFeedData to feed data to the
97 // specified IBindStatusCallback
98 TEST_F(MonikerPatchTest, BSCBFeedData) {
99   CComObjectStackEx<MockBindStatusCallbackImpl> mock;
100   const char data[] = "ReadStreamCacheTest";
101   const DWORD size = sizeof(data);
102   const CLIPFORMAT cf = 0xd0d0;
103   const DWORD flags = BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION;
104   const DWORD kArbitraryreadSize = 0xdeadbabe;
105
106   char read_buffer1[size] = {0}, read_buffer2[size] = {0};
107   DWORD read_size1 = size, read_size2 = kArbitraryreadSize;
108   HRESULT ret1 = E_FAIL, ret2 = E_FAIL;
109
110   EXPECT_CALL(mock, OnDataAvailable(flags, size,
111                     testing::Field(&FORMATETC::cfFormat, cf),
112                     testing::Field(&STGMEDIUM::tymed, TYMED_ISTREAM)))
113       .WillOnce(testing::DoAll(
114           ReadStream(read_buffer1, &read_size1, &ret1),
115           ReadStream(read_buffer2, &read_size2, &ret2),
116           Return(S_OK)));
117
118   EXPECT_HRESULT_SUCCEEDED(CacheStream::BSCBFeedData(&mock, data, size, cf,
119                                                      flags, false));
120
121   EXPECT_HRESULT_SUCCEEDED(ret1);
122   EXPECT_STREQ(data, read_buffer1);
123   EXPECT_EQ(size, read_size1);
124
125   EXPECT_EQ(E_PENDING, ret2);
126   EXPECT_STREQ("", read_buffer2);
127   EXPECT_EQ(kArbitraryreadSize, read_size2);
128 }
129
130 const wchar_t kSmallHtmlMetaTag[] = L"sub_frame1.html";
131 const wchar_t kSmallHtmlNoMetaTag[] = L"host_browser.html";
132
133 // Test various aspects of the SniffData class
134 TEST_F(MonikerPatchTest, SniffDataMetaTag) {
135   std::string small_html_meta_tag, small_html_no_meta_tag;
136   ASSERT_TRUE(ReadFileAsString(kSmallHtmlMetaTag, &small_html_meta_tag));
137   ASSERT_TRUE(ReadFileAsString(kSmallHtmlNoMetaTag, &small_html_no_meta_tag));
138
139   base::win::ScopedComPtr<IStream> stream_with_meta, stream_no_meta;
140   ASSERT_TRUE(StringToStream(small_html_meta_tag, stream_with_meta.Receive()));
141   ASSERT_TRUE(StringToStream(small_html_no_meta_tag,
142                              stream_no_meta.Receive()));
143
144   // Initialize 2 sniffers 1 with meta tag and 1 without.
145   SniffData sniffer1, sniffer2;
146   EXPECT_HRESULT_SUCCEEDED(sniffer1.InitializeCache(std::wstring()));
147   EXPECT_HRESULT_SUCCEEDED(sniffer2.InitializeCache(std::wstring()));
148   EXPECT_HRESULT_SUCCEEDED(sniffer1.ReadIntoCache(stream_with_meta, true));
149   EXPECT_HRESULT_SUCCEEDED(sniffer2.ReadIntoCache(stream_no_meta, true));
150
151   // Verify renderer type and size read.
152   EXPECT_TRUE(sniffer1.is_chrome());
153   EXPECT_EQ(SniffData::OTHER, sniffer2.renderer_type());
154   EXPECT_EQ(small_html_meta_tag.size(), sniffer1.size());
155   EXPECT_EQ(small_html_no_meta_tag.size(), sniffer2.size());
156 }
157
158 // Now test how the data is fed back the the bind status callback.
159 // case 1: callback reads data in 1 read
160 TEST_F(MonikerPatchTest, SniffDataPlayback1) {
161   std::string small_html_meta_tag;
162   base::win::ScopedComPtr<IStream> stream_with_meta;
163   SniffData sniffer;
164
165   EXPECT_HRESULT_SUCCEEDED(sniffer.InitializeCache(std::wstring()));
166   ASSERT_TRUE(ReadFileAsString(kSmallHtmlMetaTag, &small_html_meta_tag));
167   ASSERT_TRUE(StringToStream(small_html_meta_tag, stream_with_meta.Receive()));
168   EXPECT_HRESULT_SUCCEEDED(sniffer.ReadIntoCache(stream_with_meta, true));
169
170   CComObjectStackEx<MockBindStatusCallbackImpl> mock;
171   const CLIPFORMAT cf = 0xd0d0;
172   const DWORD flags = BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION;
173   const DWORD data_size = small_html_meta_tag.size();
174
175   DWORD read_size1 = data_size * 2;
176   scoped_ptr<char[]> read_buffer1(new char[read_size1]);
177   ZeroMemory(read_buffer1.get(), read_size1);
178
179   char read_buffer2[10] = {0};
180   DWORD read_size2 = sizeof(read_buffer2);
181   HRESULT ret1 = E_FAIL, ret2 = E_FAIL;
182
183   EXPECT_CALL(mock, OnDataAvailable(flags, data_size,
184                     testing::Field(&FORMATETC::cfFormat, cf),
185                     testing::Field(&STGMEDIUM::tymed, TYMED_ISTREAM)))
186       .WillOnce(testing::DoAll(
187           ReadStream(read_buffer1.get(), &read_size1, &ret1),
188           ReadStream(read_buffer2, &read_size2, &ret2),
189           Return(S_OK)));
190
191   EXPECT_HRESULT_SUCCEEDED(sniffer.DrainCache(&mock, flags, cf));
192
193   EXPECT_HRESULT_SUCCEEDED(ret1);
194   EXPECT_EQ(small_html_meta_tag, read_buffer1.get());
195   EXPECT_EQ(data_size, read_size1);
196
197   EXPECT_EQ(S_FALSE, ret2);
198   EXPECT_STREQ("", read_buffer2);
199   EXPECT_EQ(sizeof(read_buffer2), read_size2);
200 }
201
202 // case 2: callback reads data in 2 reads.
203 TEST_F(MonikerPatchTest, SniffDataPlayback2) {
204   std::string small_html_meta_tag;
205   base::win::ScopedComPtr<IStream> stream_with_meta;
206   SniffData sniffer;
207
208   EXPECT_HRESULT_SUCCEEDED(sniffer.InitializeCache(std::wstring()));
209   ASSERT_TRUE(ReadFileAsString(kSmallHtmlMetaTag, &small_html_meta_tag));
210   ASSERT_TRUE(StringToStream(small_html_meta_tag, stream_with_meta.Receive()));
211   EXPECT_HRESULT_SUCCEEDED(sniffer.ReadIntoCache(stream_with_meta, true));
212
213   CComObjectStackEx<MockBindStatusCallbackImpl> mock;
214   const CLIPFORMAT cf = 0xd0d0;
215   const DWORD flags = BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION;
216   const DWORD data_size = small_html_meta_tag.size();
217
218   DWORD read_size1 = data_size / 2; // First read is half the data.
219   DWORD read_size2 = data_size; // Second read, try to read past data.
220   scoped_ptr<char[]> read_buffer1(new char[read_size1]);
221   scoped_ptr<char[]> read_buffer2(new char[read_size2]);
222   ZeroMemory(read_buffer1.get(), read_size1);
223   ZeroMemory(read_buffer2.get(), read_size2);
224
225   char read_buffer3[10] = {0};
226   DWORD read_size3 = sizeof(read_buffer3);
227   HRESULT ret1 = E_FAIL, ret2 = E_FAIL, ret3 = E_FAIL;
228
229   EXPECT_CALL(mock, OnDataAvailable(flags, data_size,
230                     testing::Field(&FORMATETC::cfFormat, cf),
231                     testing::Field(&STGMEDIUM::tymed, TYMED_ISTREAM)))
232       .WillOnce(testing::DoAll(
233           ReadStream(read_buffer1.get(), &read_size1, &ret1),
234           ReadStream(read_buffer2.get(), &read_size2, &ret2),
235           ReadStream(read_buffer3, &read_size3, &ret3),
236           Return(S_OK)));
237
238   EXPECT_HRESULT_SUCCEEDED(sniffer.DrainCache(&mock, flags, cf));
239
240   EXPECT_HRESULT_SUCCEEDED(ret1);
241   EXPECT_HRESULT_SUCCEEDED(ret2);
242   EXPECT_EQ(data_size/2, read_size1);
243   EXPECT_EQ(data_size - read_size1, read_size2);
244
245   std::string data_read;
246   data_read.append(read_buffer1.get(), read_size1);
247   data_read.append(read_buffer2.get(), read_size2);
248   EXPECT_EQ(small_html_meta_tag, data_read);
249
250   EXPECT_EQ(S_FALSE, ret3);
251   EXPECT_STREQ("", read_buffer3);
252   EXPECT_EQ(sizeof(read_buffer3), read_size3);
253 }