aboutgitcodelistschat:MatrixIRC
path: root/tests/unit/test_op_call.c
blob: 6ffef998589a69746fee9bfb2a14c06e088bc55a (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15














                         
                             






                        

                                                         

               
                                                             
                                 
                           







                                                               


                                           
 















                                                                              
                                                            

                                          



























                                                                          


                                                             



                                   






                                           
                                                                  
                            
                           



                           



                       

                                                  



                                                                               


                                           



                                                                                



                                           



                                 
                                                                                







                                           
                            



                           



                                                        

                                                  
                                                  



                                        









                                                                                
                            
                           
                   
                                  

                
                                                  
                                                  
                              


                                 

                                                                               


        
                          
 
                 
                    
 

                                             
 


                                                     
 
                                 
 
                 







                          
                            






                                                              
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
#include <sched.h>
#include <sys/wait.h>
#include <sys/syscall.h>

#include <check.h>

#include "../../gluten.h"
#include "../../operations.h"

struct args_write_file {
	char *file;
	char *t;
	ssize_t size;
};

static void write_file(char *file, char *t, ssize_t size)
{
	int fd;

	fd = open(file, O_CREAT | O_RDWR, S_IWUSR | S_IRUSR);
	ck_assert_int_ge(fd, -1);
	write(fd, t, size);
	close(fd);
}

static int write_file_get_fd(char *file, char *t, ssize_t size)
{
	int fd;

	write_file(file, t, size);
	fd = open(file, O_RDONLY, S_IWUSR);
	unlink(file);
	return fd;
}

static int write_file_clone(void *a)
{
	struct args_write_file *args = (struct args_write_file *)a;
	write_file(args->file, args->t, args->size);
	pause();
	return 0;
}

static pid_t create_func_ns(int (*fn)(void *), void *arg, struct ns_spec ns[])
{
	char stack[STACK_SIZE];
	pid_t child;
	int flags = SIGCHLD;
	unsigned int i;

	for (i = 0; i < sizeof(sizeof(enum ns_type)); i++) {
		if (ns[i].type == NS_NONE)
			continue;
		switch (i) {
		case NS_CGROUP:
			flags |= CLONE_NEWCGROUP;
			break;
		case NS_IPC:
			flags |= CLONE_NEWIPC;
			break;
		case NS_NET:
			flags |= CLONE_NEWNET;
			break;
		case NS_MOUNT:
			flags |= CLONE_NEWNS;
			break;
		case NS_PID:
			flags |= CLONE_NEWPID;
			break;
		case NS_USER:
			flags |= CLONE_NEWUSER;
			break;
		case NS_UTS:
			flags |= CLONE_NEWUTS;
			break;
		case NS_TIME:
			fprintf(stderr,
				"option NS_TIME not suppoted by clone\n");
			break;
		default:
			fprintf(stderr, "unrecognized option %d\n", i);
		}
	}
	child = clone(fn, stack + sizeof(stack), flags, arg);
	if (child == -1) {
		perror("clone");
		exit(EXIT_FAILURE);
	}
	return child;
}

START_TEST(test_with_open_read_ns)
{
	char test_file[] = "/tmp/test.txt";
	char t[PATH_MAX] = "Hello Test";
	struct args_write_file args = { test_file, t, sizeof(t) };
	struct op_call call;
	int flags = O_RDWR;
	struct arg_clone c;
	char buf[PATH_MAX];
	unsigned i;
	long count;
	pid_t pid;
	int ret;

	c.args = &call;
	count = sizeof(buf);
	for (i = 0; i < sizeof(enum ns_type); i++)
		call.context.ns[i].type = NS_NONE;
	call.context.ns[NS_MOUNT].type = NS_SPEC_PID;
	pid = create_func_ns(write_file_clone, (void *)&args, call.context.ns);
	call.context.ns[NS_MOUNT].pid = pid;
	call.nr = SYS_open;
	call.args[0] = (void *)&test_file;
	call.args[1] = (void *)(long)flags;
	ret = do_call(&c);
	ck_assert_int_eq(ret, 0);
	ck_assert_msg(c.ret >= 0, "expect ret %ld should be nonegative", c.ret);

	call.nr = SYS_read;
	call.args[0] = (void *)(long)c.ret;
	call.args[1] = (void *)&buf;
	call.args[2] = (void *)count;
	ret = do_call(&c);
	kill(pid, SIGCONT);

	ck_assert_int_eq(ret, 0);
	ck_assert_msg(c.ret == count, "expect ret %ld to be %ld", c.ret, count);
	ck_assert_str_eq(t, buf);
}
END_TEST

START_TEST(test_with_read)
{
	char test_file[] = "/tmp/test.txt";
	char t[PATH_MAX] = "Hello Test";
	struct op_call call;
	struct arg_clone c;
	char buf[PATH_MAX];
	unsigned i;
	long count;
	int fd, ret;

	c.args = &call;
	fd = write_file_get_fd(test_file, t, sizeof(t));
	count = sizeof(buf);
	for (i = 0; i < sizeof(enum ns_type); i++)
		call.context.ns[i].type = NS_NONE;
	call.nr = SYS_read;
	call.args[0] = (void *)(long)fd;
	call.args[1] = (void *)&buf;
	call.args[2] = (void *)count;
	ret = do_call(&c);

	ck_assert_int_eq(ret, 0);
	ck_assert_msg(c.ret == count, "expect ret %ld to be %ld", c.ret, count);
	ck_assert_str_eq(t, buf);
}
END_TEST

START_TEST(test_with_getppid)
{
	struct op_call call;
	struct arg_clone c;
	unsigned i;
	long pid = (long)getpid();
	int ret;

	for (i = 0; i < sizeof(enum ns_type); i++)
		call.context.ns[i].type = NS_NONE;
	call.nr = SYS_getppid;
	c.args = &call;
	ret = do_call(&c);
	ck_assert_int_eq(ret, 0);
	ck_assert_msg(c.ret == pid, "expect ret %ld to be equal to %ld", c.ret,
		      pid);
}
END_TEST

Suite *op_call_suite(void)
{
	Suite *s;
	TCase *tops;

	s = suite_create("Perform ops call");
	tops = tcase_create("op calls");

	tcase_add_test(tops, test_with_getppid);
	tcase_add_test(tops, test_with_read);
	tcase_add_test(tops, test_with_open_read_ns);

	suite_add_tcase(s, tops);

	return s;
}

int main(void)
{
	int no_failed = 0;
	Suite *s;
	SRunner *runner;

	s = op_call_suite();
	runner = srunner_create(s);

	srunner_run_all(runner, CK_VERBOSE);
	no_failed = srunner_ntests_failed(runner);
	srunner_free(runner);
	return (no_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}