OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 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 <utility> |
| 6 |
| 7 #include "content/browser/webui/i18n_source_stream.h" |
| 8 #include "net/base/io_buffer.h" |
| 9 #include "net/base/test_completion_callback.h" |
| 10 #include "net/filter/mock_source_stream.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" |
| 12 |
| 13 namespace content { |
| 14 |
| 15 namespace { |
| 16 |
| 17 // These constants are rather arbitrary, though the offsets and other sizes must |
| 18 // be less than kBufferSize. |
| 19 const int kBufferSize = 256; |
| 20 const int kSmallBufferSize = 1; |
| 21 |
| 22 const int kShortReplacementOffset = 5; |
| 23 const char kShortReplacementKey[] = "a"; |
| 24 const char kShortReplacementToken[] = "$i18n{a}"; |
| 25 const char kShortReplacementValue[] = "short"; |
| 26 |
| 27 const int kLongReplacementOffset = 33; |
| 28 const char kLongReplacementKey[] = "aLongerReplacementName"; |
| 29 const char kLongReplacementToken[] = "$i18n{aLongerReplacementName}"; |
| 30 const char kLongReplacementValue[] = "second replacement"; |
| 31 |
| 32 const int kSourceSize = |
| 33 50 + arraysize(kShortReplacementToken) + arraysize(kLongReplacementToken); |
| 34 const int kResultSize = |
| 35 50 + arraysize(kShortReplacementValue) + arraysize(kLongReplacementValue); |
| 36 |
| 37 struct I18nTestParam { |
| 38 I18nTestParam(int buf_size, net::MockSourceStream::Mode read_mode) |
| 39 : buffer_size(buf_size), mode(read_mode) {} |
| 40 |
| 41 const int buffer_size; |
| 42 const net::MockSourceStream::Mode mode; |
| 43 }; |
| 44 |
| 45 } // namespace |
| 46 |
| 47 class I18nSourceStreamTest : public ::testing::TestWithParam<I18nTestParam> { |
| 48 protected: |
| 49 I18nSourceStreamTest() : output_buffer_size_(GetParam().buffer_size) {} |
| 50 |
| 51 // Helpful function to initialize the test fixture. |
| 52 void Init() { |
| 53 source_data_len_ = kBufferSize; |
| 54 for (size_t i = 0; i < source_data_len_; i++) |
| 55 source_data_[i] = i % 256; |
| 56 |
| 57 // Inserts must be done last to first as they appear in the buffer. |
| 58 InsertText(source_data_, source_data_len_, kLongReplacementOffset, |
| 59 kLongReplacementToken); |
| 60 InsertText(source_data_, source_data_len_, kShortReplacementOffset, |
| 61 kShortReplacementToken); |
| 62 |
| 63 result_data_len_ = kBufferSize; |
| 64 for (size_t i = 0; i < result_data_len_; i++) |
| 65 result_data_[i] = i % 256; |
| 66 |
| 67 // Inserts must be done last to first as they appear in the buffer. |
| 68 InsertText(result_data_, result_data_len_, kLongReplacementOffset, |
| 69 kLongReplacementValue); |
| 70 InsertText(result_data_, result_data_len_, kShortReplacementOffset, |
| 71 kShortReplacementValue); |
| 72 |
| 73 output_buffer_ = new net::IOBuffer(output_buffer_size_); |
| 74 std::unique_ptr<net::MockSourceStream> source(new net::MockSourceStream()); |
| 75 source_ = source.get(); |
| 76 |
| 77 replacements_[kShortReplacementKey] = kShortReplacementValue; |
| 78 replacements_[kLongReplacementKey] = kLongReplacementValue; |
| 79 stream_ = I18nSourceStream::Create( |
| 80 std::move(source), net::SourceStream::TYPE_NONE, &replacements_); |
| 81 } |
| 82 |
| 83 // If MockSourceStream::Mode is ASYNC, completes 1 read from |mock_stream| and |
| 84 // wait for |callback| to complete. If Mode is not ASYNC, does nothing and |
| 85 // returns |previous_result|. |
| 86 int CompleteReadIfAsync(int previous_result, |
| 87 net::TestCompletionCallback* callback, |
| 88 net::MockSourceStream* mock_stream) { |
| 89 if (GetParam().mode == net::MockSourceStream::ASYNC) { |
| 90 EXPECT_EQ(net::ERR_IO_PENDING, previous_result); |
| 91 mock_stream->CompleteNextRead(); |
| 92 return callback->WaitForResult(); |
| 93 } |
| 94 return previous_result; |
| 95 } |
| 96 |
| 97 void InsertText(char* buffer, |
| 98 size_t buffer_length, |
| 99 size_t offset, |
| 100 const char* text) { |
| 101 // Intended to be dead simple so that it can be confirmed |
| 102 // as correct by hand. |
| 103 size_t text_length = strlen(text); |
| 104 memmove(buffer + offset + text_length, buffer + offset, |
| 105 buffer_length - offset - text_length); |
| 106 memcpy(buffer + offset, text, text_length); |
| 107 } |
| 108 |
| 109 char* source_data() { return source_data_; } |
| 110 size_t source_data_len() { return source_data_len_; } |
| 111 |
| 112 char* result_data() { return result_data_; } |
| 113 size_t result_data_len() { return result_data_len_; } |
| 114 |
| 115 net::IOBuffer* output_buffer() { return output_buffer_.get(); } |
| 116 char* output_data() { return output_buffer_->data(); } |
| 117 size_t output_buffer_size() { return output_buffer_size_; } |
| 118 |
| 119 net::MockSourceStream* source() { return source_; } |
| 120 I18nSourceStream* stream() { return stream_.get(); } |
| 121 |
| 122 // Reads from |stream_| until an error occurs or the EOF is reached. |
| 123 // When an error occurs, returns the net error code. When an EOF is reached, |
| 124 // returns the number of bytes read and appends data read to |output|. |
| 125 int ReadStream(std::string* output) { |
| 126 int bytes_read = 0; |
| 127 while (true) { |
| 128 net::TestCompletionCallback callback; |
| 129 int rv = stream_->Read(output_buffer(), output_buffer_size(), |
| 130 callback.callback()); |
| 131 if (rv == net::ERR_IO_PENDING) |
| 132 rv = CompleteReadIfAsync(rv, &callback, source()); |
| 133 if (rv == net::OK) |
| 134 break; |
| 135 if (rv < net::OK) |
| 136 return rv; |
| 137 EXPECT_GT(rv, net::OK); |
| 138 bytes_read += rv; |
| 139 output->append(output_data(), rv); |
| 140 } |
| 141 return bytes_read; |
| 142 } |
| 143 |
| 144 private: |
| 145 char source_data_[kBufferSize]; |
| 146 size_t source_data_len_; |
| 147 |
| 148 char result_data_[kBufferSize]; |
| 149 size_t result_data_len_; |
| 150 |
| 151 scoped_refptr<net::IOBuffer> output_buffer_; |
| 152 const int output_buffer_size_; |
| 153 |
| 154 net::MockSourceStream* source_; |
| 155 std::unique_ptr<I18nSourceStream> stream_; |
| 156 |
| 157 ui::TemplateReplacements replacements_; |
| 158 }; |
| 159 |
| 160 INSTANTIATE_TEST_CASE_P( |
| 161 I18nSourceStreamTests, |
| 162 I18nSourceStreamTest, |
| 163 ::testing::Values(I18nTestParam(kBufferSize, net::MockSourceStream::SYNC), |
| 164 I18nTestParam(kSmallBufferSize, |
| 165 net::MockSourceStream::SYNC))); |
| 166 |
| 167 TEST_P(I18nSourceStreamTest, EmptyStream) { |
| 168 Init(); |
| 169 source()->AddReadResult("", 0, net::OK, GetParam().mode); |
| 170 std::string actual_output; |
| 171 int result = ReadStream(&actual_output); |
| 172 EXPECT_EQ(net::OK, result); |
| 173 EXPECT_EQ("i18n", stream()->Description()); |
| 174 } |
| 175 |
| 176 TEST_P(I18nSourceStreamTest, NoTranslations) { |
| 177 Init(); |
| 178 const char kText[] = "This text has no i18n replacements."; |
| 179 size_t kTextLength = strlen(kText); |
| 180 source()->AddReadResult(kText, kTextLength, net::OK, GetParam().mode); |
| 181 source()->AddReadResult(kText + kTextLength, 0, net::OK, GetParam().mode); |
| 182 std::string actual_output; |
| 183 int rv = ReadStream(&actual_output); |
| 184 EXPECT_EQ(static_cast<int>(kTextLength), rv); |
| 185 EXPECT_EQ(std::string(kText, kTextLength), actual_output); |
| 186 EXPECT_EQ("i18n", stream()->Description()); |
| 187 } |
| 188 |
| 189 TEST_P(I18nSourceStreamTest, I18nOneRead) { |
| 190 Init(); |
| 191 source()->AddReadResult(source_data(), kSourceSize, net::OK, GetParam().mode); |
| 192 source()->AddReadResult(source_data() + kSourceSize, 0, net::OK, |
| 193 GetParam().mode); |
| 194 std::string actual_output; |
| 195 int rv = ReadStream(&actual_output); |
| 196 EXPECT_EQ(static_cast<int>(kResultSize), rv); |
| 197 EXPECT_EQ(std::string(result_data(), kResultSize), actual_output); |
| 198 EXPECT_EQ("i18n", stream()->Description()); |
| 199 } |
| 200 |
| 201 TEST_P(I18nSourceStreamTest, I18nInMultipleReads) { |
| 202 Init(); |
| 203 size_t chunk_size = 5; |
| 204 size_t written = 0; |
| 205 while (written + chunk_size < kSourceSize) { |
| 206 source()->AddReadResult(source_data() + written, chunk_size, net::OK, |
| 207 GetParam().mode); |
| 208 written += chunk_size; |
| 209 } |
| 210 source()->AddReadResult(source_data() + written, kSourceSize - written, |
| 211 net::OK, GetParam().mode); |
| 212 source()->AddReadResult(source_data() + kSourceSize, 0, net::OK, |
| 213 GetParam().mode); |
| 214 std::string actual_output; |
| 215 int rv = ReadStream(&actual_output); |
| 216 EXPECT_EQ(static_cast<int>(kResultSize), rv); |
| 217 EXPECT_EQ(std::string(result_data(), kResultSize), actual_output); |
| 218 EXPECT_EQ("i18n", stream()->Description()); |
| 219 } |
| 220 |
| 221 } // namespace content |
OLD | NEW |