Skip to content

Commit 610cf73

Browse files
vmagrometa-codesync[bot]
authored andcommitted
[antlir2][unprivileged_dir] tests for this package format
Summary: We had no tests for this, add some Test Plan: ``` ❯ buck2 test fbcode//antlir/antlir2/test_images/package/unprivileged_dir/... Buck UI: https://www.internalfb.com/buck2/a6dd557e-7df8-41de-bda4-979ad8cd0e00 Tests finished: Pass 1. Fail 0. Fatal 0. Skip 0. Omit 0. Infra Failure 0. Build failure 0 ``` https://www.internalfb.com/intern/testinfra/testrun/1970325171802203 ``` ❯ buck2 test fbcode//mode/opt fbcode//antlir/antlir2/test_images/package/unprivileged_dir/... Buck UI: https://www.internalfb.com/buck2/358f79fe-0d72-4246-8188-8e85ecf2ef88 Tests finished: Pass 1. Fail 0. Fatal 0. Skip 0. Omit 0. Infra Failure 0. Build failure 0 ``` https://www.internalfb.com/intern/testinfra/testrun/1970325171802311 Reviewed By: sergeyfd Differential Revision: D87681847 fbshipit-source-id: 83cae9ed5aad76fc41c9485562502a628779c01a
1 parent bb60a97 commit 610cf73

2 files changed

Lines changed: 142 additions & 0 deletions

File tree

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
load("//antlir/antlir2/bzl/feature:defs.bzl", "feature")
2+
load("//antlir/antlir2/bzl/image:defs.bzl", "image")
3+
load("//antlir/antlir2/bzl/package:defs.bzl", "package")
4+
load("//antlir/antlir2/testing:image_test.bzl", "image_python_test")
5+
6+
oncall("antlir")
7+
8+
package.unprivileged_dir(
9+
name = "test.unprivileged_dir",
10+
layer = "//antlir/antlir2/test_images/package:standard",
11+
)
12+
13+
image.layer(
14+
name = "test-layer",
15+
features = [
16+
feature.install(
17+
src = ":test.unprivileged_dir",
18+
dst = "/unprivileged_dir",
19+
),
20+
feature.rpms_install(rpms = [
21+
"bash",
22+
"coreutils",
23+
]),
24+
],
25+
)
26+
27+
image_python_test(
28+
name = "test-unprivileged_dir",
29+
srcs = ["test_unprivileged_dir.py"],
30+
layer = ":test-layer",
31+
deps = ["//later:lib"],
32+
)
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
#
3+
# This source code is licensed under the MIT license found in the
4+
# LICENSE file in the root directory of this source tree.
5+
6+
# pyre-strict
7+
8+
import importlib.resources
9+
import os
10+
import os.path
11+
import stat
12+
from pathlib import Path
13+
14+
from later.unittest import TestCase
15+
16+
17+
class TestUnprivilegedDir(TestCase):
18+
def setUp(self) -> None:
19+
self.maxDiff = None
20+
21+
def test_standard(self) -> None:
22+
# python_unittest resources are often (but not always and not entirely)
23+
# packaged up as a symlink tree. This makes looking at the actual
24+
# metadata of the underlying dir really hard...
25+
# So, we can compromise and still write a useful test by ensuring:
26+
# 1) all file/dir names we expect do exist
27+
# 2) an executable file is executable
28+
# 3) a symlink has the right target
29+
# 4) a file has the correct contents
30+
# 5) a large file has the correct number of bytes
31+
# 6) all files are owned by the unprivileged user
32+
path = Path("/unprivileged_dir")
33+
uid = os.getuid()
34+
gid = os.getgid()
35+
36+
root = Path(os.path.realpath(path))
37+
files = set()
38+
dirs = set()
39+
stats = {}
40+
for dirpath, dirnames, filenames in root.walk():
41+
for dirname in dirnames:
42+
item = dirpath / dirname
43+
dirs.add(str(item.relative_to(root)))
44+
try:
45+
stat_info = item.stat()
46+
except FileNotFoundError:
47+
stat_info = item.lstat()
48+
stats[str(item.relative_to(root))] = stat_info
49+
for filename in filenames:
50+
item = dirpath / filename
51+
files.add(str(item.relative_to(root)))
52+
try:
53+
stat_info = item.stat()
54+
except FileNotFoundError:
55+
stat_info = item.lstat()
56+
stats[str(item.relative_to(root))] = stat_info
57+
58+
# 1) all file/dir names we expect do exist
59+
self.assertEqual({"hardlink", "default-dir", ".meta"}, dirs)
60+
self.assertEqual(
61+
{
62+
"only-readable-by-root",
63+
"default-dir/relative-file-symlink",
64+
"absolute-dir-symlink",
65+
".meta/target",
66+
"i-have-xattrs",
67+
"i-have-caps",
68+
"i-am-owned-by-nonstandard",
69+
"absolute-file-symlink",
70+
"antlir2-large-file-256M",
71+
"hardlink/hello",
72+
"default-dir/executable",
73+
"hardlink/aloha",
74+
"relative-dir-symlink",
75+
},
76+
files,
77+
)
78+
79+
# 2) an executable file is executable
80+
self.assertEqual(
81+
"-r-xr-xr-x",
82+
stat.filemode(stats["default-dir/executable"].st_mode),
83+
"executable is not actually executable",
84+
)
85+
86+
# 3) a symlink has the right target
87+
try:
88+
target = (root / "absolute-file-symlink").resolve()
89+
self.assertEqual("/default-dir/executable", str(target))
90+
except FileNotFoundError as e:
91+
# packaging issues are weird...
92+
self.assertEqual("/default-dir/executable", e.filename)
93+
94+
# I can't figure out a sane way to check a relative symlink here...
95+
96+
# 4) a file has the correct contents
97+
with open(root / "hardlink/hello") as f:
98+
self.assertEqual("Hello world\n", f.read())
99+
100+
# 5) a large file has the correct number of bytes
101+
self.assertEqual(
102+
268435513,
103+
stats["antlir2-large-file-256M"].st_size,
104+
"large file was not copied fully",
105+
)
106+
107+
# 6) all files are owned by the unprivileged user
108+
for relpath, stat_info in stats.items():
109+
self.assertEqual(uid, stat_info.st_uid, f"{relpath} owned by wrong user")
110+
self.assertEqual(gid, stat_info.st_gid, f"{relpath} owned by wrong group")

0 commit comments

Comments
 (0)