blob: 094186df9c06936e73cf8aae95aad10dcd4c6d69 [file] [log] [blame]
Avi Drissman3e1a26c2022-09-15 20:26:031// Copyright 2016 The Chromium Authors
dschuyler613a1032016-12-15 19:22:352// 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
Keishi Hattori0e45c022021-11-27 09:25:527#include "base/memory/raw_ptr.h"
dschuyler613a1032016-12-15 19:22:358#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"
Reilly Grantf31ae652017-11-16 20:40:0412#include "ui/base/webui/i18n_source_stream.h"
dschuyler613a1032016-12-15 19:22:3513
Reilly Grantf31ae652017-11-16 20:40:0414namespace ui {
dschuyler613a1032016-12-15 19:22:3515
16namespace {
17
dschuyleread12ef2017-01-10 02:36:1318// This constant is rather arbitrary, though the offsets and other sizes must
dschuyler613a1032016-12-15 19:22:3519// be less than kBufferSize.
20const int kBufferSize = 256;
dschuyler613a1032016-12-15 19:22:3521
dschuyleread12ef2017-01-10 02:36:1322const int kMinimumSize = 1;
23const int kSmallSize = 5; // Arbitrary small value > 1.
24const int kInOneReadSize = INT_MAX;
dschuyler613a1032016-12-15 19:22:3525
dschuyleread12ef2017-01-10 02:36:1326struct I18nTest {
27 constexpr I18nTest(const char* input, const char* expected_output)
28 : input(input), expected_output(expected_output) {}
dschuyler613a1032016-12-15 19:22:3529
dschuyleread12ef2017-01-10 02:36:1330 const char* input;
31 const char* expected_output;
32};
33
34constexpr I18nTest kTestEmpty = I18nTest("", "");
35
36constexpr I18nTest kTestNoReplacements =
37 I18nTest("This text has no i18n replacements.",
38 "This text has no i18n replacements.");
39
40constexpr I18nTest kTestTagAtEndOfLine =
41 I18nTest("test with tag at end of line $",
42 "test with tag at end of line $");
43
44constexpr I18nTest kTestOneReplacement = I18nTest("$i18n{alpha}", "apple");
45
46constexpr I18nTest kTestOneReplacementPlus =
47 I18nTest("Extra text $i18n{alpha}.", "Extra text apple.");
48
49constexpr I18nTest kTestThreeReplacements =
50 I18nTest("$i18n{alpha}^$i18n{beta}_$i18n{gamma}", "apple^banana_carrot");
51
52constexpr I18nTest kTestExtraBraces =
53 I18nTest("($i18n{alpha})^_^_^_^_$i18n{beta}_beta_$i18n{gamma}}}}}}",
54 "(apple)^_^_^_^_banana_beta_carrot}}}}}");
55
56// These tests with generic names are sequences that might catch an error in the
57// future, depending on how the code changes.
58constexpr I18nTest kTest1 =
59 I18nTest(" } $($i18n{gamma})^_^_^_^_$i18n{alpha}_$i18n{gamma}$",
60 " } $(carrot)^_^_^_^_apple_carrot$");
61
62constexpr I18nTest kTest2 =
63 I18nTest("$i18n{alpha} gamma}{ ^_^_^_^_$abc{beta}:$i18n{gamma}z",
64 "apple gamma}{ ^_^_^_^_$abc{beta}:carrotz");
dschuyler613a1032016-12-15 19:22:3565
66struct I18nTestParam {
dschuyleread12ef2017-01-10 02:36:1367 constexpr I18nTestParam(
68 const I18nTest* test,
69 int buf_size,
70 int read_size,
71 net::MockSourceStream::Mode read_mode = net::MockSourceStream::SYNC)
72 : buffer_size(buf_size),
73 read_size(read_size),
74 mode(read_mode),
75 test(test) {}
dschuyler613a1032016-12-15 19:22:3576
77 const int buffer_size;
dschuyleread12ef2017-01-10 02:36:1378 const int read_size;
dschuyler613a1032016-12-15 19:22:3579 const net::MockSourceStream::Mode mode;
dschuyleread12ef2017-01-10 02:36:1380 const I18nTest* test;
dschuyler613a1032016-12-15 19:22:3581};
82
83} // namespace
84
85class I18nSourceStreamTest : public ::testing::TestWithParam<I18nTestParam> {
86 protected:
87 I18nSourceStreamTest() : output_buffer_size_(GetParam().buffer_size) {}
88
89 // Helpful function to initialize the test fixture.
90 void Init() {
Victor Costandab6b732018-09-05 23:04:3691 output_buffer_ = base::MakeRefCounted<net::IOBuffer>(output_buffer_size_);
dschuyler613a1032016-12-15 19:22:3592 std::unique_ptr<net::MockSourceStream> source(new net::MockSourceStream());
93 source_ = source.get();
94
dschuyleread12ef2017-01-10 02:36:1395 replacements_["alpha"] = "apple";
96 replacements_["beta"] = "banana";
97 replacements_["gamma"] = "carrot";
dschuyler613a1032016-12-15 19:22:3598 stream_ = I18nSourceStream::Create(
99 std::move(source), net::SourceStream::TYPE_NONE, &replacements_);
100 }
101
102 // If MockSourceStream::Mode is ASYNC, completes 1 read from |mock_stream| and
103 // wait for |callback| to complete. If Mode is not ASYNC, does nothing and
104 // returns |previous_result|.
105 int CompleteReadIfAsync(int previous_result,
106 net::TestCompletionCallback* callback,
107 net::MockSourceStream* mock_stream) {
108 if (GetParam().mode == net::MockSourceStream::ASYNC) {
109 EXPECT_EQ(net::ERR_IO_PENDING, previous_result);
110 mock_stream->CompleteNextRead();
111 return callback->WaitForResult();
112 }
113 return previous_result;
114 }
115
dschuyler613a1032016-12-15 19:22:35116 net::IOBuffer* output_buffer() { return output_buffer_.get(); }
117 char* output_data() { return output_buffer_->data(); }
118 size_t output_buffer_size() { return output_buffer_size_; }
119
120 net::MockSourceStream* source() { return source_; }
121 I18nSourceStream* stream() { return stream_.get(); }
122
dschuyleread12ef2017-01-10 02:36:13123 void PushReadResults(const char* input, size_t chunk_size) {
124 size_t written = 0;
125 size_t source_size = strlen(GetParam().test->input);
126 while (written != source_size) {
127 size_t write_size = std::min(chunk_size, source_size - written);
128 source()->AddReadResult(input + written, write_size, net::OK,
129 GetParam().mode);
130 written += write_size;
131 }
132 source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
133 }
134
dschuyler613a1032016-12-15 19:22:35135 // Reads from |stream_| until an error occurs or the EOF is reached.
136 // When an error occurs, returns the net error code. When an EOF is reached,
137 // returns the number of bytes read and appends data read to |output|.
138 int ReadStream(std::string* output) {
139 int bytes_read = 0;
140 while (true) {
141 net::TestCompletionCallback callback;
142 int rv = stream_->Read(output_buffer(), output_buffer_size(),
143 callback.callback());
144 if (rv == net::ERR_IO_PENDING)
145 rv = CompleteReadIfAsync(rv, &callback, source());
146 if (rv == net::OK)
147 break;
148 if (rv < net::OK)
149 return rv;
150 EXPECT_GT(rv, net::OK);
151 bytes_read += rv;
152 output->append(output_data(), rv);
153 }
154 return bytes_read;
155 }
156
157 private:
dschuyler613a1032016-12-15 19:22:35158 scoped_refptr<net::IOBuffer> output_buffer_;
159 const int output_buffer_size_;
160
Tom Sepezc42bc802023-02-10 23:56:49161 std::unique_ptr<I18nSourceStream> stream_; // Must outlive `source_`.
Keishi Hattori0e45c022021-11-27 09:25:52162 raw_ptr<net::MockSourceStream> source_;
dschuyler613a1032016-12-15 19:22:35163
Reilly Grantf31ae652017-11-16 20:40:04164 TemplateReplacements replacements_;
dschuyler