Commits (5)
......@@ -39,6 +39,7 @@ Depends: ${python3:Depends},
procps,
python3-pkg-resources,
python3-rstr,
python3-distro,
${misc:Depends}
Recommends:
diffoscope (>= 112~),
......
Name: reprotest
Version: 0.7.15
Release: 1%{?dist}
Summary: Build packages and check them for reproducibility
License: GPL-3+
Source0: https://salsa.debian.org/reproducible-builds/%{name}/-/archive/%{version}/%{name}-%{version}.tar.gz
BuildArch: noarch
BuildRequires: python%{python3_pkgversion}-devel
BuildRequires: python%{python3_pkgversion}-setuptools
Requires: diffoscope
Requires: disorderfs
Requires: python%{python3_pkgversion}-rstr
%description
reprotest builds the same source code twice in different environments, and
then checks the binaries produced by each build for differences. If any are
found, then diffoscope (or if unavailable then diff) is used to display them
in detail for later analysis.
It supports different types of environment such as a "null" environment (i.e.
doing the builds directly in /tmp) or various other virtual servers, for
example schroot, ssh, qemu, and several others.
reprotest is developed as part of the "reproducible builds" Debian project.
%prep
%autosetup -n %{name}-%{version}
# Remove bundled egg-info
rm -rf %{name}.egg-info
%build
%py3_build
%install
%py3_install
%files
%doc README.rst
%{_bindir}/reprotest
%{python3_sitelib}/%{name}
%{python3_sitelib}/%{name}-%{version}-py%{python3_version}.egg-info
%changelog
* Mon Jan 04 2021 Frédéric Pierret (fepitre) <frederic.pierret@qubes-os.org> - 0.7.15-1
- Initial RPM packaging.
......@@ -74,7 +74,7 @@ PRESET_DEB_DIR = ReprotestPreset(
PRESET_RPM_DIR = ReprotestPreset(
build_command='rpmbuild --rebuild',
artifact_pattern='*[^src].rpm',
artifact_pattern='rpmbuild/RPMS/*.rpm',
testbed_pre=None,
testbed_init=None,
testbed_build_pre=None,
......@@ -117,7 +117,6 @@ def preset_rpm_rpmbuild(fn):
extra_build_command = [
'--define "_build_name_fmt %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm"',
'--define "_topdir $PWD/rpmbuild"',
'--define "_rpmdir $PWD"',
'%s' % fn
]
......@@ -128,7 +127,7 @@ def preset_rpm_rpmbuild(fn):
# Disable %clean stage: workaround issue when running with +fileordering
extra_build_command += ['--noclean']
extra_build_command += ['; rm -rf $PWD/rpmbuild']
extra_build_command += ['; rm -rf $PWD/rpmbuild/BUILD*']
extra_build_command = ' '.join(extra_build_command)
return PRESET_RPM_DIR.append.build_command(' %s' % extra_build_command)
......
import distro
import pytest
SUPPORTED_DIST = ["debian", "fedora"]
def pytest_configure(config):
config.addinivalue_line(
"markers", "need_builddeps: need need_builddeps"
)
config.addinivalue_line(
"markers", "debian: filter tests for debian only"
)
config.addinivalue_line(
"markers", "fedora: filter tests for fedora only"
)
def pytest_runtest_setup(item):
# get current dist
dist = distro.id()
# filter markers
supported_dist = set(SUPPORTED_DIST).intersection(
mark.name for mark in item.iter_markers())
if supported_dist and dist not in supported_dist:
pytest.skip("cannot run on {}".format(dist))
......@@ -4,10 +4,10 @@
import contextlib
import logging
import os
import pytest
import subprocess
import sys
import pytest
import reprotest
from reprotest.build import VariationSpec, Variations, VARIATIONS
......@@ -20,6 +20,7 @@ if REPROTEST_TEST_DONTVARY:
TEST_VARIATIONS = frozenset(VARIATIONS.keys()) - frozenset(REPROTEST_TEST_DONTVARY)
def check_reproducibility(command, virtual_server, reproducible):
result = reprotest.check(
reprotest.TestArgs.of(command, 'tests', 'artifact'),
......@@ -27,6 +28,7 @@ def check_reproducibility(command, virtual_server, reproducible):
Variations.of(VariationSpec.default(TEST_VARIATIONS)))
assert result == reproducible
def check_command_line(command_line, code=None):
try:
retcode = 0
......@@ -41,6 +43,7 @@ def check_command_line(command_line, code=None):
else:
assert(retcode in code)
@pytest.fixture(scope='module', params=REPROTEST_TEST_SERVERS)
def virtual_server(request):
if request.param == 'null':
......@@ -52,11 +55,6 @@ def virtual_server(request):
else:
raise ValueError(request.param)
def test_simple_builds(virtual_server):
check_reproducibility('python3 mock_build.py', virtual_server, True)
with pytest.raises(Exception):
check_reproducibility('python3 mock_failure.py', virtual_server)
check_reproducibility('python3 mock_build.py irreproducible', virtual_server, False)
@contextlib.contextmanager
def setup_logging(debug):
......@@ -82,6 +80,14 @@ def setup_logging(debug):
logger.removeHandler(ch)
logger.setLevel(oldLevel)
def test_simple_builds(virtual_server):
check_reproducibility('python3 mock_build.py', virtual_server, True)
with pytest.raises(Exception):
check_reproducibility('python3 mock_failure.py', virtual_server)
check_reproducibility('python3 mock_build.py irreproducible', virtual_server, False)
# TODO: test all variations that we support
@pytest.mark.parametrize('captures', list(VARIATIONS.keys()))
def test_variations(virtual_server, captures):
......@@ -89,6 +95,7 @@ def test_variations(virtual_server, captures):
with setup_logging(False):
check_reproducibility('python3 mock_build.py ' + captures, virtual_server, expected)
@pytest.mark.need_builddeps
def test_self_build(virtual_server):
# at time of writing (2016-09-23) these are not expected to reproduce;
......@@ -98,6 +105,7 @@ def test_self_build(virtual_server):
assert(1 == subprocess.call(REPROTEST + ['python3 setup.py bdist', 'dist/*.tar.gz'] + virtual_server))
assert(1 == subprocess.call(REPROTEST + ['python3 setup.py sdist', 'dist/*.tar.gz'] + virtual_server))
def test_command_lines():
test_args, _, _ = check_command_line(".".split(), 0)
assert test_args.artifact_pattern is not None
......@@ -128,7 +136,8 @@ def test_command_lines():
_, testbed_args, _ = check_command_line(". -- schroot unstable-amd64-sbuild".split(), 0)
assert testbed_args.virtual_server_args == ['schroot', 'unstable-amd64-sbuild']
# TODO: don't call it if we don't have debian/, e.g. for other distros
@pytest.mark.debian
@pytest.mark.need_builddeps
def test_debian_build(virtual_server):
# This is a bit dirty though it works - when building the debian package,
......
......@@ -11,8 +11,8 @@ from reprotest.shell_syn import *
def test_basic():
assert (sanitize_globs("""lol \$ *"\$ s" "" '' ' ' " " ' ' "" """)
== '''./lol ./\$ ./*"\$ s" ./"" ./'' ./' ' ./" " ./' ' ./""''')
assert (sanitize_globs("""lol \\$ *"\\$ s" "" '' ' ' " " ' ' "" """)
== '''./lol ./\\$ ./*"\\$ s" ./"" ./'' ./' ' ./" " ./' ' ./""''')
assert (sanitize_globs("""*"*"'*' ../hm wut???""")
== '''./*"*"'*' ./../hm ./wut???''')
......@@ -30,6 +30,7 @@ def test_basic():
assert sanitize_globs('-rf') == './-rf'
assert sanitize_globs('/') == './/'
def test_shlex_quote():
for _ in range(65536):
x = ''.join(random.choice(string.printable) for _ in range(random.randint(0, 32)))
......