1*ec63e07aSXin Li // Copyright 2019 Google LLC
2*ec63e07aSXin Li //
3*ec63e07aSXin Li // Licensed under the Apache License, Version 2.0 (the "License");
4*ec63e07aSXin Li // you may not use this file except in compliance with the License.
5*ec63e07aSXin Li // You may obtain a copy of the License at
6*ec63e07aSXin Li //
7*ec63e07aSXin Li // https://www.apache.org/licenses/LICENSE-2.0
8*ec63e07aSXin Li //
9*ec63e07aSXin Li // Unless required by applicable law or agreed to in writing, software
10*ec63e07aSXin Li // distributed under the License is distributed on an "AS IS" BASIS,
11*ec63e07aSXin Li // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*ec63e07aSXin Li // See the License for the specific language governing permissions and
13*ec63e07aSXin Li // limitations under the License.
14*ec63e07aSXin Li
15*ec63e07aSXin Li #include "sandboxed_api/sandbox2/mounts.h"
16*ec63e07aSXin Li
17*ec63e07aSXin Li #include <unistd.h>
18*ec63e07aSXin Li
19*ec63e07aSXin Li #include <cstddef>
20*ec63e07aSXin Li #include <string>
21*ec63e07aSXin Li #include <vector>
22*ec63e07aSXin Li
23*ec63e07aSXin Li #include "gmock/gmock.h"
24*ec63e07aSXin Li #include "gtest/gtest.h"
25*ec63e07aSXin Li #include "absl/status/status.h"
26*ec63e07aSXin Li #include "absl/strings/match.h"
27*ec63e07aSXin Li #include "absl/strings/str_cat.h"
28*ec63e07aSXin Li #include "sandboxed_api/testing.h"
29*ec63e07aSXin Li #include "sandboxed_api/util/path.h"
30*ec63e07aSXin Li #include "sandboxed_api/util/status_matchers.h"
31*ec63e07aSXin Li #include "sandboxed_api/util/temp_file.h"
32*ec63e07aSXin Li
33*ec63e07aSXin Li namespace sandbox2 {
34*ec63e07aSXin Li namespace {
35*ec63e07aSXin Li
36*ec63e07aSXin Li namespace file = ::sapi::file;
37*ec63e07aSXin Li using ::sapi::CreateNamedTempFileAndClose;
38*ec63e07aSXin Li using ::sapi::CreateTempDir;
39*ec63e07aSXin Li using ::sapi::GetTestSourcePath;
40*ec63e07aSXin Li using ::sapi::GetTestTempPath;
41*ec63e07aSXin Li using ::sapi::IsOk;
42*ec63e07aSXin Li using ::sapi::StatusIs;
43*ec63e07aSXin Li using ::testing::Eq;
44*ec63e07aSXin Li using ::testing::StrEq;
45*ec63e07aSXin Li using ::testing::UnorderedElementsAreArray;
46*ec63e07aSXin Li
47*ec63e07aSXin Li constexpr size_t kTmpfsSize = 1024;
48*ec63e07aSXin Li
TEST(MountTreeTest,TestInvalidFilenames)49*ec63e07aSXin Li TEST(MountTreeTest, TestInvalidFilenames) {
50*ec63e07aSXin Li Mounts mounts;
51*ec63e07aSXin Li
52*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile(""), StatusIs(absl::StatusCode::kInvalidArgument));
53*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("a"),
54*ec63e07aSXin Li StatusIs(absl::StatusCode::kInvalidArgument));
55*ec63e07aSXin Li EXPECT_THAT(mounts.AddFileAt("/a", ""),
56*ec63e07aSXin Li StatusIs(absl::StatusCode::kInvalidArgument));
57*ec63e07aSXin Li EXPECT_THAT(mounts.AddFileAt("", "/a"),
58*ec63e07aSXin Li StatusIs(absl::StatusCode::kInvalidArgument));
59*ec63e07aSXin Li EXPECT_THAT(mounts.AddFileAt("/a", "a"),
60*ec63e07aSXin Li StatusIs(absl::StatusCode::kInvalidArgument));
61*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("/"),
62*ec63e07aSXin Li StatusIs(absl::StatusCode::kInvalidArgument));
63*ec63e07aSXin Li EXPECT_THAT(mounts.AddFileAt("/a", "/"),
64*ec63e07aSXin Li StatusIs(absl::StatusCode::kInvalidArgument));
65*ec63e07aSXin Li EXPECT_THAT(mounts.Remove("/"), StatusIs(absl::StatusCode::kInvalidArgument));
66*ec63e07aSXin Li }
67*ec63e07aSXin Li
TEST(MountTreeTest,TestAddFile)68*ec63e07aSXin Li TEST(MountTreeTest, TestAddFile) {
69*ec63e07aSXin Li Mounts mounts;
70*ec63e07aSXin Li
71*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("/a"), IsOk());
72*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("/b"), IsOk());
73*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("/c/d"), IsOk());
74*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("/c/e"), IsOk());
75*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("/c/dd/e"), IsOk());
76*ec63e07aSXin Li
77*ec63e07aSXin Li EXPECT_THAT(mounts.AddFileAt("/a", "/f"), IsOk());
78*ec63e07aSXin Li }
79*ec63e07aSXin Li
TEST(MountTreeTest,TestAddDir)80*ec63e07aSXin Li TEST(MountTreeTest, TestAddDir) {
81*ec63e07aSXin Li Mounts mounts;
82*ec63e07aSXin Li
83*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectoryAt("/a", "/a"), IsOk());
84*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectoryAt("/c/d", "/c/d"), IsOk());
85*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectoryAt("/c/d/e", "/c/d/e"), IsOk());
86*ec63e07aSXin Li }
87*ec63e07aSXin Li
TEST(MountTreeTest,TestAddTmpFs)88*ec63e07aSXin Li TEST(MountTreeTest, TestAddTmpFs) {
89*ec63e07aSXin Li Mounts mounts;
90*ec63e07aSXin Li
91*ec63e07aSXin Li EXPECT_THAT(mounts.AddTmpfs("/a", kTmpfsSize), IsOk());
92*ec63e07aSXin Li EXPECT_THAT(mounts.AddTmpfs("/a/b", kTmpfsSize), IsOk());
93*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("/a/b/c"), IsOk());
94*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectoryAt("/a/b/d", "/a/b/d"), IsOk());
95*ec63e07aSXin Li }
96*ec63e07aSXin Li
TEST(MountTreeTest,TestRemove)97*ec63e07aSXin Li TEST(MountTreeTest, TestRemove) {
98*ec63e07aSXin Li Mounts mounts;
99*ec63e07aSXin Li EXPECT_THAT(mounts.AddTmpfs("/a", kTmpfsSize), IsOk());
100*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("/b/c/d"), IsOk());
101*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("/c/c/d"), IsOk());
102*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectoryAt("/d/b/d", "/d/b/d"), IsOk());
103*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectoryAt("/e/b/d", "/e/b/d"), IsOk());
104*ec63e07aSXin Li EXPECT_THAT(mounts.Remove("/a/b"), StatusIs(absl::StatusCode::kNotFound));
105*ec63e07aSXin Li EXPECT_THAT(mounts.Remove("/a"), IsOk());
106*ec63e07aSXin Li EXPECT_THAT(mounts.Remove("/b/c/d/e"), StatusIs(absl::StatusCode::kNotFound));
107*ec63e07aSXin Li EXPECT_THAT(mounts.Remove("/b/c/e"), StatusIs(absl::StatusCode::kNotFound));
108*ec63e07aSXin Li EXPECT_THAT(mounts.Remove("/b/c/d"), IsOk());
109*ec63e07aSXin Li EXPECT_THAT(mounts.Remove("/c"), IsOk());
110*ec63e07aSXin Li EXPECT_THAT(mounts.Remove("/d/b/d/e"), StatusIs(absl::StatusCode::kNotFound));
111*ec63e07aSXin Li EXPECT_THAT(mounts.Remove("/d/b/d"), IsOk());
112*ec63e07aSXin Li EXPECT_THAT(mounts.Remove("/e"), IsOk());
113*ec63e07aSXin Li EXPECT_THAT(mounts.Remove("/f"), StatusIs(absl::StatusCode::kNotFound));
114*ec63e07aSXin Li }
115*ec63e07aSXin Li
TEST(MountTreeTest,TestMultipleInsertionFileSymlink)116*ec63e07aSXin Li TEST(MountTreeTest, TestMultipleInsertionFileSymlink) {
117*ec63e07aSXin Li Mounts mounts;
118*ec63e07aSXin Li
119*ec63e07aSXin Li SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
120*ec63e07aSXin Li CreateNamedTempFileAndClose(
121*ec63e07aSXin Li file::JoinPath(GetTestTempPath(), "testdir_")));
122*ec63e07aSXin Li SAPI_ASSERT_OK_AND_ASSIGN(std::string symlink_path,
123*ec63e07aSXin Li CreateNamedTempFileAndClose(
124*ec63e07aSXin Li file::JoinPath(GetTestTempPath(), "testdir_")));
125*ec63e07aSXin Li
126*ec63e07aSXin Li ASSERT_THAT(unlink(symlink_path.c_str()), Eq(0));
127*ec63e07aSXin Li ASSERT_THAT(symlink(path.c_str(), symlink_path.c_str()), Eq(0));
128*ec63e07aSXin Li
129*ec63e07aSXin Li EXPECT_THAT(mounts.AddFileAt(path, "/a"), IsOk());
130*ec63e07aSXin Li EXPECT_THAT(mounts.AddFileAt(path, "/a"), IsOk());
131*ec63e07aSXin Li EXPECT_THAT(mounts.AddFileAt(symlink_path, "/a"), IsOk());
132*ec63e07aSXin Li }
133*ec63e07aSXin Li
TEST(MountTreeTest,TestMultipleInsertionUpgradeToWritable)134*ec63e07aSXin Li TEST(MountTreeTest, TestMultipleInsertionUpgradeToWritable) {
135*ec63e07aSXin Li Mounts mounts;
136*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("/a"), IsOk());
137*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("/a", /*is_ro=*/false), IsOk());
138*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectory("/b"), IsOk());
139*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectory("/b", /*is_ro=*/false), IsOk());
140*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("/c", /*is_ro=*/false), IsOk());
141*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("/c"), IsOk());
142*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectory("/d", /*is_ro=*/false), IsOk());
143*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectory("/d"), IsOk());
144*ec63e07aSXin Li }
145*ec63e07aSXin Li
TEST(MountTreeTest,TestMultipleInsertionDirSymlink)146*ec63e07aSXin Li TEST(MountTreeTest, TestMultipleInsertionDirSymlink) {
147*ec63e07aSXin Li Mounts mounts;
148*ec63e07aSXin Li
149*ec63e07aSXin Li SAPI_ASSERT_OK_AND_ASSIGN(
150*ec63e07aSXin Li std::string path,
151*ec63e07aSXin Li CreateTempDir(file::JoinPath(GetTestTempPath(), "testdir_")));
152*ec63e07aSXin Li SAPI_ASSERT_OK_AND_ASSIGN(std::string symlink_path,
153*ec63e07aSXin Li CreateNamedTempFileAndClose(
154*ec63e07aSXin Li file::JoinPath(GetTestTempPath(), "testdir_")));
155*ec63e07aSXin Li
156*ec63e07aSXin Li ASSERT_THAT(unlink(symlink_path.c_str()), Eq(0));
157*ec63e07aSXin Li ASSERT_THAT(symlink(path.c_str(), symlink_path.c_str()), Eq(0));
158*ec63e07aSXin Li
159*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectoryAt(path, "/a"), IsOk());
160*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectoryAt(path, "/a"), IsOk());
161*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectoryAt(symlink_path, "/a"), IsOk());
162*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectoryAt(symlink_path, "/a"), IsOk());
163*ec63e07aSXin Li }
164*ec63e07aSXin Li
TEST(MountTreeTest,TestMultipleInsertion)165*ec63e07aSXin Li TEST(MountTreeTest, TestMultipleInsertion) {
166*ec63e07aSXin Li Mounts mounts;
167*ec63e07aSXin Li
168*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("/c/d"), IsOk());
169*ec63e07aSXin Li
170*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("/c"),
171*ec63e07aSXin Li StatusIs(absl::StatusCode::kFailedPrecondition));
172*ec63e07aSXin Li EXPECT_THAT(mounts.AddFileAt("/f", "/c"),
173*ec63e07aSXin Li StatusIs(absl::StatusCode::kFailedPrecondition));
174*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectoryAt("/f", "/c"), IsOk());
175*ec63e07aSXin Li
176*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("/c/d/e"),
177*ec63e07aSXin Li StatusIs(absl::StatusCode::kFailedPrecondition));
178*ec63e07aSXin Li EXPECT_THAT(mounts.AddFileAt("/f", "/c/d/e"),
179*ec63e07aSXin Li StatusIs(absl::StatusCode::kFailedPrecondition));
180*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectoryAt("/f", "/c/d/e"),
181*ec63e07aSXin Li StatusIs(absl::StatusCode::kFailedPrecondition));
182*ec63e07aSXin Li }
183*ec63e07aSXin Li
TEST(MountTreeTest,TestEvilNullByte)184*ec63e07aSXin Li TEST(MountTreeTest, TestEvilNullByte) {
185*ec63e07aSXin Li Mounts mounts;
186*ec63e07aSXin Li // create the filename with a null byte this way as g4 fix forces newlines
187*ec63e07aSXin Li // otherwise.
188*ec63e07aSXin Li std::string filename = "/a/b";
189*ec63e07aSXin Li filename[2] = '\0';
190*ec63e07aSXin Li
191*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile(filename),
192*ec63e07aSXin Li StatusIs(absl::StatusCode::kInvalidArgument));
193*ec63e07aSXin Li EXPECT_THAT(mounts.AddFileAt(filename, "/a"),
194*ec63e07aSXin Li StatusIs(absl::StatusCode::kInvalidArgument));
195*ec63e07aSXin Li EXPECT_THAT(mounts.AddFileAt("/a", filename),
196*ec63e07aSXin Li StatusIs(absl::StatusCode::kInvalidArgument));
197*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectoryAt(filename, "/a"),
198*ec63e07aSXin Li StatusIs(absl::StatusCode::kInvalidArgument));
199*ec63e07aSXin Li EXPECT_THAT(mounts.AddDirectoryAt("/a", filename),
200*ec63e07aSXin Li StatusIs(absl::StatusCode::kInvalidArgument));
201*ec63e07aSXin Li EXPECT_THAT(mounts.AddTmpfs(filename, kTmpfsSize),
202*ec63e07aSXin Li StatusIs(absl::StatusCode::kInvalidArgument));
203*ec63e07aSXin Li EXPECT_THAT(mounts.Remove(filename),
204*ec63e07aSXin Li StatusIs(absl::StatusCode::kInvalidArgument));
205*ec63e07aSXin Li }
206*ec63e07aSXin Li
TEST(MountTreeTest,TestMinimalDynamicBinary)207*ec63e07aSXin Li TEST(MountTreeTest, TestMinimalDynamicBinary) {
208*ec63e07aSXin Li Mounts mounts;
209*ec63e07aSXin Li EXPECT_THAT(mounts.AddMappingsForBinary(
210*ec63e07aSXin Li GetTestSourcePath("sandbox2/testcases/minimal_dynamic")),
211*ec63e07aSXin Li IsOk());
212*ec63e07aSXin Li EXPECT_THAT(mounts.AddFile("/lib/x86_64-linux-gnu/libc.so.6"), IsOk());
213*ec63e07aSXin Li }
214*ec63e07aSXin Li
TEST(MountTreeTest,TestList)215*ec63e07aSXin Li TEST(MountTreeTest, TestList) {
216*ec63e07aSXin Li struct TestCase {
217*ec63e07aSXin Li const char* path;
218*ec63e07aSXin Li const bool is_ro;
219*ec63e07aSXin Li };
220*ec63e07aSXin Li // clang-format off
221*ec63e07aSXin Li constexpr TestCase kTestCases[] = {
222*ec63e07aSXin Li // NOTE: Directories have a trailing '/'; files don't.
223*ec63e07aSXin Li {"/a/b", true},
224*ec63e07aSXin Li {"/a/c/", true},
225*ec63e07aSXin Li {"/a/c/d/e/f/g", true},
226*ec63e07aSXin Li {"/h", true},
227*ec63e07aSXin Li {"/i/j/k", false},
228*ec63e07aSXin Li {"/i/l/", false},
229*ec63e07aSXin Li };
230*ec63e07aSXin Li // clang-format on
231*ec63e07aSXin Li
232*ec63e07aSXin Li Mounts mounts;
233*ec63e07aSXin Li
234*ec63e07aSXin Li // Create actual directories and files on disk and selectively add
235*ec63e07aSXin Li for (const auto& test_case : kTestCases) {
236*ec63e07aSXin Li const auto inside_path = test_case.path;
237*ec63e07aSXin Li const std::string outside_path = absl::StrCat("/some/dir/", inside_path);
238*ec63e07aSXin Li if (absl::EndsWith(outside_path, "/")) {
239*ec63e07aSXin Li ASSERT_THAT(
240*ec63e07aSXin Li mounts.AddDirectoryAt(file::CleanPath(outside_path),
241*ec63e07aSXin Li file::CleanPath(inside_path), test_case.is_ro),
242*ec63e07aSXin Li IsOk());
243*ec63e07aSXin Li } else {
244*ec63e07aSXin Li ASSERT_THAT(
245*ec63e07aSXin Li mounts.AddFileAt(file::CleanPath(outside_path),
246*ec63e07aSXin Li file::CleanPath(inside_path), test_case.is_ro),
247*ec63e07aSXin Li IsOk());
248*ec63e07aSXin Li }
249*ec63e07aSXin Li }
250*ec63e07aSXin Li
251*ec63e07aSXin Li ASSERT_THAT(mounts.AddTmpfs(file::CleanPath("/d"), 1024 * 1024), IsOk());
252*ec63e07aSXin Li
253*ec63e07aSXin Li std::vector<std::string> outside_entries;
254*ec63e07aSXin Li std::vector<std::string> inside_entries;
255*ec63e07aSXin Li mounts.RecursivelyListMounts(&outside_entries, &inside_entries);
256*ec63e07aSXin Li
257*ec63e07aSXin Li // clang-format off
258*ec63e07aSXin Li EXPECT_THAT(
259*ec63e07aSXin Li inside_entries,
260*ec63e07aSXin Li UnorderedElementsAreArray({
261*ec63e07aSXin Li "R /a/b",
262*ec63e07aSXin Li "R /a/c/",
263*ec63e07aSXin Li "R /a/c/d/e/f/g",
264*ec63e07aSXin Li "R /h",
265*ec63e07aSXin Li "W /i/j/k",
266*ec63e07aSXin Li "W /i/l/",
267*ec63e07aSXin Li "/d",
268*ec63e07aSXin Li }));
269*ec63e07aSXin Li EXPECT_THAT(
270*ec63e07aSXin Li outside_entries,
271*ec63e07aSXin Li UnorderedElementsAreArray({
272*ec63e07aSXin Li absl::StrCat("/some/dir/", "a/b"),
273*ec63e07aSXin Li absl::StrCat("/some/dir/", "a/c/"),
274*ec63e07aSXin Li absl::StrCat("/some/dir/", "a/c/d/e/f/g"),
275*ec63e07aSXin Li absl::StrCat("/some/dir/", "h"),
276*ec63e07aSXin Li absl::StrCat("/some/dir/", "i/j/k"),
277*ec63e07aSXin Li absl::StrCat("/some/dir/", "i/l/"),
278*ec63e07aSXin Li absl::StrCat("tmpfs: size=", 1024*1024),
279*ec63e07aSXin Li }));
280*ec63e07aSXin Li // clang-format on
281*ec63e07aSXin Li }
282*ec63e07aSXin Li
TEST(MountTreeTest,TestIsWritable)283*ec63e07aSXin Li TEST(MountTreeTest, TestIsWritable) {
284*ec63e07aSXin Li MountTree::Node nodes[7];
285*ec63e07aSXin Li MountTree::FileNode* fn0 = nodes[0].mutable_file_node();
286*ec63e07aSXin Li fn0->set_writable(false);
287*ec63e07aSXin Li fn0->set_outside("foo");
288*ec63e07aSXin Li MountTree::FileNode* fn1 = nodes[1].mutable_file_node();
289*ec63e07aSXin Li fn1->set_writable(true);
290*ec63e07aSXin Li fn1->set_outside("bar");
291*ec63e07aSXin Li MountTree::DirNode* dn0 = nodes[2].mutable_dir_node();
292*ec63e07aSXin Li dn0->set_writable(false);
293*ec63e07aSXin Li dn0->set_outside("foo");
294*ec63e07aSXin Li MountTree::DirNode* dn1 = nodes[3].mutable_dir_node();
295*ec63e07aSXin Li dn1->set_writable(true);
296*ec63e07aSXin Li dn1->set_outside("bar");
297*ec63e07aSXin Li MountTree::RootNode* rn0 = nodes[4].mutable_root_node();
298*ec63e07aSXin Li rn0->set_writable(false);
299*ec63e07aSXin Li MountTree::RootNode* rn1 = nodes[5].mutable_root_node();
300*ec63e07aSXin Li rn1->set_writable(true);
301*ec63e07aSXin Li MountTree::TmpfsNode* tn0 = nodes[6].mutable_tmpfs_node();
302*ec63e07aSXin Li tn0->set_tmpfs_options("option1");
303*ec63e07aSXin Li
304*ec63e07aSXin Li EXPECT_FALSE(internal::IsWritable(nodes[0]));
305*ec63e07aSXin Li EXPECT_TRUE(internal::IsWritable(nodes[1]));
306*ec63e07aSXin Li EXPECT_FALSE(internal::IsWritable(nodes[2]));
307*ec63e07aSXin Li EXPECT_TRUE(internal::IsWritable(nodes[3]));
308*ec63e07aSXin Li EXPECT_FALSE(internal::IsWritable(nodes[4]));
309*ec63e07aSXin Li EXPECT_TRUE(internal::IsWritable(nodes[5]));
310*ec63e07aSXin Li EXPECT_FALSE(internal::IsWritable(nodes[6]));
311*ec63e07aSXin Li }
312*ec63e07aSXin Li
TEST(MountTreeTest,TestHasSameTarget)313*ec63e07aSXin Li TEST(MountTreeTest, TestHasSameTarget) {
314*ec63e07aSXin Li MountTree::Node nodes[10];
315*ec63e07aSXin Li MountTree::FileNode* fn0 = nodes[0].mutable_file_node();
316*ec63e07aSXin Li fn0->set_writable(false);
317*ec63e07aSXin Li fn0->set_outside("foo");
318*ec63e07aSXin Li MountTree::FileNode* fn1 = nodes[1].mutable_file_node();
319*ec63e07aSXin Li fn1->set_writable(true);
320*ec63e07aSXin Li fn1->set_outside("foo");
321*ec63e07aSXin Li MountTree::FileNode* fn2 = nodes[2].mutable_file_node();
322*ec63e07aSXin Li fn2->set_writable(false);
323*ec63e07aSXin Li fn2->set_outside("bar");
324*ec63e07aSXin Li MountTree::DirNode* dn0 = nodes[3].mutable_dir_node();
325*ec63e07aSXin Li dn0->set_writable(false);
326*ec63e07aSXin Li dn0->set_outside("foo");
327*ec63e07aSXin Li MountTree::DirNode* dn1 = nodes[4].mutable_dir_node();
328*ec63e07aSXin Li dn1->set_writable(true);
329*ec63e07aSXin Li dn1->set_outside("foo");
330*ec63e07aSXin Li MountTree::DirNode* dn2 = nodes[5].mutable_dir_node();
331*ec63e07aSXin Li dn2->set_writable(false);
332*ec63e07aSXin Li dn2->set_outside("bar");
333*ec63e07aSXin Li MountTree::TmpfsNode* tn0 = nodes[6].mutable_tmpfs_node();
334*ec63e07aSXin Li tn0->set_tmpfs_options("option1");
335*ec63e07aSXin Li MountTree::TmpfsNode* tn1 = nodes[7].mutable_tmpfs_node();
336*ec63e07aSXin Li tn1->set_tmpfs_options("option2");
337*ec63e07aSXin Li MountTree::RootNode* rn0 = nodes[8].mutable_root_node();
338*ec63e07aSXin Li rn0->set_writable(false);
339*ec63e07aSXin Li MountTree::RootNode* rn1 = nodes[9].mutable_root_node();
340*ec63e07aSXin Li rn1->set_writable(true);
341*ec63e07aSXin Li
342*ec63e07aSXin Li // Compare same file nodes
343*ec63e07aSXin Li EXPECT_TRUE(internal::HasSameTarget(nodes[0], nodes[0]));
344*ec63e07aSXin Li // Compare almost same file nodes (ro vs rw)
345*ec63e07aSXin Li EXPECT_TRUE(internal::HasSameTarget(nodes[0], nodes[1]));
346*ec63e07aSXin Li // Compare different file nodes
347*ec63e07aSXin Li EXPECT_FALSE(internal::HasSameTarget(nodes[0], nodes[2]));
348*ec63e07aSXin Li // Compare file node with dir node
349*ec63e07aSXin Li EXPECT_FALSE(internal::HasSameTarget(nodes[0], nodes[3]));
350*ec63e07aSXin Li
351*ec63e07aSXin Li // Compare same dir nodes
352*ec63e07aSXin Li EXPECT_TRUE(internal::HasSameTarget(nodes[3], nodes[3]));
353*ec63e07aSXin Li // Compare almost same dir nodes (ro vs rw)
354*ec63e07aSXin Li EXPECT_TRUE(internal::HasSameTarget(nodes[3], nodes[4]));
355*ec63e07aSXin Li // Compare different dir nodes
356*ec63e07aSXin Li EXPECT_FALSE(internal::HasSameTarget(nodes[3], nodes[5]));
357*ec63e07aSXin Li // Compare dir node with tmpfs node
358*ec63e07aSXin Li EXPECT_FALSE(internal::HasSameTarget(nodes[3], nodes[6]));
359*ec63e07aSXin Li
360*ec63e07aSXin Li // Compare same tmpfs nodes
361*ec63e07aSXin Li EXPECT_TRUE(internal::HasSameTarget(nodes[6], nodes[6]));
362*ec63e07aSXin Li // Compare different tmpfs nodes
363*ec63e07aSXin Li EXPECT_FALSE(internal::HasSameTarget(nodes[6], nodes[7]));
364*ec63e07aSXin Li // Compare dir node with root node
365*ec63e07aSXin Li EXPECT_FALSE(internal::HasSameTarget(nodes[6], nodes[8]));
366*ec63e07aSXin Li
367*ec63e07aSXin Li // Compare same root nodes
368*ec63e07aSXin Li EXPECT_TRUE(internal::HasSameTarget(nodes[8], nodes[8]));
369*ec63e07aSXin Li // Compare almost same root nodes (ro vs rw)
370*ec63e07aSXin Li EXPECT_TRUE(internal::HasSameTarget(nodes[8], nodes[9]));
371*ec63e07aSXin Li }
372*ec63e07aSXin Li
TEST(MountTreeTest,TestNodeEquivalence)373*ec63e07aSXin Li TEST(MountTreeTest, TestNodeEquivalence) {
374*ec63e07aSXin Li MountTree::Node nodes[8];
375*ec63e07aSXin Li MountTree::FileNode* fn0 = nodes[0].mutable_file_node();
376*ec63e07aSXin Li fn0->set_writable(false);
377*ec63e07aSXin Li fn0->set_outside("foo");
378*ec63e07aSXin Li MountTree::FileNode* fn1 = nodes[1].mutable_file_node();
379*ec63e07aSXin Li fn1->set_writable(false);
380*ec63e07aSXin Li fn1->set_outside("bar");
381*ec63e07aSXin Li MountTree::DirNode* dn0 = nodes[2].mutable_dir_node();
382*ec63e07aSXin Li dn0->set_writable(false);
383*ec63e07aSXin Li dn0->set_outside("foo");
384*ec63e07aSXin Li MountTree::DirNode* dn1 = nodes[3].mutable_dir_node();
385*ec63e07aSXin Li dn1->set_writable(false);
386*ec63e07aSXin Li dn1->set_outside("bar");
387*ec63e07aSXin Li MountTree::TmpfsNode* tn0 = nodes[4].mutable_tmpfs_node();
388*ec63e07aSXin Li tn0->set_tmpfs_options("option1");
389*ec63e07aSXin Li MountTree::TmpfsNode* tn1 = nodes[5].mutable_tmpfs_node();
390*ec63e07aSXin Li tn1->set_tmpfs_options("option2");
391*ec63e07aSXin Li MountTree::RootNode* rn0 = nodes[6].mutable_root_node();
392*ec63e07aSXin Li rn0->set_writable(false);
393*ec63e07aSXin Li MountTree::RootNode* rn1 = nodes[7].mutable_root_node();
394*ec63e07aSXin Li rn1->set_writable(true);
395*ec63e07aSXin Li
396*ec63e07aSXin Li for (const MountTree::Node& n : nodes) {
397*ec63e07aSXin Li ASSERT_TRUE(n.IsInitialized());
398*ec63e07aSXin Li }
399*ec63e07aSXin Li // Compare same file nodes
400*ec63e07aSXin Li EXPECT_TRUE(internal::IsEquivalentNode(nodes[0], nodes[0]));
401*ec63e07aSXin Li // Compare with different file node
402*ec63e07aSXin Li EXPECT_FALSE(internal::IsEquivalentNode(nodes[0], nodes[1]));
403*ec63e07aSXin Li // compare file node with dir node
404*ec63e07aSXin Li EXPECT_FALSE(internal::IsEquivalentNode(nodes[0], nodes[2]));
405*ec63e07aSXin Li
406*ec63e07aSXin Li // Compare same dir nodes
407*ec63e07aSXin Li EXPECT_TRUE(internal::IsEquivalentNode(nodes[2], nodes[2]));
408*ec63e07aSXin Li // Compare with different dir node
409*ec63e07aSXin Li EXPECT_FALSE(internal::IsEquivalentNode(nodes[2], nodes[3]));
410*ec63e07aSXin Li // Compare dir node with tmpfs node
411*ec63e07aSXin Li EXPECT_FALSE(internal::IsEquivalentNode(nodes[2], nodes[4]));
412*ec63e07aSXin Li
413*ec63e07aSXin Li // Compare same tmpfs nodes
414*ec63e07aSXin Li EXPECT_TRUE(internal::IsEquivalentNode(nodes[4], nodes[4]));
415*ec63e07aSXin Li // Compare with different tmpfs nodes
416*ec63e07aSXin Li EXPECT_FALSE(internal::IsEquivalentNode(nodes[4], nodes[5]));
417*ec63e07aSXin Li // Compare tmpfs node with root node
418*ec63e07aSXin Li EXPECT_FALSE(internal::IsEquivalentNode(nodes[4], nodes[6]));
419*ec63e07aSXin Li
420*ec63e07aSXin Li // Compare same root nodes
421*ec63e07aSXin Li EXPECT_TRUE(internal::IsEquivalentNode(nodes[6], nodes[6]));
422*ec63e07aSXin Li // Compare different root node
423*ec63e07aSXin Li EXPECT_FALSE(internal::IsEquivalentNode(nodes[6], nodes[7]));
424*ec63e07aSXin Li // Compare root node with file node
425*ec63e07aSXin Li EXPECT_FALSE(internal::IsEquivalentNode(nodes[6], nodes[0]));
426*ec63e07aSXin Li }
427*ec63e07aSXin Li
TEST(MountsResolvePathTest,Files)428*ec63e07aSXin Li TEST(MountsResolvePathTest, Files) {
429*ec63e07aSXin Li Mounts mounts;
430*ec63e07aSXin Li ASSERT_THAT(mounts.AddFileAt("/A", "/a"), IsOk());
431*ec63e07aSXin Li ASSERT_THAT(mounts.AddFileAt("/B", "/d/b"), IsOk());
432*ec63e07aSXin Li ASSERT_THAT(mounts.AddFileAt("/C/D/E", "/d/c/e/f/h"), IsOk());
433*ec63e07aSXin Li std::string resolved;
434*ec63e07aSXin Li SAPI_ASSERT_OK_AND_ASSIGN(resolved, mounts.ResolvePath("/a"));
435*ec63e07aSXin Li EXPECT_THAT(resolved, StrEq("/A"));
436*ec63e07aSXin Li SAPI_ASSERT_OK_AND_ASSIGN(resolved, mounts.ResolvePath("/d/b"));
437*ec63e07aSXin Li EXPECT_THAT(resolved, StrEq("/B"));
438*ec63e07aSXin Li SAPI_ASSERT_OK_AND_ASSIGN(resolved, mounts.ResolvePath("/d/c/e/f/h"));
439*ec63e07aSXin Li EXPECT_THAT(resolved, StrEq("/C/D/E"));
440*ec63e07aSXin Li ASSERT_THAT(mounts.ResolvePath("/f"), StatusIs(absl::StatusCode::kNotFound));
441*ec63e07aSXin Li ASSERT_THAT(mounts.ResolvePath("/d"), StatusIs(absl::StatusCode::kNotFound));
442*ec63e07aSXin Li ASSERT_THAT(mounts.ResolvePath("/d/c/e/f"),
443*ec63e07aSXin Li StatusIs(absl::StatusCode::kNotFound));
444*ec63e07aSXin Li ASSERT_THAT(mounts.ResolvePath("/d/d"),
445*ec63e07aSXin Li StatusIs(absl::StatusCode::kNotFound));
446*ec63e07aSXin Li }
447*ec63e07aSXin Li
TEST(MountsResolvePathTest,Dirs)448*ec63e07aSXin Li TEST(MountsResolvePathTest, Dirs) {
449*ec63e07aSXin Li Mounts mounts;
450*ec63e07aSXin Li ASSERT_THAT(mounts.AddDirectoryAt("/A", "/a"), IsOk());
451*ec63e07aSXin Li ASSERT_THAT(mounts.AddDirectoryAt("/B", "/d/b"), IsOk());
452*ec63e07aSXin Li ASSERT_THAT(mounts.AddDirectoryAt("/C/D/E", "/d/c/e/f/h"), IsOk());
453*ec63e07aSXin Li ASSERT_THAT(mounts.AddFileAt("/J/G/H", "/d/c/e/f/h/j"), IsOk());
454*ec63e07aSXin Li ASSERT_THAT(mounts.AddDirectoryAt("/K/L/M", "/d/c/e/f/h/k"), IsOk());
455*ec63e07aSXin Li std::string resolved;
456*ec63e07aSXin Li SAPI_ASSERT_OK_AND_ASSIGN(resolved, mounts.ResolvePath("/a"));
457*ec63e07aSXin Li EXPECT_THAT(resolved, StrEq("/A"));
458*ec63e07aSXin Li SAPI_ASSERT_OK_AND_ASSIGN(resolved, mounts.ResolvePath("/a/b/c/d/e"));
459*ec63e07aSXin Li EXPECT_THAT(resolved, StrEq("/A/b/c/d/e"));
460*ec63e07aSXin Li SAPI_ASSERT_OK_AND_ASSIGN(resolved, mounts.ResolvePath("/d/b"));
461*ec63e07aSXin Li EXPECT_THAT(resolved, StrEq("/B"));
462*ec63e07aSXin Li SAPI_ASSERT_OK_AND_ASSIGN(resolved, mounts.ResolvePath("/d/c/e/f/h"));
463*ec63e07aSXin Li EXPECT_THAT(resolved, StrEq("/C/D/E"));
464*ec63e07aSXin Li SAPI_ASSERT_OK_AND_ASSIGN(resolved, mounts.ResolvePath("/d/c/e/f/h/i"));
465*ec63e07aSXin Li EXPECT_THAT(resolved, StrEq("/C/D/E/i"));
466*ec63e07aSXin Li SAPI_ASSERT_OK_AND_ASSIGN(resolved, mounts.ResolvePath("/d/c/e/f/h/j"));
467*ec63e07aSXin Li EXPECT_THAT(resolved, StrEq("/J/G/H"));
468*ec63e07aSXin Li SAPI_ASSERT_OK_AND_ASSIGN(resolved, mounts.ResolvePath("/d/c/e/f/h/k"));
469*ec63e07aSXin Li EXPECT_THAT(resolved, StrEq("/K/L/M"));
470*ec63e07aSXin Li SAPI_ASSERT_OK_AND_ASSIGN(resolved, mounts.ResolvePath("/d/c/e/f/h/k/a"));
471*ec63e07aSXin Li EXPECT_THAT(resolved, StrEq("/K/L/M/a"));
472*ec63e07aSXin Li ASSERT_THAT(mounts.ResolvePath("/f"), StatusIs(absl::StatusCode::kNotFound));
473*ec63e07aSXin Li ASSERT_THAT(mounts.ResolvePath("/d"), StatusIs(absl::StatusCode::kNotFound));
474*ec63e07aSXin Li ASSERT_THAT(mounts.ResolvePath("/d/c/e/f"),
475*ec63e07aSXin Li StatusIs(absl::StatusCode::kNotFound));
476*ec63e07aSXin Li ASSERT_THAT(mounts.ResolvePath("/d/d"),
477*ec63e07aSXin Li StatusIs(absl::StatusCode::kNotFound));
478*ec63e07aSXin Li }
479*ec63e07aSXin Li
480*ec63e07aSXin Li } // namespace
481*ec63e07aSXin Li } // namespace sandbox2
482