2020-07-01 13:22:24 +01:00
|
|
|
import platform
|
2020-07-10 12:46:32 +01:00
|
|
|
import random
|
|
|
|
|
import shutil
|
2020-06-26 21:37:02 +01:00
|
|
|
import subprocess
|
|
|
|
|
import textwrap
|
2020-07-10 13:04:50 +01:00
|
|
|
from pathlib import Path, PurePath
|
2020-06-26 21:37:02 +01:00
|
|
|
|
2020-06-26 21:41:00 +01:00
|
|
|
import pytest
|
|
|
|
|
|
|
|
|
|
from cibuildwheel.docker_container import DockerContainer
|
2020-07-20 02:23:07 +02:00
|
|
|
from cibuildwheel.environment import EnvironmentAssignment
|
2020-06-26 21:41:00 +01:00
|
|
|
|
2020-07-08 22:56:33 +01:00
|
|
|
# for these tests we use manylinux2014 images, because they're available on
|
|
|
|
|
# multi architectures and include python3.8
|
2020-07-01 13:22:24 +01:00
|
|
|
pm = platform.machine()
|
|
|
|
|
if pm == "x86_64":
|
2020-07-08 22:56:33 +01:00
|
|
|
DEFAULT_IMAGE = 'quay.io/pypa/manylinux2014_x86_64:2020-05-17-2f8ac3b'
|
2020-07-01 13:22:24 +01:00
|
|
|
elif pm == "aarch64":
|
2020-07-08 22:56:33 +01:00
|
|
|
DEFAULT_IMAGE = 'quay.io/pypa/manylinux2014_aarch64:2020-05-17-2f8ac3b'
|
2020-07-01 13:22:24 +01:00
|
|
|
elif pm == "ppc64le":
|
2020-07-08 22:56:33 +01:00
|
|
|
DEFAULT_IMAGE = 'quay.io/pypa/manylinux2014_ppc64le:2020-05-17-2f8ac3b'
|
2020-07-01 13:22:24 +01:00
|
|
|
elif pm == "s390x":
|
2020-07-08 22:56:33 +01:00
|
|
|
DEFAULT_IMAGE = 'quay.io/pypa/manylinux2014_s390x:2020-05-17-2f8ac3b'
|
2020-06-26 21:37:02 +01:00
|
|
|
|
2020-06-26 21:41:00 +01:00
|
|
|
|
2020-06-28 10:53:03 +01:00
|
|
|
@pytest.mark.docker
|
2020-06-26 21:37:02 +01:00
|
|
|
def test_simple():
|
|
|
|
|
with DockerContainer(DEFAULT_IMAGE) as container:
|
|
|
|
|
assert container.call(['echo', 'hello'], capture_output=True) == 'hello\n'
|
|
|
|
|
|
2020-06-26 21:41:00 +01:00
|
|
|
|
2020-06-28 10:53:03 +01:00
|
|
|
@pytest.mark.docker
|
2020-06-26 21:37:02 +01:00
|
|
|
def test_no_lf():
|
|
|
|
|
with DockerContainer(DEFAULT_IMAGE) as container:
|
|
|
|
|
assert container.call(['printf', 'hello'], capture_output=True) == 'hello'
|
|
|
|
|
|
2020-06-26 21:41:00 +01:00
|
|
|
|
2020-06-28 10:53:03 +01:00
|
|
|
@pytest.mark.docker
|
2020-06-26 21:37:02 +01:00
|
|
|
def test_environment():
|
|
|
|
|
with DockerContainer(DEFAULT_IMAGE) as container:
|
|
|
|
|
assert container.call(['sh', '-c', 'echo $TEST_VAR'], env={'TEST_VAR': '1'}, capture_output=True) == '1\n'
|
|
|
|
|
|
2020-06-26 21:41:00 +01:00
|
|
|
|
2020-07-20 01:04:26 +02:00
|
|
|
@pytest.mark.docker
|
|
|
|
|
def test_cwd():
|
|
|
|
|
with DockerContainer(DEFAULT_IMAGE, cwd='/cibuildwheel/working_directory') as container:
|
|
|
|
|
assert container.call(['pwd'], capture_output=True) == '/cibuildwheel/working_directory\n'
|
|
|
|
|
assert container.call(['pwd'], capture_output=True, cwd='/opt') == '/opt\n'
|
|
|
|
|
|
|
|
|
|
|
2020-06-28 10:53:03 +01:00
|
|
|
@pytest.mark.docker
|
2020-06-26 21:37:02 +01:00
|
|
|
def test_container_removed():
|
|
|
|
|
with DockerContainer(DEFAULT_IMAGE) as container:
|
2020-06-26 21:47:42 +01:00
|
|
|
docker_containers_listing = subprocess.run('docker container ls', shell=True, check=True, stdout=subprocess.PIPE, universal_newlines=True).stdout
|
2020-06-26 21:37:02 +01:00
|
|
|
assert container.name in docker_containers_listing
|
|
|
|
|
old_container_name = container.name
|
|
|
|
|
|
2020-06-26 21:47:42 +01:00
|
|
|
docker_containers_listing = subprocess.run('docker container ls', shell=True, check=True, stdout=subprocess.PIPE, universal_newlines=True).stdout
|
2020-06-26 21:37:02 +01:00
|
|
|
assert old_container_name not in docker_containers_listing
|
|
|
|
|
|
2020-06-26 21:41:00 +01:00
|
|
|
|
2020-06-28 10:53:03 +01:00
|
|
|
@pytest.mark.docker
|
2020-06-26 21:37:02 +01:00
|
|
|
def test_large_environment():
|
|
|
|
|
# max environment variable size is 128kB
|
|
|
|
|
long_env_var_length = 127*1024
|
|
|
|
|
large_environment = {
|
|
|
|
|
'a': '0'*long_env_var_length,
|
|
|
|
|
'b': '0'*long_env_var_length,
|
|
|
|
|
'c': '0'*long_env_var_length,
|
|
|
|
|
'd': '0'*long_env_var_length,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
with DockerContainer(DEFAULT_IMAGE) as container:
|
|
|
|
|
# check the length of d
|
|
|
|
|
assert container.call(['sh', '-c', 'echo ${#d}'], env=large_environment, capture_output=True) == f'{long_env_var_length}\n'
|
|
|
|
|
|
2020-06-26 21:41:00 +01:00
|
|
|
|
2020-06-28 10:53:03 +01:00
|
|
|
@pytest.mark.docker
|
2020-06-26 21:37:02 +01:00
|
|
|
def test_binary_output():
|
|
|
|
|
with DockerContainer(DEFAULT_IMAGE) as container:
|
2020-07-08 22:56:33 +01:00
|
|
|
# note: the below embedded snippets are in python2
|
2020-06-26 21:37:02 +01:00
|
|
|
|
|
|
|
|
# check that we can pass though arbitrary binary data without erroring
|
|
|
|
|
container.call(['/usr/bin/python2', '-c', textwrap.dedent('''
|
|
|
|
|
import sys
|
|
|
|
|
sys.stdout.write(''.join(chr(n) for n in range(0, 256)))
|
|
|
|
|
''')])
|
|
|
|
|
|
|
|
|
|
# check that we can capture arbitrary binary data
|
|
|
|
|
output = container.call(['/usr/bin/python2', '-c', textwrap.dedent('''
|
|
|
|
|
import sys
|
|
|
|
|
sys.stdout.write(''.join(chr(n % 256) for n in range(0, 512)))
|
|
|
|
|
''')], capture_output=True)
|
|
|
|
|
|
|
|
|
|
data = bytes(output, encoding='utf8', errors='surrogateescape')
|
|
|
|
|
|
|
|
|
|
for i in range(0, 512):
|
|
|
|
|
assert data[i] == i % 256
|
|
|
|
|
|
|
|
|
|
# check that environment variables can carry binary data, except null characters
|
|
|
|
|
# (https://www.gnu.org/software/libc/manual/html_node/Environment-Variables.html)
|
|
|
|
|
binary_data = bytes(n for n in range(1, 256))
|
|
|
|
|
binary_data_string = str(binary_data, encoding='utf8', errors='surrogateescape')
|
|
|
|
|
output = container.call(
|
|
|
|
|
['python2', '-c', 'import os, sys; sys.stdout.write(os.environ["TEST_VAR"])'],
|
|
|
|
|
env={'TEST_VAR': binary_data_string},
|
|
|
|
|
capture_output=True,
|
|
|
|
|
)
|
|
|
|
|
assert output == binary_data_string
|
2020-07-08 22:56:33 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.docker
|
|
|
|
|
def test_file_operations(tmp_path: Path):
|
|
|
|
|
with DockerContainer(DEFAULT_IMAGE) as container:
|
|
|
|
|
# test copying a file in
|
2020-07-10 12:46:32 +01:00
|
|
|
test_binary_data = bytes(random.randrange(256) for _ in range(1000))
|
2020-07-08 22:56:33 +01:00
|
|
|
original_test_file = tmp_path / 'test.dat'
|
|
|
|
|
original_test_file.write_bytes(test_binary_data)
|
|
|
|
|
|
|
|
|
|
dst_file = PurePath('/tmp/test.dat')
|
|
|
|
|
|
|
|
|
|
container.copy_into(original_test_file, dst_file)
|
|
|
|
|
|
|
|
|
|
output = container.call(['cat', dst_file], capture_output=True)
|
|
|
|
|
assert test_binary_data == bytes(output, encoding='utf8', errors='surrogateescape')
|
|
|
|
|
|
2020-07-10 13:04:50 +01:00
|
|
|
|
2020-07-10 12:46:32 +01:00
|
|
|
@pytest.mark.docker
|
|
|
|
|
def test_dir_operations(tmp_path: Path):
|
|
|
|
|
with DockerContainer(DEFAULT_IMAGE) as container:
|
|
|
|
|
test_binary_data = bytes(random.randrange(256) for _ in range(1000))
|
|
|
|
|
original_test_file = tmp_path / 'test.dat'
|
|
|
|
|
original_test_file.write_bytes(test_binary_data)
|
|
|
|
|
|
2020-07-08 22:56:33 +01:00
|
|
|
# test copying a dir in
|
|
|
|
|
test_dir = tmp_path / 'test_dir'
|
2020-07-10 12:46:32 +01:00
|
|
|
test_dir.mkdir()
|
|
|
|
|
test_file = test_dir / 'test.dat'
|
|
|
|
|
shutil.copyfile(original_test_file, test_file)
|
2020-07-08 22:56:33 +01:00
|
|
|
|
2020-07-10 12:46:32 +01:00
|
|
|
dst_dir = PurePath('/tmp/test_dir')
|
|
|
|
|
dst_file = dst_dir / 'test.dat'
|
|
|
|
|
container.copy_into(test_dir, dst_dir)
|
|
|
|
|
|
|
|
|
|
output = container.call(['cat', dst_file], capture_output=True)
|
|
|
|
|
assert test_binary_data == bytes(output, encoding='utf8', errors='surrogateescape')
|
|
|
|
|
|
|
|
|
|
# test glob
|
2020-07-10 12:57:05 +01:00
|
|
|
assert container.glob(dst_dir, '*.dat') == [dst_file]
|
2020-07-10 12:46:32 +01:00
|
|
|
|
|
|
|
|
# test copy dir out
|
|
|
|
|
new_test_dir = tmp_path / 'test_dir_new'
|
|
|
|
|
container.copy_out(dst_dir, new_test_dir)
|
|
|
|
|
|
|
|
|
|
assert test_binary_data == (new_test_dir / 'test.dat').read_bytes()
|
2020-07-20 02:23:07 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.docker
|
|
|
|
|
def test_environment_executor():
|
|
|
|
|
with DockerContainer(DEFAULT_IMAGE) as container:
|
|
|
|
|
assignment = EnvironmentAssignment("TEST=$(echo 42)")
|
|
|
|
|
assert assignment.evaluated_value({}, container.environment_executor) == "42"
|