Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(382)

Side by Side Diff: content/browser/webui/i18n_source_stream_unittest.cc

Issue 2610063003: [i18n streaming] improve unit tests (Closed)
Patch Set: updated Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <utility> 5 #include <utility>
6 6
7 #include "content/browser/webui/i18n_source_stream.h" 7 #include "content/browser/webui/i18n_source_stream.h"
8 #include "net/base/io_buffer.h" 8 #include "net/base/io_buffer.h"
9 #include "net/base/test_completion_callback.h" 9 #include "net/base/test_completion_callback.h"
10 #include "net/filter/mock_source_stream.h" 10 #include "net/filter/mock_source_stream.h"
11 #include "testing/gtest/include/gtest/gtest.h" 11 #include "testing/gtest/include/gtest/gtest.h"
12 12
13 namespace content { 13 namespace content {
14 14
15 namespace { 15 namespace {
16 16
17 // These constants are rather arbitrary, though the offsets and other sizes must 17 // This constant is rather arbitrary, though the offsets and other sizes must
18 // be less than kBufferSize. 18 // be less than kBufferSize.
19 const int kBufferSize = 256; 19 const int kBufferSize = 256;
20 const int kSmallBufferSize = 1;
21 20
22 const int kShortReplacementOffset = 5; 21 const int kMinimumSize = 1;
23 const char kShortReplacementKey[] = "a"; 22 const int kSmallSize = 5; // Arbitrary small value > 1.
24 const char kShortReplacementToken[] = "$i18n{a}"; 23 const int kInOneReadSize = INT_MAX;
25 const char kShortReplacementValue[] = "short";
26 24
27 const int kLongReplacementOffset = 33; 25 struct I18nTest {
28 const char kLongReplacementKey[] = "aLongerReplacementName"; 26 constexpr I18nTest(const char* input, const char* expected_output)
29 const char kLongReplacementToken[] = "$i18n{aLongerReplacementName}"; 27 : input(input), expected_output(expected_output) {}
30 const char kLongReplacementValue[] = "second replacement";
31 28
32 const int kSourceSize = 29 const char* input;
33 50 + arraysize(kShortReplacementToken) + arraysize(kLongReplacementToken); 30 const char* expected_output;
34 const int kResultSize = 31 };
35 50 + arraysize(kShortReplacementValue) + arraysize(kLongReplacementValue); 32
33 constexpr I18nTest kTestEmpty = I18nTest("", "");
34
35 constexpr I18nTest kTestNoReplacements =
36 I18nTest("This text has no i18n replacements.",
37 "This text has no i18n replacements.");
38
39 constexpr I18nTest kTestTagAtEndOfLine =
40 I18nTest("test with tag at end of line $",
41 "test with tag at end of line $");
42
43 constexpr I18nTest kTestOneReplacement = I18nTest("$i18n{alpha}", "apple");
44
45 constexpr I18nTest kTestOneReplacementPlus =
46 I18nTest("Extra text $i18n{alpha}.", "Extra text apple.");
47
48 constexpr I18nTest kTestThreeReplacements =
49 I18nTest("$i18n{alpha}^$i18n{beta}_$i18n{gamma}", "apple^banana_carrot");
50
51 constexpr I18nTest kTestExtraBraces =
52 I18nTest("($i18n{alpha})^_^_^_^_$i18n{beta}_beta_$i18n{gamma}}}}}}",
53 "(apple)^_^_^_^_banana_beta_carrot}}}}}");
54
55 // These tests with generic names are sequences that might catch an error in the
56 // future, depending on how the code changes.
57 constexpr I18nTest kTest1 =
58 I18nTest(" } $($i18n{gamma})^_^_^_^_$i18n{alpha}_$i18n{gamma}$",
59 " } $(carrot)^_^_^_^_apple_carrot$");
60
61 constexpr I18nTest kTest2 =
62 I18nTest("$i18n{alpha} gamma}{ ^_^_^_^_$abc{beta}:$i18n{gamma}z",
63 "apple gamma}{ ^_^_^_^_$abc{beta}:carrotz");
36 64
37 struct I18nTestParam { 65 struct I18nTestParam {
38 I18nTestParam(int buf_size, net::MockSourceStream::Mode read_mode) 66 constexpr I18nTestParam(
39 : buffer_size(buf_size), mode(read_mode) {} 67 const I18nTest* test,
68 int buf_size,
69 int read_size,
70 net::MockSourceStream::Mode read_mode = net::MockSourceStream::SYNC)
71 : buffer_size(buf_size),
72 read_size(read_size),
73 mode(read_mode),
74 test(test) {}
40 75
41 const int buffer_size; 76 const int buffer_size;
77 const int read_size;
42 const net::MockSourceStream::Mode mode; 78 const net::MockSourceStream::Mode mode;
79 const I18nTest* test;
43 }; 80 };
44 81
45 } // namespace 82 } // namespace
46 83
47 class I18nSourceStreamTest : public ::testing::TestWithParam<I18nTestParam> { 84 class I18nSourceStreamTest : public ::testing::TestWithParam<I18nTestParam> {
48 protected: 85 protected:
49 I18nSourceStreamTest() : output_buffer_size_(GetParam().buffer_size) {} 86 I18nSourceStreamTest() : output_buffer_size_(GetParam().buffer_size) {}
50 87
51 // Helpful function to initialize the test fixture. 88 // Helpful function to initialize the test fixture.
52 void Init() { 89 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_); 90 output_buffer_ = new net::IOBuffer(output_buffer_size_);
74 std::unique_ptr<net::MockSourceStream> source(new net::MockSourceStream()); 91 std::unique_ptr<net::MockSourceStream> source(new net::MockSourceStream());
75 source_ = source.get(); 92 source_ = source.get();
76 93
77 replacements_[kShortReplacementKey] = kShortReplacementValue; 94 replacements_["alpha"] = "apple";
78 replacements_[kLongReplacementKey] = kLongReplacementValue; 95 replacements_["beta"] = "banana";
96 replacements_["gamma"] = "carrot";
79 stream_ = I18nSourceStream::Create( 97 stream_ = I18nSourceStream::Create(
80 std::move(source), net::SourceStream::TYPE_NONE, &replacements_); 98 std::move(source), net::SourceStream::TYPE_NONE, &replacements_);
81 } 99 }
82 100
83 // If MockSourceStream::Mode is ASYNC, completes 1 read from |mock_stream| and 101 // 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 102 // wait for |callback| to complete. If Mode is not ASYNC, does nothing and
85 // returns |previous_result|. 103 // returns |previous_result|.
86 int CompleteReadIfAsync(int previous_result, 104 int CompleteReadIfAsync(int previous_result,
87 net::TestCompletionCallback* callback, 105 net::TestCompletionCallback* callback,
88 net::MockSourceStream* mock_stream) { 106 net::MockSourceStream* mock_stream) {
89 if (GetParam().mode == net::MockSourceStream::ASYNC) { 107 if (GetParam().mode == net::MockSourceStream::ASYNC) {
90 EXPECT_EQ(net::ERR_IO_PENDING, previous_result); 108 EXPECT_EQ(net::ERR_IO_PENDING, previous_result);
91 mock_stream->CompleteNextRead(); 109 mock_stream->CompleteNextRead();
92 return callback->WaitForResult(); 110 return callback->WaitForResult();
93 } 111 }
94 return previous_result; 112 return previous_result;
95 } 113 }
96 114
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(); } 115 net::IOBuffer* output_buffer() { return output_buffer_.get(); }
116 char* output_data() { return output_buffer_->data(); } 116 char* output_data() { return output_buffer_->data(); }
117 size_t output_buffer_size() { return output_buffer_size_; } 117 size_t output_buffer_size() { return output_buffer_size_; }
118 118
119 net::MockSourceStream* source() { return source_; } 119 net::MockSourceStream* source() { return source_; }
120 I18nSourceStream* stream() { return stream_.get(); } 120 I18nSourceStream* stream() { return stream_.get(); }
121 121
122 void PushReadResults(const char* input, size_t chunk_size) {
123 size_t written = 0;
124 size_t source_size = strlen(GetParam().test->input);
125 while (written != source_size) {
126 size_t write_size = std::min(chunk_size, source_size - written);
127 source()->AddReadResult(input + written, write_size, net::OK,
128 GetParam().mode);
129 written += write_size;
130 }
131 source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
132 }
133
122 // Reads from |stream_| until an error occurs or the EOF is reached. 134 // 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, 135 // 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|. 136 // returns the number of bytes read and appends data read to |output|.
125 int ReadStream(std::string* output) { 137 int ReadStream(std::string* output) {
126 int bytes_read = 0; 138 int bytes_read = 0;
127 while (true) { 139 while (true) {
128 net::TestCompletionCallback callback; 140 net::TestCompletionCallback callback;
129 int rv = stream_->Read(output_buffer(), output_buffer_size(), 141 int rv = stream_->Read(output_buffer(), output_buffer_size(),
130 callback.callback()); 142 callback.callback());
131 if (rv == net::ERR_IO_PENDING) 143 if (rv == net::ERR_IO_PENDING)
132 rv = CompleteReadIfAsync(rv, &callback, source()); 144 rv = CompleteReadIfAsync(rv, &callback, source());
133 if (rv == net::OK) 145 if (rv == net::OK)
134 break; 146 break;
135 if (rv < net::OK) 147 if (rv < net::OK)
136 return rv; 148 return rv;
137 EXPECT_GT(rv, net::OK); 149 EXPECT_GT(rv, net::OK);
138 bytes_read += rv; 150 bytes_read += rv;
139 output->append(output_data(), rv); 151 output->append(output_data(), rv);
140 } 152 }
141 return bytes_read; 153 return bytes_read;
142 } 154 }
143 155
144 private: 156 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_; 157 scoped_refptr<net::IOBuffer> output_buffer_;
152 const int output_buffer_size_; 158 const int output_buffer_size_;
153 159
154 net::MockSourceStream* source_; 160 net::MockSourceStream* source_;
155 std::unique_ptr<I18nSourceStream> stream_; 161 std::unique_ptr<I18nSourceStream> stream_;
156 162
157 ui::TemplateReplacements replacements_; 163 ui::TemplateReplacements replacements_;
158 }; 164 };
159 165
160 INSTANTIATE_TEST_CASE_P( 166 INSTANTIATE_TEST_CASE_P(
161 I18nSourceStreamTests, 167 I18nSourceStreamTests,
162 I18nSourceStreamTest, 168 I18nSourceStreamTest,
163 ::testing::Values(I18nTestParam(kBufferSize, net::MockSourceStream::SYNC), 169 ::testing::Values(
164 I18nTestParam(kSmallBufferSize, 170 I18nTestParam(&kTest1, kBufferSize, kInOneReadSize),
165 net::MockSourceStream::SYNC))); 171 I18nTestParam(&kTest1, kBufferSize, kSmallSize),
172 I18nTestParam(&kTest1, kMinimumSize, kMinimumSize),
173 I18nTestParam(&kTest1, kMinimumSize, kSmallSize),
166 174
167 TEST_P(I18nSourceStreamTest, EmptyStream) { 175 I18nTestParam(&kTest2, kBufferSize, kInOneReadSize),
176 I18nTestParam(&kTest2, kBufferSize, kSmallSize),
177 I18nTestParam(&kTest2, kMinimumSize, kMinimumSize),
178 I18nTestParam(&kTest2, kMinimumSize, kSmallSize),
179
180 I18nTestParam(&kTestEmpty, kBufferSize, kInOneReadSize),
181 I18nTestParam(&kTestEmpty, kBufferSize, kSmallSize),
182 I18nTestParam(&kTestEmpty, kMinimumSize, kMinimumSize),
183 I18nTestParam(&kTestEmpty, kMinimumSize, kSmallSize),
184
185 I18nTestParam(&kTestExtraBraces, kBufferSize, kInOneReadSize),
186 I18nTestParam(&kTestExtraBraces, kBufferSize, kSmallSize),
187 I18nTestParam(&kTestExtraBraces, kMinimumSize, kMinimumSize),
188 I18nTestParam(&kTestExtraBraces, kMinimumSize, kSmallSize),
189
190 I18nTestParam(&kTestNoReplacements, kBufferSize, kInOneReadSize),
191 I18nTestParam(&kTestNoReplacements, kBufferSize, kSmallSize),
192 I18nTestParam(&kTestNoReplacements, kMinimumSize, kMinimumSize),
193 I18nTestParam(&kTestNoReplacements, kMinimumSize, kSmallSize),
194
195 I18nTestParam(&kTestOneReplacement, kBufferSize, kInOneReadSize),
196 I18nTestParam(&kTestOneReplacement, kBufferSize, kSmallSize),
197 I18nTestParam(&kTestOneReplacement, kMinimumSize, kMinimumSize),
198 I18nTestParam(&kTestOneReplacement, kMinimumSize, kSmallSize),
199
200 I18nTestParam(&kTestOneReplacementPlus, kBufferSize, kInOneReadSize),
201 I18nTestParam(&kTestOneReplacementPlus, kBufferSize, kSmallSize),
202 I18nTestParam(&kTestOneReplacementPlus, kMinimumSize, kMinimumSize),
203 I18nTestParam(&kTestOneReplacementPlus, kMinimumSize, kSmallSize),
204
205 I18nTestParam(&kTestTagAtEndOfLine, kBufferSize, kInOneReadSize),
206 I18nTestParam(&kTestTagAtEndOfLine, kBufferSize, kSmallSize),
207 I18nTestParam(&kTestTagAtEndOfLine, kMinimumSize, kMinimumSize),
208 I18nTestParam(&kTestTagAtEndOfLine, kMinimumSize, kSmallSize),
209
210 I18nTestParam(&kTestThreeReplacements, kBufferSize, kInOneReadSize),
211 I18nTestParam(&kTestThreeReplacements, kBufferSize, kSmallSize),
212 I18nTestParam(&kTestThreeReplacements, kMinimumSize, kMinimumSize),
213 I18nTestParam(&kTestThreeReplacements, kMinimumSize, kSmallSize)));
214
215 TEST_P(I18nSourceStreamTest, FilterTests) {
168 Init(); 216 Init();
169 source()->AddReadResult("", 0, net::OK, GetParam().mode); 217 // Create the chain of read buffers.
218 PushReadResults(GetParam().test->input, GetParam().read_size);
219
220 // Process the buffers.
170 std::string actual_output; 221 std::string actual_output;
171 int result = ReadStream(&actual_output); 222 int rv = ReadStream(&actual_output);
172 EXPECT_EQ(net::OK, result); 223
224 // Check the results.
225 std::string expected_output(GetParam().test->expected_output);
226 ASSERT_EQ(expected_output.size(), static_cast<size_t>(rv));
mmenke 2017/01/06 22:39:40 optional: This is redundant with the EXPECT_EQ on
dschuyler 2017/01/09 20:14:07 Converted to expect rather than assert. I agree th
227 EXPECT_EQ(expected_output, actual_output);
173 EXPECT_EQ("i18n", stream()->Description()); 228 EXPECT_EQ("i18n", stream()->Description());
174 } 229 }
175 230
176 TEST_P(I18nSourceStreamTest, NoTranslations) { 231 TEST_P(I18nSourceStreamTest, LargeFilterTests) {
177 Init(); 232 Init();
178 const char kText[] = "This text has no i18n replacements."; 233 std::string padding;
179 size_t kTextLength = strlen(kText); 234 // 251 and 599 are prime and avoid power-of-two repetition.
180 source()->AddReadResult(kText, kTextLength, net::OK, GetParam().mode); 235 int padding_modulus = 251;
181 source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode); 236 int pad_size = 599;
237 padding.resize(pad_size);
238 for (int i = 0; i < pad_size; ++i)
239 padding[i] = i % padding_modulus;
240
241 // Create the chain of read buffers.
242 int pad_count = 128; // Arbitrary number of pads to add.
mmenke 2017/01/06 22:39:40 nit: const int kPadCount
dschuyler 2017/01/09 20:14:07 Done.
243 for (int i = 0; i < pad_count; ++i) {
244 source()->AddReadResult(padding.c_str(), padding.size(), net::OK,
245 GetParam().mode);
246 }
247 PushReadResults(GetParam().test->input, GetParam().read_size);
248
249 // Process the buffers.
182 std::string actual_output; 250 std::string actual_output;
183 int rv = ReadStream(&actual_output); 251 int rv = ReadStream(&actual_output);
184 EXPECT_EQ(static_cast<int>(kTextLength), rv); 252
185 EXPECT_EQ(kText, actual_output); 253 // Check the results.
254 size_t total_padding = pad_count * padding.size();
255 std::string expected_output(GetParam().test->expected_output);
256 ASSERT_EQ(expected_output.size() + total_padding, static_cast<size_t>(rv));
257 for (int i = 0; i < pad_count; ++i) {
258 EXPECT_EQ(actual_output.substr(i * padding.size(), padding.size()),
259 padding);
260 }
261 EXPECT_EQ(expected_output, &actual_output[total_padding]);
186 EXPECT_EQ("i18n", stream()->Description()); 262 EXPECT_EQ("i18n", stream()->Description());
187 } 263 }
188 264
189 TEST_P(I18nSourceStreamTest, I18nOneRead) {
190 Init();
191 source()->AddReadResult(source_data(), kSourceSize, net::OK, GetParam().mode);
192 source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
193 std::string actual_output;
194 int rv = ReadStream(&actual_output);
195 EXPECT_EQ(static_cast<int>(kResultSize), rv);
196 EXPECT_EQ(std::string(result_data(), kResultSize), actual_output);
197 EXPECT_EQ("i18n", stream()->Description());
198 }
199
200 TEST_P(I18nSourceStreamTest, I18nInMultipleReads) {
201 Init();
202 size_t chunk_size = 5;
203 size_t written = 0;
204 while (written + chunk_size < kSourceSize) {
205 source()->AddReadResult(source_data() + written, chunk_size, net::OK,
206 GetParam().mode);
207 written += chunk_size;
208 }
209 source()->AddReadResult(source_data() + written, kSourceSize - written,
210 net::OK, GetParam().mode);
211 source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
212 std::string actual_output;
213 int rv = ReadStream(&actual_output);
214 EXPECT_EQ(static_cast<int>(kResultSize), rv);
215 EXPECT_EQ(std::string(result_data(), kResultSize), actual_output);
216 EXPECT_EQ("i18n", stream()->Description());
217 }
218
219 TEST_P(I18nSourceStreamTest, I18nTagAtEndOfLine) {
220 Init();
221 const char kSourceData[] = "test with tag at end of line $";
222 const size_t source_size = strlen(kSourceData);
223 source()->AddReadResult(kSourceData, source_size, net::OK, GetParam().mode);
224 source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
225 std::string actual_output;
226 int rv = ReadStream(&actual_output);
227 EXPECT_EQ(static_cast<int>(source_size), rv);
228 EXPECT_EQ(kSourceData, actual_output);
229 EXPECT_EQ("i18n", stream()->Description());
230 }
231
232 } // namespace content 265 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698