chromium/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/extras/sqlite/sqlite_persistent_cookie_store.h"

#include <stdint.h>

#include <map>
#include <memory>
#include <optional>
#include <set>
#include <utility>
#include <vector>

#include "base/containers/span.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/sequence_checker.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "crypto/encryptor.h"
#include "crypto/symmetric_key.h"
#include "net/base/test_completion_callback.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/cookie_store_test_callbacks.h"
#include "net/extras/sqlite/cookie_crypto_delegate.h"
#include "net/log/net_log_capture_mode.h"
#include "net/log/test_net_log.h"
#include "net/log/test_net_log_util.h"
#include "net/test/test_with_task_environment.h"
#include "sql/database.h"
#include "sql/meta_table.h"
#include "sql/statement.h"
#include "sql/transaction.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#include "url/third_party/mozilla/url_parse.h"

namespace net {

namespace {

const base::FilePath::CharType kCookieFilename[] =);

class CookieCryptor : public CookieCryptoDelegate {};

CookieCryptor::CookieCryptor()
    :{}

base::OnceClosure CookieCryptor::GetInitClosure(base::OnceClosure callback) {}

void CookieCryptor::Init(base::OnceClosure callback) {}

bool CookieCryptor::EncryptString(const std::string& plaintext,
                                  std::string* ciphertext) {}

bool CookieCryptor::DecryptString(const std::string& ciphertext,
                                  std::string* plaintext) {}

void CookieCryptor::InitComplete() {}

// Matches the CanonicalCookie's strictly_unique_key and last_access_date
// against a unique_ptr<CanonicalCookie>.
MATCHER_P2(MatchesCookieKeyAndLastAccessDate,
           StrictlyUniqueKey,
           last_access_date,
           "") {}

// Matches every field of a CanonicalCookie against a
// unique_ptr<CanonicalCookie>.
MATCHER_P(MatchesEveryCookieField, cookie, "") {}

}  // namespace

CanonicalCookieVector;

class SQLitePersistentCookieStoreTest : public TestWithTaskEnvironment {};

TEST_F(SQLitePersistentCookieStoreTest, TestInvalidVersionRecovery) {}

TEST_F(SQLitePersistentCookieStoreTest, TestInvalidMetaTableRecovery) {}

// Test if data is stored as expected in the SQLite database.
TEST_F(SQLitePersistentCookieStoreTest, TestPersistance) {}

TEST_F(SQLitePersistentCookieStoreTest, TestSessionCookiesDeletedOnStartup) {}

// Test that priority load of cookies for a specific domain key could be
// completed before the entire store is loaded.
TEST_F(SQLitePersistentCookieStoreTest, TestLoadCookiesForKey) {}

TEST_F(SQLitePersistentCookieStoreTest, TestBeforeCommitCallback) {}

// Test that we can force the database to be written by calling Flush().
TEST_F(SQLitePersistentCookieStoreTest, TestFlush) {}

// Test loading old session cookies from the disk.
TEST_F(SQLitePersistentCookieStoreTest, TestLoadOldSessionCookies) {}

// Test refusing to load old session cookies from the disk.
TEST_F(SQLitePersistentCookieStoreTest, TestDontLoadOldSessionCookies) {}

// Confirm bad cookies on disk don't get looaded, and that we also remove them
// from the database.
TEST_F(SQLitePersistentCookieStoreTest, FilterBadCookiesAndFixupDb) {}

TEST_F(SQLitePersistentCookieStoreTest, PersistIsPersistent) {}

TEST_F(SQLitePersistentCookieStoreTest, PriorityIsPersistent) {}

TEST_F(SQLitePersistentCookieStoreTest, SameSiteIsPersistent) {}

TEST_F(SQLitePersistentCookieStoreTest, SameSiteExtendedTreatedAsUnspecified) {}

TEST_F(SQLitePersistentCookieStoreTest, SourcePortIsPersistent) {}

TEST_F(SQLitePersistentCookieStoreTest, UpdateToEncryption) {}

