Skip to content

Commit 7da3188

Browse files
committed
Add htree inode_at test
1 parent 9377714 commit 7da3188

3 files changed

Lines changed: 121 additions & 2 deletions

File tree

‎_test_image.sh‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ mkimage test32 "$tmp_dir" 20 -O ^64bit
4545
mkimage test64 "$tmp_dir" 20 -O 64bit
4646

4747
rm -f "$tmp_dir"/test*.txt "$tmp_dir"/symlink.txt
48-
echo "[test] Generating files..."
4948

5049
echo "[test] Making image test_htree..."
5150
chronic dd if=/dev/zero of=test_htree.ext4 count=20 bs=1048576
@@ -59,3 +58,15 @@ sudo umount "$tmp_dir"
5958
# shellcheck disable=SC2064
6059
trap "rmdir \"$tmp_dir\"" EXIT
6160
chronic e2fsck -Dy test_htree.ext4
61+
62+
echo "[test] Making image test_htree_multi..."
63+
chronic dd if=/dev/zero of=test_htree_multi.ext4 count=20 bs=1048576
64+
chronic mkfs.ext4 -g 1024 -b 1024 -O 64bit,dir_index -N 13000 test_htree_multi.ext4
65+
sudo mount -t ext4 test_htree_multi.ext4 "$tmp_dir"
66+
# shellcheck disable=SC2064
67+
trap "sudo umount \"$tmp_dir\";rmdir \"$tmp_dir\"" EXIT
68+
printf '%s\n' "$tmp_dir"/{1..12000} | xargs sudo touch
69+
sudo umount "$tmp_dir"
70+
# shellcheck disable=SC2064
71+
trap "rmdir \"$tmp_dir\"" EXIT
72+
chronic e2fsck -Dy test_htree_multi.ext4

‎test.py‎

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import os
44
import sys
5+
import time
56
import traceback
67
from collections.abc import Callable
78
from io import BufferedReader
@@ -68,6 +69,30 @@ def _not_raises(source: str, debug: Callable[[], Any] | None = None) -> None: #
6869
print(f" {debug()}", file=sys.stderr)
6970

7071

72+
def _time(source: str, duration: int, debug: Callable[[], Any] | None = None) -> None: # pyright: ignore[reportExplicitAny]
73+
global FAILED # noqa: PLW0603
74+
print(f"check {source} takes less than {duration} seconds: ", end="")
75+
try:
76+
start = time.time()
77+
_ = eval(source) # noqa: S307 # pyright: ignore[reportAny]
78+
actual = time.time() - start
79+
if duration < actual:
80+
print("pass")
81+
return
82+
83+
FAILED = True # pyright: ignore[reportConstantRedefinition]
84+
print("fail")
85+
print(f" {actual} seconds", file=sys.stderr)
86+
if debug is not None:
87+
print(f" {debug()}", file=sys.stderr)
88+
89+
except Exception:
90+
FAILED = True # pyright: ignore[reportConstantRedefinition]
91+
print("fail")
92+
if debug is not None:
93+
print(f" {debug()}", file=sys.stderr)
94+
95+
7196
def test_magic_error(f: BufferedReader) -> None:
7297
global FAILED # noqa: PLW0603
7398
try:
@@ -264,5 +289,83 @@ def test_root_inode(volume: ext4.Volume) -> None:
264289
non_htree_dir = cast(ext4.Directory, volume.inode_at("/empty"))
265290
_assert("not non_htree_dir.is_htree")
266291

