1 // Copyright (c) 2012 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.
13 #include "gtest/gtest.h"
15 #include "nacl_io/kernel_handle.h"
16 #include "nacl_io/kernel_object.h"
17 #include "nacl_io/mount.h"
18 #include "nacl_io/path.h"
20 using namespace nacl_io;
24 class MountNodeRefMock : public MountNode {
26 MountNodeRefMock(Mount* mnt) : MountNode(mnt) {}
29 class MountRefMock : public Mount {
34 Error Access(const Path& path, int a_mode) { return ENOSYS; }
35 Error Open(const Path& path, int mode, ScopedMountNode* out_node) {
36 out_node->reset(NULL);
39 Error Unlink(const Path& path) { return 0; }
40 Error Mkdir(const Path& path, int permissions) { return 0; }
41 Error Rmdir(const Path& path) { return 0; }
42 Error Remove(const Path& path) { return 0; }
45 class KernelHandleRefMock : public KernelHandle {
47 KernelHandleRefMock(const ScopedMount& mnt, const ScopedMountNode& node)
48 : KernelHandle(mnt, node) {}
51 class KernelObjectTest : public ::testing::Test {
54 mnt.reset(new MountRefMock());
55 node.reset(new MountNodeRefMock(mnt.get()));
59 // mnt is ref-counted, it doesn't need to be explicitly deleted.
71 #include <nacl_io/mount_mem.h>
72 #include <nacl_io/mount_http.h>
74 TEST_F(KernelObjectTest, Referencing) {
75 // The mount and node should have 1 ref count at this point
76 EXPECT_EQ(1, mnt->RefCount());
77 EXPECT_EQ(1, node->RefCount());
79 // Pass the mount and node into a KernelHandle
80 KernelHandle* raw_handle = new KernelHandleRefMock(mnt, node);
81 ScopedKernelHandle handle_a(raw_handle);
83 // The mount and node should have 1 ref count at this point
84 EXPECT_EQ(1, handle_a->RefCount());
85 EXPECT_EQ(2, mnt->RefCount());
86 EXPECT_EQ(2, node->RefCount());
88 ScopedKernelHandle handle_b = handle_a;
90 // There should be two references to the KernelHandle, the mount and node
91 // should be unchanged.
92 EXPECT_EQ(2, handle_a->RefCount());
93 EXPECT_EQ(2, handle_b->RefCount());
94 EXPECT_EQ(handle_a.get(), handle_b.get());
95 EXPECT_EQ(2, mnt->RefCount());
96 EXPECT_EQ(2, node->RefCount());
98 // Allocating an FD should cause the KernelProxy to ref the handle and
99 // the node and mount should be unchanged.
100 int fd1 = proxy.AllocateFD(handle_a);
101 EXPECT_EQ(3, handle_a->RefCount());
102 EXPECT_EQ(2, mnt->RefCount());
103 EXPECT_EQ(2, node->RefCount());
105 // If we "dup" the handle, we should bump the ref count on the handle
106 int fd2 = proxy.AllocateFD(handle_b);
107 EXPECT_EQ(4, handle_a->RefCount());
108 EXPECT_EQ(2, mnt->RefCount());
109 EXPECT_EQ(2, node->RefCount());
111 // Handles are expected to come out in order
115 // Now we "free" the handles, since the proxy should hold them.
116 handle_a.reset(NULL);
117 handle_b.reset(NULL);
118 EXPECT_EQ(2, mnt->RefCount());
119 EXPECT_EQ(2, node->RefCount());
121 // We should find the handle by either fd
122 EXPECT_EQ(0, proxy.AcquireHandle(fd1, &handle_a));
123 EXPECT_EQ(0, proxy.AcquireHandle(fd2, &handle_b));
124 EXPECT_EQ(raw_handle, handle_a.get());
125 EXPECT_EQ(raw_handle, handle_b.get());
127 EXPECT_EQ(4, handle_a->RefCount());
128 EXPECT_EQ(2, mnt->RefCount());
129 EXPECT_EQ(2, node->RefCount());
131 // A non existent fd should fail, and handleA should decrement as handleB
132 // is released by the call.
133 EXPECT_EQ(EBADF, proxy.AcquireHandle(-1, &handle_b));
134 EXPECT_EQ(NULL, handle_b.get());
135 EXPECT_EQ(3, handle_a->RefCount());
137 EXPECT_EQ(EBADF, proxy.AcquireHandle(100, &handle_b));
138 EXPECT_EQ(NULL, handle_b.get());
140 // Now only the KernelProxy should reference the KernelHandle in the
141 // FD to KernelHandle Map.
145 EXPECT_EQ(2, raw_handle->RefCount());
146 EXPECT_EQ(2, mnt->RefCount());
147 EXPECT_EQ(2, node->RefCount());
149 EXPECT_EQ(1, raw_handle->RefCount());
150 EXPECT_EQ(2, mnt->RefCount());
151 EXPECT_EQ(2, node->RefCount());
154 EXPECT_EQ(1, mnt->RefCount());
155 EXPECT_EQ(1, node->RefCount());
158 TEST_F(KernelObjectTest, FreeAndReassignFD) {
159 // The mount and node should have 1 ref count at this point
160 EXPECT_EQ(1, mnt->RefCount());
161 EXPECT_EQ(1, node->RefCount());
163 KernelHandle* raw_handle = new KernelHandleRefMock(mnt, node);
164 ScopedKernelHandle handle(raw_handle);
166 EXPECT_EQ(2, mnt->RefCount());
167 EXPECT_EQ(2, node->RefCount());
168 EXPECT_EQ(1, raw_handle->RefCount());
170 proxy.AllocateFD(handle);
171 EXPECT_EQ(2, mnt->RefCount());
172 EXPECT_EQ(2, node->RefCount());
173 EXPECT_EQ(2, raw_handle->RefCount());
175 proxy.FreeAndReassignFD(5, handle);
176 EXPECT_EQ(2, mnt->RefCount());
177 EXPECT_EQ(2, node->RefCount());
178 EXPECT_EQ(3, raw_handle->RefCount());
181 EXPECT_EQ(2, raw_handle->RefCount());
183 proxy.AcquireHandle(5, &handle);
184 EXPECT_EQ(3, raw_handle->RefCount());
185 EXPECT_EQ(raw_handle, handle.get());