bool CompareCookies(const std::unique_ptr<CanonicalCookie>& a,
                    const std::unique_ptr<CanonicalCookie>& b) {}

// Confirm the store can handle having cookies with identical creation
// times stored in it.
TEST_F(SQLitePersistentCookieStoreTest, IdenticalCreationTimes) {}

TEST_F(SQLitePersistentCookieStoreTest, KeyInconsistency) {}

TEST_F(SQLitePersistentCookieStoreTest, OpsIfInitFailed) {}

TEST_F(SQLitePersistentCookieStoreTest, Coalescing) {}

TEST_F(SQLitePersistentCookieStoreTest, NoCoalesceUnrelated) {}

// Locking is only supported on Windows.
#if BUILDFLAG(IS_WIN)

class SQLitePersistentCookieStoreExclusiveAccessTest
    : public SQLitePersistentCookieStoreTest,
      public ::testing::WithParamInterface<bool> {
 protected:
  const bool& ShouldBeExclusive() { return GetParam(); }
};

TEST_P(SQLitePersistentCookieStoreExclusiveAccessTest, LockedStore) {
  Create(/*crypt_cookies=*/false, /*restore_old_session_cookies=*/false,
         /*use_current_thread=*/true,
         /*enable_exclusive_access=*/ShouldBeExclusive());

  base::RunLoop run_loop;
  store_->Load(base::BindLambdaForTesting(
                   [&](CanonicalCookieVector cookies) { run_loop.Quit(); }),
               NetLogWithSource());
  run_loop.Run();

  std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::CreateForTesting(
      GURL("http://www.example.com/path"), "Tasty=Yes", base::Time::Now());

  // Wedge the background thread to make sure that it doesn't start consuming
  // the queue.
  background_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&SQLitePersistentCookieStoreTest::WaitOnDBEvent,
                                base::Unretained(this)));

  store_->AddCookie(*cookie);

  {
    base::File file(
        temp_dir_.GetPath().Append(kCookieFilename),
        base::File::Flags::FLAG_OPEN_ALWAYS | base::File::Flags::FLAG_READ);
    // If locked, should not be able to open file even for read.
    EXPECT_EQ(ShouldBeExclusive(), !file.IsValid());
  }

  db_thread_event_.Signal();
}

TEST_P(SQLitePersistentCookieStoreExclusiveAccessTest, LockedStoreAlreadyOpen) {
  base::HistogramTester histograms;
  base::File file(
      temp_dir_.GetPath().Append(kCookieFilename),
      base::File::Flags::FLAG_CREATE | base::File::Flags::FLAG_READ);
  ASSERT_TRUE(file.IsValid());

  Create(/*crypt_cookies=*/false, /*restore_old_session_cookies=*/false,
         /*use_current_thread=*/true,
         /*enable_exclusive_access=*/ShouldBeExclusive());

  base::RunLoop run_loop;
  store_->Load(base::BindLambdaForTesting(
                   [&](CanonicalCookieVector cookies) { run_loop.Quit(); }),
               NetLogWithSource());
  run_loop.Run();

  // Note: The non-exclusive path is verified in the TearDown for the fixture.
  if (ShouldBeExclusive()) {
    expect_init_errors_ = true;
    histograms.ExpectUniqueSample("Cookie.ErrorInitializeDB",
                                  sql::SqliteLoggedResultCode::kCantOpen, 1);
    histograms.ExpectUniqueSample("Cookie.WinGetLastErrorInitializeDB",
                                  ERROR_SHARING_VIOLATION, 1);
  }
}

INSTANTIATE_TEST_SUITE_P(All,
                         SQLitePersistentCookieStoreExclusiveAccessTest,
                         ::testing::Bool(),
                         [](const auto& info) {
                           return info.param ? "Exclusive" : "NotExclusive";
                         });

#endif  // BUILDFLAG(IS_WIN)

TEST_F(SQLitePersistentCookieStoreTest, CorruptStore) {}

