| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef IOS_NET_COOKIES_SYSTEM_COOKIE_STORE_UNITTEST_TEMPLATE_H_ |
| #define IOS_NET_COOKIES_SYSTEM_COOKIE_STORE_UNITTEST_TEMPLATE_H_ |
| |
| #import <Foundation/Foundation.h> |
| |
| #import <optional> |
| |
| #import "base/barrier_closure.h" |
| #import "base/functional/bind.h" |
| #import "base/functional/callback.h" |
| #import "base/memory/ptr_util.h" |
| #import "base/run_loop.h" |
| #import "base/test/ios/wait_util.h" |
| #import "ios/net/cookies/cookie_store_ios_test_util.h" |
| #import "ios/net/cookies/system_cookie_store.h" |
| #import "net/base/apple/url_conversions.h" |
| #import "testing/gtest/include/gtest/gtest.h" |
| #import "testing/gtest_mac.h" |
| #import "testing/platform_test.h" |
| #import "url/gurl.h" |
| |
| namespace net { |
| |
| // This class defines tests that implementations of SystemCookieStore should |
| // pass in order to be conformant. |
| // To use this test, A delegate class should be created for each implementation. |
| // The delegate class has to implement the following functions: |
| // GetCookieStore() |
| // Returns a SystemCookieStore implementation object. |
| // bool IsCookieSet(NSHttpCookie cookie, NSURL url) |
| // Returns wether |cookie| is set for |url| in the internal cookie store or |
| // not. |
| // ClearCookies() |
| // Deletes all cookies in the internal cookie store. |
| // int CookiesCount() |
| // Returns the number of cookies set in the internal cookie store. |
| template <typename SystemCookieStoreTestDelegate> |
| class SystemCookieStoreTest : public PlatformTest { |
| public: |
| SystemCookieStoreTest() |
| : test_cookie_url1_([NSURL URLWithString:@"http://foo.google.com/bar"]), |
| test_cookie_url2_([NSURL URLWithString:@"http://bar.xyz.abc/"]), |
| test_cookie_url3_([NSURL URLWithString:@"http://123.foo.bar/"]) { |
| ClearCookies(); |
| } |
| |
| // Gets the SystemCookieStore implementation class instance. |
| SystemCookieStore* GetCookieStore() { return delegate_.GetCookieStore(); } |
| |
| // Returns wether |system_cookie| is set in |delegate_| cookiestore or not. |
| bool IsCookieSet(NSHTTPCookie* system_cookie, NSURL* url) { |
| return delegate_.IsCookieSet(system_cookie, url); |
| } |
| |
| // Clears the |delegate_| cookie store. |
| void ClearCookies() { delegate_.ClearCookies(); } |
| |
| // Returns the number of cookies set in the |delegate_| cookie store. |
| int CookiesCount() { return delegate_.CookiesCount(); } |
| |
| // Creates a cookie with `name`, `value` and `url`. |
| NSHTTPCookie* CreateCookie(NSString* name, NSString* value, NSURL* url) { |
| return [NSHTTPCookie cookieWithProperties:@{ |
| NSHTTPCookiePath : url.path, |
| NSHTTPCookieName : name, |
| NSHTTPCookieValue : value, |
| NSHTTPCookieDomain : url.host, |
| }]; |
| } |
| |
| // Sets |cookie| in the SystemCookieStore, doesn't care about |
| // callback and doesn't set creation time. |
| void SetCookieInStoreWithNoCallback(NSHTTPCookie* cookie) { |
| base::RunLoop run_loop; |
| GetCookieStore()->SetCookieAsync(cookie, |
| /*optional_creation_time=*/std::nullopt, |
| run_loop.QuitClosure()); |
| run_loop.Run(); |
| } |
| |
| protected: |
| NSURL* test_cookie_url1_; |
| NSURL* test_cookie_url2_; |
| NSURL* test_cookie_url3_; |
| |
| private: |
| SystemCookieStoreTestDelegate delegate_; |
| }; |
| |
| TYPED_TEST_SUITE_P(SystemCookieStoreTest); |
| |
| TYPED_TEST_P(SystemCookieStoreTest, SetCookieAsync) { |
| NSHTTPCookie* system_cookie = |
| this->CreateCookie(@"a", @"b", this->test_cookie_url1_); |
| this->SetCookieInStoreWithNoCallback(system_cookie); |
| EXPECT_TRUE(this->IsCookieSet(system_cookie, this->test_cookie_url1_)); |
| } |
| |
| // Tests that inserting multiple cookies with identical creation times works. |
| TYPED_TEST_P(SystemCookieStoreTest, SetCookieAsyncWithIdenticalCreationTime) { |
| NSHTTPCookie* system_cookie_1 = |
| this->CreateCookie(@"a", @"b", this->test_cookie_url1_); |
| NSHTTPCookie* system_cookie_2 = |
| this->CreateCookie(@"c", @"d", this->test_cookie_url2_); |
| SystemCookieStore* cookie_store = this->GetCookieStore(); |
| const base::Time creation_time = base::Time::Now(); |
| |
| base::RunLoop run_loop; |
| base::RepeatingClosure closure = |
| base::BarrierClosure(2, run_loop.QuitClosure()); |
| cookie_store->SetCookieAsync(system_cookie_1, creation_time, closure); |
| cookie_store->SetCookieAsync(system_cookie_2, creation_time, closure); |
| run_loop.Run(); |
| |
| EXPECT_TRUE(this->IsCookieSet(system_cookie_1, this->test_cookie_url1_)); |
| EXPECT_TRUE(this->IsCookieSet(system_cookie_2, this->test_cookie_url2_)); |
| } |
| |
| // Tests cases of GetAllCookiesAsync and GetCookiesForURLAsync. |
| TYPED_TEST_P(SystemCookieStoreTest, GetCookiesAsync) { |
| SystemCookieStore* cookie_store = this->GetCookieStore(); |
| NSMutableDictionary* input_cookies = [[NSMutableDictionary alloc] init]; |
| NSHTTPCookie* system_cookie = |
| this->CreateCookie(@"a", @"b", this->test_cookie_url1_); |
| [input_cookies setValue:system_cookie forKey:@"a"]; |
| this->SetCookieInStoreWithNoCallback(system_cookie); |
| |
| system_cookie = this->CreateCookie(@"x", @"d", this->test_cookie_url2_); |
| [input_cookies setValue:system_cookie forKey:@"x"]; |
| this->SetCookieInStoreWithNoCallback(system_cookie); |
| system_cookie = this->CreateCookie(@"l", @"m", this->test_cookie_url3_); |
| [input_cookies setValue:system_cookie forKey:@"l"]; |
| this->SetCookieInStoreWithNoCallback(system_cookie); |
| |
| // Test GetCookieForURLAsync. |
| NSHTTPCookie* input_cookie = [input_cookies valueForKey:@"a"]; |
| |
| { |
| base::RunLoop run_loop; |
| __block NSArray<NSHTTPCookie*>* result_cookies = nil; |
| cookie_store->GetCookiesForURLAsync( |
| GURLWithNSURL(this->test_cookie_url1_), |
| base::BindOnce(^(NSArray<NSHTTPCookie*>* result) { |
| result_cookies = result; |
| }).Then(run_loop.QuitClosure())); |
| run_loop.Run(); |
| |
| EXPECT_EQ(1u, result_cookies.count); |
| NSHTTPCookie* result_cookie = result_cookies[0]; |
| EXPECT_NSEQ(input_cookie.name, result_cookie.name); |
| EXPECT_NSEQ(input_cookie.value, result_cookie.value); |
| } |
| |
| // Test GetAllCookies |
| { |
| base::RunLoop run_loop; |
| __block NSArray<NSHTTPCookie*>* result_cookies = nil; |
| cookie_store->GetAllCookiesAsync( |
| base::BindOnce(^(NSArray<NSHTTPCookie*>* result) { |
| result_cookies = result; |
| }).Then(run_loop.QuitClosure())); |
| run_loop.Run(); |
| |
| EXPECT_EQ(3u, result_cookies.count); |
| for (NSHTTPCookie* cookie in result_cookies) { |
| NSHTTPCookie* existing_cookie = [input_cookies valueForKey:cookie.name]; |
| EXPECT_TRUE(existing_cookie); |
| EXPECT_NSEQ(existing_cookie.name, cookie.name); |
| EXPECT_NSEQ(existing_cookie.value, cookie.value); |
| EXPECT_NSEQ(existing_cookie.domain, cookie.domain); |
| } |
| } |
| } |
| |
| // Tests deleting cookies for different URLs and for different |
| // cookie key/value pairs. |
| TYPED_TEST_P(SystemCookieStoreTest, DeleteCookiesAsync) { |
| SystemCookieStore* cookie_store = this->GetCookieStore(); |
| NSHTTPCookie* system_cookie1 = |
| this->CreateCookie(@"a", @"b", this->test_cookie_url1_); |
| this->SetCookieInStoreWithNoCallback(system_cookie1); |
| NSHTTPCookie* system_cookie2 = |
| this->CreateCookie(@"x", @"d", this->test_cookie_url2_); |
| cookie_store->SetCookieAsync(system_cookie2, |
| /*optional_creation_time=*/std::nullopt, |
| SystemCookieStore::SystemCookieCallback()); |
| this->SetCookieInStoreWithNoCallback(system_cookie2); |
| EXPECT_EQ(2, this->CookiesCount()); |
| EXPECT_TRUE(this->IsCookieSet(system_cookie2, this->test_cookie_url2_)); |
| |
| { |
| base::RunLoop run_loop; |
| cookie_store->DeleteCookieAsync(system_cookie2, run_loop.QuitClosure()); |
| run_loop.Run(); |
| |
| EXPECT_FALSE(this->IsCookieSet(system_cookie2, this->test_cookie_url2_)); |
| EXPECT_EQ(1, this->CookiesCount()); |
| } |
| |
| { |
| base::RunLoop run_loop; |
| cookie_store->DeleteCookieAsync(system_cookie1, run_loop.QuitClosure()); |
| run_loop.Run(); |
| |
| EXPECT_FALSE(this->IsCookieSet(system_cookie1, this->test_cookie_url1_)); |
| EXPECT_EQ(0, this->CookiesCount()); |
| } |
| } |
| |
| TYPED_TEST_P(SystemCookieStoreTest, ClearCookiesAsync) { |
| SystemCookieStore* cookie_store = this->GetCookieStore(); |
| this->SetCookieInStoreWithNoCallback( |
| this->CreateCookie(@"a", @"b", this->test_cookie_url1_)); |
| this->SetCookieInStoreWithNoCallback( |
| this->CreateCookie(@"x", @"d", this->test_cookie_url2_)); |
| EXPECT_EQ(2, this->CookiesCount()); |
| |
| base::RunLoop run_loop; |
| cookie_store->ClearStoreAsync(run_loop.QuitClosure()); |
| run_loop.Run(); |
| |
| EXPECT_EQ(0, this->CookiesCount()); |
| } |
| |
| TYPED_TEST_P(SystemCookieStoreTest, GetCookieAcceptPolicy) { |
| SystemCookieStore* cookie_store = this->GetCookieStore(); |
| EXPECT_EQ([NSHTTPCookieStorage sharedHTTPCookieStorage].cookieAcceptPolicy, |
| cookie_store->GetCookieAcceptPolicy()); |
| [NSHTTPCookieStorage sharedHTTPCookieStorage].cookieAcceptPolicy = |
| NSHTTPCookieAcceptPolicyNever; |
| EXPECT_EQ(NSHTTPCookieAcceptPolicyNever, |
| cookie_store->GetCookieAcceptPolicy()); |
| [NSHTTPCookieStorage sharedHTTPCookieStorage].cookieAcceptPolicy = |
| NSHTTPCookieAcceptPolicyAlways; |
| EXPECT_EQ(NSHTTPCookieAcceptPolicyAlways, |
| cookie_store->GetCookieAcceptPolicy()); |
| } |
| |
| REGISTER_TYPED_TEST_SUITE_P(SystemCookieStoreTest, |
| SetCookieAsync, |
| SetCookieAsyncWithIdenticalCreationTime, |
| GetCookiesAsync, |
| DeleteCookiesAsync, |
| ClearCookiesAsync, |
| GetCookieAcceptPolicy); |
| |
| } // namespace net |
| |
| #endif // IOS_NET_COOKIES_SYSTEM_COOKIE_STORE_UNITTEST_TEMPLATE_H_ |