15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/scoped_temp_dir.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h"
109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/run_loop.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/test_data_directory.h"
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/extras/sqlite/sqlite_channel_id_store.h"
15bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "net/ssl/ssl_client_cert_type.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/test/cert_test_util.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/statement.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace net {
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst base::FilePath::CharType kTestChannelIDFilename[] =
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    FILE_PATH_LITERAL("ChannelID");
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class SQLiteChannelIDStoreTest : public testing::Test {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void Load(ScopedVector<DefaultChannelIDStore::ChannelID>* channel_ids) {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    store_->Load(base::Bind(&SQLiteChannelIDStoreTest::OnLoaded,
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            base::Unretained(this),
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            &run_loop));
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    channel_ids->swap(channel_ids_);
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    channel_ids_.clear();
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnLoaded(
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::RunLoop* run_loop,
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      scoped_ptr<ScopedVector<DefaultChannelIDStore::ChannelID> > channel_ids) {
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    channel_ids_.swap(*channel_ids);
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop->Quit();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void ReadTestKeyAndCert(std::string* key, std::string* cert) {
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::FilePath key_path =
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        GetTestCertsDirectory().AppendASCII("unittest.originbound.key.der");
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::FilePath cert_path =
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        GetTestCertsDirectory().AppendASCII("unittest.originbound.der");
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ASSERT_TRUE(base::ReadFileToString(key_path, key));
5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ASSERT_TRUE(base::ReadFileToString(cert_path, cert));
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static base::Time GetTestCertExpirationTime() {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cert expiration time from 'dumpasn1 unittest.originbound.der':
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // GeneralizedTime 19/11/2111 02:23:45 GMT
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // base::Time::FromUTCExploded can't generate values past 2038 on 32-bit
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // linux, so we use the raw value here.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return base::Time::FromInternalValue(GG_INT64_C(16121816625000000));
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static base::Time GetTestCertCreationTime() {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // UTCTime 13/12/2011 02:23:45 GMT
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time::Exploded exploded_time;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exploded_time.year = 2011;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exploded_time.month = 12;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exploded_time.day_of_week = 0;  // Unused.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exploded_time.day_of_month = 13;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exploded_time.hour = 2;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exploded_time.minute = 23;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exploded_time.second = 45;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exploded_time.millisecond = 0;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return base::Time::FromUTCExploded(exploded_time);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    store_ = new SQLiteChannelIDStore(
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        temp_dir_.path().Append(kTestChannelIDFilename),
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::MessageLoopProxy::current());
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ScopedVector<DefaultChannelIDStore::ChannelID> channel_ids;
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Load(&channel_ids);
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_EQ(0u, channel_ids.size());
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure the store gets written at least once.
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    store_->AddChannelID(
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        DefaultChannelIDStore::ChannelID("google.com",
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         base::Time::FromInternalValue(1),
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         base::Time::FromInternalValue(2),
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         "a",
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         "b"));
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ScopedTempDir temp_dir_;
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<SQLiteChannelIDStore> store_;
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScopedVector<DefaultChannelIDStore::ChannelID> channel_ids_;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test if data is stored as expected in the SQLite database.
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(SQLiteChannelIDStoreTest, TestPersistence) {
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  store_->AddChannelID(
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      DefaultChannelIDStore::ChannelID("foo.com",
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                       base::Time::FromInternalValue(3),
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                       base::Time::FromInternalValue(4),
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                       "c",
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                       "d"));
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScopedVector<DefaultChannelIDStore::ChannelID> channel_ids;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Replace the store effectively destroying the current one and forcing it
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to write its data to disk. Then we can see if after loading it again it
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is still there.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  store_ = NULL;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure we wait until the destructor has run.
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  store_ =
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new SQLiteChannelIDStore(temp_dir_.path().Append(kTestChannelIDFilename),
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               base::MessageLoopProxy::current());
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reload and test for persistence
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Load(&channel_ids);
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(2U, channel_ids.size());
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DefaultChannelIDStore::ChannelID* goog_channel_id;
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DefaultChannelIDStore::ChannelID* foo_channel_id;
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (channel_ids[0]->server_identifier() == "google.com") {
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    goog_channel_id = channel_ids[0];
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    foo_channel_id = channel_ids[1];
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    goog_channel_id = channel_ids[1];
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    foo_channel_id = channel_ids[0];
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ("google.com", goog_channel_id->server_identifier());
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_STREQ("a", goog_channel_id->private_key().c_str());
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_STREQ("b", goog_channel_id->cert().c_str());
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(1, goog_channel_id->creation_time().ToInternalValue());
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(2, goog_channel_id->expiration_time().ToInternalValue());
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ("foo.com", foo_channel_id->server_identifier());
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_STREQ("c", foo_channel_id->private_key().c_str());
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_STREQ("d", foo_channel_id->cert().c_str());
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(3, foo_channel_id->creation_time().ToInternalValue());
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(4, foo_channel_id->expiration_time().ToInternalValue());
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now delete the cert and check persistence again.
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  store_->DeleteChannelID(*channel_ids[0]);
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  store_->DeleteChannelID(*channel_ids[1]);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  store_ = NULL;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure we wait until the destructor has run.
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  channel_ids.clear();
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  store_ =
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new SQLiteChannelIDStore(temp_dir_.path().Append(kTestChannelIDFilename),
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               base::MessageLoopProxy::current());
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reload and check if the cert has been removed.
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Load(&channel_ids);
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(0U, channel_ids.size());
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Close the store.
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  store_ = NULL;
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Make sure we wait until the destructor has run.
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::RunLoop().RunUntilIdle();
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Test if data is stored as expected in the SQLite database.
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_F(SQLiteChannelIDStoreTest, TestDeleteAll) {
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  store_->AddChannelID(
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      DefaultChannelIDStore::ChannelID("foo.com",
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                       base::Time::FromInternalValue(3),
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                       base::Time::FromInternalValue(4),
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                       "c",
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                       "d"));
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScopedVector<DefaultChannelIDStore::ChannelID> channel_ids;
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Replace the store effectively destroying the current one and forcing it
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // to write its data to disk. Then we can see if after loading it again it
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // is still there.
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  store_ = NULL;
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Make sure we wait until the destructor has run.
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::RunLoop().RunUntilIdle();
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  store_ =
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new SQLiteChannelIDStore(temp_dir_.path().Append(kTestChannelIDFilename),
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               base::MessageLoopProxy::current());
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Reload and test for persistence
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Load(&channel_ids);
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_EQ(2U, channel_ids.size());
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // DeleteAll except foo.com (shouldn't fail if one is missing either).
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::list<std::string> delete_server_identifiers;
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  delete_server_identifiers.push_back("google.com");
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  delete_server_identifiers.push_back("missing.com");
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  store_->DeleteAllInList(delete_server_identifiers);
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Now check persistence again.
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  store_ = NULL;
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Make sure we wait until the destructor has run.
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::RunLoop().RunUntilIdle();
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  channel_ids.clear();
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  store_ =
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new SQLiteChannelIDStore(temp_dir_.path().Append(kTestChannelIDFilename),
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               base::MessageLoopProxy::current());
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Reload and check that only foo.com persisted in store.
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Load(&channel_ids);
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_EQ(1U, channel_ids.size());
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_EQ("foo.com", channel_ids[0]->server_identifier());
2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Close the store.
2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  store_ = NULL;
2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Make sure we wait until the destructor has run.
2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::RunLoop().RunUntilIdle();
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(SQLiteChannelIDStoreTest, TestUpgradeV1) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset the store.  We'll be using a different database for this test.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  store_ = NULL;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath v1_db_path(temp_dir_.path().AppendASCII("v1db"));
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string key_data;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cert_data;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadTestKeyAndCert(&key_data, &cert_data);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a version 1 database.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Connection db;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(db.Open(v1_db_path));
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(db.Execute(
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY,"
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "value LONGVARCHAR);"
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "INSERT INTO \"meta\" VALUES('version','1');"
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "INSERT INTO \"meta\" VALUES('last_compatible_version','1');"
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "CREATE TABLE origin_bound_certs ("
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "origin TEXT NOT NULL UNIQUE PRIMARY KEY,"
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "private_key BLOB NOT NULL,cert BLOB NOT NULL);"));
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Statement add_smt(db.GetUniqueStatement(
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "INSERT INTO origin_bound_certs (origin, private_key, cert) "
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "VALUES (?,?,?)"));
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    add_smt.BindString(0, "google.com");
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    add_smt.BindBlob(1, key_data.data(), key_data.size());
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    add_smt.BindBlob(2, cert_data.data(), cert_data.size());
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(add_smt.Run());
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(db.Execute(
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "INSERT INTO \"origin_bound_certs\" VALUES("
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "'foo.com',X'AA',X'BB');"));
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load and test the DB contents twice.  First time ensures that we can use
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the updated values immediately.  Second time ensures that the updated
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // values are stored and read correctly on next load.
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 2; ++i) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE(i);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ScopedVector<DefaultChannelIDStore::ChannelID> channel_ids;
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    store_ =
2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        new SQLiteChannelIDStore(v1_db_path, base::MessageLoopProxy::current());
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // Load the database. Because the existing v1 certs are implicitly of type
256bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // RSA, which is unsupported, they're discarded.
2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Load(&channel_ids);
2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_EQ(0U, channel_ids.size());
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    store_ = NULL;
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::RunLoop().RunUntilIdle();
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify the database version is updated.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sql::Connection db;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(db.Open(v1_db_path));
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sql::Statement smt(db.GetUniqueStatement(
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "SELECT value FROM meta WHERE key = \"version\""));
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(smt.Step());
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(4, smt.ColumnInt(0));
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(smt.Step());
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(SQLiteChannelIDStoreTest, TestUpgradeV2) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset the store.  We'll be using a different database for this test.
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  store_ = NULL;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath v2_db_path(temp_dir_.path().AppendASCII("v2db"));
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string key_data;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cert_data;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadTestKeyAndCert(&key_data, &cert_data);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a version 2 database.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Connection db;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(db.Open(v2_db_path));
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(db.Execute(
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY,"
2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "value LONGVARCHAR);"
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "INSERT INTO \"meta\" VALUES('version','2');"
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "INSERT INTO \"meta\" VALUES('last_compatible_version','1');"
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "CREATE TABLE origin_bound_certs ("
2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "origin TEXT NOT NULL UNIQUE PRIMARY KEY,"
2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "private_key BLOB NOT NULL,"
2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "cert BLOB NOT NULL,"
2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "cert_type INTEGER);"));
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Statement add_smt(db.GetUniqueStatement(
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "INSERT INTO origin_bound_certs (origin, private_key, cert, cert_type) "
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "VALUES (?,?,?,?)"));
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    add_smt.BindString(0, "google.com");
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    add_smt.BindBlob(1, key_data.data(), key_data.size());
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    add_smt.BindBlob(2, cert_data.data(), cert_data.size());
307bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    add_smt.BindInt64(3, 64);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(add_smt.Run());
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(db.Execute(
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "INSERT INTO \"origin_bound_certs\" VALUES("
3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "'foo.com',X'AA',X'BB',64);"));
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load and test the DB contents twice.  First time ensures that we can use
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the updated values immediately.  Second time ensures that the updated
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // values are saved and read correctly on next load.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 2; ++i) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE(i);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ScopedVector<DefaultChannelIDStore::ChannelID> channel_ids;
3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    store_ =
3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        new SQLiteChannelIDStore(v2_db_path, base::MessageLoopProxy::current());
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // Load the database and ensure the certs can be read.
3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Load(&channel_ids);
3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_EQ(2U, channel_ids.size());
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_EQ("google.com", channel_ids[0]->server_identifier());
3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ASSERT_EQ(GetTestCertExpirationTime(), channel_ids[0]->expiration_time());
3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_EQ(key_data, channel_ids[0]->private_key());
3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_EQ(cert_data, channel_ids[0]->cert());
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_EQ("foo.com", channel_ids[1]->server_identifier());
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Undecodable cert, expiration time will be uninitialized.
3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_EQ(base::Time(), channel_ids[1]->expiration_time());
3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_STREQ("\xaa", channel_ids[1]->private_key().c_str());
3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_STREQ("\xbb", channel_ids[1]->cert().c_str());
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    store_ = NULL;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure we wait until the destructor has run.
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::RunLoop().RunUntilIdle();
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify the database version is updated.
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sql::Connection db;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(db.Open(v2_db_path));
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sql::Statement smt(db.GetUniqueStatement(
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "SELECT value FROM meta WHERE key = \"version\""));
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(smt.Step());
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(4, smt.ColumnInt(0));
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(smt.Step());
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(SQLiteChannelIDStoreTest, TestUpgradeV3) {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset the store.  We'll be using a different database for this test.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  store_ = NULL;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath v3_db_path(temp_dir_.path().AppendASCII("v3db"));
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string key_data;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cert_data;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadTestKeyAndCert(&key_data, &cert_data);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a version 3 database.
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Connection db;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(db.Open(v3_db_path));
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(db.Execute(
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY,"
3731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "value LONGVARCHAR);"
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "INSERT INTO \"meta\" VALUES('version','3');"
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "INSERT INTO \"meta\" VALUES('last_compatible_version','1');"
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "CREATE TABLE origin_bound_certs ("
3771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "origin TEXT NOT NULL UNIQUE PRIMARY KEY,"
3781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "private_key BLOB NOT NULL,"
3791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "cert BLOB NOT NULL,"
3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "cert_type INTEGER,"
3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "expiration_time INTEGER);"));
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Statement add_smt(db.GetUniqueStatement(
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "INSERT INTO origin_bound_certs (origin, private_key, cert, cert_type, "
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "expiration_time) VALUES (?,?,?,?,?)"));
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    add_smt.BindString(0, "google.com");
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    add_smt.BindBlob(1, key_data.data(), key_data.size());
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    add_smt.BindBlob(2, cert_data.data(), cert_data.size());
389bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    add_smt.BindInt64(3, 64);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    add_smt.BindInt64(4, 1000);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(add_smt.Run());
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(db.Execute(
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "INSERT INTO \"origin_bound_certs\" VALUES("
3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "'foo.com',X'AA',X'BB',64,2000);"));
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load and test the DB contents twice.  First time ensures that we can use
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the updated values immediately.  Second time ensures that the updated
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // values are saved and read correctly on next load.
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 2; ++i) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE(i);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ScopedVector<DefaultChannelIDStore::ChannelID> channel_ids;
4051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    store_ =
4061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        new SQLiteChannelIDStore(v3_db_path, base::MessageLoopProxy::current());
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
408bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // Load the database and ensure the certs can be read.
4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Load(&channel_ids);
4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_EQ(2U, channel_ids.size());
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_EQ("google.com", channel_ids[0]->server_identifier());
4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_EQ(1000, channel_ids[0]->expiration_time().ToInternalValue());
4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ASSERT_EQ(GetTestCertCreationTime(), channel_ids[0]->creation_time());
4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_EQ(key_data, channel_ids[0]->private_key());
4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_EQ(cert_data, channel_ids[0]->cert());
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_EQ("foo.com", channel_ids[1]->server_identifier());
4195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_EQ(2000, channel_ids[1]->expiration_time().ToInternalValue());
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Undecodable cert, creation time will be uninitialized.
4215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_EQ(base::Time(), channel_ids[1]->creation_time());
4225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_STREQ("\xaa", channel_ids[1]->private_key().c_str());
4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_STREQ("\xbb", channel_ids[1]->cert().c_str());
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    store_ = NULL;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure we wait until the destructor has run.
427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::RunLoop().RunUntilIdle();
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify the database version is updated.
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sql::Connection db;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(db.Open(v3_db_path));
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sql::Statement smt(db.GetUniqueStatement(
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "SELECT value FROM meta WHERE key = \"version\""));
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(smt.Step());
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(4, smt.ColumnInt(0));
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(smt.Step());
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
441bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
4425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(SQLiteChannelIDStoreTest, TestRSADiscarded) {
443bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Reset the store.  We'll be using a different database for this test.
444bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  store_ = NULL;
445bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
446bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  base::FilePath v4_db_path(temp_dir_.path().AppendASCII("v4dbrsa"));
447bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
448bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  std::string key_data;
449bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  std::string cert_data;
450bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ReadTestKeyAndCert(&key_data, &cert_data);
451bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
452bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Create a version 4 database with a mix of RSA and ECDSA certs.
453bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  {
454bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    sql::Connection db;
455bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    ASSERT_TRUE(db.Open(v4_db_path));
456bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    ASSERT_TRUE(db.Execute(
457bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        "CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY,"
4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "value LONGVARCHAR);"
459bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        "INSERT INTO \"meta\" VALUES('version','4');"
460bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        "INSERT INTO \"meta\" VALUES('last_compatible_version','1');"
461bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        "CREATE TABLE origin_bound_certs ("
4621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "origin TEXT NOT NULL UNIQUE PRIMARY KEY,"
4631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "private_key BLOB NOT NULL,"
4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "cert BLOB NOT NULL,"
4651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "cert_type INTEGER,"
4661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "expiration_time INTEGER,"
4671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        "creation_time INTEGER);"));
468bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
469bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    sql::Statement add_smt(db.GetUniqueStatement(
470bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        "INSERT INTO origin_bound_certs "
471bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        "(origin, private_key, cert, cert_type, expiration_time, creation_time)"
472bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        " VALUES (?,?,?,?,?,?)"));
473bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    add_smt.BindString(0, "google.com");
474bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    add_smt.BindBlob(1, key_data.data(), key_data.size());
475bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    add_smt.BindBlob(2, cert_data.data(), cert_data.size());
476bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    add_smt.BindInt64(3, 64);
477bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    add_smt.BindInt64(4, GetTestCertExpirationTime().ToInternalValue());
478bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    add_smt.BindInt64(5, base::Time::Now().ToInternalValue());
479bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    ASSERT_TRUE(add_smt.Run());
480bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
481bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    add_smt.Clear();
482bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    add_smt.Assign(db.GetUniqueStatement(
483bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        "INSERT INTO origin_bound_certs "
484bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        "(origin, private_key, cert, cert_type, expiration_time, creation_time)"
485bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        " VALUES (?,?,?,?,?,?)"));
486bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    add_smt.BindString(0, "foo.com");
487bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    add_smt.BindBlob(1, key_data.data(), key_data.size());
488bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    add_smt.BindBlob(2, cert_data.data(), cert_data.size());
489bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    add_smt.BindInt64(3, 1);
490bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    add_smt.BindInt64(4, GetTestCertExpirationTime().ToInternalValue());
491bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    add_smt.BindInt64(5, base::Time::Now().ToInternalValue());
492bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    ASSERT_TRUE(add_smt.Run());
493bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
494bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
4951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScopedVector<DefaultChannelIDStore::ChannelID> channel_ids;
4961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  store_ =
4971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new SQLiteChannelIDStore(v4_db_path, base::MessageLoopProxy::current());
498bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
499bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Load the database and ensure the certs can be read.
5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Load(&channel_ids);
501bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Only the ECDSA cert (for google.com) is read, the RSA one is discarded.
5025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(1U, channel_ids.size());
503bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
5045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ("google.com", channel_ids[0]->server_identifier());
5051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_EQ(GetTestCertExpirationTime(), channel_ids[0]->expiration_time());
5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(key_data, channel_ids[0]->private_key());
5075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(cert_data, channel_ids[0]->cert());
508bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
509bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  store_ = NULL;
510bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Make sure we wait until the destructor has run.
511bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  base::RunLoop().RunUntilIdle();
512bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
5131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace net
515