| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2015 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/callback.h" |
| 9 #include "net/base/io_buffer.h" |
| 10 #include "net/filter/mock_stream_source.h" |
| 11 #include "net/filter/sdch_stream_delegate.h" |
| 12 #include "net/filter/sdch_stream_source.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" |
| 14 |
| 15 namespace { |
| 16 |
| 17 using net::Error; |
| 18 using net::MockStreamSource; |
| 19 using net::SdchStreamSource; |
| 20 |
| 21 const size_t kBufferSize = 4096; |
| 22 const char* kDictionaryError = "dictionary error"; |
| 23 const char* kDecodingError = "decoding error"; |
| 24 |
| 25 static const char kTestVcdiffDictionary[] = |
| 26 "DictionaryFor" |
| 27 "SdchCompression1SdchCompression2SdchCompression3SdchCompression\n"; |
| 28 static const char kTestData[] = |
| 29 "0000000000000000000000000000000000000000000000" |
| 30 "0000000000000000000000000000TestData " |
| 31 "SdchCompression1SdchCompression2SdchCompression3SdchCompression" |
| 32 "00000000000000000000000000000000000000000000000000000000000000000000000000" |
| 33 "000000000000000000000000000000000000000\n"; |
| 34 static const char kSdchCompressedTestData[] = |
| 35 "\326\303\304\0\0\001M\0\201S\202\004\0\201E\006\001" |
| 36 "00000000000000000000000000000000000000000000000000000000000000000000000000" |
| 37 "TestData 00000000000000000000000000000000000000000000000000000000000000000" |
| 38 "000000000000000000000000000000000000000000000000\n\001S\023\077\001r\r"; |
| 39 |
| 40 class SdchStreamTest : public ::testing::Test, |
| 41 public net::SdchStreamSourceDelegate { |
| 42 public: |
| 43 SdchStreamTest() |
| 44 : dictionary_error_handled_(false), decoding_error_handled_(false) {} |
| 45 |
| 46 void SetUp() override { |
| 47 ::testing::Test::SetUp(); |
| 48 |
| 49 out_buffer_ = new net::IOBuffer(kBufferSize); |
| 50 |
| 51 scoped_ptr<MockStreamSource> source(new MockStreamSource); |
| 52 source_ = source.get(); |
| 53 sdch_stream_.reset(new SdchStreamSource(std::move(source), this)); |
| 54 } |
| 55 |
| 56 net::IOBuffer* out_buffer() { return out_buffer_.get(); } |
| 57 char* out_data() { return out_buffer_->data(); } |
| 58 size_t out_buffer_size() { return kBufferSize; } |
| 59 |
| 60 Error last_error() { return last_error_; } |
| 61 size_t last_bytes_read() { return last_bytes_read_; } |
| 62 |
| 63 MockStreamSource* source() { return source_; } |
| 64 SdchStreamSource* sdch_stream() { return sdch_stream_.get(); } |
| 65 |
| 66 bool dictionary_error_handled() { return dictionary_error_handled_; } |
| 67 bool decoding_error_handled() { return decoding_error_handled_; } |
| 68 std::string last_get_dictionary_id() { return last_get_dictionary_id_; } |
| 69 |
| 70 net::StreamSource::OnReadCompleteCallback callback() { |
| 71 return base::Bind(&SdchStreamTest::OnReadComplete, base::Unretained(this)); |
| 72 } |
| 73 |
| 74 void OnReadComplete(Error error, size_t bytes_read) { |
| 75 last_error_ = error; |
| 76 last_bytes_read_ = bytes_read; |
| 77 } |
| 78 |
| 79 void ReadStream() { |
| 80 last_error_ = sdch_stream()->Read(out_buffer(), out_buffer_size(), |
| 81 &last_bytes_read_, callback()); |
| 82 } |
| 83 |
| 84 void SetTestDictionary(const std::string& dictionary_id, |
| 85 const std::string& dictionary_text) { |
| 86 test_dictionary_id_ = dictionary_id; |
| 87 test_dictionary_text_ = dictionary_text; |
| 88 } |
| 89 |
| 90 void AppendDictionaryIdTo(std::string* resp, std::string* server_id) { |
| 91 std::string client_id; |
| 92 net::SdchManager::GenerateHash(kTestVcdiffDictionary, &client_id, |
| 93 server_id); |
| 94 SetTestDictionary(*server_id, kTestVcdiffDictionary); |
| 95 char response[server_id->size() + 1]; |
| 96 memcpy(response, server_id->data(), server_id->size()); |
| 97 response[server_id->size()] = '\0'; |
| 98 resp->append(response, server_id->size() + 1); |
| 99 } |
| 100 |
| 101 // SdchStreamSourceDelegate implementation. |
| 102 bool HandleDictionaryError(SdchStreamSource* source) override { |
| 103 dictionary_error_handled_ = true; |
| 104 sdch_stream()->ReplaceOutput(kDictionaryError, strlen(kDictionaryError)); |
| 105 return true; |
| 106 } |
| 107 |
| 108 bool HandleDecodingError(SdchStreamSource* source) override { |
| 109 decoding_error_handled_ = true; |
| 110 sdch_stream()->ReplaceOutput(kDecodingError, strlen(kDictionaryError)); |
| 111 return true; |
| 112 } |
| 113 |
| 114 bool GetDictionary(const std::string& server_id, |
| 115 const std::string** text) override { |
| 116 last_get_dictionary_id_ = server_id; |
| 117 if (server_id == test_dictionary_id_) { |
| 118 *text = &test_dictionary_text_; |
| 119 return true; |
| 120 } |
| 121 return false; |
| 122 } |
| 123 |
| 124 void NotifyStreamDone() override {} |
| 125 |
| 126 private: |
| 127 // Owned by sdch_stream_. |
| 128 MockStreamSource* source_; |
| 129 scoped_ptr<SdchStreamSource> sdch_stream_; |
| 130 |
| 131 scoped_refptr<net::IOBuffer> out_buffer_; |
| 132 |
| 133 std::string test_dictionary_id_; |
| 134 std::string test_dictionary_text_; |
| 135 |
| 136 size_t last_bytes_read_; |
| 137 Error last_error_; |
| 138 std::string last_get_dictionary_id_; |
| 139 bool dictionary_error_handled_; |
| 140 bool decoding_error_handled_; |
| 141 }; |
| 142 |
| 143 TEST_F(SdchStreamTest, EmptyStream) { |
| 144 source()->AddReadResult("", 0, net::OK, true); |
| 145 ReadStream(); |
| 146 EXPECT_EQ(net::OK, last_error()); |
| 147 EXPECT_EQ(0U, last_bytes_read()); |
| 148 } |
| 149 |
| 150 // Ensure that GetDictionary() is not called at all if the SDCH dictionary ID is |
| 151 // malformed. |
| 152 TEST_F(SdchStreamTest, BogusDictionaryId) { |
| 153 char id[] = {0x1f, '0', '0', '0', '0', '0', '0', '0', 0x0}; |
| 154 source()->AddReadResult(id, sizeof(id), net::OK, true); |
| 155 SetTestDictionary(id, "..."); |
| 156 ReadStream(); |
| 157 EXPECT_TRUE(dictionary_error_handled()); |
| 158 EXPECT_EQ("", last_get_dictionary_id()); |
| 159 EXPECT_EQ(net::OK, last_error()); |
| 160 EXPECT_EQ(strlen(kDictionaryError), last_bytes_read()); |
| 161 EXPECT_EQ(0, memcmp(kDictionaryError, out_data(), last_bytes_read())); |
| 162 } |
| 163 |
| 164 // Ensure that the stream's dictionary error handler is called if GetDictionary |
| 165 // returns no dictionary. |
| 166 TEST_F(SdchStreamTest, NoDictionaryError) { |
| 167 char id[] = "00000000"; |
| 168 source()->AddReadResult(id, sizeof(id), net::OK, true); |
| 169 ReadStream(); |
| 170 EXPECT_TRUE(dictionary_error_handled()); |
| 171 EXPECT_EQ(id, last_get_dictionary_id()); |
| 172 } |
| 173 |
| 174 TEST_F(SdchStreamTest, DictionaryLoaded) { |
| 175 std::string response; |
| 176 std::string server_id; |
| 177 AppendDictionaryIdTo(&response, &server_id); |
| 178 source()->AddReadResult(response.data(), response.size(), net::OK, true); |
| 179 ReadStream(); |
| 180 EXPECT_FALSE(dictionary_error_handled()); |
| 181 EXPECT_EQ(server_id, last_get_dictionary_id()); |
| 182 } |
| 183 |
| 184 TEST_F(SdchStreamTest, DecompressOneBlockSync) { |
| 185 std::string response; |
| 186 std::string server_id; |
| 187 AppendDictionaryIdTo(&response, &server_id); |
| 188 source()->AddReadResult(response.data(), response.size(), net::OK, true); |
| 189 source()->AddReadResult(kSdchCompressedTestData, |
| 190 sizeof(kSdchCompressedTestData) - 1, net::OK, true); |
| 191 ReadStream(); |
| 192 EXPECT_FALSE(dictionary_error_handled()); |
| 193 EXPECT_FALSE(decoding_error_handled()); |
| 194 EXPECT_EQ(server_id, last_get_dictionary_id()); |
| 195 EXPECT_EQ(net::OK, last_error()); |
| 196 EXPECT_EQ(sizeof(kTestData) - 1, last_bytes_read()); |
| 197 EXPECT_EQ(0, memcmp(kTestData, out_data(), last_bytes_read())); |
| 198 } |
| 199 |
| 200 TEST_F(SdchStreamTest, DecompressTwoBlocksSync) { |
| 201 std::string response; |
| 202 std::string server_id; |
| 203 AppendDictionaryIdTo(&response, &server_id); |
| 204 source()->AddReadResult(response.data(), response.size(), net::OK, true); |
| 205 source()->AddReadResult(kSdchCompressedTestData, 32, net::OK, true); |
| 206 source()->AddReadResult(kSdchCompressedTestData + 32, |
| 207 sizeof(kSdchCompressedTestData) - 1 - 32, net::OK, |
| 208 true); |
| 209 ReadStream(); |
| 210 EXPECT_FALSE(dictionary_error_handled()); |
| 211 EXPECT_FALSE(decoding_error_handled()); |
| 212 EXPECT_EQ(server_id, last_get_dictionary_id()); |
| 213 EXPECT_EQ(net::OK, last_error()); |
| 214 EXPECT_EQ(sizeof(kTestData) - 1, last_bytes_read()); |
| 215 EXPECT_EQ(0, memcmp(kTestData, out_data(), last_bytes_read())); |
| 216 } |
| 217 |
| 218 TEST_F(SdchStreamTest, DecompressOneBlockAsync) { |
| 219 std::string response; |
| 220 std::string server_id; |
| 221 AppendDictionaryIdTo(&response, &server_id); |
| 222 source()->AddReadResult(response.data(), response.size(), net::OK, false); |
| 223 source()->AddReadResult(kSdchCompressedTestData, |
| 224 sizeof(kSdchCompressedTestData) - 1, net::OK, false); |
| 225 ReadStream(); |
| 226 EXPECT_EQ(net::ERR_IO_PENDING, last_error()); |
| 227 source()->CompleteNextRead(); |
| 228 // The callback hasn't been called yet, because the first read didn't return |
| 229 // any bytes that could be decoded to produce output. |
| 230 EXPECT_EQ(net::ERR_IO_PENDING, last_error()); |
| 231 source()->CompleteNextRead(); |
| 232 EXPECT_FALSE(dictionary_error_handled()); |
| 233 EXPECT_FALSE(decoding_error_handled()); |
| 234 EXPECT_EQ(server_id, last_get_dictionary_id()); |
| 235 EXPECT_EQ(net::OK, last_error()); |
| 236 EXPECT_EQ(sizeof(kTestData) - 1, last_bytes_read()); |
| 237 EXPECT_EQ(0, memcmp(kTestData, out_data(), last_bytes_read())); |
| 238 } |
| 239 |
| 240 } // namespace |
| OLD | NEW |