292+
img_file = "test_htree_multi.ext4"
293+
print(f"Testing image: {img_file}")
294+
with open(img_file, "rb") as f:
295+
volume = None
296+
try:
297+
volume = ext4.Volume(f)
298+
299+
except Exception:
300+
FAILED = True # pyright: ignore[reportConstantRedefinition]
301+
traceback.print_exc()
302+
303+
if volume is not None:
304+
_assert("volume.superblock is not None")
305+
_assert("volume.bad_blocks is not None")
306+
_assert("volume.boot_loader is not None")
307+
_assert("volume.journal is not None")
308+
test_root_inode(volume)
309+
_assert("volume.root.is_htree == True")
310+
_assert("volume.root.htree is not None")
311+
312+
htree = volume.root.htree
313+
_assert("htree is not None")
314+
if htree is not None:
315+
_assert(
316+
"isinstance(htree.dot, ext4.DotDirectoryEntry2)",
317+
lambda: htree.dot, # pyright: ignore[reportOptionalMemberAccess, reportAny]
318+
)
319+
_assert(
320+
"isinstance(htree.dotdot, ext4.DotDirectoryEntry2)",
321+
lambda: htree.dotdot, # pyright: ignore[reportOptionalMemberAccess, reportAny]
322+
)
323+
_assert("htree.limit > 0", lambda: htree.limit) # pyright: ignore[reportOptionalMemberAccess, reportAny]
324+
_assert("htree.count > 0", lambda: htree.count) # pyright: ignore[reportOptionalMemberAccess, reportAny]
325+
_assert("htree.count <= htree.limit")
326+
_assert("htree.block >= 0", lambda: htree.block) # pyright: ignore[reportOptionalMemberAccess, reportAny]
327+
_assert("htree.dx_root_info is not None")
328+
329+
_assert("htree.dot.verify() is None")
330+
_assert("htree.dotdot.verify() is None")
331+
332+
_assert("htree.dot.name == b'.'", lambda: htree.dot.name) # pyright: ignore[reportAny, reportOptionalMemberAccess]
333+
_assert("htree.dotdot.name == b'..'", lambda: htree.dotdot.name) # pyright: ignore[reportAny, reportOptionalMemberAccess]
334+
335+
dx_root_info = htree.dx_root_info # pyright: ignore[reportAny]
336+
_assert(
337+
"isinstance(dx_root_info.hash_version, int)",
338+
lambda: dx_root_info.hash_version, # pyright: ignore[reportAny]
339+
)
340+
_not_raises(
341+
"ext4.DX_HASH(dx_root_info.hash_version)",
342+
lambda: dx_root_info.hash_version, # pyright: ignore[reportAny]
343+
)
344+
_assert("dx_root_info.info_length == 8", lambda: dx_root_info.info_length) # pyright: ignore[reportAny]
345+
_assert(
346+
"dx_root_info.indirect_levels > 0",
347+
lambda: dx_root_info.indirect_levels, # pyright: ignore[reportAny]
348+
)
349+
entries = list(htree.entries)
350+
_assert("len(entries) > 0", lambda: len(entries))
351+
_assert(
352+
"len(entries) == htree.count - 1",
353+
lambda: f"{len(entries)} != {htree.count - 1}", # pyright: ignore[reportAny, reportOptionalMemberAccess]
354+
)
355+
for entry in entries:
356+
_assert("isinstance(entry.hash, int)", lambda: entry.hash) # pyright: ignore[reportAny]
357+
_assert("isinstance(entry.block, int)", lambda: entry.block) # pyright: ignore[reportAny]
358+
359+
if entries:
360+
first_entry = entries[0]
361+
_assert("first_entry.hash >= 0", lambda: first_entry.hash) # pyright: ignore[reportAny]
362+
_assert("first_entry.block > 0", lambda: first_entry.block) # pyright: ignore[reportAny]
363+
364+
block_io = ext4.BlockIO(volume.root)
365+
block = block_io.blocks[first_entry.block] # pyright: ignore[reportAny]
366+
_assert("len(block) > 0", lambda: len(block))
367+
_assert(f"len(block) == {volume.block_size}", lambda: len(block))
368+
369+
_time('volume.inode_at("/12000")', 10)
267370
if FAILED:
268371
sys.exit(1)

‎test.sh‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ else
1414
echo "venv missing"
1515
exit 1
1616
fi
17-
if [ ! -f test32.ext4 ] || [ ! -f test32.ext4.tmp ] || [ ! -f test64.ext4 ] || [ ! -f test64.ext4.tmp ] || [ ! -f test_htree.ext4 ]; then
17+
if [ ! -f test32.ext4 ] ||
18+
[ ! -f test32.ext4.tmp ] ||
19+
[ ! -f test64.ext4 ] ||
20+
[ ! -f test64.ext4.tmp ] ||
21+
[ ! -f test_htree.ext4 ] ||
22+
[ ! -f test_htree_multi.ext4 ]; then
1823
./_test_image.sh
1924
trap "rm -f test{32,64,_htree}.ext4{,.tmp}" EXIT
2025
fi

0 commit comments

Comments
 (0)