Make developerPrivate API available in stable.
[chromium-blink-merge.git] / content / common / page_state_serialization_unittest.cc
blob07b9cf8181b52eb5d478dbb158e00c09a7f27d76
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 <math.h>
7 #include "base/base64.h"
8 #include "base/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 #if defined(OS_WIN)
22 inline bool isnan(double num) { return !!_isnan(num); }
23 #endif
25 base::NullableString16 NS16(const char* s) {
26 return s ? base::NullableString16(ASCIIToUTF16(s), false) :
27 base::NullableString16();
30 //-----------------------------------------------------------------------------
32 template <typename T>
33 void ExpectEquality(const T& a, const T& b) {
34 EXPECT_EQ(a, b);
37 template <typename T>
38 void ExpectEquality(const std::vector<T>& a, const std::vector<T>& b) {
39 EXPECT_EQ(a.size(), b.size());
40 for (size_t i = 0; i < std::min(a.size(), b.size()); ++i)
41 ExpectEquality(a[i], b[i]);
44 template <>
45 void ExpectEquality(const ExplodedHttpBodyElement& a,
46 const ExplodedHttpBodyElement& b) {
47 EXPECT_EQ(a.type, b.type);
48 EXPECT_EQ(a.data, b.data);
49 EXPECT_EQ(a.file_path, b.file_path);
50 EXPECT_EQ(a.filesystem_url, b.filesystem_url);
51 EXPECT_EQ(a.file_start, b.file_start);
52 EXPECT_EQ(a.file_length, b.file_length);
53 if (!(isnan(a.file_modification_time) && isnan(b.file_modification_time)))
54 EXPECT_DOUBLE_EQ(a.file_modification_time, b.file_modification_time);
55 EXPECT_EQ(a.deprecated_blob_url, b.deprecated_blob_url);
58 template <>
59 void ExpectEquality(const ExplodedHttpBody& a, const ExplodedHttpBody& b) {
60 EXPECT_EQ(a.http_content_type, b.http_content_type);
61 EXPECT_EQ(a.identifier, b.identifier);
62 EXPECT_EQ(a.contains_passwords, b.contains_passwords);
63 EXPECT_EQ(a.is_null, b.is_null);
64 ExpectEquality(a.elements, b.elements);
67 template <>
68 void ExpectEquality(const ExplodedFrameState& a, const ExplodedFrameState& b) {
69 EXPECT_EQ(a.url_string, b.url_string);
70 EXPECT_EQ(a.original_url_string, b.original_url_string);
71 EXPECT_EQ(a.referrer, b.referrer);
72 EXPECT_EQ(a.target, b.target);
73 EXPECT_EQ(a.parent, b.parent);
74 EXPECT_EQ(a.title, b.title);
75 EXPECT_EQ(a.alternate_title, b.alternate_title);
76 EXPECT_EQ(a.state_object, b.state_object);
77 ExpectEquality(a.document_state, b.document_state);
78 EXPECT_EQ(a.scroll_offset, b.scroll_offset);
79 EXPECT_EQ(a.item_sequence_number, b.item_sequence_number);
80 EXPECT_EQ(a.document_sequence_number, b.document_sequence_number);
81 EXPECT_EQ(a.visit_count, b.visit_count);
82 EXPECT_EQ(a.visited_time, b.visited_time);
83 EXPECT_EQ(a.page_scale_factor, b.page_scale_factor);
84 EXPECT_EQ(a.is_target_item, b.is_target_item);
85 ExpectEquality(a.http_body, b.http_body);
86 ExpectEquality(a.children, b.children);
89 void ExpectEquality(const ExplodedPageState& a, const ExplodedPageState& b) {
90 ExpectEquality(a.referenced_files, b.referenced_files);
91 ExpectEquality(a.top, b.top);
94 //-----------------------------------------------------------------------------
96 class PageStateSerializationTest : public testing::Test {
97 public:
98 void PopulateFrameState(ExplodedFrameState* frame_state) {
99 // Invent some data for the various fields.
100 frame_state->url_string = NS16("http://dev.chromium.org/");
101 frame_state->original_url_string = frame_state->url_string;
102 frame_state->referrer = NS16("https://www.google.com/search?q=dev.chromium.org");
103 frame_state->target = NS16("foo");
104 frame_state->parent = NS16("bar");
105 frame_state->title = NS16("The Chromium Projects");
106 frame_state->alternate_title = NS16(NULL);
107 frame_state->state_object = NS16(NULL);
108 frame_state->document_state.push_back(NS16("1"));
109 frame_state->document_state.push_back(NS16("q"));
110 frame_state->document_state.push_back(NS16("text"));
111 frame_state->document_state.push_back(NS16("dev.chromium.org"));
112 frame_state->scroll_offset = gfx::Point(0, 100);
113 frame_state->item_sequence_number = 1;
114 frame_state->document_sequence_number = 2;
115 frame_state->visit_count = 10;
116 frame_state->visited_time = 12345.0;
117 frame_state->page_scale_factor = 2.0;
118 frame_state->is_target_item = true;
121 void PopulateHttpBody(ExplodedHttpBody* http_body,
122 std::vector<base::NullableString16>* referenced_files) {
123 http_body->is_null = false;
124 http_body->identifier = 12345;
125 http_body->contains_passwords = false;
126 http_body->http_content_type = NS16("text/foo");
128 ExplodedHttpBodyElement e1;
129 e1.type = WebKit::WebHTTPBody::Element::TypeData;
130 e1.data = "foo";
131 http_body->elements.push_back(e1);
133 ExplodedHttpBodyElement e2;
134 e2.type = WebKit::WebHTTPBody::Element::TypeFile;
135 e2.file_path = NS16("file.txt");
136 e2.file_start = 100;
137 e2.file_length = 1024;
138 e2.file_modification_time = 9999.0;
139 http_body->elements.push_back(e2);
141 referenced_files->push_back(e2.file_path);
144 void PopulateFrameStateForBackwardsCompatTest(
145 ExplodedFrameState* frame_state,
146 bool is_child) {
147 frame_state->url_string = NS16("http://chromium.org/");
148 frame_state->original_url_string = frame_state->url_string;
149 frame_state->referrer = NS16("http://google.com/");
150 if (!is_child)
151 frame_state->target = NS16("target");
152 frame_state->parent = NS16("parent");
153 frame_state->title = NS16("title");
154 frame_state->alternate_title = NS16("alternateTitle");
155 frame_state->scroll_offset = gfx::Point(42, -42);
156 frame_state->item_sequence_number = 123;
157 frame_state->document_sequence_number = 456;
158 frame_state->visit_count = 42*42;
159 frame_state->visited_time = 13.37;
160 frame_state->page_scale_factor = 2.0f;
161 frame_state->is_target_item = true;
163 frame_state->document_state.push_back(
164 NS16("\n\r?% WebKit serialized form state version 8 \n\r=&"));
165 frame_state->document_state.push_back(NS16("form key"));
166 frame_state->document_state.push_back(NS16("1"));
167 frame_state->document_state.push_back(NS16("foo"));
168 frame_state->document_state.push_back(NS16("file"));
169 frame_state->document_state.push_back(NS16("2"));
170 frame_state->document_state.push_back(NS16("file.txt"));
171 frame_state->document_state.push_back(NS16("displayName"));
173 if (!is_child) {
174 frame_state->http_body.http_content_type = NS16("foo/bar");
175 frame_state->http_body.identifier = 789;
176 frame_state->http_body.is_null = false;
178 ExplodedHttpBodyElement e1;
179 e1.type = WebKit::WebHTTPBody::Element::TypeData;
180 e1.data = "first data block";
181 frame_state->http_body.elements.push_back(e1);
183 ExplodedHttpBodyElement e2;
184 e2.type = WebKit::WebHTTPBody::Element::TypeFile;
185 e2.file_path = NS16("file.txt");
186 frame_state->http_body.elements.push_back(e2);
188 ExplodedHttpBodyElement e3;
189 e3.type = WebKit::WebHTTPBody::Element::TypeData;
190 e3.data = "data the second";
191 frame_state->http_body.elements.push_back(e3);
193 ExplodedFrameState child_state;
194 PopulateFrameStateForBackwardsCompatTest(&child_state, true);
195 frame_state->children.push_back(child_state);
199 void PopulatePageStateForBackwardsCompatTest(ExplodedPageState* page_state) {
200 page_state->referenced_files.push_back(NS16("file.txt"));
201 PopulateFrameStateForBackwardsCompatTest(&page_state->top, false);
204 void TestBackwardsCompat(int version) {
205 const char* suffix = "";
207 #if defined(OS_ANDROID)
208 // Unfortunately, the format of version 11 is different on Android, so we
209 // need to use a special reference file.
210 if (version == 11)
211 suffix = "_android";
212 #endif
214 base::FilePath path;
215 PathService::Get(content::DIR_TEST_DATA, &path);
216 path = path.AppendASCII("page_state").AppendASCII(
217 base::StringPrintf("serialized_v%d%s.dat", version, suffix));
219 std::string file_contents;
220 if (!base::ReadFileToString(path, &file_contents)) {
221 ADD_FAILURE() << "File not found: " << path.value();
222 return;
225 std::string trimmed_contents;
226 EXPECT_TRUE(RemoveChars(file_contents, "\r\n", &trimmed_contents));
228 std::string encoded;
229 EXPECT_TRUE(base::Base64Decode(trimmed_contents, &encoded));
231 ExplodedPageState output;
232 #if defined(OS_ANDROID)
233 // Because version 11 of the file format unfortunately bakes in the device
234 // scale factor on Android, perform this test by assuming a preset device
235 // scale factor, ignoring the device scale factor of the current device.
236 const float kPresetDeviceScaleFactor = 2.0f;
237 EXPECT_TRUE(DecodePageStateWithDeviceScaleFactorForTesting(
238 encoded,
239 kPresetDeviceScaleFactor,
240 &output));
241 #else
242 EXPECT_TRUE(DecodePageState(encoded, &output));
243 #endif
245 ExplodedPageState expected;
246 PopulatePageStateForBackwardsCompatTest(&expected);
248 ExpectEquality(expected, output);
252 TEST_F(PageStateSerializationTest, BasicEmpty) {
253 ExplodedPageState input;
255 std::string encoded;
256 EXPECT_TRUE(EncodePageState(input, &encoded));
258 ExplodedPageState output;
259 EXPECT_TRUE(DecodePageState(encoded, &output));
261 ExpectEquality(input, output);
264 TEST_F(PageStateSerializationTest, BasicFrame) {
265 ExplodedPageState input;
266 PopulateFrameState(&input.top);
268 std::string encoded;
269 EXPECT_TRUE(EncodePageState(input, &encoded));
271 ExplodedPageState output;
272 EXPECT_TRUE(DecodePageState(encoded, &output));
274 ExpectEquality(input, output);
277 TEST_F(PageStateSerializationTest, BasicFramePOST) {
278 ExplodedPageState input;
279 PopulateFrameState(&input.top);
280 PopulateHttpBody(&input.top.http_body, &input.referenced_files);
282 std::string encoded;
283 EXPECT_TRUE(EncodePageState(input, &encoded));
285 ExplodedPageState output;
286 EXPECT_TRUE(DecodePageState(encoded, &output));
288 ExpectEquality(input, output);
291 TEST_F(PageStateSerializationTest, BasicFrameSet) {
292 ExplodedPageState input;
293 PopulateFrameState(&input.top);
295 // Add some child frames.
296 for (int i = 0; i < 4; ++i) {
297 ExplodedFrameState child_state;
298 PopulateFrameState(&child_state);
299 input.top.children.push_back(child_state);
302 std::string encoded;
303 EXPECT_TRUE(EncodePageState(input, &encoded));
305 ExplodedPageState output;
306 EXPECT_TRUE(DecodePageState(encoded, &output));
308 ExpectEquality(input, output);
311 TEST_F(PageStateSerializationTest, BasicFrameSetPOST) {
312 ExplodedPageState input;
313 PopulateFrameState(&input.top);
315 // Add some child frames.
316 for (int i = 0; i < 4; ++i) {
317 ExplodedFrameState child_state;
318 PopulateFrameState(&child_state);
320 // Simulate a form POST on a subframe.
321 if (i == 2)
322 PopulateHttpBody(&child_state.http_body, &input.referenced_files);
324 input.top.children.push_back(child_state);
327 std::string encoded;
328 EncodePageState(input, &encoded);
330 ExplodedPageState output;
331 DecodePageState(encoded, &output);
333 ExpectEquality(input, output);
336 TEST_F(PageStateSerializationTest, BadMessagesTest1) {
337 Pickle p;
338 // Version 14
339 p.WriteInt(14);
340 // Empty strings.
341 for (int i = 0; i < 6; ++i)
342 p.WriteInt(-1);
343 // Bad real number.
344 p.WriteInt(-1);
346 std::string s(static_cast<const char*>(p.data()), p.size());
348 ExplodedPageState output;
349 EXPECT_FALSE(DecodePageState(s, &output));
352 TEST_F(PageStateSerializationTest, BadMessagesTest2) {
353 double d = 0;
354 Pickle p;
355 // Version 14
356 p.WriteInt(14);
357 // Empty strings.
358 for (int i = 0; i < 6; ++i)
359 p.WriteInt(-1);
360 // More misc fields.
361 p.WriteData(reinterpret_cast<const char*>(&d), sizeof(d));
362 p.WriteInt(1);
363 p.WriteInt(1);
364 p.WriteInt(0);
365 p.WriteInt(0);
366 p.WriteInt(-1);
367 p.WriteInt(0);
368 // WebForm
369 p.WriteInt(1);
370 p.WriteInt(WebKit::WebHTTPBody::Element::TypeData);
372 std::string s(static_cast<const char*>(p.data()), p.size());
374 ExplodedPageState output;
375 EXPECT_FALSE(DecodePageState(s, &output));
378 TEST_F(PageStateSerializationTest, DumpExpectedPageStateForBackwardsCompat) {
379 // Comment out this return statement to enable this code. Use this code to
380 // generate data, based on the current serialization format, for the
381 // BackwardsCompat_vXX tests.
382 return;
384 ExplodedPageState state;
385 PopulatePageStateForBackwardsCompatTest(&state);
387 std::string encoded;
388 EXPECT_TRUE(EncodePageState(state, &encoded));
390 std::string base64;
391 EXPECT_TRUE(base::Base64Encode(encoded, &base64));
393 base::FilePath path;
394 PathService::Get(base::DIR_TEMP, &path);
395 path = path.AppendASCII("expected.dat");
397 FILE* fp = file_util::OpenFile(path, "wb");
398 ASSERT_TRUE(fp);
400 const size_t kRowSize = 76;
401 for (size_t offset = 0; offset < base64.size(); offset += kRowSize) {
402 size_t length = std::min(base64.size() - offset, kRowSize);
403 std::string segment(&base64[offset], length);
404 segment.push_back('\n');
405 fwrite(segment.data(), segment.size(), 1, fp);
408 fclose(fp);
411 #if !defined(OS_ANDROID)
412 // TODO(darin): Re-enable for Android once this test accounts for systems with
413 // a device scale factor not equal to 2.
414 TEST_F(PageStateSerializationTest, BackwardsCompat_v11) {
415 TestBackwardsCompat(11);
417 #endif
419 TEST_F(PageStateSerializationTest, BackwardsCompat_v12) {
420 TestBackwardsCompat(12);
423 TEST_F(PageStateSerializationTest, BackwardsCompat_v13) {
424 TestBackwardsCompat(13);
427 TEST_F(PageStateSerializationTest, BackwardsCompat_v14) {
428 TestBackwardsCompat(14);
431 } // namespace
432 } // namespace content