[v3,6/7] tests: add configuration file test via RPC

Submitted by Adrian Reber on June 28, 2018, 4:02 p.m.

Details

Message ID 1530201754-4493-7-git-send-email-adrian@lisas.de
State New
Series "Series without cover letter"
Headers show

Commit Message

Adrian Reber June 28, 2018, 4:02 p.m.
From: Adrian Reber <areber@redhat.com>

This test checks the following things:

 * Does configuration file parsing work at all.
 * Does the parser detect wrong options.
 * Does the configuration file work via RPC.
 * Do the configuration file options not overwrite the RPC settings in
   the default setup.
 * Is it possible to tell CRIU to prefer the configuration file via RPC.

Signed-off-by: Adrian Reber <areber@redhat.com>
---
 Makefile                       |   1 +
 test/others/rpc/Makefile       |   2 +
 test/others/rpc/config_file.py | 185 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 188 insertions(+)
 create mode 100755 test/others/rpc/config_file.py

Patch hide | download patch | download mbox

diff --git a/Makefile b/Makefile
index 9474495..2377673 100644
--- a/Makefile
+++ b/Makefile
@@ -378,6 +378,7 @@  help:
 
 lint:
 	flake8 --config=scripts/flake8.cfg test/zdtm.py
+	flake8 --config=scripts/flake8.cfg test/others/rpc/config_file.py
 
 include Makefile.install
 
diff --git a/test/others/rpc/Makefile b/test/others/rpc/Makefile
index 2b15873..964a591 100644
--- a/test/others/rpc/Makefile
+++ b/test/others/rpc/Makefile
@@ -14,6 +14,8 @@  run: all
 	chmod a+rw build/pidfile
 	sudo -g '#1000' -u '#1000' ./run.sh
 	sudo -g '#1000' -u '#1000' ./version.py
+	# run the configuration file via RPC test cases
+	./config_file.py build
 
 criu: ../../../criu/criu
 	cp ../../../criu/criu $@
