12
12
# See the License for the specific language governing permissions and
13
13
# limitations under the License.
14
14
15
+ import hashlib
15
16
import os
16
17
import platform
17
18
import subprocess
@@ -43,9 +44,29 @@ def _get_path(self, filename):
43
44
else :
44
45
return path
45
46
47
+ def assertFileSha256Equal (self , filename , sha ):
48
+ hash = hashlib .sha256 ()
49
+ with open (filename , "rb" ) as f :
50
+ while True :
51
+ buf = f .read (2 ** 20 )
52
+ if not buf :
53
+ break
54
+ hash .update (buf )
55
+ self .assertEqual (hash .hexdigest (), sha )
56
+
57
+ def assertAllEntriesHasReproducibleMetadata (self , zf ):
58
+ for zinfo in zf .infolist ():
59
+ self .assertEqual (zinfo .date_time , (1980 , 1 , 1 , 0 , 0 , 0 ), msg = zinfo .filename )
60
+ self .assertEqual (zinfo .create_system , 3 , msg = zinfo .filename )
61
+ self .assertEqual (zinfo .external_attr , 0o777 << 16 , msg = zinfo .filename )
62
+ self .assertEqual (
63
+ zinfo .compress_type , zipfile .ZIP_DEFLATED , msg = zinfo .filename
64
+ )
65
+
46
66
def test_py_library_wheel (self ):
47
67
filename = self ._get_path ("example_minimal_library-0.0.1-py3-none-any.whl" )
48
68
with zipfile .ZipFile (filename ) as zf :
69
+ self .assertAllEntriesHasReproducibleMetadata (zf )
49
70
self .assertEqual (
50
71
zf .namelist (),
51
72
[
@@ -56,12 +77,16 @@ def test_py_library_wheel(self):
56
77
"example_minimal_library-0.0.1.dist-info/RECORD" ,
57
78
],
58
79
)
80
+ self .assertFileSha256Equal (
81
+ filename , "6da8e06a3fdd9ae5ee9fa8f796610723c05a4b0d7fde0ec5179401e956204139"
82
+ )
59
83
60
84
def test_py_package_wheel (self ):
61
85
filename = self ._get_path (
62
86
"example_minimal_package-0.0.1-py3-none-any.whl" ,
63
87
)
64
88
with zipfile .ZipFile (filename ) as zf :
89
+ self .assertAllEntriesHasReproducibleMetadata (zf )
65
90
self .assertEqual (
66
91
zf .namelist (),
67
92
[
@@ -74,12 +99,16 @@ def test_py_package_wheel(self):
74
99
"example_minimal_package-0.0.1.dist-info/RECORD" ,
75
100
],
76
101
)
102
+ self .assertFileSha256Equal (
103
+ filename , "2948b0b5e0aa421e0b40f78b74018bbc2f218165f211da0a4609e431e8e52bee"
104
+ )
77
105
78
106
def test_customized_wheel (self ):
79
107
filename = self ._get_path (
80
108
"example_customized-0.0.1-py3-none-any.whl" ,
81
109
)
82
110
with zipfile .ZipFile (filename ) as zf :
111
+ self .assertAllEntriesHasReproducibleMetadata (zf )
83
112
self .assertEqual (
84
113
zf .namelist (),
85
114
[
@@ -159,12 +188,16 @@ def test_customized_wheel(self):
159
188
first = first.main:f
160
189
second = second.main:s""" ,
161
190
)
191
+ self .assertFileSha256Equal (
192
+ filename , "66f0c1bfe2cedb2f4cf08d4fe955096860186c0a2f3524e0cb02387a55ac3e63"
193
+ )
162
194
163
195
def test_legacy_filename_escaping (self ):
164
196
filename = self ._get_path (
165
197
"file_name_escaping-0.0.1_r7-py3-none-any.whl" ,
166
198
)
167
199
with zipfile .ZipFile (filename ) as zf :
200
+ self .assertAllEntriesHasReproducibleMetadata (zf )
168
201
self .assertEquals (
169
202
zf .namelist (),
170
203
[
@@ -193,6 +226,9 @@ def test_legacy_filename_escaping(self):
193
226
UNKNOWN
194
227
""" ,
195
228
)
229
+ self .assertFileSha256Equal (
230
+ filename , "593c6ab58627f2446d0f1ef2956fd6d42104eedce4493c72d462f7ebf8cb74fa"
231
+ )
196
232
197
233
def test_filename_escaping (self ):
198
234
filename = self ._get_path (
@@ -234,6 +270,7 @@ def test_custom_package_root_wheel(self):
234
270
)
235
271
236
272
with zipfile .ZipFile (filename ) as zf :
273
+ self .assertAllEntriesHasReproducibleMetadata (zf )
237
274
self .assertEqual (
238
275
zf .namelist (),
239
276
[
@@ -255,13 +292,17 @@ def test_custom_package_root_wheel(self):
255
292
# Ensure RECORD files do not have leading forward slashes
256
293
for line in record_contents .splitlines ():
257
294
self .assertFalse (line .startswith ("/" ))
295
+ self .assertFileSha256Equal (
296
+ filename , "1b1fa3a4e840211084ef80049d07947b845c99bedb2778496d30e0c1524686ac"
297
+ )
258
298
259
299
def test_custom_package_root_multi_prefix_wheel (self ):
260
300
filename = self ._get_path (
261
301
"example_custom_package_root_multi_prefix-0.0.1-py3-none-any.whl" ,
262
302
)
263
303
264
304
with zipfile .ZipFile (filename ) as zf :
305
+ self .assertAllEntriesHasReproducibleMetadata (zf )
265
306
self .assertEqual (
266
307
zf .namelist (),
267
308
[
@@ -282,13 +323,17 @@ def test_custom_package_root_multi_prefix_wheel(self):
282
323
# Ensure RECORD files do not have leading forward slashes
283
324
for line in record_contents .splitlines ():
284
325
self .assertFalse (line .startswith ("/" ))
326
+ self .assertFileSha256Equal (
327
+ filename , "f0422d7a338de3c76bf2525927fd93c0f47f2e9c60ecc0944e3e32b642c28137"
328
+ )
285
329
286
330
def test_custom_package_root_multi_prefix_reverse_order_wheel (self ):
287
331
filename = self ._get_path (
288
332
"example_custom_package_root_multi_prefix_reverse_order-0.0.1-py3-none-any.whl" ,
289
333
)
290
334
291
335
with zipfile .ZipFile (filename ) as zf :
336
+ self .assertAllEntriesHasReproducibleMetadata (zf )
292
337
self .assertEqual (
293
338
zf .namelist (),
294
339
[
@@ -309,12 +354,16 @@ def test_custom_package_root_multi_prefix_reverse_order_wheel(self):
309
354
# Ensure RECORD files do not have leading forward slashes
310
355
for line in record_contents .splitlines ():
311
356
self .assertFalse (line .startswith ("/" ))
357
+ self .assertFileSha256Equal (
358
+ filename , "4f9e8c917b4050f121ac81e9a2bb65723ef09a1b90b35d93792ac3a62a60efa3"
359
+ )
312
360
313
361
def test_python_requires_wheel (self ):
314
362
filename = self ._get_path (
315
363
"example_python_requires_in_a_package-0.0.1-py3-none-any.whl" ,
316
364
)
317
365
with zipfile .ZipFile (filename ) as zf :
366
+ self .assertAllEntriesHasReproducibleMetadata (zf )
318
367
metadata_contents = zf .read (
319
368
"example_python_requires_in_a_package-0.0.1.dist-info/METADATA"
320
369
)
@@ -330,6 +379,9 @@ def test_python_requires_wheel(self):
330
379
UNKNOWN
331
380
""" ,
332
381
)
382
+ self .assertFileSha256Equal (
383
+ filename , "9bfe8197d379f88715458a75e45c1f521a8b9d3cc43fe19b407c4ab207228b7c"
384
+ )
333
385
334
386
def test_python_abi3_binary_wheel (self ):
335
387
arch = "amd64"
@@ -346,6 +398,7 @@ def test_python_abi3_binary_wheel(self):
346
398
f"example_python_abi3_binary_wheel-0.0.1-cp38-abi3-{ os_string } _{ arch } .whl" ,
347
399
)
348
400
with zipfile .ZipFile (filename ) as zf :
401
+ self .assertAllEntriesHasReproducibleMetadata (zf )
349
402
metadata_contents = zf .read (
350
403
"example_python_abi3_binary_wheel-0.0.1.dist-info/METADATA"
351
404
)
@@ -380,6 +433,7 @@ def test_rule_creates_directory_and_is_included_in_wheel(self):
380
433
)
381
434
382
435
with zipfile .ZipFile (filename ) as zf :
436
+ self .assertAllEntriesHasReproducibleMetadata (zf )
383
437
self .assertEqual (
384
438
zf .namelist (),
385
439
[
@@ -390,13 +444,17 @@ def test_rule_creates_directory_and_is_included_in_wheel(self):
390
444
"use_rule_with_dir_in_outs-0.0.1.dist-info/RECORD" ,
391
445
],
392
446
)
447
+ self .assertFileSha256Equal (
448
+ filename , "8ad5f639cc41ac6ac67eb70f6553a7fdecabaf3a1b952c3134eaea59610c2a64"
449
+ )
393
450
394
451
def test_rule_expands_workspace_status_keys_in_wheel_metadata (self ):
395
452
filename = self ._get_path (
396
453
"example_minimal_library_BUILD_USER_-0.1._BUILD_TIMESTAMP_-py3-none-any.whl"
397
454
)
398
455
399
456
with zipfile .ZipFile (filename ) as zf :
457
+ self .assertAllEntriesHasReproducibleMetadata (zf )
400
458
metadata_file = None
401
459
for f in zf .namelist ():
402
460
self .assertNotIn ("_BUILD_TIMESTAMP_" , f )
0 commit comments