Skip to content

Commit

Permalink
tests: Test concurrent operations
Browse files Browse the repository at this point in the history
Test that concurrent commits and prunes can succeed. Mostly this is a
check that the new locking works correctly and the concurrent processes
will properly wait until they've acquired the appropriate repository
lock.

Closes: #1343
Approved by: cgwalters
  • Loading branch information
cgwalters authored and rh-atomic-bot committed Dec 5, 2017
1 parent df7f33e commit 3f4506f
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 0 deletions.
1 change: 1 addition & 0 deletions Makefile-tests.am
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ _installed_or_uninstalled_test_scripts = \
tests/test-xattrs.sh \
tests/test-auto-summary.sh \
tests/test-prune.sh \
tests/test-concurrency.py \
tests/test-refs.sh \
tests/test-demo-buildsystem.sh \
tests/test-switchroot.sh \
Expand Down
107 changes: 107 additions & 0 deletions tests/test-concurrency.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/usr/bin/env python
#
# Copyright (C) 2017 Colin Walters <[email protected]>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

from __future__ import print_function
import os
import sys
import shutil
import subprocess
from multiprocessing import cpu_count

def fatal(msg):
sys.stderr.write(msg)
sys.stderr.write('\n')
sys.exit(1)

# Create 20 files with content based on @dname + a serial, basically to have
# different files with different checksums.
def mktree(dname, serial=0):
print('Creating tree', dname, file=sys.stderr)
os.mkdir(dname, 0755)
for v in xrange(20):
with open('{}/{}'.format(dname, v), 'w') as f:
f.write('{} {} {}\n'.format(dname, serial, v))

subprocess.check_call(['ostree', '--repo=repo', 'init', '--mode=bare'])
# like the bit in libtest, but let's do it unconditionally since it's simpler,
# and we don't need xattr coverage for this
with open('repo/config', 'a') as f:
f.write('disable-xattrs=true\n')

def commit(v):
tdir='tree{}'.format(v)
cmd = ['ostree', '--repo=repo', 'commit', '--fsync=0', '-b', tdir, '--tree=dir='+tdir]
proc = subprocess.Popen(cmd)
print('PID {}'.format(proc.pid), *cmd, file=sys.stderr)
return proc
def prune():
cmd = ['ostree', '--repo=repo', 'prune', '--refs-only']
proc = subprocess.Popen(cmd)
print('PID {}:'.format(proc.pid), *cmd, file=sys.stderr)
return proc

def wait_check(proc):
pid = proc.pid
proc.wait()
if proc.returncode != 0:
sys.stderr.write("process {} exited with code {}\n".format(proc.pid, proc.returncode))
return False
else:
sys.stderr.write('PID {} exited OK\n'.format(pid))
return True

print("1..2")

def run(n_committers, n_pruners):
# The number of committers needs to be even since we only create half as
# many trees
n_committers += n_committers % 2

committers = set()
pruners = set()

print('n_committers', n_committers, 'n_pruners', n_pruners, file=sys.stderr)
n_trees = n_committers / 2
for v in xrange(n_trees):
mktree('tree{}'.format(v))

for v in xrange(n_committers):
committers.add(commit(v / 2))
for v in xrange(n_pruners):
pruners.add(prune())

failed = False
for committer in committers:
if not wait_check(committer):
failed = True
for pruner in pruners:
if not wait_check(pruner):
failed = True
if failed:
fatal('A child process exited abnormally')

for v in xrange(n_trees):
shutil.rmtree('tree{}'.format(v))

# No concurrent pruning
run(cpu_count()/2 + 2, 0)
print("ok no concurrent prunes")

run(cpu_count()/2 + 4, 3)
print("ok concurrent prunes")

0 comments on commit 3f4506f

Please sign in to comment.