diff --git a/test/others/rpc/config_file.py b/test/others/rpc/config_file.py
new file mode 100755
index 0000000..74b4b16
--- /dev/null
+++ b/test/others/rpc/config_file.py
@@ -0,0 +1,185 @@ 
+#!/usr/bin/python2
+
+import os
+import socket
+import sys
+import rpc_pb2 as rpc
+import argparse
+import subprocess
+from tempfile import mkstemp
+import time
+
+log_file = 'config_file_test.log'
+does_not_exist = 'does-not.exist'
+
+
+def setup_swrk():
+	print('Connecting to CRIU in swrk mode.')
+	css = socket.socketpair(socket.AF_UNIX, socket.SOCK_SEQPACKET)
+	swrk = subprocess.Popen(['./criu', "swrk", "%d" % css[0].fileno()])
+	css[0].close()
+	return swrk, css[1]
+
+
+def setup_config_file(content):
+	# Creating a temporary file which will be used as configuration file.
+	fd, path = mkstemp()
+
+	with os.fdopen(fd, 'w') as f:
+		f.write(content)
+
+	os.environ['CRIU_CONFIG_FILE'] = path
+
+	return path
+
+
+def cleanup_config_file(path):
+	del os.environ['CRIU_CONFIG_FILE']
+	os.unlink(path)
+
+
+def setup_criu_dump_request():
+	# Create criu msg, set it's type to dump request
+	# and set dump options. Checkout more options in protobuf/rpc.proto
+	req = rpc.criu_req()
+	req.type = rpc.DUMP
+	req.opts.leave_running = True
+	req.opts.log_level = 4
+	req.opts.log_file = log_file
+	req.opts.images_dir_fd = os.open(args['dir'], os.O_DIRECTORY)
+	# Not necessary, just for testing
+	req.opts.tcp_established = True
+	req.opts.shell_job = True
+	return req
+
+
+def do_rpc(s, req):
+	# Send request
+	s.send(req.SerializeToString())
+
+	# Recv response
+	resp = rpc.criu_resp()
+	MAX_MSG_SIZE = 1024
+	resp.ParseFromString(s.recv(MAX_MSG_SIZE))
+
+	s.close()
+	return resp
+
+
+def test_broken_configuration_file():
+	# Testing RPC configuration file mode with a broken configuration file.
+	# This should fail
+	content = 'hopefully-this-option-will-never=exist'
+	path = setup_config_file(content)
+	swrk, s = setup_swrk()
+	s.close()
+	# This test is only about detecting wrong configuration files.
+	# If we do not sleep it might happen that kill CRIU before
+	# it parses the configuration file. A short sleep makes sure
+	# that the configuration file has been parsed. Hopefully.
+	# (I am sure this will fail horribly at some point)
+	time.sleep(0.3)
+	swrk.kill()
+	return_code = swrk.wait()
+	# delete temporary file again
+	cleanup_config_file(path)
+	if return_code != 1:
+		print('FAIL: CRIU should have returned 1 instead of %d' % return_code)
+		sys.exit(-1)
+
+
+def search_in_log_file(log, message):
+	with open(os.path.join(args['dir'], log)) as f:
+		if message not in f.read():
+			print('FAIL: Missing the expected error message (%s) in the log file' % message)
+			sys.exit(-1)
+
+
+def check_results(resp, log):
+	# Check if the specified log file exists
+	if not os.path.isfile(os.path.join(args['dir'], log)):
+		print('FAIL: Expected log file %s does not exist' % log)
+		sys.exit(-1)
+	# Dump should have failed with: 'The criu itself is within dumped tree'
+	if resp.type != rpc.DUMP:
+		print('FAIL: Unexpected msg type %r' % resp.type)
+		sys.exit(-1)
+	if 'The criu itself is within dumped tree' not in resp.cr_errmsg:
+		print('FAIL: Missing the expected error message in RPC response')
+		sys.exit(-1)
+	# Look into the log file for the same message
+	search_in_log_file(log, 'The criu itself is within dumped tree')
+
+
+def test_rpc_without_configuration_file():
+	# Testing without configuration file
+	# Just doing a dump and checking for the logfile
+	req = setup_criu_dump_request()
+	_, s = setup_swrk()
+	resp = do_rpc(s, req)
+	s.close()
+	check_results(resp, log_file)
+
+
+def test_rpc_with_configuration_file():
+	# Testing with configuration file
+	# Just doing a dump and checking for the logfile
+
+	# Setting a different log file via configuration file
+	# This should not work as RPC settings overwrite configuration
+	# file settings in the default configuration.
+	log = does_not_exist
+	content = 'log-file ' + log + '\n'
+	content += 'no-tcp-established\nno-shell-job'
+	path = setup_config_file(content)
+	req = setup_criu_dump_request()
+	_, s = setup_swrk()
+	do_rpc(s, req)
+	s.close()
+	cleanup_config_file(path)
+	# Check if the specified log file exists
+	# It should not as configuration files do not overwrite RPC values.
+	if os.path.isfile(os.path.join(args['dir'], log)):
+		print('FAIL: log file %s should not exist' % log)
+		sys.exit(-1)
+
+
+def test_rpc_with_configuration_file_overwriting_rpc():
+	# Testing with configuration file
+	# Just doing a dump and checking for the logfile
+
+	# Setting a different log file via configuration file
+	# This should not work as RPC settings overwrite configuration
+	# file settings in the default configuration.
+	log = does_not_exist
+	content = 'log-file ' + log + '\n'
+	content += 'no-tcp-established\nno-shell-job'
+	path = setup_config_file(content)
+	req = setup_criu_dump_request()
+	req.opts.prefer_config_file = True
+	_, s = setup_swrk()
+	resp = do_rpc(s, req)
+	s.close()
+	cleanup_config_file(path)
+	check_results(resp, log)
+
+	search_in_log_file(log, 'Using tcp_established_ok from configuration file')
+	search_in_log_file(log, 'Using shell_job from configuration file')
+
+
+parser = argparse.ArgumentParser(description="Test config files using CRIU RPC")
+parser.add_argument('dir', type = str, help = "Directory where CRIU images should be placed")
+
+args = vars(parser.parse_args())
+
+try:
+	# optional cleanup
+	os.unlink(os.path.join(args['dir'], does_not_exist))
+	os.unlink(os.path.join(args['dir'], log_file))
+except OSError:
+	pass
+
+test_broken_configuration_file()
+test_rpc_without_configuration_file()
+test_rpc_with_configuration_file()
+test_rpc_with_configuration_file_overwriting_rpc()