bool CreateV18Schema(sql::Database* db) {}

bool CreateV20Schema(sql::Database* db) {}

bool CreateV21Schema(sql::Database* db) {}

bool CreateV22Schema(sql::Database* db) {}

bool CreateV23Schema(sql::Database* db) {}

int GetDBCurrentVersionNumber(sql::Database* db) {}

std::vector<CanonicalCookie> CookiesForMigrationTest() {}

// Versions 18, 19, and 20 use the same schema so they can reuse this function.
// AddV20CookiesToDB (and future versions) need to set max_expiration_delta to
// base::Days(400) to simulate expiration limits introduced in version 19.
bool AddV18CookiesToDB(sql::Database* db,
                       base::TimeDelta max_expiration_delta) {}

bool AddV20CookiesToDB(sql::Database* db) {}

bool AddV21CookiesToDB(sql::Database* db) {}

bool AddV22CookiesToDB(sql::Database* db,
                       const std::vector<CanonicalCookie>& cookies) {}

bool AddV23EncryptedCookiesToDB(sql::Database* db,
                                const std::vector<CanonicalCookie>& cookies,
                                CookieCryptoDelegate* crypto) {}

// Confirm the cookie list passed in has the above cookies in it.
void ConfirmCookiesAfterMigrationTest(
    std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies,
    bool expect_last_update_date = false) {}

void ConfirmDatabaseVersionAfterMigration(const base::FilePath path,
                                          int version) {}

TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion19) {}

TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion20) {}

TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion21) {}

TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion22) {}

TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion23) {}

TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion24) {}

TEST_F(SQLitePersistentCookieStoreTest, CannotModifyHostName) {}

TEST_F(SQLitePersistentCookieStoreTest, ShortHash) {}

TEST_F(SQLitePersistentCookieStoreTest,
       UpgradeToSchemaVersion23_ConfirmSourceSchemeRecalculation) {}

class SQLitePersistentCookieStoreTest_OriginBoundCookies
    : public SQLitePersistentCookieStoreTest {};

// Tests that cookies which differ only in their scheme and port are considered
// distinct.
TEST_F(SQLitePersistentCookieStoreTest_OriginBoundCookies,
       UniquenessConstraint) {}

// Tests that deleting a cookie correctly takes the scheme and port into
// account.
TEST_F(SQLitePersistentCookieStoreTest_OriginBoundCookies, DeleteCookie) {}

// Tests that updating a cookie correctly takes the scheme and port into
// account.
TEST_F(SQLitePersistentCookieStoreTest_OriginBoundCookies,
       UpdateCookieAccessTime) {}

TEST_F(SQLitePersistentCookieStoreTest, SavingPartitionedCookies) {}

TEST_F(SQLitePersistentCookieStoreTest, LoadingPartitionedCookies) {}

std::unique_ptr<CanonicalCookie> CreatePartitionedCookie(
    const std::string& name,
    const std::string& domain,
    const std::string& top_frame_site_key,
    CookiePartitionKey::AncestorChainBit ancestor_chain_bit,
    CookieSourceScheme scheme = CookieSourceScheme::kUnset,
    bool partitioned_cookies_enabled = true) {}

// Pairs contain a cookie, and hard coded value for has_cross_site_ancestor
// value.
//
// During migration we have no way of knowing if a cross site ancestor was
// present. When the existing domain and the top_level_site of the partition key
// are the same. The default behavior is to set the cross site value to
// kSameSite, so ignore the kCrossSite cookie when testing migration.
std::vector<std::pair<CanonicalCookie, std::string>>
GenerateHasCrossSiteAncestorCookiesAndVals(bool migrating = false) {}

TEST_F(SQLitePersistentCookieStoreTest,
       UpgradeToSchemaVersion23_AddingHasCrossSiteAncestor) {}

TEST_F(SQLitePersistentCookieStoreTest,
       TestValueOfHasCrossSiteAncestorOnDoCommit) {}

}  // namespace net