Add ICU message format support
[chromium-blink-merge.git] / content / common / page_state_serialization_unittest.cc
blobabb2a3958760c6a8b6a60d48350635781f515f1e
1 // Copyright 2013 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.
5 #include <cmath>
7 #include "base/base64.h"
8 #include "base/files/file_util.h"
9 #include "base/path_service.h"
10 #include "base/pickle.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "content/common/page_state_serialization.h"
15 #include "content/public/common/content_paths.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 namespace content {
19 namespace {
21 base::NullableString16 NS16(const char* s) {
22 return s ? base::NullableString16(base::ASCIIToUTF16(s), false) :
23 base::NullableString16();
26 //-----------------------------------------------------------------------------
28 template <typename T>
29 void ExpectEquality(const T& a, const T& b) {
30 EXPECT_EQ(a, b);
33 template <typename T>
34 void ExpectEquality(const std::vector<T>& a, const std::vector<T>& b) {
35 EXPECT_EQ(a.size(), b.size());
36 for (size_t i = 0; i < std::min(a.size(), b.size()); ++i)
37 ExpectEquality(a[i], b[i]);
40 template <>
41 void ExpectEquality(const ExplodedHttpBodyElement& a,
42 const ExplodedHttpBodyElement& b) {
43 EXPECT_EQ(a.type, b.type);
44 EXPECT_EQ(a.data, b.data);
45 EXPECT_EQ(a.file_path, b.file_path);
46 EXPECT_EQ(a.filesystem_url, b.filesystem_url);
47 EXPECT_EQ(a.file_start, b.file_start);
48 EXPECT_EQ(a.file_length, b.file_length);
49 if (!(std::isnan(a.file_modification_time) &&
50 std::isnan(b.file_modification_time))) {
51 EXPECT_DOUBLE_EQ(a.file_modification_time, b.file_modification_time);
53 EXPECT_EQ(a.blob_uuid, b.blob_uuid);
56 template <>
57 void ExpectEquality(const ExplodedHttpBody& a, const ExplodedHttpBody& b) {
58 EXPECT_EQ(a.http_content_type, b.http_content_type);
59 EXPECT_EQ(a.identifier, b.identifier);
60 EXPECT_EQ(a.contains_passwords, b.contains_passwords);
61 EXPECT_EQ(a.is_null, b.is_null);
62 ExpectEquality(a.elements, b.elements);
65 template <>
66 void ExpectEquality(const ExplodedFrameState& a, const ExplodedFrameState& b) {
67 EXPECT_EQ(a.url_string, b.url_string);
68 EXPECT_EQ(a.referrer, b.referrer);
69 EXPECT_EQ(a.referrer_policy, b.referrer_policy);
70 EXPECT_EQ(a.target, b.target);
71 EXPECT_EQ(a.state_object, b.state_object);
72 ExpectEquality(a.document_state, b.document_state);
73 EXPECT_EQ(a.scroll_restoration_type, b.scroll_restoration_type);
74 EXPECT_EQ(a.pinch_viewport_scroll_offset, b.pinch_viewport_scroll_offset);
75 EXPECT_EQ(a.scroll_offset, b.scroll_offset);
76 EXPECT_EQ(a.item_sequence_number, b.item_sequence_number);
77 EXPECT_EQ(a.document_sequence_number, b.document_sequence_number);
78 EXPECT_EQ(a.page_scale_factor, b.page_scale_factor);
79 ExpectEquality(a.http_body, b.http_body);
80 ExpectEquality(a.children, b.children);
83 void ExpectEquality(const ExplodedPageState& a, const ExplodedPageState& b) {
84 ExpectEquality(a.referenced_files, b.referenced_files);
85 ExpectEquality(a.top, b.top);
88 //-----------------------------------------------------------------------------
90 class PageStateSerializationTest : public testing::Test {
91 public:
92 void PopulateFrameState(ExplodedFrameState* frame_state) {
93 // Invent some data for the various fields.
94 frame_state->url_string = NS16("http://dev.chromium.org/");
95 frame_state->referrer = NS16("https://www.google.com/search?q=dev.chromium.org");
96 frame_state->referrer_policy = blink::WebReferrerPolicyAlways;
97 frame_state->target = NS16("foo");
98 frame_state->state_object = NS16(NULL);
99 frame_state->document_state.push_back(NS16("1"));
100 frame_state->document_state.push_back(NS16("q"));
101 frame_state->document_state.push_back(NS16("text"));
102 frame_state->document_state.push_back(NS16("dev.chromium.org"));
103 frame_state->scroll_restoration_type =
104 blink::WebHistoryScrollRestorationManual;
105 frame_state->pinch_viewport_scroll_offset = gfx::PointF(10, 15);
106 frame_state->scroll_offset = gfx::Point(0, 100);
107 frame_state->item_sequence_number = 1;
108 frame_state->document_sequence_number = 2;
109 frame_state->page_scale_factor = 2.0;
112 void PopulateHttpBody(ExplodedHttpBody* http_body,
113 std::vector<base::NullableString16>* referenced_files) {
114 http_body->is_null = false;
115 http_body->identifier = 12345;
116 http_body->contains_passwords = false;
117 http_body->http_content_type = NS16("text/foo");
119 ExplodedHttpBodyElement e1;
120 e1.type = blink::WebHTTPBody::Element::TypeData;
121 e1.data = "foo";
122 http_body->elements.push_back(e1);
124 ExplodedHttpBodyElement e2;
125 e2.type = blink::WebHTTPBody::Element::TypeFile;
126 e2.file_path = NS16("file.txt");
127 e2.file_start = 100;
128 e2.file_length = 1024;
129 e2.file_modification_time = 9999.0;
130 http_body->elements.push_back(e2);
132 referenced_files->push_back(e2.file_path);
135 void PopulateFrameStateForBackwardsCompatTest(
136 ExplodedFrameState* frame_state,
137 bool is_child) {
138 frame_state->url_string = NS16("http://chromium.org/");
139 frame_state->referrer = NS16("http://google.com/");
140 frame_state->referrer_policy = blink::WebReferrerPolicyDefault;
141 if (!is_child)
142 frame_state->target = NS16("target");
143 frame_state->scroll_restoration_type =
144 blink::WebHistoryScrollRestorationAuto;
145 frame_state->pinch_viewport_scroll_offset = gfx::PointF(-1, -1);
146 frame_state->scroll_offset = gfx::Point(42, -42);
147 frame_state->item_sequence_number = 123;
148 frame_state->document_sequence_number = 456;
149 frame_state->page_scale_factor = 2.0f;
151 frame_state->document_state.push_back(
152 NS16("\n\r?% WebKit serialized form state version 8 \n\r=&"));
153 frame_state->document_state.push_back(NS16("form key"));
154 frame_state->document_state.push_back(NS16("1"));
155 frame_state->document_state.push_back(NS16("foo"));
156 frame_state->document_state.push_back(NS16("file"));
157 frame_state->document_state.push_back(NS16("2"));
158 frame_state->document_state.push_back(NS16("file.txt"));
159 frame_state->document_state.push_back(NS16("displayName"));
161 if (!is_child) {
162 frame_state->http_body.http_content_type = NS16("foo/bar");
163 frame_state->http_body.identifier = 789;
164 frame_state->http_body.is_null = false;
166 ExplodedHttpBodyElement e1;
167 e1.type = blink::WebHTTPBody::Element::TypeData;
168 e1.data = "first data block";
169 frame_state->http_body.elements.push_back(e1);
171 ExplodedHttpBodyElement e2;
172 e2.type = blink::WebHTTPBody::Element::TypeFile;
173 e2.file_path = NS16("file.txt");
174 frame_state->http_body.elements.push_back(e2);
176 ExplodedHttpBodyElement e3;
177 e3.type = blink::WebHTTPBody::Element::TypeData;
178 e3.data = "data the second";
179 frame_state->http_body.elements.push_back(e3);
181 ExplodedFrameState child_state;
182 PopulateFrameStateForBackwardsCompatTest(&child_state, true);
183 frame_state->children.push_back(child_state);
187 void PopulatePageStateForBackwardsCompatTest(ExplodedPageState* page_state) {
188 page_state->referenced_files.push_back(NS16("file.txt"));
189 PopulateFrameStateForBackwardsCompatTest(&page_state->top, false);
192 void TestBackwardsCompat(int version) {
193 const char* suffix = "";
195 #if defined(OS_ANDROID)
196 // Unfortunately, the format of version 11 is different on Android, so we
197 // need to use a special reference file.
198 if (version == 11)
199 suffix = "_android";
200 #endif
202 base::FilePath path;
203 PathService::Get(content::DIR_TEST_DATA, &path);
204 path = path.AppendASCII("page_state").AppendASCII(
205 base::StringPrintf("serialized_v%d%s.dat", version, suffix));
207 std::string file_contents;
208 if (!base::ReadFileToString(path, &file_contents)) {
209 ADD_FAILURE() << "File not found: " << path.value();
210 return;
213 std::string trimmed_contents;
214 EXPECT_TRUE(base::RemoveChars(file_contents, "\r\n", &trimmed_contents));
216 std::string encoded;
217 EXPECT_TRUE(base::Base64Decode(trimmed_contents, &encoded));
219 ExplodedPageState output;
220 #if defined(OS_ANDROID)
221 // Because version 11 of the file format unfortunately bakes in the device
222 // scale factor on Android, perform this test by assuming a preset device
223 // scale factor, ignoring the device scale factor of the current device.
224 const float kPresetDeviceScaleFactor = 2.0f;
225 EXPECT_TRUE(DecodePageStateWithDeviceScaleFactorForTesting(
226 encoded,
227 kPresetDeviceScaleFactor,
228 &output));
229 #else
230 EXPECT_TRUE(DecodePageState(encoded, &output));
231 #endif
233 ExplodedPageState expected;
234 PopulatePageStateForBackwardsCompatTest(&expected);
236 ExpectEquality(expected, output);
240 TEST_F(PageStateSerializationTest, BasicEmpty) {
241 ExplodedPageState input;
243 std::string encoded;
244 EXPECT_TRUE(EncodePageState(input, &encoded));
246 ExplodedPageState output;
247 EXPECT_TRUE(DecodePageState(encoded, &output));
249 ExpectEquality(input, output);
252 TEST_F(PageStateSerializationTest, BasicFrame) {
253 ExplodedPageState input;
254 PopulateFrameState(&input.top);
256 std::string encoded;
257 EXPECT_TRUE(EncodePageState(input, &encoded));
259 ExplodedPageState output;
260 EXPECT_TRUE(DecodePageState(encoded, &output));
262 ExpectEquality(input, output);
265 TEST_F(PageStateSerializationTest, BasicFramePOST) {
266 ExplodedPageState input;
267 PopulateFrameState(&input.top);
268 PopulateHttpBody(&input.top.http_body, &input.referenced_files);
270 std::string encoded;
271 EXPECT_TRUE(EncodePageState(input, &encoded));
273 ExplodedPageState output;
274 EXPECT_TRUE(DecodePageState(encoded, &output));
276 ExpectEquality(input, output);
279 TEST_F(PageStateSerializationTest, BasicFrameSet) {
280 ExplodedPageState input;
281 PopulateFrameState(&input.top);
283 // Add some child frames.
284 for (int i = 0; i < 4; ++i) {
285 ExplodedFrameState child_state;
286 PopulateFrameState(&child_state);
287 input.top.children.push_back(child_state);
290 std::string encoded;
291 EXPECT_TRUE(EncodePageState(input, &encoded));
293 ExplodedPageState output;
294 EXPECT_TRUE(DecodePageState(encoded, &output));
296 ExpectEquality(input, output);
299 TEST_F(PageStateSerializationTest, BasicFrameSetPOST) {
300 ExplodedPageState input;
301 PopulateFrameState(&input.top);
303 // Add some child frames.
304 for (int i = 0; i < 4; ++i) {
305 ExplodedFrameState child_state;
306 PopulateFrameState(&child_state);
308 // Simulate a form POST on a subframe.
309 if (i == 2)
310 PopulateHttpBody(&child_state.http_body, &input.referenced_files);
312 input.top.children.push_back(child_state);
315 std::string encoded;
316 EncodePageState(input, &encoded);
318 ExplodedPageState output;
319 DecodePageState(encoded, &output);
321 ExpectEquality(input, output);
324 TEST_F(PageStateSerializationTest, BadMessagesTest1) {
325 base::Pickle p;
326 // Version 14
327 p.WriteInt(14);
328 // Empty strings.
329 for (int i = 0; i < 6; ++i)
330 p.WriteInt(-1);
331 // Bad real number.
332 p.WriteInt(-1);
334 std::string s(static_cast<const char*>(p.data()), p.size());
336 ExplodedPageState output;
337 EXPECT_FALSE(DecodePageState(s, &output));
340 TEST_F(PageStateSerializationTest, BadMessagesTest2) {
341 double d = 0;
342 base::Pickle p;
343 // Version 14
344 p.WriteInt(14);
345 // Empty strings.
346 for (int i = 0; i < 6; ++i)
347 p.WriteInt(-1);
348 // More misc fields.
349 p.WriteData(reinterpret_cast<const char*>(&d), sizeof(d));
350 p.WriteInt(1);
351 p.WriteInt(1);
352 p.WriteInt(0);
353 p.WriteInt(0);
354 p.WriteInt(-1);
355 p.WriteInt(0);
356 // WebForm
357 p.WriteInt(1);
358 p.WriteInt(blink::WebHTTPBody::Element::TypeData);
360 std::string s(static_cast<const char*>(p.data()), p.size());
362 ExplodedPageState output;
363 EXPECT_FALSE(DecodePageState(s, &output));
366 TEST_F(PageStateSerializationTest, DumpExpectedPageStateForBackwardsCompat) {
367 // Change to #if 1 to enable this code. Use this code to generate data, based
368 // on the current serialization format, for the BackwardsCompat_vXX tests.
369 #if 0
370 ExplodedPageState state;
371 PopulatePageStateForBackwardsCompatTest(&state);
373 std::string encoded;
374 EXPECT_TRUE(EncodePageState(state, &encoded));
376 std::string base64;
377 base::Base64Encode(encoded, &base64);
379 base::FilePath path;
380 PathService::Get(base::DIR_TEMP, &path);
381 path = path.AppendASCII("expected.dat");
383 FILE* fp = base::OpenFile(path, "wb");
384 ASSERT_TRUE(fp);
386 const size_t kRowSize = 76;
387 for (size_t offset = 0; offset < base64.size(); offset += kRowSize) {
388 size_t length = std::min(base64.size() - offset, kRowSize);
389 std::string segment(&base64[offset], length);
390 segment.push_back('\n');
391 ASSERT_EQ(1U, fwrite(segment.data(), segment.size(), 1, fp));
394 fclose(fp);
395 #endif
398 #if !defined(OS_ANDROID)
399 // TODO(darin): Re-enable for Android once this test accounts for systems with
400 // a device scale factor not equal to 2.
401 TEST_F(PageStateSerializationTest, BackwardsCompat_v11) {
402 TestBackwardsCompat(11);
404 #endif
406 TEST_F(PageStateSerializationTest, BackwardsCompat_v12) {
407 TestBackwardsCompat(12);
410 TEST_F(PageStateSerializationTest, BackwardsCompat_v13) {
411 TestBackwardsCompat(13);
414 TEST_F(PageStateSerializationTest, BackwardsCompat_v14) {
415 TestBackwardsCompat(14);
418 TEST_F(PageStateSerializationTest, BackwardsCompat_v15) {
419 TestBackwardsCompat(15);
422 TEST_F(PageStateSerializationTest, BackwardsCompat_v16) {
423 TestBackwardsCompat(16);
426 TEST_F(PageStateSerializationTest, BackwardsCompat_v18) {
427 TestBackwardsCompat(18);
430 TEST_F(PageStateSerializationTest, BackwardsCompat_v20) {
431 TestBackwardsCompat(20);
434 TEST_F(PageStateSerializationTest, BackwardsCompat_v21) {
435 TestBackwardsCompat(21);
438 TEST_F(PageStateSerializationTest, BackwardsCompat_v22) {
439 TestBackwardsCompat(22);
442 } // namespace
443 } // namespace content