1// Copyright 2014 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 "base/bind.h"
6#include "base/message_loop/message_loop.h"
7#include "base/strings/utf_string_conversions.h"
8#include "base/threading/thread.h"
9#include "storage/common/database/database_connections.h"
10#include "testing/gtest/include/gtest/gtest.h"
11
12using base::ASCIIToUTF16;
13using storage::DatabaseConnections;
14using storage::DatabaseConnectionsWrapper;
15
16namespace content {
17
18namespace {
19
20void RemoveConnectionTask(
21    const std::string& origin_id, const base::string16& database_name,
22    scoped_refptr<DatabaseConnectionsWrapper> obj,
23    bool* did_task_execute) {
24  *did_task_execute = true;
25  obj->RemoveOpenConnection(origin_id, database_name);
26}
27
28void ScheduleRemoveConnectionTask(
29    base::Thread* thread,  const std::string& origin_id,
30    const base::string16& database_name,
31    scoped_refptr<DatabaseConnectionsWrapper> obj,
32    bool* did_task_execute) {
33  thread->message_loop()->PostTask(
34      FROM_HERE,
35      base::Bind(&RemoveConnectionTask, origin_id, database_name, obj,
36                 did_task_execute));
37}
38
39}  // anonymous namespace
40
41TEST(DatabaseConnectionsTest, DatabaseConnectionsTest) {
42  const std::string kOriginId("origin_id");
43  const base::string16 kName(ASCIIToUTF16("database_name"));
44  const base::string16 kName2(ASCIIToUTF16("database_name2"));
45  const int64 kSize = 1000;
46
47  DatabaseConnections connections;
48
49  EXPECT_TRUE(connections.IsEmpty());
50  EXPECT_FALSE(connections.IsDatabaseOpened(kOriginId, kName));
51  EXPECT_FALSE(connections.IsOriginUsed(kOriginId));
52
53  connections.AddConnection(kOriginId, kName);
54  EXPECT_FALSE(connections.IsEmpty());
55  EXPECT_TRUE(connections.IsDatabaseOpened(kOriginId, kName));
56  EXPECT_TRUE(connections.IsOriginUsed(kOriginId));
57  EXPECT_EQ(0, connections.GetOpenDatabaseSize(kOriginId, kName));
58  connections.SetOpenDatabaseSize(kOriginId, kName, kSize);
59  EXPECT_EQ(kSize, connections.GetOpenDatabaseSize(kOriginId, kName));
60
61  connections.RemoveConnection(kOriginId, kName);
62  EXPECT_TRUE(connections.IsEmpty());
63  EXPECT_FALSE(connections.IsDatabaseOpened(kOriginId, kName));
64  EXPECT_FALSE(connections.IsOriginUsed(kOriginId));
65
66  connections.AddConnection(kOriginId, kName);
67  connections.SetOpenDatabaseSize(kOriginId, kName, kSize);
68  EXPECT_EQ(kSize, connections.GetOpenDatabaseSize(kOriginId, kName));
69  connections.AddConnection(kOriginId, kName);
70  EXPECT_EQ(kSize, connections.GetOpenDatabaseSize(kOriginId, kName));
71  EXPECT_FALSE(connections.IsEmpty());
72  EXPECT_TRUE(connections.IsDatabaseOpened(kOriginId, kName));
73  EXPECT_TRUE(connections.IsOriginUsed(kOriginId));
74  connections.AddConnection(kOriginId, kName2);
75  EXPECT_TRUE(connections.IsDatabaseOpened(kOriginId, kName2));
76
77  DatabaseConnections another;
78  another.AddConnection(kOriginId, kName);
79  another.AddConnection(kOriginId, kName2);
80
81  std::vector<std::pair<std::string, base::string16> > closed_dbs;
82  connections.RemoveConnections(another, &closed_dbs);
83  EXPECT_EQ(1u, closed_dbs.size());
84  EXPECT_EQ(kOriginId, closed_dbs[0].first);
85  EXPECT_EQ(kName2, closed_dbs[0].second);
86  EXPECT_FALSE(connections.IsDatabaseOpened(kOriginId, kName2));
87  EXPECT_TRUE(connections.IsDatabaseOpened(kOriginId, kName));
88  EXPECT_EQ(kSize, connections.GetOpenDatabaseSize(kOriginId, kName));
89  another.RemoveAllConnections();
90  connections.RemoveAllConnections();
91  EXPECT_TRUE(connections.IsEmpty());
92
93  // Ensure the return value properly indicates the initial
94  // addition and final removal.
95  EXPECT_TRUE(connections.AddConnection(kOriginId, kName));
96  EXPECT_FALSE(connections.AddConnection(kOriginId, kName));
97  EXPECT_FALSE(connections.AddConnection(kOriginId, kName));
98  EXPECT_FALSE(connections.RemoveConnection(kOriginId, kName));
99  EXPECT_FALSE(connections.RemoveConnection(kOriginId, kName));
100  EXPECT_TRUE(connections.RemoveConnection(kOriginId, kName));
101}
102
103TEST(DatabaseConnectionsTest, DatabaseConnectionsWrapperTest) {
104  const std::string kOriginId("origin_id");
105  const base::string16 kName(ASCIIToUTF16("database_name"));
106
107  base::MessageLoop message_loop;
108  scoped_refptr<DatabaseConnectionsWrapper> obj(new DatabaseConnectionsWrapper);
109  EXPECT_FALSE(obj->HasOpenConnections());
110  obj->AddOpenConnection(kOriginId, kName);
111  EXPECT_TRUE(obj->HasOpenConnections());
112  obj->AddOpenConnection(kOriginId, kName);
113  EXPECT_TRUE(obj->HasOpenConnections());
114  obj->RemoveOpenConnection(kOriginId, kName);
115  EXPECT_TRUE(obj->HasOpenConnections());
116  obj->RemoveOpenConnection(kOriginId, kName);
117  EXPECT_FALSE(obj->HasOpenConnections());
118  obj->WaitForAllDatabasesToClose();  // should return immediately
119
120  // Test WaitForAllDatabasesToClose with the last connection
121  // being removed on the current thread.
122  obj->AddOpenConnection(kOriginId, kName);
123  bool did_task_execute = false;
124  base::MessageLoop::current()->PostTask(
125      FROM_HERE,
126      base::Bind(&RemoveConnectionTask, kOriginId, kName, obj,
127                 &did_task_execute));
128  obj->WaitForAllDatabasesToClose();  // should return after the task executes
129  EXPECT_TRUE(did_task_execute);
130  EXPECT_FALSE(obj->HasOpenConnections());
131
132  // Test WaitForAllDatabasesToClose with the last connection
133  // being removed on another thread.
134  obj->AddOpenConnection(kOriginId, kName);
135  base::Thread thread("WrapperTestThread");
136  thread.Start();
137  did_task_execute = false;
138  base::MessageLoop::current()->PostTask(
139      FROM_HERE,
140      base::Bind(&ScheduleRemoveConnectionTask, &thread, kOriginId, kName, obj,
141                 &did_task_execute));
142  obj->WaitForAllDatabasesToClose();  // should return after the task executes
143  EXPECT_TRUE(did_task_execute);
144  EXPECT_FALSE(obj->HasOpenConnections());
145}
146
147}  // namespace content
148