blob: 8c3406e3c55918a42cd2d9c64141be6e6916037a [file] [log] [blame]
Narayan Kamathaef84a12020-01-02 15:20:13 +00001#include <gtest/gtest.h>
2
3#include "node-inl.h"
4
5#include <algorithm>
Nikita Ioffe890e6f22020-06-18 17:35:08 +01006#include <limits>
Narayan Kamathaef84a12020-01-02 15:20:13 +00007#include <memory>
8#include <mutex>
9
10using mediaprovider::fuse::dirhandle;
11using mediaprovider::fuse::handle;
12using mediaprovider::fuse::node;
Narayan Kamath568f17a2020-02-19 13:45:29 +000013using mediaprovider::fuse::NodeTracker;
Narayan Kamathaef84a12020-01-02 15:20:13 +000014
15// Listed as a friend class to struct node so it can observe implementation
16// details if required. The only implementation detail that is worth writing
17// tests around at the moment is the reference count.
18class NodeTest : public ::testing::Test {
19 public:
Narayan Kamath568f17a2020-02-19 13:45:29 +000020 NodeTest() : tracker_(NodeTracker(&lock_)) {}
21
Narayan Kamathaef84a12020-01-02 15:20:13 +000022 uint32_t GetRefCount(node* node) { return node->refcount_; }
23
24 std::recursive_mutex lock_;
Narayan Kamath568f17a2020-02-19 13:45:29 +000025 NodeTracker tracker_;
Narayan Kamathaef84a12020-01-02 15:20:13 +000026
27 // Forward destruction here, as NodeTest is a friend class.
28 static void destroy(node* node) { delete node; }
29
Narayan Kamatheca34252020-02-11 13:08:37 +000030 static void acquire(node* node) { node->Acquire(); }
31
Narayan Kamathaef84a12020-01-02 15:20:13 +000032 typedef std::unique_ptr<node, decltype(&NodeTest::destroy)> unique_node_ptr;
33
Zimbb7c3762020-09-23 13:50:08 +010034 unique_node_ptr CreateNode(node* parent, const std::string& path, const int transforms = 0) {
35 return unique_node_ptr(node::Create(parent, path, "", true, transforms, &lock_, &tracker_),
36 &NodeTest::destroy);
Narayan Kamathaef84a12020-01-02 15:20:13 +000037 }
Nikita Ioffe890e6f22020-06-18 17:35:08 +010038
Zim53c2d702020-09-23 12:18:27 +010039 static class node* ForChild(class node* node, const std::string& name,
40 const std::function<bool(class node*)>& callback) {
41 return node->ForChild(name, callback);
42 }
43
Nikita Ioffe890e6f22020-06-18 17:35:08 +010044 // Expose NodeCompare for testing.
45 node::NodeCompare cmp;
Narayan Kamathaef84a12020-01-02 15:20:13 +000046};
47
48TEST_F(NodeTest, TestCreate) {
49 unique_node_ptr node = CreateNode(nullptr, "/path");
50
51 ASSERT_EQ("/path", node->GetName());
52 ASSERT_EQ(1, GetRefCount(node.get()));
53 ASSERT_FALSE(node->HasCachedHandle());
54}
55
56TEST_F(NodeTest, TestCreate_withParent) {
57 unique_node_ptr parent = CreateNode(nullptr, "/path");
58 ASSERT_EQ(1, GetRefCount(parent.get()));
59
60 // Adding a child to a parent node increments its refcount.
61 unique_node_ptr child = CreateNode(parent.get(), "subdir");
62 ASSERT_EQ(2, GetRefCount(parent.get()));
63
64 // Make sure the node has been added to the parents list of children.
Narayan Kamatheca34252020-02-11 13:08:37 +000065 ASSERT_EQ(child.get(), parent->LookupChildByName("subdir", false /* acquire */));
66 ASSERT_EQ(1, GetRefCount(child.get()));
Narayan Kamathaef84a12020-01-02 15:20:13 +000067}
68
69TEST_F(NodeTest, TestRelease) {
Zimbb7c3762020-09-23 13:50:08 +010070 node* node = node::Create(nullptr, "/path", "", true, 0, &lock_, &tracker_);
Narayan Kamatheca34252020-02-11 13:08:37 +000071 acquire(node);
72 acquire(node);
Narayan Kamathaef84a12020-01-02 15:20:13 +000073 ASSERT_EQ(3, GetRefCount(node));
74
75 ASSERT_FALSE(node->Release(1));
76 ASSERT_EQ(2, GetRefCount(node));
77
78 // A Release that makes refcount go negative should be a no-op.
79 ASSERT_FALSE(node->Release(10000));
80 ASSERT_EQ(2, GetRefCount(node));
81
82 // Finally, let the refcount go to zero.
83 ASSERT_TRUE(node->Release(2));
84}
85
Zim53c2d702020-09-23 12:18:27 +010086TEST_F(NodeTest, TestRenameName) {
Zim87c7bf82020-01-07 18:11:27 +000087 unique_node_ptr parent = CreateNode(nullptr, "/path");
88
89 unique_node_ptr child = CreateNode(parent.get(), "subdir");
90 ASSERT_EQ(2, GetRefCount(parent.get()));
Narayan Kamatheca34252020-02-11 13:08:37 +000091 ASSERT_EQ(child.get(), parent->LookupChildByName("subdir", false /* acquire */));
Zim87c7bf82020-01-07 18:11:27 +000092
93 child->Rename("subdir_new", parent.get());
94
95 ASSERT_EQ(2, GetRefCount(parent.get()));
Narayan Kamatheca34252020-02-11 13:08:37 +000096 ASSERT_EQ(nullptr, parent->LookupChildByName("subdir", false /* acquire */));
97 ASSERT_EQ(child.get(), parent->LookupChildByName("subdir_new", false /* acquire */));
Zim87c7bf82020-01-07 18:11:27 +000098
99 ASSERT_EQ("/path/subdir_new", child->BuildPath());
Narayan Kamatheca34252020-02-11 13:08:37 +0000100 ASSERT_EQ(1, GetRefCount(child.get()));
Zim87c7bf82020-01-07 18:11:27 +0000101}
102
Zim53c2d702020-09-23 12:18:27 +0100103TEST_F(NodeTest, TestRenameParent) {
Zim87c7bf82020-01-07 18:11:27 +0000104 unique_node_ptr parent1 = CreateNode(nullptr, "/path1");
105 unique_node_ptr parent2 = CreateNode(nullptr, "/path2");
106
107 unique_node_ptr child = CreateNode(parent1.get(), "subdir");
108 ASSERT_EQ(2, GetRefCount(parent1.get()));
Narayan Kamatheca34252020-02-11 13:08:37 +0000109 ASSERT_EQ(child.get(), parent1->LookupChildByName("subdir", false /* acquire */));
Zim87c7bf82020-01-07 18:11:27 +0000110
111 child->Rename("subdir", parent2.get());
112 ASSERT_EQ(1, GetRefCount(parent1.get()));
Narayan Kamatheca34252020-02-11 13:08:37 +0000113 ASSERT_EQ(nullptr, parent1->LookupChildByName("subdir", false /* acquire */));
Zim87c7bf82020-01-07 18:11:27 +0000114
115 ASSERT_EQ(2, GetRefCount(parent2.get()));
Narayan Kamatheca34252020-02-11 13:08:37 +0000116 ASSERT_EQ(child.get(), parent2->LookupChildByName("subdir", false /* acquire */));
Zim87c7bf82020-01-07 18:11:27 +0000117
118 ASSERT_EQ("/path2/subdir", child->BuildPath());
Narayan Kamatheca34252020-02-11 13:08:37 +0000119 ASSERT_EQ(1, GetRefCount(child.get()));
Zim87c7bf82020-01-07 18:11:27 +0000120}
121
Zim53c2d702020-09-23 12:18:27 +0100122TEST_F(NodeTest, TestRenameNameAndParent) {
Narayan Kamathaef84a12020-01-02 15:20:13 +0000123 unique_node_ptr parent1 = CreateNode(nullptr, "/path1");
124 unique_node_ptr parent2 = CreateNode(nullptr, "/path2");
125
126 unique_node_ptr child = CreateNode(parent1.get(), "subdir");
127 ASSERT_EQ(2, GetRefCount(parent1.get()));
Narayan Kamatheca34252020-02-11 13:08:37 +0000128 ASSERT_EQ(child.get(), parent1->LookupChildByName("subdir", false /* acquire */));
Narayan Kamathaef84a12020-01-02 15:20:13 +0000129
130 child->Rename("subdir_new", parent2.get());
131 ASSERT_EQ(1, GetRefCount(parent1.get()));
Narayan Kamatheca34252020-02-11 13:08:37 +0000132 ASSERT_EQ(nullptr, parent1->LookupChildByName("subdir", false /* acquire */));
133 ASSERT_EQ(nullptr, parent1->LookupChildByName("subdir_new", false /* acquire */));
Narayan Kamathaef84a12020-01-02 15:20:13 +0000134
135 ASSERT_EQ(2, GetRefCount(parent2.get()));
Narayan Kamatheca34252020-02-11 13:08:37 +0000136 ASSERT_EQ(child.get(), parent2->LookupChildByName("subdir_new", false /* acquire */));
Narayan Kamathaef84a12020-01-02 15:20:13 +0000137
138 ASSERT_EQ("/path2/subdir_new", child->BuildPath());
Narayan Kamatheca34252020-02-11 13:08:37 +0000139 ASSERT_EQ(1, GetRefCount(child.get()));
Narayan Kamathaef84a12020-01-02 15:20:13 +0000140}
141
Zim53c2d702020-09-23 12:18:27 +0100142TEST_F(NodeTest, TestRenameNameForChild) {
143 unique_node_ptr parent = CreateNode(nullptr, "/path");
144
Zimbb7c3762020-09-23 13:50:08 +0100145 unique_node_ptr child0 = CreateNode(parent.get(), "subdir", 0 /* transforms */);
146 unique_node_ptr child1 = CreateNode(parent.get(), "subdir", 1 /* transforms */);
147 ASSERT_EQ(3, GetRefCount(parent.get()));
148 ASSERT_EQ(child0.get(),
149 parent->LookupChildByName("subdir", false /* acquire */, 0 /* transforms */));
150 ASSERT_EQ(child1.get(),
151 parent->LookupChildByName("subdir", false /* acquire */, 1 /* transforms */));
Zim53c2d702020-09-23 12:18:27 +0100152
153 parent->RenameChild("subdir", "subdir_new", parent.get());
154
Zimbb7c3762020-09-23 13:50:08 +0100155 ASSERT_EQ(3, GetRefCount(parent.get()));
156 ASSERT_EQ(nullptr,
157 parent->LookupChildByName("subdir", false /* acquire */, 0 /* transforms */));
158 ASSERT_EQ(nullptr,
159 parent->LookupChildByName("subdir", false /* acquire */, 1 /* transforms */));
160 ASSERT_EQ(child0.get(),
161 parent->LookupChildByName("subdir_new", false /* acquire */, 0 /* transforms */));
162 ASSERT_EQ(child1.get(),
163 parent->LookupChildByName("subdir_new", false /* acquire */, 1 /* transforms */));
Zim53c2d702020-09-23 12:18:27 +0100164
Zimbb7c3762020-09-23 13:50:08 +0100165 ASSERT_EQ("/path/subdir_new", child0->BuildPath());
166 ASSERT_EQ("/path/subdir_new", child1->BuildPath());
167 ASSERT_EQ(1, GetRefCount(child0.get()));
168 ASSERT_EQ(1, GetRefCount(child1.get()));
Zim53c2d702020-09-23 12:18:27 +0100169}
170
171TEST_F(NodeTest, TestRenameParentForChild) {
172 unique_node_ptr parent1 = CreateNode(nullptr, "/path1");
173 unique_node_ptr parent2 = CreateNode(nullptr, "/path2");
174
Zimbb7c3762020-09-23 13:50:08 +0100175 unique_node_ptr child0 = CreateNode(parent1.get(), "subdir", 0 /* transforms */);
176 unique_node_ptr child1 = CreateNode(parent1.get(), "subdir", 1 /* transforms */);
177 ASSERT_EQ(3, GetRefCount(parent1.get()));
178 ASSERT_EQ(child0.get(),
179 parent1->LookupChildByName("subdir", false /* acquire */, 0 /* transforms */));
180 ASSERT_EQ(child1.get(),
181 parent1->LookupChildByName("subdir", false /* acquire */, 1 /* transforms */));
Zim53c2d702020-09-23 12:18:27 +0100182
183 parent1->RenameChild("subdir", "subdir", parent2.get());
184 ASSERT_EQ(1, GetRefCount(parent1.get()));
Zimbb7c3762020-09-23 13:50:08 +0100185 ASSERT_EQ(nullptr,
186 parent1->LookupChildByName("subdir", false /* acquire */, 0 /* transforms */));
187 ASSERT_EQ(nullptr,
188 parent1->LookupChildByName("subdir", false /* acquire */, 1 /* transforms */));
Zim53c2d702020-09-23 12:18:27 +0100189
Zimbb7c3762020-09-23 13:50:08 +0100190 ASSERT_EQ(3, GetRefCount(parent2.get()));
191 ASSERT_EQ(child0.get(),
192 parent2->LookupChildByName("subdir", false /* acquire */, 0 /* transforms */));
193 ASSERT_EQ(child1.get(),
194 parent2->LookupChildByName("subdir", false /* acquire */, 1 /* transforms */));
Zim53c2d702020-09-23 12:18:27 +0100195
Zimbb7c3762020-09-23 13:50:08 +0100196 ASSERT_EQ("/path2/subdir", child0->BuildPath());
197 ASSERT_EQ("/path2/subdir", child1->BuildPath());
198 ASSERT_EQ(1, GetRefCount(child0.get()));
199 ASSERT_EQ(1, GetRefCount(child1.get()));
Zim53c2d702020-09-23 12:18:27 +0100200}
201
202TEST_F(NodeTest, TestRenameNameAndParentForChild) {
203 unique_node_ptr parent1 = CreateNode(nullptr, "/path1");
204 unique_node_ptr parent2 = CreateNode(nullptr, "/path2");
205
Zimbb7c3762020-09-23 13:50:08 +0100206 unique_node_ptr child0 = CreateNode(parent1.get(), "subdir", 0 /* transforms */);
207 unique_node_ptr child1 = CreateNode(parent1.get(), "subdir", 1 /* transforms */);
208 ASSERT_EQ(3, GetRefCount(parent1.get()));
209 ASSERT_EQ(child0.get(),
210 parent1->LookupChildByName("subdir", false /* acquire */, 0 /* transforms */));
211 ASSERT_EQ(child1.get(),
212 parent1->LookupChildByName("subdir", false /* acquire */, 1 /* transforms */));
Zim53c2d702020-09-23 12:18:27 +0100213
214 parent1->RenameChild("subdir", "subdir_new", parent2.get());
215 ASSERT_EQ(1, GetRefCount(parent1.get()));
Zimbb7c3762020-09-23 13:50:08 +0100216 ASSERT_EQ(nullptr,
217 parent1->LookupChildByName("subdir", false /* acquire */, 0 /* transforms */));
218 ASSERT_EQ(nullptr,
219 parent1->LookupChildByName("subdir_new", false /* acquire */, 0 /* transforms */));
220 ASSERT_EQ(nullptr,
221 parent1->LookupChildByName("subdir", false /* acquire */, 1 /* transforms */));
222 ASSERT_EQ(nullptr,
223 parent1->LookupChildByName("subdir_new", false /* acquire */, 1 /* transforms */));
Zim53c2d702020-09-23 12:18:27 +0100224
Zimbb7c3762020-09-23 13:50:08 +0100225 ASSERT_EQ(3, GetRefCount(parent2.get()));
226 ASSERT_EQ(nullptr,
227 parent1->LookupChildByName("subdir_new", false /* acquire */, 0 /* transforms */));
228 ASSERT_EQ(nullptr,
229 parent1->LookupChildByName("subdir_new", false /* acquire */, 1 /* transforms */));
Zim53c2d702020-09-23 12:18:27 +0100230
Zimbb7c3762020-09-23 13:50:08 +0100231 ASSERT_EQ("/path2/subdir_new", child0->BuildPath());
232 ASSERT_EQ("/path2/subdir_new", child1->BuildPath());
233 ASSERT_EQ(1, GetRefCount(child0.get()));
234 ASSERT_EQ(1, GetRefCount(child1.get()));
Zim53c2d702020-09-23 12:18:27 +0100235}
236
Narayan Kamathaef84a12020-01-02 15:20:13 +0000237TEST_F(NodeTest, TestBuildPath) {
238 unique_node_ptr parent = CreateNode(nullptr, "/path");
239 ASSERT_EQ("/path", parent->BuildPath());
240
241 unique_node_ptr child = CreateNode(parent.get(), "subdir");
242 ASSERT_EQ("/path/subdir", child->BuildPath());
243
244 unique_node_ptr child2 = CreateNode(parent.get(), "subdir2");
245 ASSERT_EQ("/path/subdir2", child2->BuildPath());
246
247 unique_node_ptr subchild = CreateNode(child2.get(), "subsubdir");
248 ASSERT_EQ("/path/subdir2/subsubdir", subchild->BuildPath());
249}
250
251TEST_F(NodeTest, TestSetDeleted) {
252 unique_node_ptr parent = CreateNode(nullptr, "/path");
253 unique_node_ptr child = CreateNode(parent.get(), "subdir");
254
Narayan Kamatheca34252020-02-11 13:08:37 +0000255 ASSERT_EQ(child.get(), parent->LookupChildByName("subdir", false /* acquire */));
Narayan Kamathaef84a12020-01-02 15:20:13 +0000256 child->SetDeleted();
Narayan Kamatheca34252020-02-11 13:08:37 +0000257 ASSERT_EQ(nullptr, parent->LookupChildByName("subdir", false /* acquire */));
Narayan Kamathaef84a12020-01-02 15:20:13 +0000258}
259
Zim53c2d702020-09-23 12:18:27 +0100260TEST_F(NodeTest, TestSetDeletedForChild) {
261 unique_node_ptr parent = CreateNode(nullptr, "/path");
Zimbb7c3762020-09-23 13:50:08 +0100262 unique_node_ptr child0 = CreateNode(parent.get(), "subdir", 0 /* transforms */);
263 unique_node_ptr child1 = CreateNode(parent.get(), "subdir", 1 /* transforms */);
Zim53c2d702020-09-23 12:18:27 +0100264
Zimbb7c3762020-09-23 13:50:08 +0100265 ASSERT_EQ(child0.get(),
266 parent->LookupChildByName("subdir", false /* acquire */, 0 /* transforms */));
267 ASSERT_EQ(child1.get(),
268 parent->LookupChildByName("subdir", false /* acquire */, 1 /* transforms */));
Zim53c2d702020-09-23 12:18:27 +0100269 parent->SetDeletedForChild("subdir");
Zimbb7c3762020-09-23 13:50:08 +0100270 ASSERT_EQ(nullptr,
271 parent->LookupChildByName("subdir", false /* acquire */, 0 /* transforms */));
272 ASSERT_EQ(nullptr,
273 parent->LookupChildByName("subdir", false /* acquire */, 1 /* transforms */));
Zim53c2d702020-09-23 12:18:27 +0100274}
275
Narayan Kamathaef84a12020-01-02 15:20:13 +0000276TEST_F(NodeTest, DeleteTree) {
277 unique_node_ptr parent = CreateNode(nullptr, "/path");
278
279 // This is the tree that we intend to delete.
Zimbb7c3762020-09-23 13:50:08 +0100280 node* child = node::Create(parent.get(), "subdir", "", true, 0, &lock_, &tracker_);
281 node::Create(child, "s1", "", true, 0, &lock_, &tracker_);
282 node* subchild2 = node::Create(child, "s2", "", true, 0, &lock_, &tracker_);
283 node::Create(subchild2, "sc2", "", true, 0, &lock_, &tracker_);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000284
Narayan Kamatheca34252020-02-11 13:08:37 +0000285 ASSERT_EQ(child, parent->LookupChildByName("subdir", false /* acquire */));
Narayan Kamathaef84a12020-01-02 15:20:13 +0000286 node::DeleteTree(child);
Narayan Kamatheca34252020-02-11 13:08:37 +0000287 ASSERT_EQ(nullptr, parent->LookupChildByName("subdir", false /* acquire */));
Narayan Kamathaef84a12020-01-02 15:20:13 +0000288}
289
290TEST_F(NodeTest, LookupChildByName_empty) {
291 unique_node_ptr parent = CreateNode(nullptr, "/path");
292 unique_node_ptr child = CreateNode(parent.get(), "subdir");
293
Narayan Kamatheca34252020-02-11 13:08:37 +0000294 ASSERT_EQ(child.get(), parent->LookupChildByName("subdir", false /* acquire */));
295 ASSERT_EQ(nullptr, parent->LookupChildByName("", false /* acquire */));
296}
297
Zimbb7c3762020-09-23 13:50:08 +0100298TEST_F(NodeTest, LookupChildByName_transforms) {
299 unique_node_ptr parent = CreateNode(nullptr, "/path");
300 unique_node_ptr child0 = CreateNode(parent.get(), "subdir", 0 /* transforms */);
301 unique_node_ptr child1 = CreateNode(parent.get(), "subdir", 1 /* transforms */);
302
303 ASSERT_EQ(child0.get(), parent->LookupChildByName("subdir", false /* acquire */));
304 ASSERT_EQ(child0.get(),
305 parent->LookupChildByName("subdir", false /* acquire */, 0 /* transforms */));
306 ASSERT_EQ(child1.get(),
307 parent->LookupChildByName("subdir", false /* acquire */, 1 /* transforms */));
308 ASSERT_EQ(nullptr,
309 parent->LookupChildByName("subdir", false /* acquire */, 2 /* transforms */));
310}
311
Narayan Kamatheca34252020-02-11 13:08:37 +0000312TEST_F(NodeTest, LookupChildByName_refcounts) {
313 unique_node_ptr parent = CreateNode(nullptr, "/path");
314 unique_node_ptr child = CreateNode(parent.get(), "subdir");
315
316 ASSERT_EQ(child.get(), parent->LookupChildByName("subdir", false /* acquire */));
317 ASSERT_EQ(1, GetRefCount(child.get()));
318
319 ASSERT_EQ(child.get(), parent->LookupChildByName("subdir", true /* acquire */));
320 ASSERT_EQ(2, GetRefCount(child.get()));
Narayan Kamathaef84a12020-01-02 15:20:13 +0000321}
322
323TEST_F(NodeTest, LookupAbsolutePath) {
324 unique_node_ptr parent = CreateNode(nullptr, "/path");
325 unique_node_ptr child = CreateNode(parent.get(), "subdir");
326 unique_node_ptr child2 = CreateNode(parent.get(), "subdir2");
327 unique_node_ptr subchild = CreateNode(child2.get(), "subsubdir");
328
329 ASSERT_EQ(parent.get(), node::LookupAbsolutePath(parent.get(), "/path"));
330 ASSERT_EQ(parent.get(), node::LookupAbsolutePath(parent.get(), "/path/"));
331 ASSERT_EQ(nullptr, node::LookupAbsolutePath(parent.get(), "/path2"));
332
333 ASSERT_EQ(child.get(), node::LookupAbsolutePath(parent.get(), "/path/subdir"));
334 ASSERT_EQ(child.get(), node::LookupAbsolutePath(parent.get(), "/path/subdir/"));
335 // TODO(narayan): Are the two cases below intentional behaviour ?
336 ASSERT_EQ(child.get(), node::LookupAbsolutePath(parent.get(), "/path//subdir"));
337 ASSERT_EQ(child.get(), node::LookupAbsolutePath(parent.get(), "/path///subdir"));
338
339 ASSERT_EQ(child2.get(), node::LookupAbsolutePath(parent.get(), "/path/subdir2"));
340 ASSERT_EQ(child2.get(), node::LookupAbsolutePath(parent.get(), "/path/subdir2/"));
341
342 ASSERT_EQ(nullptr, node::LookupAbsolutePath(parent.get(), "/path/subdir3/"));
343
344 ASSERT_EQ(subchild.get(), node::LookupAbsolutePath(parent.get(), "/path/subdir2/subsubdir"));
345 ASSERT_EQ(nullptr, node::LookupAbsolutePath(parent.get(), "/path/subdir/subsubdir"));
346}
347
348TEST_F(NodeTest, AddDestroyHandle) {
349 unique_node_ptr node = CreateNode(nullptr, "/path");
350
Zim148cbe22020-11-17 15:58:29 +0000351 handle* h = new handle(-1, new mediaprovider::fuse::RedactionInfo, true /* cached */,
352 false /* passthrough */, 0 /* uid */);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000353 node->AddHandle(h);
354 ASSERT_TRUE(node->HasCachedHandle());
355
356 node->DestroyHandle(h);
357 ASSERT_FALSE(node->HasCachedHandle());
358
359 // Should all crash the process as the handle is no longer associated with
360 // the node in question.
361 EXPECT_DEATH(node->DestroyHandle(h), "");
362 EXPECT_DEATH(node->DestroyHandle(nullptr), "");
Zim148cbe22020-11-17 15:58:29 +0000363 std::unique_ptr<handle> h2(new handle(-1, new mediaprovider::fuse::RedactionInfo,
364 true /* cached */, false /* passthrough */, 0 /* uid */));
Narayan Kamathaef84a12020-01-02 15:20:13 +0000365 EXPECT_DEATH(node->DestroyHandle(h2.get()), "");
366}
Zim89962312020-04-22 21:21:53 +0100367
368TEST_F(NodeTest, CaseInsensitive) {
369 unique_node_ptr parent = CreateNode(nullptr, "/path");
Zim89962312020-04-22 21:21:53 +0100370 unique_node_ptr mixed_child = CreateNode(parent.get(), "cHiLd");
371
Zim0852ba72020-06-09 11:50:33 +0100372 node* upper_child = parent->LookupChildByName("CHILD", false /* acquire */);
373 node* lower_child = parent->LookupChildByName("child", false /* acquire */);
Zim89962312020-04-22 21:21:53 +0100374
Zim0852ba72020-06-09 11:50:33 +0100375 ASSERT_EQ(mixed_child.get(), lower_child);
376 ASSERT_EQ(mixed_child.get(), upper_child);
Zim89962312020-04-22 21:21:53 +0100377}
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100378
379TEST_F(NodeTest, RenameSameNameSameParent) {
380 unique_node_ptr parent = CreateNode(nullptr, "/path1");
381 unique_node_ptr child = CreateNode(parent.get(), "subdir");
382
383 ASSERT_EQ(child.get(), parent->LookupChildByName("SuBdIr", false /* acquire */));
384 ASSERT_EQ(2, GetRefCount(parent.get()));
385
386 child->Rename("subdir", parent.get());
387
388 ASSERT_EQ(child.get(), parent->LookupChildByName("SuBdIr", false /* acquire */));
389 ASSERT_EQ(2, GetRefCount(parent.get()));
390}
391
392TEST_F(NodeTest, RenameRoot) {
393 unique_node_ptr root = CreateNode(nullptr, "/root");
394 ASSERT_EQ(1, GetRefCount(root.get()));
395
396 root->Rename("/i-am-root!", nullptr);
397
398 ASSERT_EQ("/i-am-root!", root->GetName());
399 ASSERT_EQ(1, GetRefCount(root.get()));
400}
401
402TEST_F(NodeTest, NodeCompareDefinesLinearOrder) {
403 unique_node_ptr node_a = CreateNode(nullptr, "a");
404 unique_node_ptr node_b = CreateNode(nullptr, "B");
405 unique_node_ptr node_c = CreateNode(nullptr, "c");
406
407 ASSERT_FALSE(cmp.operator()(node_a.get(), node_a.get()));
408 ASSERT_FALSE(cmp.operator()(node_b.get(), node_b.get()));
409 ASSERT_FALSE(cmp.operator()(node_c.get(), node_c.get()));
410
411 auto check_fn = [&](const node* lhs_node, const node* rhs_node) {
412 ASSERT_TRUE(cmp.operator()(lhs_node, rhs_node));
413 ASSERT_FALSE(cmp.operator()(rhs_node, lhs_node));
414 };
415
416 check_fn(node_a.get(), node_b.get());
417 check_fn(node_b.get(), node_c.get());
418 check_fn(node_a.get(), node_c.get());
419
420 // ("A", 0) < node_a < ("a", max_uintptr_t) < node_b
421 ASSERT_TRUE(cmp.operator()(std::make_pair("A", 0), node_a.get()));
422 ASSERT_TRUE(cmp.operator()(node_a.get(),
423 std::make_pair("A", std::numeric_limits<uintptr_t>::max())));
424 ASSERT_TRUE(cmp.operator()(std::make_pair("A", std::numeric_limits<uintptr_t>::max()),
425 node_b.get()));
426}
427
428TEST_F(NodeTest, LookupChildByName_ChildrenWithSameName) {
429 unique_node_ptr parent = CreateNode(nullptr, "/path");
430 unique_node_ptr foo1 = CreateNode(parent.get(), "FoO");
431 unique_node_ptr foo2 = CreateNode(parent.get(), "fOo");
432 unique_node_ptr bar1 = CreateNode(parent.get(), "BAR");
433 unique_node_ptr bar2 = CreateNode(parent.get(), "bar");
434 unique_node_ptr baz1 = CreateNode(parent.get(), "baZ");
435 unique_node_ptr baz2 = CreateNode(parent.get(), "Baz");
436
437 auto test_fn = [&](const std::string& name, node* first, node* second) {
438 auto node1 = parent->LookupChildByName(name, false /* acquire */);
439 ASSERT_EQ(std::min(first, second), node1);
440 node1->SetDeleted();
441
442 auto node2 = parent->LookupChildByName(name, false /* acquire */);
443 ASSERT_EQ(std::max(first, second), node2);
444 node2->SetDeleted();
445
446 ASSERT_EQ(nullptr, parent->LookupChildByName(name, false /* acquire */));
447 };
448
449 test_fn("foo", foo1.get(), foo2.get());
450 test_fn("bAr", bar1.get(), bar2.get());
451 test_fn("BaZ", baz1.get(), baz2.get());
452}
Zim53c2d702020-09-23 12:18:27 +0100453
454TEST_F(NodeTest, ForChild) {
455 unique_node_ptr parent = CreateNode(nullptr, "/path");
456 unique_node_ptr foo1 = CreateNode(parent.get(), "FoO");
457 unique_node_ptr foo2 = CreateNode(parent.get(), "fOo");
458 unique_node_ptr foo3 = CreateNode(parent.get(), "foo");
459 foo3->SetDeleted();
460
461 std::vector<node*> match_all;
462 auto test_fn_match_all = [&](node* child) {
463 match_all.push_back(child);
464 return false;
465 };
466
467 std::vector<node*> match_first;
468 auto test_fn_match_first = [&](node* child) {
469 match_first.push_back(child);
470 return true;
471 };
472
473 std::vector<node*> match_none;
474 auto test_fn_match_none = [&](node* child) {
475 match_none.push_back(child);
476 return false;
477 };
478
479 node* node_all = ForChild(parent.get(), "foo", test_fn_match_all);
480 ASSERT_EQ(nullptr, node_all);
481 ASSERT_EQ(2, match_all.size());
482 ASSERT_EQ(std::min(foo1.get(), foo2.get()), match_all[0]);
483 ASSERT_EQ(std::max(foo1.get(), foo2.get()), match_all[1]);
484
485 node* node_first = ForChild(parent.get(), "foo", test_fn_match_first);
486 ASSERT_EQ(std::min(foo1.get(), foo2.get()), node_first);
487 ASSERT_EQ(1, match_first.size());
488 ASSERT_EQ(std::min(foo1.get(), foo2.get()), match_first[0]);
489
490 node* node_none = ForChild(parent.get(), "bar", test_fn_match_none);
491 ASSERT_EQ(nullptr, node_none);
492 ASSERT_TRUE(match_none.empty());
493}