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

Side by Side Diff: content/common/page_state_serialization_unittest.cc

Issue 16335022: Re-implement PageState serialization without a Blink API dependency. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « content/common/page_state_serialization.cc ('k') | content/content_common.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 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.
4
5 #include <math.h>
6
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/stringprintf.h"
12 #include "base/strings/string_util.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"
17
18 namespace content {
19 namespace {
20
21 #if defined(OS_WIN)
22 inline bool isnan(double num) { return !!_isnan(num); }
23 #endif
24
25 NullableString16 NS16(const char* s) {
26 return s ? NullableString16(ASCIIToUTF16(s), false) : NullableString16();
27 }
28
29 //-----------------------------------------------------------------------------
30
31 template <typename T>
32 void ExpectEquality(const T& a, const T& b) {
33 EXPECT_EQ(a, b);
34 }
35
36 template <typename T>
37 void ExpectEquality(const std::vector<T>& a, const std::vector<T>& b) {
38 EXPECT_EQ(a.size(), b.size());
39 for (size_t i = 0; i < std::min(a.size(), b.size()); ++i)
40 ExpectEquality(a[i], b[i]);
41 }
42
43 template <>
44 void ExpectEquality(const ExplodedHttpBodyElement& a,
45 const ExplodedHttpBodyElement& b) {
46 EXPECT_EQ(a.type, b.type);
47 EXPECT_EQ(a.data, b.data);
48 EXPECT_EQ(a.file_path, b.file_path);
49 EXPECT_EQ(a.url, b.url);
50 EXPECT_EQ(a.file_start, b.file_start);
51 EXPECT_EQ(a.file_length, b.file_length);
52 if (!(isnan(a.file_modification_time) && isnan(b.file_modification_time)))
53 EXPECT_DOUBLE_EQ(a.file_modification_time, b.file_modification_time);
54 }
55
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);
63 }
64
65 template <>
66 void ExpectEquality(const ExplodedFrameState& a, const ExplodedFrameState& b) {
67 EXPECT_EQ(a.url_string, b.url_string);
68 EXPECT_EQ(a.original_url_string, b.original_url_string);
69 EXPECT_EQ(a.referrer, b.referrer);
70 EXPECT_EQ(a.target, b.target);
71 EXPECT_EQ(a.parent, b.parent);
72 EXPECT_EQ(a.title, b.title);
73 EXPECT_EQ(a.alternate_title, b.alternate_title);
74 EXPECT_EQ(a.state_object, b.state_object);
75 ExpectEquality(a.document_state, b.document_state);
76 EXPECT_EQ(a.scroll_offset, b.scroll_offset);
77 EXPECT_EQ(a.item_sequence_number, b.item_sequence_number);
78 EXPECT_EQ(a.document_sequence_number, b.document_sequence_number);
79 EXPECT_EQ(a.visit_count, b.visit_count);
80 EXPECT_EQ(a.visited_time, b.visited_time);
81 EXPECT_EQ(a.page_scale_factor, b.page_scale_factor);
82 EXPECT_EQ(a.is_target_item, b.is_target_item);
83 ExpectEquality(a.http_body, b.http_body);
84 ExpectEquality(a.children, b.children);
85 }
86
87 void ExpectEquality(const ExplodedPageState& a, const ExplodedPageState& b) {
88 ExpectEquality(a.referenced_files, b.referenced_files);
89 ExpectEquality(a.top, b.top);
90 }
91
92 //-----------------------------------------------------------------------------
93
94 class PageStateSerializationTest : public testing::Test {
95 public:
96 void PopulateFrameState(ExplodedFrameState* frame_state) {
97 // Invent some data for the various fields.
98 frame_state->url_string = NS16("http://dev.chromium.org/");
99 frame_state->original_url_string = frame_state->url_string;
100 frame_state->referrer = NS16("https://www.google.com/search?q=dev.chromium.o rg");
101 frame_state->target = NS16("foo");
102 frame_state->parent = NS16("bar");
103 frame_state->title = NS16("The Chromium Projects");
104 frame_state->alternate_title = NS16(NULL);
105 frame_state->state_object = NS16(NULL);
106 frame_state->document_state.push_back(NS16("1"));
107 frame_state->document_state.push_back(NS16("q"));
108 frame_state->document_state.push_back(NS16("text"));
109 frame_state->document_state.push_back(NS16("dev.chromium.org"));
110 frame_state->scroll_offset = gfx::Point(0, 100);
111 frame_state->item_sequence_number = 1;
112 frame_state->document_sequence_number = 2;
113 frame_state->visit_count = 10;
114 frame_state->visited_time = 12345.0;
115 frame_state->page_scale_factor = 2.0;
116 frame_state->is_target_item = true;
117 }
118
119 void PopulateHttpBody(ExplodedHttpBody* http_body,
120 std::vector<base::FilePath>* referenced_files) {
121 http_body->is_null = false;
122 http_body->identifier = 12345;
123 http_body->contains_passwords = false;
124 http_body->http_content_type = NS16("text/foo");
125
126 ExplodedHttpBodyElement e1;
127 e1.type = WebKit::WebHTTPBody::Element::TypeData;
128 e1.data = "foo";
129 http_body->elements.push_back(e1);
130
131 ExplodedHttpBodyElement e2;
132 e2.type = WebKit::WebHTTPBody::Element::TypeFile;
133 e2.file_start = 100;
134 e2.file_length = 1024;
135 e2.file_modification_time = 9999.0;
136 PathService::Get(base::DIR_TEMP, &e2.file_path);
137 http_body->elements.push_back(e2);
138
139 referenced_files->push_back(e2.file_path);
140 }
141
142 void PopulateFrameStateForBackwardsCompatTest(
143 ExplodedFrameState* frame_state,
144 bool is_child) {
145 frame_state->url_string = NS16("http://chromium.org/");
146 frame_state->original_url_string = frame_state->url_string;
147 frame_state->referrer = NS16("http://google.com/");
148 if (!is_child)
149 frame_state->target = NS16("target");
150 frame_state->parent = NS16("parent");
151 frame_state->title = NS16("title");
152 frame_state->alternate_title = NS16("alternateTitle");
153 frame_state->scroll_offset = gfx::Point(42, -42);
154 frame_state->item_sequence_number = 123;
155 frame_state->document_sequence_number = 456;
156 frame_state->visit_count = 42*42;
157 frame_state->visited_time = 13.37;
158 frame_state->page_scale_factor = 2.0f;
159 frame_state->is_target_item = true;
160
161 frame_state->document_state.push_back(
162 NS16("\n\r?% WebKit serialized form state version 8 \n\r=&"));
163 frame_state->document_state.push_back(NS16("form key"));
164 frame_state->document_state.push_back(NS16("1"));
165 frame_state->document_state.push_back(NS16("foo"));
166 frame_state->document_state.push_back(NS16("file"));
167 frame_state->document_state.push_back(NS16("2"));
168 frame_state->document_state.push_back(NS16("file.txt"));
169 frame_state->document_state.push_back(NS16("displayName"));
170
171 if (!is_child) {
172 frame_state->http_body.http_content_type = NS16("foo/bar");
173 frame_state->http_body.identifier = 789;
174 frame_state->http_body.is_null = false;
175
176 ExplodedHttpBodyElement e1;
177 e1.type = WebKit::WebHTTPBody::Element::TypeData;
178 e1.data = "first data block";
179 frame_state->http_body.elements.push_back(e1);
180
181 ExplodedHttpBodyElement e2;
182 e2.type = WebKit::WebHTTPBody::Element::TypeFile;
183 e2.file_path = base::FilePath::FromUTF8Unsafe("file.txt");
184 frame_state->http_body.elements.push_back(e2);
185
186 ExplodedHttpBodyElement e3;
187 e3.type = WebKit::WebHTTPBody::Element::TypeData;
188 e3.data = "data the second";
189 frame_state->http_body.elements.push_back(e3);
190
191 ExplodedFrameState child_state;
192 PopulateFrameStateForBackwardsCompatTest(&child_state, true);
193 frame_state->children.push_back(child_state);
194 }
195 }
196
197 void PopulatePageStateForBackwardsCompatTest(ExplodedPageState* page_state) {
198 page_state->referenced_files.push_back(
199 base::FilePath::FromUTF8Unsafe("file.txt"));
200 PopulateFrameStateForBackwardsCompatTest(&page_state->top, false);
201 }
202
203 void TestBackwardsCompat(int version) {
204 base::FilePath path;
205 PathService::Get(content::DIR_TEST_DATA, &path);
206 path = path.AppendASCII("page_state").AppendASCII(
207 base::StringPrintf("serialized_v%d.dat", version));
208
209 std::string file_contents;
210 if (!file_util::ReadFileToString(path, &file_contents)) {
211 ADD_FAILURE() << "File not found: " << path.value();
212 return;
213 }
214
215 std::string trimmed_contents;
216 EXPECT_TRUE(RemoveChars(file_contents, "\r\n", &trimmed_contents));
217
218 std::string encoded;
219 EXPECT_TRUE(base::Base64Decode(trimmed_contents, &encoded));
220
221 ExplodedPageState output;
222 EXPECT_TRUE(DecodePageState(encoded, &output));
223
224 ExplodedPageState expected;
225 PopulatePageStateForBackwardsCompatTest(&expected);
226
227 ExpectEquality(expected, output);
228 }
229 };
230
231 TEST_F(PageStateSerializationTest, BasicEmpty) {
232 ExplodedPageState input;
233
234 std::string encoded;
235 EXPECT_TRUE(EncodePageState(input, &encoded));
236
237 ExplodedPageState output;
238 EXPECT_TRUE(DecodePageState(encoded, &output));
239
240 ExpectEquality(input, output);
241 }
242
243 TEST_F(PageStateSerializationTest, BasicFrame) {
244 ExplodedPageState input;
245 PopulateFrameState(&input.top);
246
247 std::string encoded;
248 EXPECT_TRUE(EncodePageState(input, &encoded));
249
250 ExplodedPageState output;
251 EXPECT_TRUE(DecodePageState(encoded, &output));
252
253 ExpectEquality(input, output);
254 }
255
256 TEST_F(PageStateSerializationTest, BasicFramePOST) {
257 ExplodedPageState input;
258 PopulateFrameState(&input.top);
259 PopulateHttpBody(&input.top.http_body, &input.referenced_files);
260
261 std::string encoded;
262 EXPECT_TRUE(EncodePageState(input, &encoded));
263
264 ExplodedPageState output;
265 EXPECT_TRUE(DecodePageState(encoded, &output));
266
267 ExpectEquality(input, output);
268 }
269
270 TEST_F(PageStateSerializationTest, BasicFrameSet) {
271 ExplodedPageState input;
272 PopulateFrameState(&input.top);
273
274 // Add some child frames.
275 for (int i = 0; i < 4; ++i) {
276 ExplodedFrameState child_state;
277 PopulateFrameState(&child_state);
278 input.top.children.push_back(child_state);
279 }
280
281 std::string encoded;
282 EXPECT_TRUE(EncodePageState(input, &encoded));
283
284 ExplodedPageState output;
285 EXPECT_TRUE(DecodePageState(encoded, &output));
286
287 ExpectEquality(input, output);
288 }
289
290 TEST_F(PageStateSerializationTest, BasicFrameSetPOST) {
291 ExplodedPageState input;
292 PopulateFrameState(&input.top);
293
294 // Add some child frames.
295 for (int i = 0; i < 4; ++i) {
296 ExplodedFrameState child_state;
297 PopulateFrameState(&child_state);
298
299 // Simulate a form POST on a subframe.
300 if (i == 2)
301 PopulateHttpBody(&child_state.http_body, &input.referenced_files);
302
303 input.top.children.push_back(child_state);
304 }
305
306 std::string encoded;
307 EncodePageState(input, &encoded);
308
309 ExplodedPageState output;
310 DecodePageState(encoded, &output);
311
312 ExpectEquality(input, output);
313 }
314
315 TEST_F(PageStateSerializationTest, BadMessagesTest1) {
316 Pickle p;
317 // Version 14
318 p.WriteInt(14);
319 // Empty strings.
320 for (int i = 0; i < 6; ++i)
321 p.WriteInt(-1);
322 // Bad real number.
323 p.WriteInt(-1);
324
325 std::string s(static_cast<const char*>(p.data()), p.size());
326
327 ExplodedPageState output;
328 EXPECT_FALSE(DecodePageState(s, &output));
329 }
330
331 TEST_F(PageStateSerializationTest, BadMessagesTest2) {
332 double d = 0;
333 Pickle p;
334 // Version 14
335 p.WriteInt(14);
336 // Empty strings.
337 for (int i = 0; i < 6; ++i)
338 p.WriteInt(-1);
339 // More misc fields.
340 p.WriteData(reinterpret_cast<const char*>(&d), sizeof(d));
341 p.WriteInt(1);
342 p.WriteInt(1);
343 p.WriteInt(0);
344 p.WriteInt(0);
345 p.WriteInt(-1);
346 p.WriteInt(0);
347 // WebForm
348 p.WriteInt(1);
349 p.WriteInt(WebKit::WebHTTPBody::Element::TypeData);
350
351 std::string s(static_cast<const char*>(p.data()), p.size());
352
353 ExplodedPageState output;
354 EXPECT_FALSE(DecodePageState(s, &output));
355 }
356
357 TEST_F(PageStateSerializationTest, DumpExpectedPageStateForBackwardsCompat) {
358 // Comment out this return statement to enable this code. Use this code to
359 // generate data, based on the current serialization format, for the
360 // BackwardsCompat_vXX tests.
361 return;
362
363 ExplodedPageState state;
364 PopulatePageStateForBackwardsCompatTest(&state);
365
366 std::string encoded;
367 EXPECT_TRUE(EncodePageState(state, &encoded));
368
369 std::string base64;
370 EXPECT_TRUE(base::Base64Encode(encoded, &base64));
371
372 base::FilePath path;
373 PathService::Get(base::DIR_TEMP, &path);
374 path = path.AppendASCII("expected.dat");
375
376 FILE* fp = file_util::OpenFile(path, "wb");
377 ASSERT_TRUE(fp);
378
379 const size_t kRowSize = 76;
380 for (size_t offset = 0; offset < base64.size(); offset += kRowSize) {
381 size_t length = std::min(base64.size() - offset, kRowSize);
382 std::string segment(&base64[offset], length);
383 segment.push_back('\n');
384 fwrite(segment.data(), segment.size(), 1, fp);
385 }
386
387 file_util::CloseFile(fp);
388 }
389
390 // TODO(darin): Chrome on Android unfortunately used a different format at
391 // version 11. We need a different data file to test the code on Android.
392 #if !defined(OS_ANDROID)
393 TEST_F(PageStateSerializationTest, BackwardsCompat_v11) {
394 TestBackwardsCompat(11);
395 }
396 #endif
397
398 TEST_F(PageStateSerializationTest, BackwardsCompat_v12) {
399 TestBackwardsCompat(12);
400 }
401
402 TEST_F(PageStateSerializationTest, BackwardsCompat_v13) {
403 TestBackwardsCompat(13);
404 }
405
406 TEST_F(PageStateSerializationTest, BackwardsCompat_v14) {
407 TestBackwardsCompat(14);
408 }
409
410 } // namespace
411 } // namespace content
OLDNEW
« no previous file with comments | « content/common/page_state_serialization.cc ('k') | content/content_common.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698