@@ -34,141 +34,121 @@ def file_hash(path):
3434 return h .hexdigest ()
3535
3636
37- class TestArchive (unittest .TestCase ):
38- def _create_files (self , root ):
37+ @pytest .fixture
38+ def create_files (tmp_path ):
39+
40+ def inner ():
3941 files = {}
4042 for i in range (10 ):
41- p = os .path .join (root , f"file{ i :02d} " )
42- with open (p , "wb" ) as fh :
43- fh .write (b"file%02d" % i )
43+ p = tmp_path / f"file{ i :02d} "
44+ p .write_bytes (b"file%02d" % i )
4445 # Need to set permissions or umask may influence testing.
45- os .chmod (p , MODE_STANDARD )
46- files [f"file{ i :02d} " ] = p
46+ p .chmod (MODE_STANDARD )
47+ files [f"file{ i :02d} " ] = str ( p )
4748
4849 for i in range (10 ):
4950 files [f"file{ i + 10 :02d} " ] = io .BytesIO (b"file%02d" % (i + 10 ))
5051
5152 return files
5253
53- def _verify_basic_tarfile (self , tf ):
54- self .assertEqual (len (tf .getmembers ()), 20 )
55-
56- names = [f"file{ i :02d} " for i in range (20 )]
57- self .assertEqual (tf .getnames (), names )
58-
59- for ti in tf .getmembers ():
60- self .assertEqual (ti .uid , 0 )
61- self .assertEqual (ti .gid , 0 )
62- self .assertEqual (ti .uname , "" )
63- self .assertEqual (ti .gname , "" )
64- self .assertEqual (ti .mode , MODE_STANDARD )
65- self .assertEqual (ti .mtime , DEFAULT_MTIME )
66-
67- @pytest .mark .xfail (
68- reason = "ValueError is not thrown despite being provided directory."
69- )
70- def test_dirs_refused (self ):
71- d = tempfile .mkdtemp ()
72- try :
73- tp = os .path .join (d , "test.tar" )
74- with open (tp , "wb" ) as fh :
75- with self .assertRaisesRegex (ValueError , "not a regular" ):
76- create_tar_from_files (fh , {"test" : d })
77- finally :
78- shutil .rmtree (d )
79-
80- def test_setuid_setgid_refused (self ):
81- d = tempfile .mkdtemp ()
82- try :
83- uid = os .path .join (d , "setuid" )
84- gid = os .path .join (d , "setgid" )
85- with open (uid , "a" ):
86- pass
87- with open (gid , "a" ):
88- pass
89-
90- os .chmod (uid , MODE_STANDARD | stat .S_ISUID )
91- os .chmod (gid , MODE_STANDARD | stat .S_ISGID )
92-
93- tp = os .path .join (d , "test.tar" )
94- with open (tp , "wb" ) as fh :
95- with self .assertRaisesRegex (ValueError , "cannot add file with setuid" ):
96- create_tar_from_files (fh , {"test" : uid })
97- with self .assertRaisesRegex (ValueError , "cannot add file with setuid" ):
98- create_tar_from_files (fh , {"test" : gid })
99- finally :
100- shutil .rmtree (d )
101-
102- def test_create_tar_basic (self ):
103- d = tempfile .mkdtemp ()
104- try :
105- files = self ._create_files (d )
106-
107- tp = os .path .join (d , "test.tar" )
108- with open (tp , "wb" ) as fh :
109- create_tar_from_files (fh , files )
110-
111- # Output should be deterministic.
112- self .assertEqual (file_hash (tp ), "01cd314e277f060e98c7de6c8ea57f96b3a2065c" )
113-
114- with tarfile .open (tp , "r" ) as tf :
115- self ._verify_basic_tarfile (tf )
116-
117- finally :
118- shutil .rmtree (d )
119-
120- @pytest .mark .xfail (reason = "hash mismatch" )
121- def test_executable_preserved (self ):
122- d = tempfile .mkdtemp ()
123- try :
124- p = os .path .join (d , "exec" )
125- with open (p , "wb" ) as fh :
126- fh .write ("#!/bin/bash\n " )
127- os .chmod (p , MODE_STANDARD | stat .S_IXUSR )
128-
129- tp = os .path .join (d , "test.tar" )
130- with open (tp , "wb" ) as fh :
131- create_tar_from_files (fh , {"exec" : p })
132-
133- self .assertEqual (file_hash (tp ), "357e1b81c0b6cfdfa5d2d118d420025c3c76ee93" )
134-
135- with tarfile .open (tp , "r" ) as tf :
136- m = tf .getmember ("exec" )
137- self .assertEqual (m .mode , MODE_STANDARD | stat .S_IXUSR )
138-
139- finally :
140- shutil .rmtree (d )
141-
142- def test_create_tar_gz_basic (self ):
143- d = tempfile .mkdtemp ()
144- try :
145- files = self ._create_files (d )
146-
147- gp = os .path .join (d , "test.tar.gz" )
148- with open (gp , "wb" ) as fh :
149- create_tar_gz_from_files (fh , files )
150-
151- self .assertEqual (file_hash (gp ), "7c4da5adc5088cdf00911d5daf9a67b15de714b7" )
152-
153- with tarfile .open (gp , "r:gz" ) as tf :
154- self ._verify_basic_tarfile (tf )
155-
156- finally :
157- shutil .rmtree (d )
158-
159- def test_tar_gz_name (self ):
160- d = tempfile .mkdtemp ()
161- try :
162- files = self ._create_files (d )
163-
164- gp = os .path .join (d , "test.tar.gz" )
165- with open (gp , "wb" ) as fh :
166- create_tar_gz_from_files (fh , files , filename = "foobar" )
167-
168- self .assertEqual (file_hash (gp ), "721e00083c17d16df2edbddf40136298c06d0c49" )
169-
170- with tarfile .open (gp , "r:gz" ) as tf :
171- self ._verify_basic_tarfile (tf )
172-
173- finally :
174- shutil .rmtree (d )
54+ return inner
55+
56+
57+ def verify_basic_tarfile (tf ):
58+ assert len (tf .getmembers ()) == 20
59+
60+ names = [f"file{ i :02d} " for i in range (20 )]
61+ assert tf .getnames () == names
62+
63+ for ti in tf .getmembers ():
64+ assert ti .uid == 0
65+ assert ti .gid == 0
66+ assert ti .uname == ""
67+ assert ti .gname == ""
68+ assert ti .mode == MODE_STANDARD
69+ assert ti .mtime == DEFAULT_MTIME
70+
71+
72+ @pytest .mark .xfail (
73+ reason = "ValueError is not thrown despite being provided directory."
74+ )
75+ def test_dirs_refused (tmp_path ):
76+ tp = tmp_path / "test.tar"
77+ with open (tp , "wb" ) as fh :
78+ with pytest .raises (ValueError , match = "not a regular" ):
79+ create_tar_from_files (fh , {"test" : str (tmp_path )})
80+
81+
82+ def test_setuid_setgid_refused (tmp_path ):
83+ uid = tmp_path / "setuid"
84+ uid .touch ()
85+ uid .chmod (MODE_STANDARD | stat .S_ISUID )
86+
87+ gid = tmp_path / "setgid"
88+ gid .touch ()
89+ gid .chmod (MODE_STANDARD | stat .S_ISGID )
90+
91+ tp = tmp_path / "test.tar"
92+ with open (tp , "wb" ) as fh :
93+ with pytest .raises (ValueError , match = "cannot add file with setuid" ):
94+ create_tar_from_files (fh , {"test" : str (uid )})
95+ with pytest .raises (ValueError , match = "cannot add file with setuid" ):
96+ create_tar_from_files (fh , {"test" : str (gid )})
97+
98+
99+ def test_create_tar_basic (tmp_path , create_files ):
100+ files = create_files ()
101+
102+ tp = tmp_path / "test.tar"
103+ with open (tp , "wb" ) as fh :
104+ create_tar_from_files (fh , files )
105+
106+ # Output should be deterministic.
107+ assert file_hash (tp ) == "01cd314e277f060e98c7de6c8ea57f96b3a2065c"
108+
109+ with tarfile .open (tp , "r" ) as tf :
110+ verify_basic_tarfile (tf )
111+
112+
113+ @pytest .mark .xfail (reason = "hash mismatch" )
114+ def test_executable_preserved ():
115+ p = os .path .join (d , "exec" )
116+ with open (p , "wb" ) as fh :
117+ fh .write (b"#!/bin/bash\n " )
118+ os .chmod (p , MODE_STANDARD | stat .S_IXUSR )
119+
120+ tp = os .path .join (d , "test.tar" )
121+ with open (tp , "wb" ) as fh :
122+ create_tar_from_files (fh , {"exec" : p })
123+
124+ assert file_hash (tp ) == "357e1b81c0b6cfdfa5d2d118d420025c3c76ee93"
125+
126+ with tarfile .open (tp , "r" ) as tf :
127+ m = tf .getmember ("exec" )
128+ assert m .mode == MODE_STANDARD | stat .S_IXUSR
129+
130+
131+ def test_create_tar_gz_basic (tmp_path , create_files ):
132+ files = create_files ()
133+
134+ gp = tmp_path / "test.tar.gz"
135+ with open (gp , "wb" ) as fh :
136+ create_tar_gz_from_files (fh , files )
137+
138+ assert file_hash (gp ) == "7c4da5adc5088cdf00911d5daf9a67b15de714b7"
139+
140+ with tarfile .open (gp , "r:gz" ) as tf :
141+ verify_basic_tarfile (tf )
142+
143+
144+ def test_tar_gz_name (tmp_path , create_files ):
145+ files = create_files ()
146+
147+ gp = tmp_path / "test.tar.gz"
148+ with open (gp , "wb" ) as fh :
149+ create_tar_gz_from_files (fh , files , filename = "foobar" )
150+
151+ assert file_hash (gp ) == "721e00083c17d16df2edbddf40136298c06d0c49"
152+
153+ with tarfile .open (gp , "r:gz" ) as tf :
154+ verify_basic_tarfile (tf )
0 commit comments