OLD | NEW |
(Empty) | |
| 1 // Copyright 2012 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 #import <Foundation/Foundation.h> |
| 6 |
| 7 #include "base/mac/scoped_nsobject.h" |
| 8 #include "base/strings/sys_string_conversions.h" |
| 9 #import "ios/testing/ocmock_complex_type_helper.h" |
| 10 #import "ios/web/navigation/crw_session_entry.h" |
| 11 #include "ios/web/navigation/navigation_item_impl.h" |
| 12 #include "ios/web/public/referrer.h" |
| 13 #import "net/base/mac/url_conversions.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 #include "testing/gtest_mac.h" |
| 16 #include "testing/platform_test.h" |
| 17 #import "third_party/ocmock/OCMock/OCMock.h" |
| 18 #include "third_party/ocmock/gtest_support.h" |
| 19 #include "ui/base/page_transition_types.h" |
| 20 |
| 21 static NSString* const kHTTPHeaderKey1 = @"key1"; |
| 22 static NSString* const kHTTPHeaderKey2 = @"key2"; |
| 23 static NSString* const kHTTPHeaderValue1 = @"value1"; |
| 24 static NSString* const kHTTPHeaderValue2 = @"value2"; |
| 25 |
| 26 class CRWSessionEntryTest : public PlatformTest { |
| 27 public: |
| 28 static void expectEqualSessionEntries(CRWSessionEntry* entry1, |
| 29 CRWSessionEntry* entry2, |
| 30 ui::PageTransition transition); |
| 31 |
| 32 protected: |
| 33 void SetUp() override { |
| 34 GURL url("http://init.test"); |
| 35 ui::PageTransition transition = |
| 36 ui::PAGE_TRANSITION_AUTO_BOOKMARK; |
| 37 sessionEntry_.reset([[CRWSessionEntry alloc] initWithUrl:url |
| 38 referrer:web::Referrer() |
| 39 transition:transition |
| 40 useDesktopUserAgent:NO |
| 41 rendererInitiated:NO]); |
| 42 [sessionEntry_ navigationItem]->SetTimestamp(base::Time::Now()); |
| 43 [sessionEntry_ addHTTPHeaders:@{ kHTTPHeaderKey1 : kHTTPHeaderValue1 }]; |
| 44 [sessionEntry_ |
| 45 setPOSTData:[@"Test data" dataUsingEncoding:NSUTF8StringEncoding]]; |
| 46 } |
| 47 void TearDown() override { sessionEntry_.reset(); } |
| 48 |
| 49 protected: |
| 50 base::scoped_nsobject<CRWSessionEntry> sessionEntry_; |
| 51 }; |
| 52 |
| 53 @implementation OCMockComplexTypeHelper (CRWSessionEntryTest) |
| 54 typedef void (^encodeBytes_length_forKey_block)( |
| 55 const uint8_t*, NSUInteger, NSString*); |
| 56 - (void)encodeBytes:(const uint8_t*)bytes |
| 57 length:(NSUInteger)length |
| 58 forKey:(NSString*)key { |
| 59 static_cast<encodeBytes_length_forKey_block>([self blockForSelector:_cmd])( |
| 60 bytes, length, key); |
| 61 } |
| 62 |
| 63 typedef const uint8_t* (^decodeBytesForKeyBlock)(NSString*, NSUInteger*); |
| 64 - (const uint8_t*)decodeBytesForKey:(NSString*)key |
| 65 returnedLength:(NSUInteger*)lengthp { |
| 66 return static_cast<decodeBytesForKeyBlock>([self blockForSelector:_cmd])( |
| 67 key, lengthp); |
| 68 } |
| 69 @end |
| 70 |
| 71 void CRWSessionEntryTest::expectEqualSessionEntries( |
| 72 CRWSessionEntry* entry1, |
| 73 CRWSessionEntry* entry2, |
| 74 ui::PageTransition transition) { |
| 75 EXPECT_EQ(entry1.index, entry2.index); |
| 76 web::NavigationItem* navItem1 = entry1.navigationItem; |
| 77 web::NavigationItem* navItem2 = entry2.navigationItem; |
| 78 // url is not compared because it could differ after copy or archive. |
| 79 EXPECT_EQ(navItem1->GetVirtualURL(), navItem2->GetVirtualURL()); |
| 80 EXPECT_EQ(navItem1->GetReferrer().url, navItem2->GetReferrer().url); |
| 81 EXPECT_EQ(navItem1->GetTimestamp(), navItem2->GetTimestamp()); |
| 82 EXPECT_EQ(navItem1->GetTitle(), navItem2->GetTitle()); |
| 83 EXPECT_NSEQ(entry1.state, entry2.state); |
| 84 EXPECT_EQ(entry1.useDesktopUserAgent, entry2.useDesktopUserAgent); |
| 85 EXPECT_EQ(entry1.usedDataReductionProxy, entry2.usedDataReductionProxy); |
| 86 EXPECT_EQ(navItem2->GetTransitionType(), transition); |
| 87 EXPECT_NSEQ(entry1.httpHeaders, entry2.httpHeaders); |
| 88 EXPECT_TRUE((!entry1.POSTData && !entry2.POSTData) || |
| 89 [entry1.POSTData isEqualToData:entry2.POSTData]); |
| 90 EXPECT_EQ(entry1.skipResubmitDataConfirmation, |
| 91 entry2.skipResubmitDataConfirmation); |
| 92 } |
| 93 |
| 94 TEST_F(CRWSessionEntryTest, Description) { |
| 95 [sessionEntry_ navigationItem]->SetTitle(base::SysNSStringToUTF16(@"Title")); |
| 96 EXPECT_NSEQ([sessionEntry_ description], |
| 97 @"url:http://init.test/ " |
| 98 @"originalurl:http://init.test/ " |
| 99 @"title:Title " |
| 100 @"transition:2 " |
| 101 @"state:(null) " |
| 102 @"desktopUA:0 " |
| 103 @"proxy:0"); |
| 104 } |
| 105 |
| 106 TEST_F(CRWSessionEntryTest, InitWithCoder) { |
| 107 web::NavigationItem* item = [sessionEntry_ navigationItem]; |
| 108 item->SetVirtualURL(GURL("http://user.friendly")); |
| 109 item->SetTitle(base::SysNSStringToUTF16(@"Title")); |
| 110 int index = sessionEntry_.get().index; |
| 111 // Old serialized entries have no timestamp. |
| 112 item->SetTimestamp(base::Time::FromInternalValue(0)); |
| 113 |
| 114 NSURL* virtualUrl = net::NSURLWithGURL(item->GetVirtualURL()); |
| 115 NSURL* referrer = net::NSURLWithGURL(item->GetReferrer().url); |
| 116 NSString* title = base::SysUTF16ToNSString(item->GetTitle()); |
| 117 base::scoped_nsobject<id> decoder([[OCMockComplexTypeHelper alloc] |
| 118 initWithRepresentedObject:[OCMockObject mockForClass:[NSCoder class]]]); |
| 119 |
| 120 decodeBytesForKeyBlock block = ^ const uint8_t* (NSString* key, |
| 121 NSUInteger* length) { |
| 122 *length = 0; |
| 123 return NULL; |
| 124 }; |
| 125 |
| 126 [[[decoder stub] andReturnValue:[NSNumber numberWithBool:NO]] |
| 127 containsValueForKey:[OCMArg any]]; |
| 128 |
| 129 [decoder onSelector:@selector(decodeBytesForKey:returnedLength:) |
| 130 callBlockExpectation:block]; |
| 131 [[[decoder expect] andReturnValue:OCMOCK_VALUE(index)] |
| 132 decodeIntForKey:@"index"]; |
| 133 [[[decoder expect] andReturn:virtualUrl] |
| 134 decodeObjectForKey:@"virtualUrl"]; |
| 135 [[[decoder expect] andReturn:referrer] |
| 136 decodeObjectForKey:@"referrer"]; |
| 137 [[[decoder expect] andReturn:title] |
| 138 decodeObjectForKey:@"title"]; |
| 139 [[[decoder expect] andReturn:sessionEntry_.get().state] |
| 140 decodeObjectForKey:@"state"]; |
| 141 BOOL useDesktopUserAgent = sessionEntry_.get().useDesktopUserAgent; |
| 142 [[[decoder expect] andReturnValue:OCMOCK_VALUE(useDesktopUserAgent)] |
| 143 decodeBoolForKey:@"useDesktopUserAgent"]; |
| 144 BOOL usedDataReductionProxy = sessionEntry_.get().usedDataReductionProxy; |
| 145 [[[decoder expect] andReturnValue:OCMOCK_VALUE(usedDataReductionProxy)] |
| 146 decodeBoolForKey:@"usedDataReductionProxy"]; |
| 147 [[[decoder expect] andReturn:sessionEntry_.get().httpHeaders] |
| 148 decodeObjectForKey:@"httpHeaders"]; |
| 149 [[[decoder expect] andReturn:sessionEntry_.get().POSTData] |
| 150 decodeObjectForKey:@"POSTData"]; |
| 151 BOOL skipResubmitDataConfirmation = |
| 152 sessionEntry_.get().skipResubmitDataConfirmation; |
| 153 [[[decoder expect] andReturnValue:OCMOCK_VALUE(skipResubmitDataConfirmation)] |
| 154 decodeBoolForKey:@"skipResubmitDataConfirmation"]; |
| 155 |
| 156 base::scoped_nsobject<CRWSessionEntry> newSessionEntry( |
| 157 [[CRWSessionEntry alloc] initWithCoder:decoder]); |
| 158 web::NavigationItem* newItem = [newSessionEntry navigationItem]; |
| 159 |
| 160 EXPECT_OCMOCK_VERIFY(decoder); |
| 161 expectEqualSessionEntries(sessionEntry_, newSessionEntry, |
| 162 ui::PAGE_TRANSITION_RELOAD); |
| 163 EXPECT_NE(item->GetURL(), newItem->GetURL()); |
| 164 EXPECT_EQ(item->GetVirtualURL(), newItem->GetURL()); |
| 165 } |
| 166 |
| 167 TEST_F(CRWSessionEntryTest, InitWithCoderNewStyle) { |
| 168 web::NavigationItem* item = [sessionEntry_ navigationItem]; |
| 169 item->SetVirtualURL(GURL("http://user.friendly")); |
| 170 item->SetTitle(base::SysNSStringToUTF16(@"Title")); |
| 171 int index = sessionEntry_.get().index; |
| 172 int64 timestamp = item->GetTimestamp().ToInternalValue(); |
| 173 |
| 174 std::string virtualUrl = item->GetVirtualURL().spec(); |
| 175 std::string referrerUrl = item->GetReferrer().url.spec(); |
| 176 NSString* title = base::SysUTF16ToNSString(item->GetTitle()); |
| 177 base::scoped_nsobject<id> decoder([[OCMockComplexTypeHelper alloc] |
| 178 initWithRepresentedObject:[OCMockObject mockForClass:[NSCoder class]]]); |
| 179 |
| 180 const std::string emptyString; |
| 181 decodeBytesForKeyBlock block = ^ const uint8_t* (NSString* key, |
| 182 NSUInteger* length) { |
| 183 const std::string *value = &emptyString; |
| 184 if ([key isEqualToString:@"virtualUrlString"]) |
| 185 value = &virtualUrl; |
| 186 else if ([key isEqualToString:@"referrerUrlString"]) |
| 187 value = &referrerUrl; |
| 188 else |
| 189 EXPECT_TRUE(false); |
| 190 |
| 191 *length = value->size(); |
| 192 return reinterpret_cast<const uint8_t*>(value->data()); |
| 193 }; |
| 194 |
| 195 [decoder onSelector:@selector(decodeBytesForKey:returnedLength:) |
| 196 callBlockExpectation:block]; |
| 197 [[[decoder stub] andReturnValue:[NSNumber numberWithBool:YES]] |
| 198 containsValueForKey:[OCMArg any]]; |
| 199 [[[decoder expect] andReturnValue:OCMOCK_VALUE(index)] |
| 200 decodeIntForKey:@"index"]; |
| 201 web::ReferrerPolicy expectedPolicy = item->GetReferrer().policy; |
| 202 [[[decoder expect] |
| 203 andReturnValue:OCMOCK_VALUE(expectedPolicy)] |
| 204 decodeIntForKey:@"referrerPolicy"]; |
| 205 [[[decoder expect] andReturnValue:OCMOCK_VALUE(timestamp)] |
| 206 decodeInt64ForKey:@"timestamp"]; |
| 207 [[[decoder expect] andReturn:title] |
| 208 decodeObjectForKey:@"title"]; |
| 209 [[[decoder expect] andReturn:sessionEntry_.get().state] |
| 210 decodeObjectForKey:@"state"]; |
| 211 BOOL useDesktopUserAgent = sessionEntry_.get().useDesktopUserAgent; |
| 212 [[[decoder expect] andReturnValue:OCMOCK_VALUE(useDesktopUserAgent)] |
| 213 decodeBoolForKey:@"useDesktopUserAgent"]; |
| 214 BOOL usedDataReductionProxy = sessionEntry_.get().usedDataReductionProxy; |
| 215 [[[decoder expect] andReturnValue:OCMOCK_VALUE(usedDataReductionProxy)] |
| 216 decodeBoolForKey:@"usedDataReductionProxy"]; |
| 217 [[[decoder expect] andReturn:sessionEntry_.get().httpHeaders] |
| 218 decodeObjectForKey:@"httpHeaders"]; |
| 219 [[[decoder expect] andReturn:sessionEntry_.get().POSTData] |
| 220 decodeObjectForKey:@"POSTData"]; |
| 221 BOOL skipResubmitDataConfirmation = |
| 222 sessionEntry_.get().skipResubmitDataConfirmation; |
| 223 [[[decoder expect] andReturnValue:OCMOCK_VALUE(skipResubmitDataConfirmation)] |
| 224 decodeBoolForKey:@"skipResubmitDataConfirmation"]; |
| 225 |
| 226 base::scoped_nsobject<CRWSessionEntry> newSessionEntry( |
| 227 [[CRWSessionEntry alloc] initWithCoder:decoder]); |
| 228 web::NavigationItem* newItem = [newSessionEntry navigationItem]; |
| 229 |
| 230 EXPECT_OCMOCK_VERIFY(decoder); |
| 231 expectEqualSessionEntries(sessionEntry_, newSessionEntry, |
| 232 ui::PAGE_TRANSITION_RELOAD); |
| 233 EXPECT_NE(item->GetURL(), newItem->GetURL()); |
| 234 EXPECT_EQ(item->GetVirtualURL(), newItem->GetVirtualURL()); |
| 235 } |
| 236 |
| 237 TEST_F(CRWSessionEntryTest, EncodeDecode) { |
| 238 NSData *data = |
| 239 [NSKeyedArchiver archivedDataWithRootObject:sessionEntry_]; |
| 240 id decoded = [NSKeyedUnarchiver unarchiveObjectWithData:data]; |
| 241 |
| 242 expectEqualSessionEntries(sessionEntry_, decoded, |
| 243 ui::PAGE_TRANSITION_RELOAD); |
| 244 } |
| 245 |
| 246 TEST_F(CRWSessionEntryTest, EncodeWithCoder) { |
| 247 web::NavigationItem* item = [sessionEntry_ navigationItem]; |
| 248 NSString* title = base::SysUTF16ToNSString(item->GetTitle()); |
| 249 |
| 250 base::scoped_nsobject<id> coder([[OCMockComplexTypeHelper alloc] |
| 251 initWithRepresentedObject:[OCMockObject mockForClass:[NSCoder class]]]); |
| 252 |
| 253 encodeBytes_length_forKey_block block = ^(const uint8_t* bytes, |
| 254 NSUInteger length, |
| 255 NSString* key) { |
| 256 if ([key isEqualToString:@"virtualUrlString"]) { |
| 257 ASSERT_EQ(item->GetVirtualURL().spec(), |
| 258 std::string(reinterpret_cast<const char*>(bytes), length)); |
| 259 return; |
| 260 } else if ([key isEqualToString:@"referrerUrlString"]) { |
| 261 ASSERT_EQ(item->GetReferrer().url.spec(), |
| 262 std::string(reinterpret_cast<const char*>(bytes), length)); |
| 263 return; |
| 264 } |
| 265 FAIL(); |
| 266 }; |
| 267 [coder onSelector:@selector(encodeBytes:length:forKey:) |
| 268 callBlockExpectation:block]; |
| 269 [[coder expect] encodeInt:[sessionEntry_ index] forKey:@"index"]; |
| 270 [[coder expect] encodeInt:item->GetReferrer().policy |
| 271 forKey:@"referrerPolicy"]; |
| 272 [[coder expect] encodeInt64:item->GetTimestamp().ToInternalValue() |
| 273 forKey:@"timestamp"]; |
| 274 [[coder expect] encodeObject:title forKey:@"title"]; |
| 275 [[coder expect] encodeObject:[sessionEntry_ state] forKey:@"state"]; |
| 276 [[coder expect] encodeBool:[sessionEntry_ useDesktopUserAgent] |
| 277 forKey:@"useDesktopUserAgent"]; |
| 278 [[coder expect] encodeBool:[sessionEntry_ usedDataReductionProxy] |
| 279 forKey:@"usedDataReductionProxy"]; |
| 280 [[coder expect] encodeObject:[sessionEntry_ httpHeaders] |
| 281 forKey:@"httpHeaders"]; |
| 282 [[coder expect] encodeObject:[sessionEntry_ POSTData] forKey:@"POSTData"]; |
| 283 [[coder expect] encodeBool:[sessionEntry_ skipResubmitDataConfirmation] |
| 284 forKey:@"skipResubmitDataConfirmation"]; |
| 285 [sessionEntry_ encodeWithCoder:coder]; |
| 286 EXPECT_OCMOCK_VERIFY(coder); |
| 287 } |
| 288 |
| 289 TEST_F(CRWSessionEntryTest, CodingEncoding) { |
| 290 web::NavigationItem* item = [sessionEntry_ navigationItem]; |
| 291 item->SetVirtualURL(GURL("http://user.friendly")); |
| 292 NSData* data = [NSKeyedArchiver archivedDataWithRootObject:sessionEntry_]; |
| 293 EXPECT_TRUE(data != nil); |
| 294 CRWSessionEntry* unarchivedSessionEntry = |
| 295 [NSKeyedUnarchiver unarchiveObjectWithData:data]; |
| 296 ASSERT_TRUE(unarchivedSessionEntry != nil); |
| 297 web::NavigationItem* unarchivedItem = [unarchivedSessionEntry navigationItem]; |
| 298 expectEqualSessionEntries(sessionEntry_, unarchivedSessionEntry, |
| 299 ui::PAGE_TRANSITION_RELOAD); |
| 300 EXPECT_EQ(unarchivedItem->GetURL(), item->GetVirtualURL()); |
| 301 EXPECT_NE(unarchivedItem->GetURL(), item->GetURL()); |
| 302 } |
| 303 |
| 304 TEST_F(CRWSessionEntryTest, CopyWithZone) { |
| 305 CRWSessionEntry* sessionEntry2 = [sessionEntry_ copy]; |
| 306 EXPECT_NE(sessionEntry_, sessionEntry2); |
| 307 expectEqualSessionEntries( |
| 308 sessionEntry_, sessionEntry2, |
| 309 [sessionEntry_ navigationItem]->GetTransitionType()); |
| 310 } |
| 311 |
| 312 TEST_F(CRWSessionEntryTest, EmptyVirtualUrl) { |
| 313 EXPECT_EQ(GURL("http://init.test/"), |
| 314 [sessionEntry_ navigationItem]->GetURL()); |
| 315 } |
| 316 |
| 317 TEST_F(CRWSessionEntryTest, NonEmptyVirtualUrl) { |
| 318 web::NavigationItem* item = [sessionEntry_ navigationItem]; |
| 319 item->SetVirtualURL(GURL("http://user.friendly")); |
| 320 EXPECT_EQ(GURL("http://user.friendly/"), item->GetVirtualURL()); |
| 321 EXPECT_EQ(GURL("http://init.test/"), item->GetURL()); |
| 322 } |
| 323 |
| 324 TEST_F(CRWSessionEntryTest, EmptyDescription) { |
| 325 EXPECT_GT([[sessionEntry_ description] length], 0U); |
| 326 } |
| 327 |
| 328 TEST_F(CRWSessionEntryTest, CreateWithNavigationItem) { |
| 329 int index = 5; // Just pick something non-zero. |
| 330 GURL url("http://www.virtualurl.com"); |
| 331 web::Referrer referrer(GURL("http://www.referrer.com"), |
| 332 web::ReferrerPolicyDefault); |
| 333 base::string16 title = base::SysNSStringToUTF16(@"Title"); |
| 334 std::string state; |
| 335 ui::PageTransition transition = ui::PAGE_TRANSITION_GENERATED; |
| 336 |
| 337 scoped_ptr<web::NavigationItem> navigation_item( |
| 338 new web::NavigationItemImpl()); |
| 339 navigation_item->SetURL(url); |
| 340 navigation_item->SetReferrer(referrer); |
| 341 navigation_item->SetTitle(title); |
| 342 navigation_item->SetTransitionType(transition); |
| 343 |
| 344 base::scoped_nsobject<CRWSessionEntry> sessionEntry( |
| 345 [[CRWSessionEntry alloc] initWithNavigationItem:navigation_item.Pass() |
| 346 index:index]); |
| 347 web::NavigationItem* item = [sessionEntry navigationItem]; |
| 348 // Validate everything was set correctly. |
| 349 EXPECT_EQ(sessionEntry.get().index, index); |
| 350 // Desktop only persists the virtual url, all three fields are initialized |
| 351 // by it. |
| 352 EXPECT_EQ(item->GetURL(), url); |
| 353 EXPECT_EQ(item->GetVirtualURL(), url); |
| 354 EXPECT_EQ(sessionEntry.get().originalUrl, url); |
| 355 EXPECT_EQ(item->GetReferrer().url, referrer.url); |
| 356 EXPECT_EQ(item->GetTitle(), title); |
| 357 EXPECT_EQ(item->GetTransitionType(), transition); |
| 358 } |
| 359 |
| 360 TEST_F(CRWSessionEntryTest, AddHTTPHeaders) { |
| 361 EXPECT_NSEQ(@{ kHTTPHeaderKey1 : kHTTPHeaderValue1 }, |
| 362 [sessionEntry_ httpHeaders]); |
| 363 |
| 364 [sessionEntry_ addHTTPHeaders:@{ kHTTPHeaderKey1 : kHTTPHeaderValue2 }]; |
| 365 EXPECT_NSEQ(@{ kHTTPHeaderKey1 : kHTTPHeaderValue2 }, |
| 366 [sessionEntry_ httpHeaders]); |
| 367 |
| 368 [sessionEntry_ addHTTPHeaders:@{ kHTTPHeaderKey2 : kHTTPHeaderValue1 }]; |
| 369 NSDictionary* expected = @{ kHTTPHeaderKey1 : kHTTPHeaderValue2, |
| 370 kHTTPHeaderKey2 : kHTTPHeaderValue1 }; |
| 371 EXPECT_NSEQ(expected, [sessionEntry_ httpHeaders]); |
| 372 } |
| 373 |
| 374 TEST_F(CRWSessionEntryTest, RemoveHTTPHeaderForKey) { |
| 375 NSDictionary* httpHeaders = @{ kHTTPHeaderKey1 : kHTTPHeaderValue1, |
| 376 kHTTPHeaderKey2 : kHTTPHeaderValue2 }; |
| 377 [sessionEntry_ addHTTPHeaders:httpHeaders]; |
| 378 EXPECT_NSEQ(httpHeaders, [sessionEntry_ httpHeaders]); |
| 379 |
| 380 [sessionEntry_ removeHTTPHeaderForKey:kHTTPHeaderKey1]; |
| 381 EXPECT_NSEQ(@{ kHTTPHeaderKey2 : kHTTPHeaderValue2 }, |
| 382 [sessionEntry_ httpHeaders]); |
| 383 |
| 384 [sessionEntry_ removeHTTPHeaderForKey:kHTTPHeaderKey2]; |
| 385 EXPECT_TRUE([sessionEntry_ httpHeaders] == nil); |
| 386 } |
OLD | NEW |