diff options
Diffstat (limited to 'chrome_frame/test/urlmon_moniker_unittest.cc')
-rw-r--r-- | chrome_frame/test/urlmon_moniker_unittest.cc | 411 |
1 files changed, 217 insertions, 194 deletions
diff --git a/chrome_frame/test/urlmon_moniker_unittest.cc b/chrome_frame/test/urlmon_moniker_unittest.cc index 08795fc..f50bd86 100644 --- a/chrome_frame/test/urlmon_moniker_unittest.cc +++ b/chrome_frame/test/urlmon_moniker_unittest.cc @@ -5,222 +5,245 @@ #include <atlbase.h> #include <atlcom.h> +#include "base/file_util.h" +#include "base/path_service.h" #include "base/scoped_comptr_win.h" -#include "chrome_frame/bho.h" -#include "chrome_frame/urlmon_moniker.h" +#include "chrome_frame/urlmon_bind_status_callback.h" #include "chrome_frame/test/urlmon_moniker_tests.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" -using testing::_; using testing::Return; -using testing::WithArg; -using testing::WithArgs; -using testing::SetArgumentPointee; -using testing::StrEq; using testing::Eq; -class UrlmonMonikerTest : public testing::Test { +class MonikerPatchTest : public testing::Test { protected: - UrlmonMonikerTest() { + MonikerPatchTest() { } + + virtual void SetUp() { + PathService::Get(base::DIR_SOURCE_ROOT, &test_file_path_); + test_file_path_ = test_file_path_.Append(FILE_PATH_LITERAL("chrome_frame")) + .Append(FILE_PATH_LITERAL("test")) + .Append(FILE_PATH_LITERAL("data")); + } + + bool ReadFileAsString(const wchar_t* file_name, std::string* file_contents) { + EXPECT_TRUE(file_name); + FilePath file_path = test_file_path_.Append(file_name); + return file_util::ReadFileToString(file_path, file_contents); + } + + static bool StringToStream(const std::string& data, IStream** ret) { + EXPECT_TRUE(!data.empty()); + + ScopedComPtr<IStream> stream; + HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, stream.Receive()); + EXPECT_HRESULT_SUCCEEDED(hr); + if (FAILED(hr)) { + return false; + } + + DWORD written = 0; + hr = stream->Write(data.c_str(), data.size(), &written); + EXPECT_HRESULT_SUCCEEDED(hr); + EXPECT_EQ(data.size(), written); + + bool result = false; + if (SUCCEEDED(hr)) { + RewindStream(stream); + *ret = stream.Detach(); + result = true; + } + + return result; + } + + FilePath test_file_path_; }; -// Tests the ReadStreamCache class by writing content into a stream object -// and verify that reading that stream through the ReadStreamCache class -// reads the correct content and also verifies that ReadStreamCache caches -// all the reads. -TEST_F(UrlmonMonikerTest, ReadStreamCache) { - CComObjectStackEx<ReadStreamCache> read_stream; - EXPECT_EQ(NULL, read_stream.cache()); - - ScopedComPtr<IStream> test_stream; - ::CreateStreamOnHGlobal(NULL, TRUE, test_stream.Receive()); - EXPECT_TRUE(NULL != test_stream); - const char test_string[] = "ReadStreamCacheTest"; - DWORD written; - EXPECT_HRESULT_SUCCEEDED(test_stream->Write(test_string, sizeof(test_string), - &written)); - EXPECT_HRESULT_SUCCEEDED(RewindStream(test_stream)); - - read_stream.SetDelegate(test_stream); - - char buffer[0xff]; +// Tests the CacheStream class by writing content into a stream object +// and verify that reading that stream back +TEST_F(MonikerPatchTest, CacheStream) { + const char data[] = "ReadStreamCacheTest"; + char ret[2 * sizeof(data)] = {0}; DWORD read = 0; - EXPECT_HRESULT_SUCCEEDED(read_stream.Read(buffer, sizeof(buffer), &read)); - EXPECT_EQ(read, sizeof(test_string)); - EXPECT_EQ(read_stream.GetCacheSize(), sizeof(test_string)); - read_stream.RewindCache(); - IStream* cache = read_stream.cache(); - EXPECT_TRUE(NULL != cache); - if (cache) { - read = 0; - EXPECT_HRESULT_SUCCEEDED(cache->Read(buffer, sizeof(buffer), &read)); - EXPECT_EQ(read, sizeof(test_string)); - EXPECT_EQ(0, memcmp(test_string, buffer, sizeof(test_string))); - } + + // Test 1: empty stream reads nothing + CComObjectStackEx<CacheStream> cache_stream1; + EXPECT_EQ(E_PENDING, cache_stream1.Read(ret, sizeof(ret), &read)); + EXPECT_EQ(0, read); + + // Test 2: Read from initialized cache + CComObjectStackEx<CacheStream> cache_stream2; + cache_stream2.Initialize(data, sizeof(data)); + EXPECT_HRESULT_SUCCEEDED(cache_stream2.Read(ret, sizeof(ret), &read)); + EXPECT_EQ(sizeof(data), read); + EXPECT_EQ(std::string(data), std::string(ret)); + + read = 0; + EXPECT_EQ(E_PENDING, cache_stream2.Read(ret, sizeof(ret), &read)); + EXPECT_EQ(0, read); } -// Verifies that we can override bind results by using the SimpleBindingImpl -// class. -TEST_F(UrlmonMonikerTest, SimpleBindingImpl1) { - CComObjectStackEx<SimpleBindingImpl> test; - ScopedComPtr<IBinding> binding; - binding.QueryFrom(&test); - EXPECT_TRUE(binding != NULL); - test.OverrideBindResults(E_INVALIDARG); - DWORD hr = E_UNEXPECTED; - EXPECT_HRESULT_SUCCEEDED(binding->GetBindResult(NULL, &hr, NULL, NULL)); - EXPECT_EQ(E_INVALIDARG, hr); - test.OverrideBindResults(E_ACCESSDENIED); - // {1AF15145-104B-4bd8-AA4F-97CEFD40D370} - just something non-null. - GUID guid = { 0x1af15145, 0x104b, 0x4bd8, - { 0xaa, 0x4f, 0x97, 0xce, 0xfd, 0x40, 0xd3, 0x70 } }; - EXPECT_HRESULT_SUCCEEDED(binding->GetBindResult(&guid, &hr, NULL, NULL)); - EXPECT_EQ(E_ACCESSDENIED, hr); - EXPECT_TRUE(guid == GUID_NULL); +ACTION_P3(ReadStream, buffer, size, ret) { + EXPECT_EQ(TYMED_ISTREAM, arg3->tymed); + *ret = arg3->pstm->Read(buffer, *size, size); } -// Tests the SimpleBindingImpl class with a delegate. Verifies that the -// delegate gets called and also that we can override the bind results. -TEST_F(UrlmonMonikerTest, SimpleBindingImpl2) { - CComObjectStackEx<MockBindingImpl> mock; - CComObjectStackEx<SimpleBindingImpl> test; - - EXPECT_CALL(mock, QueryService(_, _, _)) - .WillOnce(Return(E_ACCESSDENIED)); - EXPECT_CALL(mock, GetBindResult(_, _, _, _)) - .WillRepeatedly(DoAll(SetArgumentPointee<1>(E_ACCESSDENIED), - Return(S_OK))); - EXPECT_CALL(mock, Abort()) - .WillOnce(Return(E_ACCESSDENIED)); - - ScopedComPtr<IServiceProvider> svc; - svc.QueryFrom(test.GetUnknown()); - EXPECT_TRUE(svc == NULL); - - test.SetDelegate(&mock); - - // Now we should have access to IServiceProvider - svc.QueryFrom(test.GetUnknown()); - EXPECT_TRUE(svc != NULL); - - ScopedComPtr<IUnknown> unk; - EXPECT_EQ(E_ACCESSDENIED, svc->QueryService(GUID_NULL, IID_NULL, - reinterpret_cast<void**>(unk.Receive()))); - - // Call through to the mock's GetBindResult implementation. - DWORD result; - test.GetBindResult(NULL, &result, NULL, NULL); - EXPECT_TRUE(result == E_ACCESSDENIED); - // Let the binding override the result code. - test.OverrideBindResults(INET_E_TERMINATED_BIND); - test.GetBindResult(NULL, &result, NULL, NULL); - EXPECT_TRUE(result == INET_E_TERMINATED_BIND); - - EXPECT_EQ(E_ACCESSDENIED, test.Abort()); +// Tests the implementation of BSCBFeedData to feed data to the +// specified IBindStatusCallback +TEST_F(MonikerPatchTest, BSCBFeedData) { + CComObjectStackEx<MockBindStatusCallbackImpl> mock; + const char data[] = "ReadStreamCacheTest"; + const DWORD size = sizeof(data); + const CLIPFORMAT cf = 0xd0d0; + const DWORD flags = BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION; + const DWORD kArbitraryreadSize = 0xdeadbabe; + + char read_buffer1[size] = {0}, read_buffer2[size] = {0}; + DWORD read_size1 = size, read_size2 = kArbitraryreadSize; + HRESULT ret1 = E_FAIL, ret2 = E_FAIL; + + EXPECT_CALL(mock, OnDataAvailable(flags, size, + testing::Field(&FORMATETC::cfFormat, cf), + testing::Field(&STGMEDIUM::tymed, TYMED_ISTREAM))) + .WillOnce(testing::DoAll( + ReadStream(read_buffer1, &read_size1, &ret1), + ReadStream(read_buffer2, &read_size2, &ret2), + Return(S_OK))); + + EXPECT_HRESULT_SUCCEEDED(CacheStream::BSCBFeedData(&mock, data, size, cf, + flags)); + + EXPECT_HRESULT_SUCCEEDED(ret1); + EXPECT_STREQ(data, read_buffer1); + EXPECT_EQ(size, read_size1); + + EXPECT_EQ(E_PENDING, ret2); + EXPECT_STREQ("", read_buffer2); + EXPECT_EQ(kArbitraryreadSize, read_size2); } -// Tests the RequestData class. Content is fed to the object via OnX methods -// and then we verify that the cached content is correct by calling -// FireHttpNegotiateEvents and see if the notifications contain the correct -// content. -TEST_F(UrlmonMonikerTest, RequestHeaders) { - scoped_refptr<RequestData> test(new RequestData()); - test->Initialize(NULL); - - const wchar_t url[] = L"http://www.chromium.org"; - const wchar_t begin_headers[] = L"Cookie: endilega\r\n"; - const wchar_t request_headers[] = L"GET / HTTP/1.0\r\nHost: cough\r\n\rn"; - const wchar_t response_headers[] = L"HTTP 200 OK\r\nHave-a: good-day\r\n\r\n"; - const wchar_t additional_headers[] = L"Referer: http://foo.com\r\n"; - - // Null pointers should be ignored. - RequestHeaders* headers = test->headers(); - EXPECT_TRUE(NULL != headers); - headers->OnBeginningTransaction(NULL, NULL, NULL); - headers->OnBeginningTransaction(url, begin_headers, additional_headers); - headers->OnResponse(500, NULL, NULL); - headers->OnResponse(200, response_headers, request_headers); - - CComObjectStackEx<MockHttpNegotiateImpl> mock; - EXPECT_CALL(mock, BeginningTransaction(StrEq(url), StrEq(begin_headers), - _, _)) - .WillOnce(Return(S_OK)); - EXPECT_CALL(mock, OnResponse(Eq(200), StrEq(response_headers), - StrEq(request_headers), _)) - .WillOnce(Return(S_OK)); - - EXPECT_EQ(0, headers->request_url().compare(url)); - - headers->FireHttpNegotiateEvents(&mock); +const wchar_t kSmallHtmlMetaTag[] = L"sub_frame1.html"; +const wchar_t kSmallHtmlNoMetaTag[] = L"host_browser.html"; + +// Test various aspects of the SniffData class +TEST_F(MonikerPatchTest, SniffDataMetaTag) { + std::string small_html_meta_tag, small_html_no_meta_tag; + ASSERT_TRUE(ReadFileAsString(kSmallHtmlMetaTag, &small_html_meta_tag)); + ASSERT_TRUE(ReadFileAsString(kSmallHtmlNoMetaTag, &small_html_no_meta_tag)); + + ScopedComPtr<IStream> stream_with_meta, stream_no_meta; + ASSERT_TRUE(StringToStream(small_html_meta_tag, stream_with_meta.Receive())); + ASSERT_TRUE(StringToStream(small_html_no_meta_tag, + stream_no_meta.Receive())); + + // Initialize 2 sniffers 1 with meta tag and 1 without. + SniffData sniffer1, sniffer2; + EXPECT_TRUE(sniffer1.InitializeCache(std::wstring())); + EXPECT_TRUE(sniffer2.InitializeCache(std::wstring())); + EXPECT_HRESULT_SUCCEEDED(sniffer1.ReadIntoCache(stream_with_meta, true)); + EXPECT_HRESULT_SUCCEEDED(sniffer2.ReadIntoCache(stream_no_meta, true)); + + // Verify renderer type and size read. + EXPECT_TRUE(sniffer1.is_chrome()); + EXPECT_EQ(SniffData::OTHER, sniffer2.renderer_type()); + EXPECT_EQ(small_html_meta_tag.size(), sniffer1.size()); + EXPECT_EQ(small_html_no_meta_tag.size(), sniffer2.size()); } -// Tests the HTML content portion of the RequestData class. -// Here we provide content in the form of a stream object and call -// OnDataAvailable to make the object cache the contents. -// Then we fetch the cached content stream by calling -// GetResetCachedContentStream and verify that it's contents are correct. -// In order to also test when data is cached outside of OnDataAvailable -// calls, we also call DelegateDataRead. In this test we simply use the -// original content again which will make the end results that the cached -// content should be double the test content. -TEST_F(UrlmonMonikerTest, RequestDataContent) { - scoped_refptr<RequestData> test(new RequestData()); - test->Initialize(NULL); +// Now test how the data is fed back the the bind status callback. +// case 1: callback reads data in 1 read +TEST_F(MonikerPatchTest, SniffDataPlayback1) { + std::string small_html_meta_tag; + ScopedComPtr<IStream> stream_with_meta; + SniffData sniffer; - CComObjectStackEx<MockBindStatusCallbackImpl> mock; + EXPECT_TRUE(sniffer.InitializeCache(std::wstring())); + ASSERT_TRUE(ReadFileAsString(kSmallHtmlMetaTag, &small_html_meta_tag)); + ASSERT_TRUE(StringToStream(small_html_meta_tag, stream_with_meta.Receive())); + EXPECT_HRESULT_SUCCEEDED(sniffer.ReadIntoCache(stream_with_meta, true)); - ScopedComPtr<IStream> data; - ::CreateStreamOnHGlobal(NULL, TRUE, data.Receive()); - const char content[] = "<html><head>" - "<meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\" />" - "</head><body>Test HTML content</body></html>"; - data->Write(content, sizeof(content) - 1, NULL); - STATSTG stat = {0}; - data->Stat(&stat, STATFLAG_NONAME); - DCHECK(stat.cbSize.LowPart == (sizeof(content) - 1)); - RewindStream(data); - - FORMATETC format = {0}; - format.cfFormat = ::RegisterClipboardFormat(L"application/chromepage"); - format.tymed = TYMED_ISTREAM; - STGMEDIUM storage = {0}; - storage.tymed = TYMED_ISTREAM; - storage.pstm = data; - - DWORD flags = BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | - BSCF_DATAFULLYAVAILABLE; - - EXPECT_CALL(mock, OnDataAvailable(Eq(flags), Eq(stat.cbSize.LowPart), _, _)) - .WillOnce(DoAll( - WithArgs<3>(testing::Invoke( - &MockBindStatusCallbackImpl::ReadAllData)), + CComObjectStackEx<MockBindStatusCallbackImpl> mock; + const CLIPFORMAT cf = 0xd0d0; + const DWORD flags = BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION; + const DWORD data_size = small_html_meta_tag.size(); + + DWORD read_size1 = data_size * 2; + scoped_ptr<char> read_buffer1(new char[read_size1]); + ZeroMemory(read_buffer1.get(), read_size1); + + char read_buffer2[10] = {0}; + DWORD read_size2 = sizeof(read_buffer2); + HRESULT ret1 = E_FAIL, ret2 = E_FAIL; + + EXPECT_CALL(mock, OnDataAvailable(flags, data_size, + testing::Field(&FORMATETC::cfFormat, cf), + testing::Field(&STGMEDIUM::tymed, TYMED_ISTREAM))) + .WillOnce(testing::DoAll( + ReadStream(read_buffer1.get(), &read_size1, &ret1), + ReadStream(read_buffer2, &read_size2, &ret2), Return(S_OK))); - size_t bytes_read = 0; - test->DelegateDataRead(&mock, flags, stat.cbSize.LowPart, &format, &storage, - &bytes_read); - - DCHECK(bytes_read == stat.cbSize.LowPart); - DCHECK(test->GetCachedContentSize() == bytes_read); - - // Also test that the CacheAll method appends the stream. - RewindStream(data); - test->CacheAll(data); - DCHECK(test->GetCachedContentSize() == (bytes_read * 2)); - - ScopedComPtr<IStream> cache; - EXPECT_HRESULT_SUCCEEDED(test->GetResetCachedContentStream(cache.Receive())); - if (cache) { - char buffer[0xffff]; - DCHECK((bytes_read * 2) <= sizeof(buffer)); - DWORD read = 0; - cache->Read(buffer, sizeof(buffer), &read); - EXPECT_EQ(read, bytes_read * 2); - EXPECT_EQ(0, memcmp(content, buffer, sizeof(content) - 1)); - EXPECT_EQ(0, memcmp(content, buffer + sizeof(content) - 1, - sizeof(content) - 1)); - } + EXPECT_HRESULT_SUCCEEDED(sniffer.DrainCache(&mock, flags, cf)); + + EXPECT_HRESULT_SUCCEEDED(ret1); + EXPECT_EQ(small_html_meta_tag, read_buffer1.get()); + EXPECT_EQ(data_size, read_size1); + + EXPECT_EQ(E_PENDING, ret2); + EXPECT_STREQ("", read_buffer2); + EXPECT_EQ(sizeof(read_buffer2), read_size2); } +// case 2: callback reads data in 2 reads. +TEST_F(MonikerPatchTest, SniffDataPlayback2) { + std::string small_html_meta_tag; + ScopedComPtr<IStream> stream_with_meta; + SniffData sniffer; + + EXPECT_TRUE(sniffer.InitializeCache(std::wstring())); + ASSERT_TRUE(ReadFileAsString(kSmallHtmlMetaTag, &small_html_meta_tag)); + ASSERT_TRUE(StringToStream(small_html_meta_tag, stream_with_meta.Receive())); + EXPECT_HRESULT_SUCCEEDED(sniffer.ReadIntoCache(stream_with_meta, true)); + + CComObjectStackEx<MockBindStatusCallbackImpl> mock; + const CLIPFORMAT cf = 0xd0d0; + const DWORD flags = BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION; + const DWORD data_size = small_html_meta_tag.size(); + + DWORD read_size1 = data_size / 2; // First read is half the data. + DWORD read_size2 = data_size; // Second read, try to read past data. + scoped_ptr<char> read_buffer1(new char[read_size1]); + scoped_ptr<char> read_buffer2(new char[read_size2]); + ZeroMemory(read_buffer1.get(), read_size1); + ZeroMemory(read_buffer2.get(), read_size2); + + char read_buffer3[10] = {0}; + DWORD read_size3 = sizeof(read_buffer3); + HRESULT ret1 = E_FAIL, ret2 = E_FAIL, ret3 = E_FAIL; + + EXPECT_CALL(mock, OnDataAvailable(flags, data_size, + testing::Field(&FORMATETC::cfFormat, cf), + testing::Field(&STGMEDIUM::tymed, TYMED_ISTREAM))) + .WillOnce(testing::DoAll( + ReadStream(read_buffer1.get(), &read_size1, &ret1), + ReadStream(read_buffer2.get(), &read_size2, &ret2), + ReadStream(read_buffer3, &read_size3, &ret3), + Return(S_OK))); + + EXPECT_HRESULT_SUCCEEDED(sniffer.DrainCache(&mock, flags, cf)); + + EXPECT_HRESULT_SUCCEEDED(ret1); + EXPECT_HRESULT_SUCCEEDED(ret2); + EXPECT_EQ(data_size/2, read_size1); + EXPECT_EQ(data_size - read_size1, read_size2); + + std::string data_read; + data_read.append(read_buffer1.get(), read_size1); + data_read.append(read_buffer2.get(), read_size2); + EXPECT_EQ(small_html_meta_tag, data_read); + + EXPECT_EQ(E_PENDING, ret3); + EXPECT_STREQ("", read_buffer3); + EXPECT_EQ(sizeof(read_buffer3), read_size3); +} |