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

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

Issue 16867005: 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
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 base::NullableString16 NS16(const char* s) {
26 return s ? base::NullableString16(ASCIIToUTF16(s), false) :
27 base::NullableString16();
28 }
29
30 //-----------------------------------------------------------------------------
31
32 template <typename T>
33 void ExpectEquality(const T& a, const T& b) {
34 EXPECT_EQ(a, b);
35 }
36
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]);
jamesr 2013/06/21 23:24:53 i think EXPECT_EQ(a[i], b[i]) should work here
darin (slow to review) 2013/06/24 08:02:10 This ExpectEquality call is needed to handle these
42 }
43
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.url, b.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 }
56
57 template <>
58 void ExpectEquality(const ExplodedHttpBody& a, const ExplodedHttpBody& b) {
59 EXPECT_EQ(a.http_content_type, b.http_content_type);
60 EXPECT_EQ(a.identifier, b.identifier);
61 EXPECT_EQ(a.contains_passwords, b.contains_passwords);
62 EXPECT_EQ(a.is_null, b.is_null);
63 ExpectEquality(a.elements, b.elements);
64 }
65
66 template <>
67 void ExpectEquality(const ExplodedFrameState& a, const ExplodedFrameState& b) {
68 EXPECT_EQ(a.url_string, b.url_string);
69 EXPECT_EQ(a.original_url_string, b.original_url_string);
70 EXPECT_EQ(a.referrer, b.referrer);
71 EXPECT_EQ(a.target, b.target);
72 EXPECT_EQ(a.parent, b.parent);
73 EXPECT_EQ(a.title, b.title);
74 EXPECT_EQ(a.alternate_title, b.alternate_title);
75 EXPECT_EQ(a.state_object, b.state_object);
76 ExpectEquality(a.document_state, b.document_state);
77 EXPECT_EQ(a.scroll_offset, b.scroll_offset);
78 EXPECT_EQ(a.item_sequence_number, b.item_sequence_number);
79 EXPECT_EQ(a.document_sequence_number, b.document_sequence_number);
80 EXPECT_EQ(a.visit_count, b.visit_count);
81 EXPECT_EQ(a.visited_time, b.visited_time);
82 EXPECT_EQ(a.page_scale_factor, b.page_scale_factor);
jamesr 2013/06/21 23:24:53 file_modificiation_time has checks for nan, but fo
83 EXPECT_EQ(a.is_target_item, b.is_target_item);
84 ExpectEquality(a.http_body, b.http_body);
85 ExpectEquality(a.children, b.children);
86 }
87
88 void ExpectEquality(const ExplodedPageState& a, const ExplodedPageState& b) {
89 ExpectEquality(a.referenced_files, b.referenced_files);
90 ExpectEquality(a.top, b.top);
91 }
92
93 //-----------------------------------------------------------------------------
94
95 class PageStateSerializationTest : public testing::Test {
96 public:
97 void PopulateFrameState(ExplodedFrameState* frame_state) {
98 // Invent some data for the various fields.
99 frame_state->url_string = NS16("http://dev.chromium.org/");
100 frame_state->original_url_string = frame_state->url_string;
101 frame_state->referrer = NS16("https://www.google.com/search?q=dev.chromium.o rg");
102 frame_state->target = NS16("foo");
103 frame_state->parent = NS16("bar");
104 frame_state->title = NS16("The Chromium Projects");
105 frame_state->alternate_title = NS16(NULL);
106 frame_state->state_object = NS16(NULL);
107 frame_state->document_state.push_back(NS16("1"));
108 frame_state->document_state.push_back(NS16("q"));
109 frame_state->document_state.push_back(NS16("text"));
110 frame_state->document_state.push_back(NS16("dev.chromium.org"));
111 frame_state->scroll_offset = gfx::Point(0, 100);
112 frame_state->item_sequence_number = 1;
113 frame_state->document_sequence_number = 2;
114 frame_state->visit_count = 10;
115 frame_state->visited_time = 12345.0;
116 frame_state->page_scale_factor = 2.0;
117 frame_state->is_target_item = true;
118 }
119
120 void PopulateHttpBody(ExplodedHttpBody* http_body,
121 std::vector<base::NullableString16>* referenced_files) {
122 http_body->is_null = false;
123 http_body->identifier = 12345;
124 http_body->contains_passwords = false;
125 http_body->http_content_type = NS16("text/foo");
126
127 ExplodedHttpBodyElement e1;
128 e1.type = WebKit::WebHTTPBody::Element::TypeData;
129 e1.data = "foo";
130 http_body->elements.push_back(e1);
131
132 ExplodedHttpBodyElement e2;
133 e2.type = WebKit::WebHTTPBody::Element::TypeFile;
134 e2.file_path = NS16("file.txt");
135 e2.file_start = 100;
136 e2.file_length = 1024;
137 e2.file_modification_time = 9999.0;
138 http_body->elements.push_back(e2);
139
140 referenced_files->push_back(e2.file_path);
141 }
142
143 void PopulateFrameStateForBackwardsCompatTest(
144 ExplodedFrameState* frame_state,
145 bool is_child) {
146 frame_state->url_string = NS16("http://chromium.org/");
147 frame_state->original_url_string = frame_state->url_string;
148 frame_state->referrer = NS16("http://google.com/");
149 if (!is_child)
150 frame_state->target = NS16("target");
151 frame_state->parent = NS16("parent");
152 frame_state->title = NS16("title");
153 frame_state->alternate_title = NS16("alternateTitle");
154 frame_state->scroll_offset = gfx::Point(42, -42);
155 frame_state->item_sequence_number = 123;
156 frame_state->document_sequence_number = 456;
157 frame_state->visit_count = 42*42;
158 frame_state->visited_time = 13.37;
159 frame_state->page_scale_factor = 2.0f;
160 frame_state->is_target_item = true;
161
162 frame_state->document_state.push_back(
163 NS16("\n\r?% WebKit serialized form state version 8 \n\r=&"));
164 frame_state->document_state.push_back(NS16("form key"));
165 frame_state->document_state.push_back(NS16("1"));
166 frame_state->document_state.push_back(NS16("foo"));
167 frame_state->document_state.push_back(NS16("file"));
168 frame_state->document_state.push_back(NS16("2"));
169 frame_state->document_state.push_back(NS16("file.txt"));
170 frame_state->document_state.push_back(NS16("displayName"));
171
172 if (!is_child) {
173 frame_state->http_body.http_content_type = NS16("foo/bar");
174 frame_state->http_body.identifier = 789;
175 frame_state->http_body.is_null = false;
176
177 ExplodedHttpBodyElement e1;
178 e1.type = WebKit::WebHTTPBody::Element::TypeData;
179 e1.data = "first data block";
180 frame_state->http_body.elements.push_back(e1);
181
182 ExplodedHttpBodyElement e2;
183 e2.type = WebKit::WebHTTPBody::Element::TypeFile;
184 e2.file_path = NS16("file.txt");
185 frame_state->http_body.elements.push_back(e2);
186
187 ExplodedHttpBodyElement e3;
188 e3.type = WebKit::WebHTTPBody::Element::TypeData;
189 e3.data = "data the second";
190 frame_state->http_body.elements.push_back(e3);
191
192 ExplodedFrameState child_state;
193 PopulateFrameStateForBackwardsCompatTest(&child_state, true);
194 frame_state->children.push_back(child_state);
195 }
196 }
197
198 void PopulatePageStateForBackwardsCompatTest(ExplodedPageState* page_state) {
199 page_state->referenced_files.push_back(NS16("file.txt"));
200 PopulateFrameStateForBackwardsCompatTest(&page_state->top, false);
201 }
202
203 void TestBackwardsCompat(int version) {
204 const char* suffix = "";
205
206 #if defined(OS_ANDROID)
207 // Unfortunately, the format of version 11 is different on Android, so we
208 // need to use a special reference file.
209 if (version == 11)
210 suffix = "_android";
211 #endif
212
213 base::FilePath path;
214 PathService::Get(content::DIR_TEST_DATA, &path);
215 path = path.AppendASCII("page_state").AppendASCII(
216 base::StringPrintf("serialized_v%d%s.dat", version, suffix));
217
218 std::string file_contents;
219 if (!file_util::ReadFileToString(path, &file_contents)) {
220 ADD_FAILURE() << "File not found: " << path.value();
221 return;
222 }
223
224 std::string trimmed_contents;
225 EXPECT_TRUE(RemoveChars(file_contents, "\r\n", &trimmed_contents));
226
227 std::string encoded;
228 EXPECT_TRUE(base::Base64Decode(trimmed_contents, &encoded));
229
230 ExplodedPageState output;
231 EXPECT_TRUE(DecodePageState(encoded, &output));
232
233 ExplodedPageState expected;
234 PopulatePageStateForBackwardsCompatTest(&expected);
235
236 ExpectEquality(expected, output);
237 }
238 };
239
240 TEST_F(PageStateSerializationTest, BasicEmpty) {
241 ExplodedPageState input;
242
243 std::string encoded;
244 EXPECT_TRUE(EncodePageState(input, &encoded));
245
246 ExplodedPageState output;
247 EXPECT_TRUE(DecodePageState(encoded, &output));
248
249 ExpectEquality(input, output);
250 }
251
252 TEST_F(PageStateSerializationTest, BasicFrame) {
253 ExplodedPageState input;
254 PopulateFrameState(&input.top);
255
256 std::string encoded;
257 EXPECT_TRUE(EncodePageState(input, &encoded));
258
259 ExplodedPageState output;
260 EXPECT_TRUE(DecodePageState(encoded, &output));
261
262 ExpectEquality(input, output);
263 }
264
265 TEST_F(PageStateSerializationTest, BasicFramePOST) {
266 ExplodedPageState input;
267 PopulateFrameState(&input.top);
268 PopulateHttpBody(&input.top.http_body, &input.referenced_files);
269
270 std::string encoded;
271 EXPECT_TRUE(EncodePageState(input, &encoded));
272
273 ExplodedPageState output;
274 EXPECT_TRUE(DecodePageState(encoded, &output));
275
276 ExpectEquality(input, output);
277 }
278
279 TEST_F(PageStateSerializationTest, BasicFrameSet) {
280 ExplodedPageState input;
281 PopulateFrameState(&input.top);
282
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);
288 }
289
290 std::string encoded;
291 EXPECT_TRUE(EncodePageState(input, &encoded));
292
293 ExplodedPageState output;
294 EXPECT_TRUE(DecodePageState(encoded, &output));
295
296 ExpectEquality(input, output);
297 }
298
299 TEST_F(PageStateSerializationTest, BasicFrameSetPOST) {
300 ExplodedPageState input;
301 PopulateFrameState(&input.top);
302
303 // Add some child frames.
304 for (int i = 0; i < 4; ++i) {
305 ExplodedFrameState child_state;
306 PopulateFrameState(&child_state);
307
308 // Simulate a form POST on a subframe.
309 if (i == 2)
310 PopulateHttpBody(&child_state.http_body, &input.referenced_files);
311
312 input.top.children.push_back(child_state);
313 }
314
315 std::string encoded;
316 EncodePageState(input, &encoded);
317
318 ExplodedPageState output;
319 DecodePageState(encoded, &output);
320
321 ExpectEquality(input, output);
322 }
323
324 TEST_F(PageStateSerializationTest, BadMessagesTest1) {
325 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);
333
334 std::string s(static_cast<const char*>(p.data()), p.size());
335
336 ExplodedPageState output;
337 EXPECT_FALSE(DecodePageState(s, &output));
338 }
339
340 TEST_F(PageStateSerializationTest, BadMessagesTest2) {
341 double d = 0;
jamesr 2013/06/21 23:24:53 should 0.0 according to http://google-styleguide.g
342 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(WebKit::WebHTTPBody::Element::TypeData);
359
360 std::string s(static_cast<const char*>(p.data()), p.size());
361
362 ExplodedPageState output;
363 EXPECT_FALSE(DecodePageState(s, &output));
364 }
365
366 TEST_F(PageStateSerializationTest, DumpExpectedPageStateForBackwardsCompat) {
367 // Comment out this return statement to enable this code. Use this code to
368 // generate data, based on the current serialization format, for the
369 // BackwardsCompat_vXX tests.
370 return;
371
372 ExplodedPageState state;
373 PopulatePageStateForBackwardsCompatTest(&state);
374
375 std::string encoded;
376 EXPECT_TRUE(EncodePageState(state, &encoded));
377
378 std::string base64;
379 EXPECT_TRUE(base::Base64Encode(encoded, &base64));
380
381 base::FilePath path;
382 PathService::Get(base::DIR_TEMP, &path);
383 path = path.AppendASCII("expected.dat");
384
385 FILE* fp = file_util::OpenFile(path, "wb");
386 ASSERT_TRUE(fp);
387
388 const size_t kRowSize = 76;
389 for (size_t offset = 0; offset < base64.size(); offset += kRowSize) {
390 size_t length = std::min(base64.size() - offset, kRowSize);
391 std::string segment(&base64[offset], length);
392 segment.push_back('\n');
393 fwrite(segment.data(), segment.size(), 1, fp);
jamesr 2013/06/21 23:24:53 does fwrite() compile on windows? i'd expect a cal
darin (slow to review) 2013/06/24 08:02:10 Yes (the windows try bots are happy). file_util::
394 }
395
396 file_util::CloseFile(fp);
397 }
398
399 TEST_F(PageStateSerializationTest, BackwardsCompat_v11) {
400 TestBackwardsCompat(11);
401 }
402
403 TEST_F(PageStateSerializationTest, BackwardsCompat_v12) {
404 TestBackwardsCompat(12);
405 }
406
407 TEST_F(PageStateSerializationTest, BackwardsCompat_v13) {
408 TestBackwardsCompat(13);
409 }
410
411 TEST_F(PageStateSerializationTest, BackwardsCompat_v14) {
412 TestBackwardsCompat(14);
413 }
414
415 } // namespace
416 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698