[CRIU] [PATCH] test: add rpc tests
Ruslan Kuprieiev
kupruser at gmail.com
Sat Sep 14 13:43:44 EDT 2013
Hi!
This patch provides tests(in C and Python) of rpc, that can be used as
examples.
Also, it contains shell script to automatize testing.
This patch requires patch "rpc: change some "required" fields to
"optional" and rename rpc.proto to criu-rpc.proto" by Ruslan Kuprieiev.
Signed-off-by: Ruslan Kuprieiev <kupruser at gmail.com>
-------------- next part --------------
diff --git a/test/rpc/Makefile b/test/rpc/Makefile
new file mode 100644
index 0000000..726fd21
--- /dev/null
+++ b/test/rpc/Makefile
@@ -0,0 +1,20 @@
+all: test-c criu-rpc_pb2.py
+
+test-c: criu-rpc.pb-c.o test.o
+ gcc $^ -o test-c -lprotobuf-c
+
+#FIXME protoc*
+criu-rpc_pb2.py: ../../protobuf/criu-rpc.proto
+ protoc --proto_path=$(CURDIR)/../../protobuf/ --python_out=. $(CURDIR)/../../protobuf/criu-rpc.proto
+
+criu-rpc.pb-c.c: ../../protobuf/criu-rpc.proto
+ protoc-c --proto_path=$(CURDIR)/../../protobuf/ --c_out=. $(CURDIR)/../../protobuf/criu-rpc.proto
+
+clean:
+ rm -f *.o
+ rm -f criu*
+ rm -f test-c
+ rm -f _*
+ rm -rf imgs_*
+ rm -f *.log
+ rm -f *.socket
diff --git a/test/rpc/run.sh b/test/rpc/run.sh
new file mode 100755
index 0000000..17f0f09
--- /dev/null
+++ b/test/rpc/run.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+
+source ../env.sh || exit 1
+
+function my_print {
+ echo -e "\n**************************************************"
+ echo -e "\t\t"$1
+ echo -e "**************************************************\n"
+
+}
+
+function my_exit {
+ if [ $1 -ne 0 ]; then
+ echo FAIL
+ fi
+
+ my_print "Shutdown service server"
+ kill -SIGTERM ${SRV_PID}
+
+ exit $1
+}
+
+IMGS_DIR_C="imgs_c"
+IMGS_DIR_PY="imgs_py"
+SERV_LOG="service.log"
+REST_C_LOG="restore-c.log"
+REST_PY_LOG="restore-py.log"
+
+my_print "Build services"
+make clean && make || { echo "Failed to build"; exit 1; }
+if [ $? -ne 0 ]; then
+ echo FAIL
+ exit 1
+fi
+rm -rf ${IMGS_DIR_C} ${IMGS_DIR_PY} ${REST_LOG_C} ${REST_LOG_PY}
+mkdir ${IMGS_DIR_C} ${IMGS_DIR_PY}
+
+my_print "Start service server"
+setsid ${CRIU} service -v4 -o ${SERV_LOG} --address ./criu_service.socket &
+SRV_PID=${!}
+if [ $? -ne 0 ]; then
+ echo FAIL
+ exit 1
+fi
+echo PID ${SRV_PID}
+sleep 1 #server needs some time to initialize
+
+my_print "Run test-c"
+./test-c
+if [ $? -ne 0 ]; then
+ my_exit 1
+fi
+
+my_print "Run test-py"
+./test.py
+if [ $? -ne 0 ]; then
+ my_exit 1
+fi
+
+my_print "Restore test-c"
+${CRIU} restore -v4 -o ${REST_C_LOG} -D ./imgs_c --shell-job
+if [ $? -ne 0 ]; then
+ my_exit 1
+fi
+
+my_print "Restore test-py"
+${CRIU} restore -v4 -o ${REST_PY_LOG} -D ./imgs_py --shell-job
+if [ $? -ne 0 ]; then
+ my_exit 1
+fi
+
+my_exit 0
diff --git a/test/rpc/test.c b/test/rpc/test.c
new file mode 100644
index 0000000..b67c082
--- /dev/null
+++ b/test/rpc/test.c
@@ -0,0 +1,160 @@
+#include "criu-rpc.pb-c.h"
+#include <stdbool.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/fcntl.h>
+#include <stdio.h>
+
+#define MAX_MSG_SIZE 1024
+
+/*
+ * recv_resp() reads criu msg from the socket,
+ * unpacks it and unwraps a dump response.
+ */
+
+static int recv_resp(int fd, CriuDumpResp **resp)
+{
+ unsigned char buf[MAX_MSG_SIZE];
+ int len;
+
+ CriuMsg *msg = 0;
+
+ len = read(fd, buf, MAX_MSG_SIZE);
+ if (len == -1) {
+ perror("Can't read resp");
+ return -1;
+ }
+
+ msg = criu_msg__unpack(NULL, len, buf);
+ if (!msg) {
+ perror("Failed unpacking resp");
+ return -1;
+ }
+
+ if (msg->type == CRIU_MSG__TYPE__DUMPRESP)
+ *resp = msg->dump_resp;
+ else {
+ perror("Unexpected msg type");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * send_req gets dump request as an argument,
+ * wraps it into criu msg and writes it to the socket
+ */
+
+static int send_req(int fd, CriuDumpReq *req)
+{
+ unsigned char buf[MAX_MSG_SIZE];
+ int len;
+
+ CriuMsg msg = CRIU_MSG__INIT;
+ msg.dump_req = req;
+ msg.type = CRIU_MSG__TYPE__DUMPREQ;
+
+ len = criu_msg__get_packed_size(&msg);
+
+ if (criu_msg__pack(&msg, buf) != len) {
+ perror("Failed packing request");
+ return -1;
+ }
+
+ if (write(fd, buf, len) == -1) {
+ perror("Can't send request");
+ return -1;
+ }
+
+ return 0;
+}
+
+int main()
+{
+ CriuDumpReq req = CRIU_DUMP_REQ__INIT;
+ CriuDumpResp *resp = NULL;
+ int fd, dir_fd;
+ int ret = 0;
+ struct sockaddr_un addr;
+ socklen_t addr_len;
+
+ /*
+ * Open a directory, in which criu will
+ * put images
+ */
+ dir_fd = open("./imgs_c", O_DIRECTORY);
+ if (dir_fd == -1) {
+ perror("Can't open dir");
+ return -1;
+ }
+
+ /*
+ * Set dump options.
+ * Checkout more in protobuf/criu-rpc.proto.
+ */
+ req.has_leave_running = true;
+ req.leave_running = true;
+ req.images_dir_fd = dir_fd;
+ req.has_shell_job = true;
+ req.shell_job = true;
+
+ /*
+ * Connect to service socket
+ */
+ fd = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
+ if (fd == -1) {
+ perror("Can't create socket");
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_LOCAL;
+ strcpy(addr.sun_path, "./criu_service.socket");
+
+ addr_len = strlen(addr.sun_path) + sizeof(addr.sun_family);
+
+ ret = connect(fd, (struct sockaddr *) &addr, addr_len);
+ if (ret == -1) {
+ perror("Cant connect to socket");
+ goto exit;
+ }
+
+ /*
+ * Send dump request
+ */
+ ret = send_req(fd, &req);
+ if (ret == -1) {
+ perror("Can't send request");
+ goto exit;
+ }
+
+ /*
+ * Recv dump response
+ */
+ ret = recv_resp(fd, &resp);
+ if (ret == -1) {
+ perror("Can't recv response");
+ goto exit;
+ }
+
+ /*
+ * Check response.
+ */
+ if (resp->success)
+ puts("Success");
+ else {
+ puts("Fail");
+ ret = -1;
+ goto exit;
+ }
+
+ if (resp->has_restored && resp->restored)
+ puts("Restored");
+
+exit:
+ close(fd);
+ close(dir_fd);
+ criu_dump_resp__free_unpacked(resp, NULL);
+ return ret;
+}
diff --git a/test/rpc/test.py b/test/rpc/test.py
new file mode 100755
index 0000000..74f0830
--- /dev/null
+++ b/test/rpc/test.py
@@ -0,0 +1,35 @@
+#!/usr/bin/python
+
+import socket, os
+import criu_rpc_pb2
+
+# Connect to service socket
+s = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
+s.connect('./criu_service.socket')
+
+# Create criu msg, set it's type to dump request
+# and set dump options
+msg_req = criu_rpc_pb2.criu_msg()
+msg_req.type = criu_rpc_pb2.criu_msg.DUMPREQ
+msg_req.dump_req.leave_running = True
+msg_req.dump_req.shell_job = True
+msg_req.dump_req.images_dir_fd = os.open('./imgs_py', os.O_DIRECTORY)
+
+# Send criu msg with request
+s.send(msg_req.SerializeToString())
+
+# Recv criu msg with response
+msg_resp = criu_rpc_pb2.criu_msg()
+MAX_MSG_SIZE = 1024
+msg_resp.ParseFromString(s.recv(MAX_MSG_SIZE))
+
+if msg_resp.type != criu_rpc_pb2.criu_msg.DUMPRESP:
+ print 'Unexpected msg type'
+else:
+ if msg_resp.dump_resp.success:
+ print 'Success'
+ else:
+ print 'Fail'
+
+ if msg_resp.dump_resp.restored:
+ print 'Restored'
More information about the CRIU
mailing list