1 // Copyright 2019 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 "components/services/storage/storage_service_impl.h"
6
7 #include "base/files/file_path.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/macros.h"
10 #include "base/run_loop.h"
11 #include "base/test/task_environment.h"
12 #include "components/services/storage/partition_impl.h"
13 #include "components/services/storage/public/mojom/partition.mojom.h"
14 #include "components/services/storage/public/mojom/storage_service.mojom.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace storage {
18
19 class StorageServiceImplTest : public testing::Test {
20 public:
21 StorageServiceImplTest() = default;
22 ~StorageServiceImplTest() override = default;
23
24 protected:
remote_service()25 mojom::StorageService* remote_service() { return remote_service_.get(); }
service_impl()26 StorageServiceImpl& service_impl() { return service_; }
27
28 private:
29 base::test::TaskEnvironment task_environment_;
30 mojo::Remote<mojom::StorageService> remote_service_;
31 StorageServiceImpl service_{remote_service_.BindNewPipeAndPassReceiver(),
32 /*io_task_runner=*/nullptr};
33
34 DISALLOW_COPY_AND_ASSIGN(StorageServiceImplTest);
35 };
36
TEST_F(StorageServiceImplTest,UniqueInMemoryPartitions)37 TEST_F(StorageServiceImplTest, UniqueInMemoryPartitions) {
38 // Verifies that every partition client bound without a path is bound to a
39 // unique partition instance.
40
41 mojo::Remote<mojom::Partition> in_memory_partition1;
42 remote_service()->BindPartition(
43 /*path=*/base::nullopt,
44 in_memory_partition1.BindNewPipeAndPassReceiver());
45 in_memory_partition1.FlushForTesting();
46
47 EXPECT_EQ(1u, service_impl().partitions().size());
48
49 mojo::Remote<mojom::Partition> in_memory_partition2;
50 remote_service()->BindPartition(
51 base::nullopt /* path */,
52 in_memory_partition2.BindNewPipeAndPassReceiver());
53 in_memory_partition2.FlushForTesting();
54
55 EXPECT_EQ(2u, service_impl().partitions().size());
56
57 // Also verify that a new client with a provided path is unique from the above
58 // partitions.
59 base::ScopedTempDir temp_dir;
60 CHECK(temp_dir.CreateUniqueTempDir());
61
62 mojo::Remote<mojom::Partition> persistent_partition;
63 remote_service()->BindPartition(
64 temp_dir.GetPath(), persistent_partition.BindNewPipeAndPassReceiver());
65 persistent_partition.FlushForTesting();
66
67 EXPECT_EQ(3u, service_impl().partitions().size());
68 }
69
TEST_F(StorageServiceImplTest,SharedPersistentPartition)70 TEST_F(StorageServiceImplTest, SharedPersistentPartition) {
71 // Verifies that multiple clients can share the same persistent partition
72 // instance.
73
74 base::ScopedTempDir temp_dir;
75 CHECK(temp_dir.CreateUniqueTempDir());
76
77 mojo::Remote<mojom::Partition> client1;
78 remote_service()->BindPartition(temp_dir.GetPath(),
79 client1.BindNewPipeAndPassReceiver());
80 client1.FlushForTesting();
81
82 EXPECT_EQ(1u, service_impl().partitions().size());
83
84 mojo::Remote<mojom::Partition> client2;
85 remote_service()->BindPartition(temp_dir.GetPath(),
86 client2.BindNewPipeAndPassReceiver());
87 client2.FlushForTesting();
88
89 EXPECT_EQ(1u, service_impl().partitions().size());
90 EXPECT_TRUE(client1.is_connected());
91 EXPECT_TRUE(client2.is_connected());
92 }
93
TEST_F(StorageServiceImplTest,PartitionDestroyedOnLastClientDisconnect)94 TEST_F(StorageServiceImplTest, PartitionDestroyedOnLastClientDisconnect) {
95 base::ScopedTempDir temp_dir;
96 CHECK(temp_dir.CreateUniqueTempDir());
97
98 mojo::Remote<mojom::Partition> client1;
99 remote_service()->BindPartition(temp_dir.GetPath(),
100 client1.BindNewPipeAndPassReceiver());
101 client1.FlushForTesting();
102
103 mojo::Remote<mojom::Partition> client2;
104 remote_service()->BindPartition(temp_dir.GetPath(),
105 client2.BindNewPipeAndPassReceiver());
106 client2.FlushForTesting();
107
108 EXPECT_EQ(1u, service_impl().partitions().size());
109
110 client1.reset();
111 client2.reset();
112
113 base::RunLoop().RunUntilIdle();
114
115 EXPECT_EQ(0u, service_impl().partitions().size());
116 }
117
TEST_F(StorageServiceImplTest,PersistentPartitionRequiresAbsolutePath)118 TEST_F(StorageServiceImplTest, PersistentPartitionRequiresAbsolutePath) {
119 mojo::Remote<mojom::Partition> client;
120 const base::FilePath kTestRelativePath{FILE_PATH_LITERAL("invalid")};
121 remote_service()->BindPartition(kTestRelativePath,
122 client.BindNewPipeAndPassReceiver());
123
124 // We should be imminently disconnected because the BindPartition request
125 // should be ignored by the service.
126 base::RunLoop loop;
127 client.set_disconnect_handler(loop.QuitClosure());
128 loop.Run();
129
130 EXPECT_FALSE(client.is_connected());
131 }
132
133 } // namespace storage
134