1414import pytest
1515from pyfakefs .fake_filesystem import FakeFileOpen , FakeFilesystem
1616
17- from xcp .cpiofile import CpioFile
17+ from xcp .cpiofile import CpioFile , StreamError
1818
1919binary_data = b"\x00 \x1b \x5b \x95 \xb1 \xb2 \xb3 \xb4 \xb5 \xb6 \xb7 \xb8 \xb9 \xcc \xdd \xee \xff "
2020
@@ -48,53 +48,79 @@ def test_cpiofile_modes(fs):
4848 if comp == "xz" and filetype == ":" :
4949 continue # streaming xz is not implemented (supported only as file)
5050 check_archive_mode (filetype + comp , fs )
51+ if filetype == "|" :
52+ check_archive_mode (filetype + comp , fs , filename = "archive." + comp )
5153
5254
53- def check_archive_mode ( archive_mode , fs ):
54- # type: (str, FakeFilesystem ) -> None
55+ def create_cpio_archive ( fs , archive_mode , filename = None ):
56+ # type: (FakeFilesystem, str, str | None ) -> io.BytesIO | None
5557 """
56- Test CpioFile in the given archive mode with verification of the archive contents .
58+ Create a CpioFile archive with files and directories from a FakeFilesystem .
5759
60+ :param fs: `FakeFilesystem` fixture representing a simulated file system for testing
5861 :param archive_mode: The archive mode is a string parameter that specifies the mode
5962 in which the CpioFile object should be opened.
60- :param fs: `FakeFilesystem` fixture representing a simulated file system for testing
63+ :param filename: The name of the file to create the cpio archive
6164 """
62- # Step 1: Create and populate a cpio archive in a BytesIO buffer
63- bytesio = io . BytesIO ()
64- archive = CpioFile .open (fileobj = bytesio , mode = "w" + archive_mode )
65- pyfakefs_populate_archive (archive , fs )
65+ cpiofile = None if filename else io . BytesIO ()
66+ fs . reset ()
67+ cpio = CpioFile .open (name = filename , fileobj = cpiofile , mode = "w" + archive_mode )
68+ pyfakefs_populate_archive (cpio , fs )
6669 if archive_mode == "|gz" :
67- archive .list (verbose = True )
68- archive .close ()
70+ cpio .list (verbose = True )
71+ cpio .close ()
72+ if not cpiofile :
73+ cpio_data = FakeFileOpen (fs )(filename , "rb" ).read ()
74+ fs .reset ()
75+ fs .create_file (filename , contents = cast (str , cpio_data ))
76+ return None
77+ fs .reset ()
78+ cpiofile .seek (0 )
79+ return cpiofile
80+
6981
82+ def check_archive_mode (archive_mode , fs , filename = None ):
83+ # type: (str, FakeFilesystem, str | None) -> None
84+ """
85+ Test CpioFile in the given archive mode with verification of the archive contents.
86+
87+ :param archive_mode: The archive mode is a string parameter that specifies the mode
88+ in which the CpioFile object should be opened.
89+ :param fs: `FakeFilesystem` fixture representing a simulated file system for testing
90+ """
7091 # Step 2: Extract the archive in a clean filesystem and verify the extracted contents
71- fs .reset ()
72- bytesio .seek (0 )
73- archive = CpioFile .open (fileobj = bytesio , mode = "r" + archive_mode )
92+ cpiofile = create_cpio_archive (fs , archive_mode , filename )
93+ archive = CpioFile .open (name = filename , fileobj = cpiofile , mode = "r" + archive_mode )
7494 archive .extractall ()
7595 pyfakefs_verify_filesystem (fs )
76- assert archive .getnames () == ["dirname" , "dirname/filename" , "dir2/symlink " ]
96+ assert archive .getnames () == ["dirname" , "dirname/filename" , "symlink" , " dir2/file_2 " ]
7797 dirs = [cpioinfo .name for cpioinfo in archive .getmembers () if cpioinfo .isdir ()]
7898 files = [cpioinfo .name for cpioinfo in archive .getmembers () if cpioinfo .isreg ()]
7999 symlinks = [cpioinfo .name for cpioinfo in archive .getmembers () if cpioinfo .issym ()]
80100 assert dirs == ["dirname" ]
81- assert files == ["dirname/filename" ]
82- assert symlinks == ["dir2/symlink" ]
83- assert archive .getmember (symlinks [0 ]).linkname == "symlink_target"
101+ assert files == ["dirname/filename" , "dir2/file_2" ]
102+ assert symlinks == ["symlink" ]
103+ assert archive .getmember (symlinks [0 ]).linkname == "dirname/filename"
104+
105+ # Test extracting a symlink to a file object:
106+ if archive_mode .startswith ("|" ): # Non-seekable streams raise StreamError
107+ with pytest .raises (StreamError ):
108+ archive .extractfile ("symlink" )
109+ else : # Expect a seekable fileobj for this test (not a stream) to work:
110+ fileobj = archive .extractfile ("symlink" )
111+ assert fileobj and fileobj .read () == binary_data
84112 archive .close ()
85113
86114 # Step 3: Extract the archive a second time using another method
87- fs .reset ()
88- bytesio .seek (0 )
89- archive = CpioFile .open (fileobj = bytesio , mode = "r" + archive_mode )
115+ cpiofile = create_cpio_archive (fs , archive_mode , filename )
116+ archive = CpioFile .open (name = filename , fileobj = cpiofile , mode = "r" + archive_mode )
90117 if archive_mode [0 ] != "|" :
91118 for cpioinfo in archive :
92119 archive .extract (cpioinfo )
93120 pyfakefs_verify_filesystem (fs )
94121 if archive_mode == "|xz" :
95122 archive .list (verbose = True )
96123 archive .close ()
97- bytesio .close ()
98124
99125
100126def pyfakefs_populate_archive (archive , fs ):
@@ -105,11 +131,12 @@ def pyfakefs_populate_archive(archive, fs):
105131 :param archive: Instance of the CpioFile class to create a new cpio archive
106132 :param fs: `FakeFilesystem` fixture representing a simulated file system for testing
107133 """
108- fs .reset ()
109134
110135 fs .create_file ("dirname/filename" , contents = cast (str , binary_data ))
111136 archive .add ("dirname" , recursive = True )
112- fs .create_symlink ("directory/symlink" , "symlink_target" )
137+ fs .create_file ("directory/file_2" , contents = cast (str , binary_data ))
138+ fs .create_symlink ("symlink" , "dirname/filename" )
139+ archive .add ("symlink" )
113140
114141 # Test special code path of archive.add(".", ...):
115142 os .chdir ("directory" )
@@ -129,7 +156,10 @@ def pyfakefs_verify_filesystem(fs):
129156
130157 :param fs: `FakeFilesystem` fixture representing a simulated file system for testing
131158 """
132- assert fs .islink ("dir2/ symlink" )
159+ assert fs .islink ("symlink" )
133160 assert fs .isfile ("dirname/filename" )
161+ assert fs .isfile ("dir2/file_2" )
134162 with FakeFileOpen (fs )("dirname/filename" , "rb" ) as contents :
135163 assert contents .read () == binary_data
164+ with FakeFileOpen (fs )("dir2/file_2" , "rb" ) as contents :
165+ assert contents .read () == binary_data
0 commit comments