On Wed, Jan 07, 2009 at 10:20:34PM +0530, Sudhir Kumar wrote: > > This patch puts the test functions in a separate file so that they > can be reused for further testing. Some of the functions were static > and hence changed to be non static. It also edits the Makefile so > that the patch compiles. > > Signed-off-by: Sudhir Kumar <[email protected]> > Acked-by: Dhaval Giani <[email protected]>
Not yet, please. > Acked-by: Balbir Singh <[email protected]> > > --- > tests/Makefile | 19 - > tests/test_functions.c | 876 > ++++++++++++++++++++++++++++++++++++++++++++++++ > tests/libcgrouptest.h | 19 - > tests/libcgrouptest01.c | 730 ---------------------------------------- > 4 files changed, 897 insertions(+), 747 deletions(-) > > Index: trunk/tests/Makefile > =================================================================== > --- trunk.orig/tests/Makefile > +++ trunk/tests/Makefile > @@ -1,18 +1,25 @@ > -LDFLAGS = -L .. > -LIBS = -lcgroup -lpthread > +LDFLAGS = -L .. -L. > +LIBS = -lcgroup -lpthread -ltest_functions > INC = -I .. > CXXFLAGS = -g -O2 -Wall -DDEBUG $(INC) > CFLAGS = -g -O2 -Wall -DDEBUG > > -TARGET= libcgrouptest01 \ > +TARGET= libtest_functions.a \ > + libcgrouptest01 \ > libcg_ba \ > setuid \ > pathtest > > all: $(TARGET) > > -libcgrouptest01: libcgrouptest01.c > - $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIBS) > +test_functions.o: test_functions.c > + $(CXX) $(CXXFLAGS) -c $< > + > +libtest_functions.a: test_functions.o > + $(AR) -cr $@ $^ > + > +libcgrouptest01: test_functions.o libcgrouptest01.c > + $(CXX) $(CXXFLAGS) -o $@ libcgrouptest01.c $(LDFLAGS) $(LIBS) > > libcg_ba: libcg_ba.cpp > $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIBS) > @@ -24,4 +31,4 @@ pathtest: pathtest.c > $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LIBS) > > clean: > - \rm -f $(TARGET) > + \rm -f $(TARGET) test_functions.o > Index: trunk/tests/test_functions.c > =================================================================== > --- /dev/null > +++ trunk/tests/test_functions.c > @@ -0,0 +1,876 @@ > +/* > + * Copyright IBM Corporation. 2008 > + * > + * Author: Sudhir Kumar <[email protected]> > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of version 2.1 of the GNU Lesser General Public License > + * as published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it would be useful, but > + * WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. > + * > + * Description: This file contains the functions for testing libcgroup apis. > + */ > + > +#include "libcgrouptest.h" > + > +/* The messages that may be useful to the user */ > +char info[NUM_MSGS][SIZE] = { > + " Parameter nullcgroup\n", /* NULLGRP */ > + " Parameter commoncgroup\n", /* COMMONGRP */ > + " Parameter not created group\n", /* NOTCRTDGRP */ > + " Parameter same cgroup\n", /* SAMEGRP */ > + " Task found in group/s\n", /* TASKINGRP */ > + " Task not found in group/s\n", /* TASKNOTINGRP */ > + " Task not found in all groups\n", /* TASKNOTINANYGRP */ > + " group found in filesystem\n", /* GRPINFS */ > + " group not found in filesystem\n", /* GRPNOTINFS */ > + " group found under both controllers\n", /* GRPINBOTHCTLS */ > + " group not found under second controller\n", /* GRPNOTIN2NDCTL */ > + " group not found under first controller\n", /* GRPNOTIN1STCTL */ > + " group modified under both controllers\n", /* GRPMODINBOTHCTLS */ > + " group not modified under second controller\n",/* GRPNOTMODIN2NDCTL */ > + " group not modified under any controller\n", /* GRPNOTMODINANYCTL */ > + " Group deleted from filesystem\n", /* GRPDELETEDINFS */ > + " Group not deleted from filesystem\n", /* GRPNOTDELETEDINFS */ > + " Group not deleted globally\n", /* GRPNOTDELETEDGLOBALY > */ > + /* In case there is no extra info messages to be printed */ > + "\n", /* NOMESSAGE */ > +}; > + > +/* > + * @param retcode error code in case any error is expected from api > + * @param i the test number > + */ > +void test_cgroup_init(int retcode, int i) > +{ > + int retval; > + > + retval = cgroup_init(); > + if (retval == retcode) > + message(i, PASS, "init()\t", retval, info[NOMESSAGE]); > + else > + message(i, FAIL, "init()", retval, info[NOMESSAGE]); > +} > + > +/* > + * @param retcode error code in case any error is expected from api > + * @param cgrp the group to assign the task to > + * @param group1 the name of the group under first (single) mountpoint > + * @param group2 the name of the group under 2nd moutpoint for multimount > + * @param i the test number > + * @param k the message enum number to print the useful message > + */ While we are at it, it might be good to keep it in doxygen format, to generate automated documentation? > +void test_cgroup_attach_task(int retcode, struct cgroup *cgrp, > + const char *group1, const char *group2, int k, int i) > +{ > + int retval; > + char tasksfile[FILENAME_MAX], tasksfile2[FILENAME_MAX]; > + /* Check, In case some error is expected due to a negative scenario */ > + if (retcode) { > + retval = cgroup_attach_task(cgrp); > + if (retval == retcode) > + message(i, PASS, "attach_task()", retval, info[k]); > + else > + message(i, FAIL, "attach_task()", retval, info[k]); > + > + return; > + } > + > + /* Now there is no error and it is a genuine call */ > + retval = cgroup_attach_task(cgrp); > + /* API returned success, so perform check */ > + if (retval == 0) { > + build_path(tasksfile, mountpoint, > + group1, "tasks"); > + > + if (check_task(tasksfile)) { > + /* multiple mounts */ > + if (fs_mounted == 2) { > + build_path(tasksfile2, mountpoint2, > + group2, "tasks"); > + if (check_task(tasksfile2)) { > + message(i, PASS, "attach_task()", > + retval, info[TASKINGRP]); > + } else { > + message(i, FAIL, "attach_task()", > + retval, info[TASKNOTINANYGRP]); > + } > + /* single mount */ This comment seems to be very oddly placed. > + } else { > + message(i, PASS, "attach_task()", > + retval, info[TASKINGRP]); > + } > + } else { > + message(i, FAIL, "attach_task()", retval, > + info[TASKNOTINGRP]); > + } > + } else { > + message(i, FAIL, "attach_task()", retval, (char *)"\n"); > + } > +} > + > +/* > + * This function is a bit ugly for now and need to be changed > + * @param ctl the controller under which group is to be created > + * @param grpname the name of the group > + * @param value_type which value out of four types > + * @param struct cval the control value structure > + * @param struct ids the permissions struct > + * @param the test number > + */ > +struct cgroup *create_new_cgroup_ds(int ctl, const char *grpname, > + int value_type, struct cntl_val_t cval, struct uid_gid_t ids, int i) hmm. Being pedantic again, but this seems odd. I would prefer struct cgroup *cgroup_new_cgroup_ds(int ctl, const char *grpname, int value_type, struct cntl_val_t cval, struct uid_git_t ids, int i) I guess. I am not sure though :( (the guideline being that it should come around midway through the function name, and not the return type) > +{ > + int retval; > + char group[FILENAME_MAX]; > + char controller_name[FILENAME_MAX], control_file[FILENAME_MAX]; > + > + strncpy(group, grpname, sizeof(group)); > + retval = set_controller(ctl, controller_name, control_file); > + if (retval) { > + fprintf(stderr, "Setting controller failled\n"); > + return NULL; > + } > + > + switch (ctl) { > + /* control values are controller specific, so will be set > + * accordingly from the config file */ > + case CPU: > + strncpy(cval.val_string, "260000", sizeof(cval.val_string)); > + break; > + > + case MEMORY: > + strncpy(cval.val_string, "7000064", sizeof(cval.val_string)); > + break; > + > + /* To be added for other controllers */ > + default: > + printf("Invalid controller name passed. Setting control value" > + " failed. Dependent tests may fail\n"); > + return NULL; > + break; > + } > + > + return new_cgroup(group, controller_name, control_file, > + value_type, cval, ids, i); > +} > + > +/* > + * @param retcode error code in case any error is expected from api > + * @param cgrp the group to be created > + * @param name the name of the group > + * @param common to test if group will be created under one or both > mountpoints > + * @param mpnt to test if group under mountpoint or mountpoint2 > + * @param ign parameter for api if to ignore the ownership > + * @param the test number > + */ > +void test_cgroup_create_cgroup(int retcode, struct cgroup *cgrp, > + const char *name, int common, int mpnt, int ign, int i) > +{ > + int retval; > + char path1_group[FILENAME_MAX], path2_group[FILENAME_MAX]; > + /* Check, In case some error is expected due to a negative scenario */ > + if (retcode) { > + retval = cgroup_create_cgroup(cgrp, ign); > + if (retval == retcode) > + message(i, PASS, "create_cgroup()", retval, > + info[NOMESSAGE]); > + else > + message(i, FAIL, "create_cgroup()", retval, > + info[NOMESSAGE]); > + > + return; > + } > + > + /* Now there is no error and it is a genuine call */ > + retval = cgroup_create_cgroup(cgrp, ign); > + if (retval) { > + message(i, FAIL, "create_cgroup()", retval, info[NOMESSAGE]); > + return; > + } > + > + /* Let us now check if the group exist in file system */ > + if (!common) { > + /* group only under one mountpoint */ > + if (mpnt == 1) > + /* group under mountpoint */ > + build_path(path1_group, mountpoint, name, NULL); > + else > + /* group under mountpoint2 */ > + build_path(path1_group, mountpoint2, name, NULL); > + > + if (group_exist(path1_group) == 0) > + message(i, PASS, "create_cgroup()", retval, > + info[GRPINFS]); > + else > + message(i, FAIL, "create_cgroup()", retval, > + info[GRPNOTINFS]); > + > + /* group under both mountpoints */ Again, pedantic, proper case (or at least consistent) for comments. > + } else { > + /* Check if the group exists under both controllers */ > + build_path(path1_group, mountpoint, name, NULL); > + if (group_exist(path1_group) == 0) { > + build_path(path2_group, mountpoint2, name, NULL); > + > + if (group_exist(path2_group) == 0) > + message(i, PASS, "create_cgroup()", > + retval, info[GRPINBOTHCTLS]); > + else > + message(i, FAIL, "create_cgroup()", > + retval, info[GRPNOTIN2NDCTL]); > + } else { > + message(i, FAIL, "create_cgroup()", retval, > + info[GRPNOTIN1STCTL]); > + } > + } > + > + return; > +} > + > +/* > + * @param retcode error code in case any error is expected from api > + * @param cgrp the group to be deleted > + * @param name the name of the group > + * @param common to test if group was created under one or both mountpoints > + * @param mpnt to test if group under mountpoint or mountpoint2 > + * @param ign parameter for api if to ignore the ownership > + * @param the test number > + */ > +void test_cgroup_delete_cgroup(int retcode, struct cgroup *cgrp, > + const char *name, int common, int mpnt, int ign, int i) > +{ > + int retval; > + char path1_group[FILENAME_MAX], path2_group[FILENAME_MAX]; > + /* Check, In case some error is expected due to a negative scenario */ > + if (retcode) { > + retval = cgroup_delete_cgroup(cgrp, ign); > + if (retval == retcode) > + message(i, PASS, "delete_cgroup()", retval, > + info[NOMESSAGE]); > + else > + message(i, FAIL, "delete_cgroup()", retval, > + info[NOMESSAGE]); > + > + return; > + } > + > + /* Now there is no error and it is a genuine call */ > + retval = cgroup_delete_cgroup(cgrp, ign); > + if (retval) { > + message(i, FAIL, "delete_cgroup()", retval, info[NOMESSAGE]); > + return; > + } > + > + /* Let us now check if the group has been deleted from file system */ > + if (!common) { > + /* check only under one mountpoint */ > + if (mpnt == 1) > + /* check group under mountpoint */ > + build_path(path1_group, mountpoint, name, NULL); > + else > + /* check group under mountpoint2 */ > + build_path(path1_group, mountpoint2, name, NULL); > + > + if (group_exist(path1_group) == -1) > + message(i, PASS, "delete_cgroup()", retval, > + info[GRPDELETEDINFS]); > + else > + message(i, FAIL, "delete_cgroup()", retval, > + info[GRPNOTDELETEDINFS]); > + > + } else { > + /* check group under both mountpoints */ > + /* Check if the group deleted under both mountpoints */ > + build_path(path1_group, mountpoint, name, NULL); > + if (group_exist(path1_group) == -1) { > + build_path(path2_group, mountpoint2, name, NULL); > + > + if (group_exist(path2_group) == -1) > + message(i, PASS, "delete_cgroup()", > + retval, info[GRPDELETEDINFS]); > + else > + message(i, FAIL, "delete_cgroup()", > + retval, info[GRPNOTDELETEDGLOBALY]); > + } else { > + message(i, FAIL, "delete_cgroup()", retval, > + info[GRPNOTDELETEDINFS]); > + } > + } > + > +} > + > +/* > + * @param name the name of the controller to be checked > + * @param exist set to 1 if the controller exists > + */ > +void get_controllers(const char *name, int *exist) Again, why not int get_controllers(const char *name)? > +{ > + int hierarchy, num_cgroups, enabled; > + FILE *fd; > + char subsys_name[FILENAME_MAX]; > + > + fd = fopen("/proc/cgroups", "r"); > + if (!fd) > + return; > + > + while (!feof(fd)) { > + fscanf(fd, "%s, %d, %d, %d", subsys_name, > + &hierarchy, &num_cgroups, &enabled); > + if (strncmp(name, subsys_name, sizeof(*name)) == 0) > + *exist = 1; > + } > + > + fclose(fd); > +} > + > +/* > + * @param path_group path to the group to be tested for existence > + */ > +int group_exist(char *path_group) > +{ > + int ret; > + ret = open(path_group, O_DIRECTORY); > + if (ret == -1) > + return ret; > + return 0; > +} > + > +/* > + * @param controller the enum for the name of the controller > + * @param controller_name name of the controller > + * @param control_file corresponding control file > + */ > +int set_controller(int controller, char *controller_name, char *control_file) > +{ > + switch (controller) { > + case MEMORY: > + if (memory == 0) > + return 1; > + > + strncpy(controller_name, "memory", FILENAME_MAX); > + strncpy(control_file, "memory.limit_in_bytes", FILENAME_MAX); > + return 0; > + break; > + > + case CPU: > + if (cpu == 0) > + return 1; > + > + strncpy(controller_name, "cpu", FILENAME_MAX); > + strncpy(control_file, "cpu.shares", FILENAME_MAX); > + return 0; > + break; > + > + case CPUSET: > + strncpy(controller_name, "cpuset", FILENAME_MAX); > + strncpy(control_file, "cpuset.cpus", FILENAME_MAX); And mems. Even mems needs to be set > + return 0; > + break; > + /* Future controllers can be added here */ > + > + default: > + printf("Invalid controller name passed. Setting controller" > + " failed. Dependent tests may fail\n"); > + return 1; > + break; > + } > +} > + > +/* > + * @param path_control_file path to the control file of the controller > + * @param value_type which value out of four types > + * @param struct cval the control value structure > + */ > +int group_modified(char *path_control_file, int value_type, > + struct cntl_val_t cval) > +{ > + bool bool_val; > + int64_t int64_val; > + u_int64_t uint64_val; > + /* 100 char looks ok for a control value as string */ > + char string_val[100]; > + FILE *fd; > + int error = 1; > + > + fd = fopen(path_control_file, "r"); > + if (!fd) { > + fprintf(stderr, "Error in opening %s\n", path_control_file); > + fprintf(stderr, "Skipping modified values check....\n"); > + return 1; > + } > + > + switch (value_type) { > + > + case BOOL: > + fscanf(fd, "%d", &bool_val); > + if (bool_val == cval.val_bool) > + error = 0; > + break; > + case INT64: > + fscanf(fd, "%lld", &int64_val); > + if (int64_val == cval.val_int64) > + error = 0; > + break; > + case UINT64: > + fscanf(fd, "%llu", &uint64_val); > + if (uint64_val == cval.val_uint64) > + error = 0; > + break; > + case STRING: > + fscanf(fd, "%s", string_val); > + if (!strncmp(string_val, cval.val_string, strlen(string_val))) > + error = 0; > + break; > + default: > + fprintf(stderr, "Wrong value_type passed " > + "in group_modified()\n"); > + fprintf(stderr, "Skipping modified values check....\n"); > + /* Can not report test result as failure */ > + error = 0; > + break; > + } > + > + fclose(fd); > + return error; > +} > + > +/* > + * @param newcontroller the controller to be added the value to > + * @param control_file name of the control file of the controller > + * @param wr the name of wrapper api > + * @param value_type which value out of four types > + * @param struct cval the control value structure > + */ > +int add_control_value(struct cgroup_controller *newcontroller, > + char *control_file, char *wr, int value_type, struct cntl_val_t cval) > +{ > + int retval; > + > + switch (value_type) { > + > + case BOOL: > + retval = cgroup_add_value_bool(newcontroller, > + control_file, cval.val_bool); > + snprintf(wr, SIZE, "add_value_bool()"); > + break; > + case INT64: > + retval = cgroup_add_value_int64(newcontroller, > + control_file, cval.val_int64); > + snprintf(wr, SIZE, "add_value_int64()"); > + break; > + case UINT64: > + retval = cgroup_add_value_uint64(newcontroller, > + control_file, cval.val_uint64); > + snprintf(wr, SIZE, "add_value_uint64()"); > + break; > + case STRING: > + retval = cgroup_add_value_string(newcontroller, > + control_file, cval.val_string); > + snprintf(wr, SIZE, "add_value_string()"); > + break; > + default: > + printf("ERROR: wrong value in add_control_value()\n"); > + return 1; > + break; > + } > + return retval; > +} > + > +/* > + * @param group the name of the group > + * @param controller_name the name of the controller to be added to the group > + * @param control_file name of the control file of the controller > + * @param value_type which value out of four types > + * @param struct cval the control value structure > + * @param struct ids the permissions struct > + * @param the test number > + */ > +struct cgroup *new_cgroup(char *group, char *controller_name, > + char *control_file, int value_type, > + struct cntl_val_t cval, struct uid_gid_t ids, int i) > +{ > + int retval; > + /* Names of wrapper apis */ > + char wr[SIZE]; > + struct cgroup *newcgroup; > + struct cgroup_controller *newcontroller; > + > + newcgroup = cgroup_new_cgroup(group); > + > + if (newcgroup) { > + retval = cgroup_set_uid_gid(newcgroup, ids.tasks_uid, > + ids.tasks_gid, ids.control_uid, ids.control_gid); > + > + if (retval) { > + snprintf(wr, SIZE, "set_uid_gid()"); > + message(i++, FAIL, wr, retval, info[NOMESSAGE]); > + } > + > + newcontroller = cgroup_add_controller(newcgroup, > + controller_name); > + if (newcontroller) { > + retval = add_control_value(newcontroller, > + control_file, wr, value_type, cval); > + > + if (!retval) { > + message(i++, PASS, "new_cgroup()", > + retval, info[NOMESSAGE]); > + } else { > + message(i++, FAIL, wr, retval , > + info[NOMESSAGE]); > + return NULL; > + } > + } else { > + /* Since these wrappers do not return an int so -1 */ > + message(i++, FAIL, "add_controller", -1, > + info[NOMESSAGE]); > + return NULL; > + } > + } else { > + message(i++, FAIL, "new_cgroup", -1, info[NOMESSAGE]); > + return NULL; > + } > + return newcgroup; > +} > + > +/* > + * @param multimnt to decide if check is for single mount or multimount > + */ > +int check_fsmounted(int multimnt) > +{ > + int count = 0; > + int ret = 1; > + struct mntent *entry = NULL, *tmp_entry = NULL; > + /* Need a better mechanism to decide memory allocation size here */ > + char entry_buffer[FILENAME_MAX * 4]; > + FILE *proc_file = NULL; > + > + tmp_entry = (struct mntent *) malloc(sizeof(struct mntent)); > + if (!tmp_entry) { > + perror("Error: failled to mallloc for mntent\n"); > + ret = errno; > + goto error; > + } > + > + proc_file = fopen("/proc/mounts", "r"); > + if (!proc_file) { > + printf("Error in opening /proc/mounts.\n"); > + ret = errno; > + goto error; > + } > + while ((entry = getmntent_r(proc_file, tmp_entry, entry_buffer, > + FILENAME_MAX*4)) != NULL) { > + if (!strncmp(entry->mnt_type, "cgroup", strlen("cgroup"))) { > + count++; > + if (multimnt) { > + if (count >= 2) { > + printf("sanity check pass. %s\n", > + entry->mnt_type); > + ret = 0; > + goto error; > + } > + } else { > + printf("sanity check pass. %s\n", > + entry->mnt_type); > + ret = 0; > + goto error; > + } > + } > + } > +error: > + if (tmp_entry) > + free(tmp_entry); > + if (proc_file) > + fclose(proc_file); > + return ret; > +} > + > +/* > + * @param tasksfile the task file to be tested for the task > + */ > +int check_task(char *tasksfile) > +{ > + FILE *file; > + pid_t curr_tid, tid; > + int pass = 0; > + > + file = fopen(tasksfile, "r"); > + if (!file) { > + printf("ERROR: in opening %s\n", tasksfile); > + printf("Exiting without running other testcases in this set\n"); > + exit(1); > + } > + > + curr_tid = cgrouptest_gettid(); > + while (!feof(file)) { > + fscanf(file, "%u", &tid); > + if (tid == curr_tid) { > + pass = 1; > + break; > + } > + } > + fclose(file); > + > + return pass; > +} > + > +/* > + * @param num the test number > + * @param pass test passed or failed > + * @param api the name of the api tested > + * @param retval the return value of the api > + * @param extra the extra message to the user about the scenario tested > + */ > +void message(int num, int pass, const char *api, int retval, char *extra) > +{ > + char res[10]; > + char buf[2*SIZE]; > + if (pass) > + strncpy(res, "PASS :", 10); > + else > + strncpy(res, "FAIL :", 10); > + > + /* Populate message buffer for the api */ > + snprintf(buf, sizeof(buf), "cgroup_%s\t\t Ret Value = ", api); > + fprintf(stdout, "TEST%2d:%s %s%d\t%s", num, res, buf, retval, extra); Why not combine into one call? > +} > + > +/* builds the path to target file/group */ > +/* > + * @param target to write the built path to > + * @param mountpoint for which mountpoint the path to be built > + * @param group the name of the group (directory) > + * @param file what file under the group > + */ > +void > +build_path(char *target, char *mountpoint, const char *group, const char > *file) > +{ > + if (!target) > + return; > + > + strncpy(target, mountpoint, FILENAME_MAX); > + > + if (group) { > + strncat(target, "/", FILENAME_MAX - strlen(target)); > + strncat(target, group, FILENAME_MAX - strlen(target)); > + } > + > + if (file) { > + strncat(target, "/", FILENAME_MAX - strlen(target)); > + strncat(target, file, FILENAME_MAX - strlen(target)); > + } > +} > + > +/* > + * @param ctl1 controller 1 to be used for testing > + * @param ctl2 controller 1 to be used for testing > + * @param the test number > + */ > +void test_cgroup_compare_cgroup(int ctl1, int ctl2, int i) > +{ > + int retval; > + > + struct cntl_val_t cval; > + cval.val_int64 = 0; > + cval.val_uint64 = 0; > + cval.val_bool = 0; > + strcpy(cval.val_string, "5000"); > + > + struct cgroup *cgroup1 = NULL, *cgroup2 = NULL; > + struct cgroup_controller *controller = NULL; > + char controller_name[FILENAME_MAX], control_file[FILENAME_MAX]; > + char wr[SIZE], extra[] = "in cgroup_compare_cgroup"; > + > + retval = cgroup_compare_cgroup(NULL, NULL); > + if (retval) > + message(i++, PASS, "compare_cgroup()", retval, info[NULLGRP]); > + else > + message(i++, FAIL, "compare_cgroup()", retval, info[NULLGRP]); > + > + cgroup1 = cgroup_new_cgroup("testgroup"); > + cgroup2 = cgroup_new_cgroup("testgroup"); > + cgroup_set_uid_gid(cgroup1, 0, 0, 0, 0); > + cgroup_set_uid_gid(cgroup2, 0, 0, 0, 0); > + > + retval = set_controller(ctl1, controller_name, control_file); > + > + controller = cgroup_add_controller(cgroup1, controller_name); > + if (controller) { > + retval = add_control_value(controller, > + control_file, wr, STRING, cval); > + if (retval) > + message(i++, FAIL, wr, retval, extra); > + } > + > + controller = cgroup_add_controller(cgroup2, controller_name); > + if (controller) { > + retval = add_control_value(controller, > + control_file, wr, STRING, cval); > + if (retval) > + message(i++, FAIL, wr, retval, extra); > + } > + > + retval = cgroup_compare_cgroup(cgroup1, cgroup2); > + if (retval) > + message(i++, FAIL, "compare_cgroup()", retval, info[NOMESSAGE]); > + else > + message(i++, PASS, "compare_cgroup()", retval, info[NOMESSAGE]); > + > + /* Test the api by putting diff number of controllers in cgroups */ > + retval = set_controller(ctl2, controller_name, control_file); > + controller = cgroup_add_controller(cgroup2, controller_name); > + if (controller) { > + retval = add_control_value(controller, > + control_file, wr, STRING, cval); > + if (retval) > + message(i++, FAIL, wr, retval, extra); > + } > + > + retval = cgroup_compare_cgroup(cgroup1, cgroup2); > + if (retval == ECGROUPNOTEQUAL) > + message(i++, PASS, "compare_cgroup()", retval, info[NOMESSAGE]); > + else > + message(i++, FAIL, "compare_cgroup()", retval, info[NOMESSAGE]); > + > + cgroup_free(&cgroup1); > + cgroup_free(&cgroup2); > +} > + > +/* > + * @param ctl1 controller 1 to be used for testing > + * @param ctl2 controller 1 to be used for testing > + * @param struct ids the permissions struct > + * @param the test number > + */ > +void test_cgroup_get_cgroup(int ctl1, int ctl2, struct uid_gid_t ids, int i) > +{ > + struct cgroup *cgroup_filled = NULL, *cgroup_a = NULL, *cgroup_b = NULL; > + struct cgroup_controller *controller = NULL; > + char controller_name[FILENAME_MAX], control_file[FILENAME_MAX]; > + struct cntl_val_t cval = {0, 0, 0, "5000"}; > + int ret; > + > + /* > + * No need to test the next 3 scenarios separately for Multimnt > + * so testing them only under single mount > + */ > + if (fs_mounted == FS_MOUNTED) { > + /* 1. Test with nullcgroup first */ > + ret = cgroup_get_cgroup(NULL); > + if (ret == ECGROUPNOTALLOWED) > + message(i++, PASS, "get_cgroup()", ret, info[NULLGRP]); > + else > + message(i++, FAIL, "get_cgroup()", ret, info[NULLGRP]); > + > + /* 2. Test with invalid name filled cgroup(non existing) */ > + cgroup_filled = cgroup_new_cgroup("nogroup"); > + if (!cgroup_filled) > + message(i++, FAIL, "new_cgroup()", 0, info[NOMESSAGE]); > + > + ret = cgroup_get_cgroup(cgroup_filled); > + if (ret) > + message(i++, PASS, "get_cgroup()", ret, > + info[NOTCRTDGRP]); > + else > + message(i++, FAIL, "get_cgroup()", ret, > + info[NOTCRTDGRP]); > + /* Free the allocated cgroup before reallocation */ > + cgroup_free(&cgroup_filled); > + > + /* 3. > + * Test with name filled cgroup. Ensure the group group1 exists > + * in the filesystem before calling this test function > + */ > + cgroup_filled = cgroup_new_cgroup("group1"); > + if (!cgroup_filled) > + message(i++, FAIL, "new_cgroup()", 0, info[NOMESSAGE]); > + > + ret = cgroup_get_cgroup(cgroup_filled); > + if (!ret) > + message(i++, PASS, "get_cgroup()", ret, > + info[NOMESSAGE]); > + else > + message(i++, FAIL, "get_cgroup()", ret, > + info[NOMESSAGE]); > + } > + > + /* SINGLE & MULTI MOUNT: Create, get and compare a cgroup */ > + > + /* get cgroup_a ds and create group_a in filesystem */ > + cgroup_a = create_new_cgroup_ds(ctl1, "group_a", STRING, cval, ids, 0); > + if (fs_mounted == FS_MULTI_MOUNTED) { > + /* Create under another controller also */ > + ret = set_controller(ctl2, controller_name, control_file); > + controller = cgroup_add_controller(cgroup_a, controller_name); > + } > + test_cgroup_create_cgroup(0, cgroup_a, "group_a", 0, 1, 1, 00); > + > + /* create group_b ds to be filled by cgroup_get_cgroup */ > + cgroup_b = cgroup_new_cgroup("group_a"); > + if (!cgroup_b) > + message(i++, FAIL, "new_cgroup()", 0, info[NOMESSAGE]); > + /* Fill the ds and compare the two */ > + ret = cgroup_get_cgroup(cgroup_b); > + if (!ret) { > + ret = cgroup_compare_cgroup(cgroup_a, cgroup_b); > + if (ret == 0) > + message(i++, PASS, "get_cgroup()", ret, info[SAMEGRP]); > + else > + message(i++, FAIL, "get_cgroup()", ret, > + info[NOMESSAGE]); > + } else { > + message(i++, FAIL, "get_cgroup()", ret, info[NOMESSAGE]); > + } > + > + /* Delete this created group from fs to leave fs clean */ > + if (fs_mounted == FS_MULTI_MOUNTED) > + test_cgroup_delete_cgroup(0, cgroup_a, "group_a", 1, 1, 0, 0); > + else > + test_cgroup_delete_cgroup(0, cgroup_a, "group_a", 0, 1, 0, 0); > + > + cgroup_free(&cgroup_a); > + cgroup_free(&cgroup_b); > + cgroup_free(&cgroup_filled); > +} > + > +/* > + * @param the test number > + */ > +void test_cgroup_add_free_controller(int i) > +{ > + struct cgroup *cgroup1 = NULL, *cgroup2 = NULL; > + struct cgroup_controller *cgctl1, *cgctl2; > + > + /* Test with a Null cgroup */ > + cgctl1 = cgroup_add_controller(cgroup1, "cpu"); > + if (!cgctl1) > + message(i++, PASS, "add_controller()", 0, info[NOMESSAGE]); > + else > + message(i++, FAIL, "add_controller()", -1, info[NOMESSAGE]); > + > + cgroup1 = cgroup_new_cgroup("testgroup"); > + cgctl1 = cgroup_add_controller(cgroup1, "cpuset"); > + if (cgctl1) > + message(i++, PASS, "add_controller()", 0, info[NOMESSAGE]); > + else > + message(i++, FAIL, "add_controller()", -1, info[NOMESSAGE]); > + > + cgctl2 = cgroup_add_controller(cgroup1, "cpu"); > + if (cgctl2) > + message(i++, PASS, "add_controller()", 0, info[NOMESSAGE]); > + else > + message(i++, FAIL, "add_controller()", -1, info[NOMESSAGE]); > + > + cgroup_free(&cgroup1); > + cgroup_free_controllers(cgroup2); > +} > + > +/* returns the tid of the current thread */ > +pid_t cgrouptest_gettid() > +{ > + return syscall(__NR_gettid); > +} > Index: trunk/tests/libcgrouptest.h > =================================================================== > --- trunk.orig/tests/libcgrouptest.h > +++ trunk/tests/libcgrouptest.h > @@ -127,26 +127,23 @@ void test_cgroup_get_cgroup(int ctl1, in > void test_cgroup_compare_cgroup(int ctl1, int ctl2, int i); > void test_cgroup_add_free_controller(int i); > void get_controllers(const char *name, int *exist); > -static int group_exist(char *path_group); > -static int set_controller(int controller, char *controller_name, > +int group_exist(char *path_group); > +int set_controller(int controller, char *controller_name, > char *control_file); > -static int group_modified(char *path_control_file, int value_type, > +int group_modified(char *path_control_file, int value_type, > struct cntl_val_t cval); > -static int add_control_value(struct cgroup_controller *newcontroller, > +int add_control_value(struct cgroup_controller *newcontroller, > char *control_file, char *wr, int value_type, struct cntl_val_t cval); > struct cgroup *new_cgroup(char *group, char *controller_name, > char *control_file, int value_type, struct cntl_val_t cval, > struct uid_gid_t ids, int i); > int check_fsmounted(int multimnt); > -static int check_task(char *tasksfile); > +int check_task(char *tasksfile); > /* function to print messages in better format */ > -static inline void message(int num, int pass, const char *api, > +void message(int num, int pass, const char *api, > int ret, char *extra); > -static inline void build_path(char *target, char *mountpoint, > +void build_path(char *target, char *mountpoint, > const char *group, const char *file); > +pid_t cgrouptest_gettid(); > > -static inline pid_t cgrouptest_gettid() > -{ > - return syscall(__NR_gettid); > -} > #endif > Index: trunk/tests/libcgrouptest01.c > =================================================================== > --- trunk.orig/tests/libcgrouptest01.c > +++ trunk/tests/libcgrouptest01.c > @@ -17,31 +17,6 @@ > #include "libcgrouptest.h" > #include <errno.h> > > -/* The messages that may be useful to the user */ > -char info[NUM_MSGS][SIZE] = { > - " Parameter nullcgroup\n", /* NULLGRP */ > - " Parameter commoncgroup\n", /* COMMONGRP */ > - " Parameter not created group\n", /* NOTCRTDGRP */ > - " Parameter same cgroup\n", /* SAMEGRP */ > - " Task found in group/s\n", /* TASKINGRP */ > - " Task not found in group/s\n", /* TASKNOTINGRP */ > - " Task not found in all groups\n", /* TASKNOTINANYGRP */ > - " group found in filesystem\n", /* GRPINFS */ > - " group not found in filesystem\n", /* GRPNOTINFS */ > - " group found under both controllers\n", /* GRPINBOTHCTLS */ > - " group not found under second controller\n", /* GRPNOTIN2NDCTL */ > - " group not found under first controller\n", /* GRPNOTIN1STCTL */ > - " group modified under both controllers\n", /* GRPMODINBOTHCTLS */ > - " group not modified under second controller\n",/* GRPNOTMODIN2NDCTL */ > - " group not modified under any controller\n", /* GRPNOTMODINANYCTL */ > - " Group deleted from filesystem\n", /* GRPDELETEDINFS */ > - " Group not deleted from filesystem\n", /* GRPNOTDELETEDINFS */ > - " Group not deleted globally\n", /* GRPNOTDELETEDGLOBALY > */ > - /* In case there is no extra info messages to be printed */ > - "\n", /* NOMESSAGE */ > -}; > - > - > int cpu, memory; > int fs_mounted; > /* We use mountpoint for single mount. > @@ -666,223 +641,6 @@ int main(int argc, char *argv[]) > return 0; > } > > - > -void test_cgroup_init(int retcode, int i) > -{ > - int retval; > - > - retval = cgroup_init(); > - if (retval == retcode) > - message(i, PASS, "init()\t", retval, info[NOMESSAGE]); > - else > - message(i, FAIL, "init()\t", retval, info[NOMESSAGE]); > -} > - > -void test_cgroup_attach_task(int retcode, struct cgroup *cgrp, > - const char *group1, const char *group2, > - int k, int i) > -{ > - int retval; > - char tasksfile[FILENAME_MAX], tasksfile2[FILENAME_MAX]; > - /* Check, In case some error is expected due to a negative scenario */ > - if (retcode) { > - retval = cgroup_attach_task(cgrp); > - if (retval == retcode) > - message(i, PASS, "attach_task()", retval, info[k]); > - else > - message(i, FAIL, "attach_task()", retval, info[k]); > - > - return; > - } > - > - /* Now there is no error and it is a genuine call */ > - retval = cgroup_attach_task(cgrp); > - if (retval == 0) { /* API returned success, so perform check */ > - build_path(tasksfile, mountpoint, > - group1, "tasks"); > - > - if (check_task(tasksfile)) { > - if (fs_mounted == 2) { /* multiple mounts */ > - build_path(tasksfile2, mountpoint2, > - group2, "tasks"); > - if (check_task(tasksfile2)) { > - message(i, PASS, "attach_task()", > - retval, info[TASKINGRP]); > - } else { > - message(i, FAIL, "attach_task()", > - retval, info[TASKNOTINANYGRP]); > - } > - } else { /* single mount */ > - message(i, PASS, "attach_task()", > - retval, info[TASKINGRP]); > - } > - } else { > - message(i, FAIL, "attach_task()", retval, > - info[TASKNOTINGRP]); > - } > - } else { > - message(i, FAIL, "attach_task()", retval, (char *)"\n"); > - } > -} > - > - > -struct cgroup *create_new_cgroup_ds(int ctl, const char *grpname, > - int value_type, struct cntl_val_t cval, struct uid_gid_t ids, int i) > -{ > - int retval; > - char group[FILENAME_MAX]; > - char controller_name[FILENAME_MAX], control_file[FILENAME_MAX]; > - > - strncpy(group, grpname, sizeof(group)); > - retval = set_controller(ctl, controller_name, control_file); > - if (retval) { > - fprintf(stderr, "Setting controller failled\n"); > - return NULL; > - } > - > - switch (ctl) { > - /* control values are controller specific, so will be set > - * accordingly from the config file */ > - case CPU: > - strncpy(cval.val_string, "260000", sizeof(cval.val_string)); > - break; > - > - case MEMORY: > - strncpy(cval.val_string, "7000064", sizeof(cval.val_string)); > - break; > - > - /* To be added for other controllers */ > - default: > - printf("Invalid controller name passed. Setting control value" > - " failed. Dependent tests may fail\n"); > - return NULL; > - break; > - } > - > - return new_cgroup(group, controller_name, control_file, > - value_type, cval, ids, i); > -} > - > - > -void test_cgroup_create_cgroup(int retcode, struct cgroup *cgrp, > - const char *name, int common, int mpnt, int ign, int i) > -{ > - int retval; > - char path1_group[FILENAME_MAX], path2_group[FILENAME_MAX]; > - /* Check, In case some error is expected due to a negative scenario */ > - if (retcode) { > - retval = cgroup_create_cgroup(cgrp, ign); > - if (retval == retcode) > - message(i, PASS, "create_cgroup()", retval, > - info[NOMESSAGE]); > - else > - message(i, FAIL, "create_cgroup()", retval, > - info[NOMESSAGE]); > - > - return; > - } > - > - /* Now there is no error and it is a genuine call */ > - retval = cgroup_create_cgroup(cgrp, ign); > - if (retval) { > - message(i, FAIL, "create_cgroup()", retval, info[NOMESSAGE]); > - return; > - } > - > - /* Let us now check if the group exist in file system */ > - if (!common) { /* group only under one mountpoint */ > - if (mpnt == 1) /* group under mountpoint */ > - build_path(path1_group, mountpoint, name, NULL); > - else /* group under mountpoint2 */ > - build_path(path1_group, mountpoint2, name, NULL); > - > - if (group_exist(path1_group) == 0) > - message(i, PASS, "create_cgroup()", retval, > - info[GRPINFS]); > - else > - message(i, FAIL, "create_cgroup()", retval, > - info[GRPNOTINFS]); > - > - } else { /* group under both mountpoints */ > - /* Check if the group exists under both controllers */ > - build_path(path1_group, mountpoint, name, NULL); > - if (group_exist(path1_group) == 0) { > - build_path(path2_group, mountpoint2, name, NULL); > - > - if (group_exist(path2_group) == 0) > - message(i, PASS, "create_cgroup()", > - retval, info[GRPINBOTHCTLS]); > - else > - message(i, FAIL, "create_cgroup()", > - retval, info[GRPNOTIN2NDCTL]); > - } else { > - message(i, FAIL, "create_cgroup()", retval, > - info[GRPNOTIN1STCTL]); > - } > - } > - > - return; > -} > - > -void test_cgroup_delete_cgroup(int retcode, struct cgroup *cgrp, > - const char *name, int common, int mpnt, int ign, int i) > -{ > - int retval; > - char path1_group[FILENAME_MAX], path2_group[FILENAME_MAX]; > - /* Check, In case some error is expected due to a negative scenario */ > - if (retcode) { > - retval = cgroup_delete_cgroup(cgrp, ign); > - if (retval == retcode) > - message(i, PASS, "delete_cgroup()", retval, > - info[NOMESSAGE]); > - else > - message(i, FAIL, "delete_cgroup()", retval, > - info[NOMESSAGE]); > - > - return; > - } > - > - /* Now there is no error and it is a genuine call */ > - retval = cgroup_delete_cgroup(cgrp, ign); > - if (retval) { > - message(i, FAIL, "delete_cgroup()", retval, info[NOMESSAGE]); > - return; > - } > - > - /* Let us now check if the group has been deleted from file system */ > - if (!common) { /* check only under one mountpoint */ > - if (mpnt == 1) /* check group under mountpoint */ > - build_path(path1_group, mountpoint, name, NULL); > - else /* check group under mountpoint2 */ > - build_path(path1_group, mountpoint2, name, NULL); > - > - if (group_exist(path1_group) == -1) > - message(i, PASS, "delete_cgroup()", retval, > - info[GRPDELETEDINFS]); > - else > - message(i, FAIL, "delete_cgroup()", retval, > - info[GRPNOTDELETEDINFS]); > - > - } else { /* check group under both mountpoints */ > - /* Check if the group deleted under both controllers */ > - build_path(path1_group, mountpoint, name, NULL); > - if (group_exist(path1_group) == -1) { > - build_path(path2_group, mountpoint2, name, NULL); > - > - if (group_exist(path2_group) == -1) > - message(i, PASS, "delete_cgroup()", > - retval, info[GRPDELETEDINFS]); > - else > - message(i, FAIL, "delete_cgroup()", > - retval, info[GRPNOTDELETEDGLOBALY]); > - } else { > - message(i, FAIL, "delete_cgroup()", retval, > - info[GRPNOTDELETEDINFS]); > - } > - } > - > -} > - > void test_cgroup_modify_cgroup(int retcode, struct cgroup *cgrp, > const char *name, int which_ctl, int ctl1, > int ctl2, int value_type, int i) > @@ -994,491 +752,3 @@ void test_cgroup_modify_cgroup(int retco > > return; > } > - > -void get_controllers(const char *name, int *exist) > -{ > - int hierarchy, num_cgroups, enabled; > - FILE *fd; > - char subsys_name[FILENAME_MAX]; > - fd = fopen("/proc/cgroups", "r"); > - if (!fd) > - return; > - > - while (!feof(fd)) { > - fscanf(fd, "%s, %d, %d, %d", subsys_name, > - &hierarchy, &num_cgroups, &enabled); > - if (strncmp(name, subsys_name, sizeof(*name)) == 0) > - *exist = 1; > - } > - > - fclose(fd); > -} > - > -static int group_exist(char *path_group) > -{ > - int ret; > - ret = open(path_group, O_DIRECTORY); > - if (ret == -1) > - return ret; > - return 0; > -} > - > -static int set_controller(int controller, char *controller_name, > - char *control_file) > -{ > - switch (controller) { > - case MEMORY: > - if (memory == 0) > - return 1; > - > - strncpy(controller_name, "memory", FILENAME_MAX); > - strncpy(control_file, "memory.limit_in_bytes", FILENAME_MAX); > - return 0; > - break; > - > - case CPU: > - if (cpu == 0) > - return 1; > - > - strncpy(controller_name, "cpu", FILENAME_MAX); > - strncpy(control_file, "cpu.shares", FILENAME_MAX); > - return 0; > - break; > - > - case CPUSET: > - strncpy(controller_name, "cpuset", FILENAME_MAX); > - /* What is the exact control file?? */ > - strncpy(control_file, "cpuset.mem_exclusive", FILENAME_MAX); > - return 0; > - break; > - /* Future controllers can be added here */ > - > - default: > - printf("Invalid controller name passed. Setting controller" > - " failed. Dependent tests may fail\n"); > - return 1; > - break; > - } > -} > - > -static int group_modified(char *path_control_file, int value_type, > - struct cntl_val_t cval) > -{ > - bool bool_val; > - int64_t int64_val; > - u_int64_t uint64_val; > - char string_val[FILENAME_MAX]; /* Doubt: what should be the size ? */ > - FILE *fd; > - int error = 1; > - > - fd = fopen(path_control_file, "r"); > - if (!fd) { > - fprintf(stderr, "Error in opening %s\n", path_control_file); > - fprintf(stderr, "Skipping modified values check....\n"); > - return 1; > - } > - > - switch (value_type) { > - > - case BOOL: > - fscanf(fd, "%d", &bool_val); > - if (bool_val == cval.val_bool) > - error = 0; > - break; > - case INT64: > - fscanf(fd, "%lld", &int64_val); > - if (int64_val == cval.val_int64) > - error = 0; > - break; > - case UINT64: > - fscanf(fd, "%llu", &uint64_val); > - if (uint64_val == cval.val_uint64) > - error = 0; > - break; > - case STRING: > - fscanf(fd, "%s", string_val); > - if (!strncmp(string_val, cval.val_string, strlen(string_val))) > - error = 0; > - break; > - default: > - fprintf(stderr, "Wrong value_type passed " > - "in group_modified()\n"); > - fprintf(stderr, "Skipping modified values check....\n"); > - error = 0; /* Can not report test result as failure */ > - break; > - } > - fclose(fd); > - return error; > -} > -static int add_control_value(struct cgroup_controller *newcontroller, > - char *control_file, char *wr, int value_type, struct cntl_val_t cval) > -{ > - int retval; > - > - switch (value_type) { > - > - case BOOL: > - retval = cgroup_add_value_bool(newcontroller, > - control_file, cval.val_bool); > - snprintf(wr, SIZE, "add_value_bool()"); > - break; > - case INT64: > - retval = cgroup_add_value_int64(newcontroller, > - control_file, cval.val_int64); > - snprintf(wr, SIZE, "add_value_int64()"); > - break; > - case UINT64: > - retval = cgroup_add_value_uint64(newcontroller, > - control_file, cval.val_uint64); > - snprintf(wr, SIZE, "add_value_uint64()"); > - break; > - case STRING: > - retval = cgroup_add_value_string(newcontroller, > - control_file, cval.val_string); > - snprintf(wr, SIZE, "add_value_string()"); > - break; > - default: > - printf("ERROR: wrong value in add_control_value()\n"); > - return 1; > - break; > - } > - return retval; > -} > - > -struct cgroup *new_cgroup(char *group, char *controller_name, > - char *control_file, int value_type, > - struct cntl_val_t cval, struct uid_gid_t ids, int i) > -{ > - int retval; > - char wr[SIZE]; /* Names of wrapper apis */ > - struct cgroup *newcgroup; > - struct cgroup_controller *newcontroller; > - > - newcgroup = cgroup_new_cgroup(group); > - > - if (newcgroup) { > - retval = cgroup_set_uid_gid(newcgroup, ids.tasks_uid, > - ids.tasks_gid, ids.control_uid, ids.control_gid); > - > - if (retval) { > - snprintf(wr, SIZE, "set_uid_gid()"); > - message(i++, FAIL, wr, retval, info[NOMESSAGE]); > - } > - > - newcontroller = cgroup_add_controller(newcgroup, > - controller_name); > - if (newcontroller) { > - retval = add_control_value(newcontroller, > - control_file, wr, value_type, cval); > - > - if (!retval) { > - message(i++, PASS, "new_cgroup()", > - retval, info[NOMESSAGE]); > - } else { > - message(i++, FAIL, wr, retval, > - info[NOMESSAGE]); > - return NULL; > - } > - } else { > - /* Since these wrappers do not return an int so -1 */ > - message(i++, FAIL, "add_controller", -1, > - info[NOMESSAGE]); > - return NULL; > - } > - } else { > - message(i++, FAIL, "new_cgroup", -1, info[NOMESSAGE]); > - return NULL; > - } > - return newcgroup; > -} > - > -int check_fsmounted(int multimnt) > -{ > - int count = 0; > - struct mntent *entry, *tmp_entry = NULL; > - /* Need a better mechanism to decide memory allocation size here */ > - char entry_buffer[FILENAME_MAX * 4]; > - FILE *proc_file = NULL; > - int ret = 1; > - > - tmp_entry = (struct mntent *) malloc(sizeof(struct mntent)); > - if (!tmp_entry) { > - perror("Error: failled to mallloc for mntent\n"); > - ret = 1; > - goto error; > - } > - > - proc_file = fopen("/proc/mounts", "r"); > - if (!proc_file) { > - printf("Error in opening /proc/mounts.\n"); > - ret = errno; > - goto error; > - } > - while ((entry = getmntent_r(proc_file, tmp_entry, entry_buffer, > - FILENAME_MAX*4)) != NULL) { > - if (!strncmp(entry->mnt_type, "cgroup", strlen("cgroup"))) { > - count++; > - if (multimnt) { > - if (count >= 2) { > - printf("sanity check pass. %s\n", > - entry->mnt_type); > - ret = 0; > - goto error; > - } > - } else { > - printf("sanity check pass. %s\n", > - entry->mnt_type); > - ret = 0; > - goto error; > - } > - } > - } > -error: > - if (tmp_entry) > - free(tmp_entry); > - if (proc_file) > - fclose(proc_file); > - return ret; > -} > - > -static int check_task(char *tasksfile) > -{ > - FILE *file; > - pid_t curr_tid, tid; > - int pass = 0; > - > - file = fopen(tasksfile, "r"); > - if (!file) { > - printf("ERROR: in opening %s\n", tasksfile); > - printf("Exiting without running other testcases in this set\n"); > - exit(1); > - } > - > - curr_tid = cgrouptest_gettid(); > - while (!feof(file)) { > - fscanf(file, "%u", &tid); > - if (tid == curr_tid) { > - pass = 1; > - break; > - } > - } > - fclose(file); > - > - return pass; > -} > - > -static inline void message(int num, int pass, const char *api, > - int retval, char *extra) > -{ > - char res[10]; > - char buf[2*SIZE]; > - if (pass) > - strncpy(res, "PASS :", 10); > - else > - strncpy(res, "FAIL :", 10); > - > - /* Populate message buffer for the api */ > - snprintf(buf, sizeof(buf), "cgroup_%s\t\t Ret Value = ", api); > - fprintf(stdout, "TEST%2d:%s %s%d\t%s", num, res, buf, retval, extra); > -} > - > -/* builds the path to target file/group */ > -static inline void build_path(char *target, char *mountpoint, > - const char *group, const char *file) > -{ > - strncpy(target, mountpoint, FILENAME_MAX); > - > - if (group) { > - strncat(target, "/", FILENAME_MAX - strlen(target)); > - strncat(target, group, FILENAME_MAX - strlen(target)); > - } > - > - if (file) { > - strncat(target, "/", FILENAME_MAX - strlen(target)); > - strncat(target, file, FILENAME_MAX - strlen(target)); > - } > -} > - > -void test_cgroup_compare_cgroup(int ctl1, int ctl2, int i) > -{ > - int retval; > - > - struct cntl_val_t cval; > - cval.val_int64 = 0; > - cval.val_uint64 = 0; > - cval.val_bool = 0; > - strcpy(cval.val_string, "5000"); > - > - struct cgroup *cgroup1, *cgroup2; > - struct cgroup_controller *controller; > - char controller_name[FILENAME_MAX], control_file[FILENAME_MAX]; > - char wr[SIZE], extra[] = "in cgroup_compare_cgroup"; > - > - retval = cgroup_compare_cgroup(NULL, NULL); > - if (retval) > - message(i++, PASS, "compare_cgroup()", retval, info[NULLGRP]); > - else > - message(i++, FAIL, "compare_cgroup()", retval, info[NULLGRP]); > - > - cgroup1 = cgroup_new_cgroup("testgroup"); > - cgroup2 = cgroup_new_cgroup("testgroup"); > - cgroup_set_uid_gid(cgroup1, 0, 0, 0, 0); > - cgroup_set_uid_gid(cgroup2, 0, 0, 0, 0); > - > - retval = set_controller(ctl1, controller_name, control_file); > - > - controller = cgroup_add_controller(cgroup1, controller_name); > - if (controller) { > - retval = add_control_value(controller, > - control_file, wr, STRING, cval); > - if (retval) > - message(i++, FAIL, wr, retval, extra); > - } > - > - controller = cgroup_add_controller(cgroup2, controller_name); > - if (controller) { > - retval = add_control_value(controller, > - control_file, wr, STRING, cval); > - if (retval) > - message(i++, FAIL, wr, retval, extra); > - } > - > - retval = cgroup_compare_cgroup(cgroup1, cgroup2); > - if (retval) > - message(i++, FAIL, "compare_cgroup()", retval, info[NOMESSAGE]); > - else > - message(i++, PASS, "compare_cgroup()", retval, info[NOMESSAGE]); > - > - /* Test the api by putting diff number of controllers in cgroups */ > - retval = set_controller(ctl2, controller_name, control_file); > - controller = cgroup_add_controller(cgroup2, controller_name); > - if (controller) { > - retval = add_control_value(controller, > - control_file, wr, STRING, cval); > - if (retval) > - message(i++, FAIL, wr, retval, extra); > - } > - > - retval = cgroup_compare_cgroup(cgroup1, cgroup2); > - if (retval == ECGROUPNOTEQUAL) > - message(i++, PASS, "compare_cgroup()", retval, info[NOMESSAGE]); > - else > - message(i++, FAIL, "compare_cgroup()", retval, info[NOMESSAGE]); > - > - cgroup_free(&cgroup1); > - cgroup_free(&cgroup2); > -} > - > -void test_cgroup_get_cgroup(int ctl1, int ctl2, struct uid_gid_t ids, int i) > -{ > - struct cgroup *cgroup_filled = NULL, *cgroup_a = NULL, *cgroup_b = NULL; > - struct cgroup_controller *controller = NULL; > - char controller_name[FILENAME_MAX], control_file[FILENAME_MAX]; > - struct cntl_val_t cval = {0, 0, 0, "5000"}; > - int ret; > - > - /* > - * No need to test the next 3 scenarios again for Multimnt > - * so testing them only under single mount > - */ > - if (fs_mounted == FS_MOUNTED) { > - /* 1. Test with nullcgroup first */ > - ret = cgroup_get_cgroup(NULL); > - if (ret == ECGROUPNOTALLOWED) > - message(i++, PASS, "get_cgroup()", ret, info[NULLGRP]); > - else > - message(i++, FAIL, "get_cgroup()", ret, info[NULLGRP]); > - > - /* 2. Test with invalid name filled cgroup(non existing) */ > - cgroup_filled = cgroup_new_cgroup("nogroup"); > - if (!cgroup_filled) > - message(i++, FAIL, "new_cgroup()", 0, info[NOMESSAGE]); > - > - ret = cgroup_get_cgroup(cgroup_filled); > - if (ret) > - message(i++, PASS, "get_cgroup()", ret, > - info[NOTCRTDGRP]); > - else > - message(i++, FAIL, "get_cgroup()", ret, > - info[NOTCRTDGRP]); > - cgroup_free(&cgroup_filled); > - > - /* 3. > - * Test with name filled cgroup. Ensure the group group1 exists > - * in the filesystem before calling this test function > - */ > - cgroup_filled = cgroup_new_cgroup("group1"); > - if (!cgroup_filled) > - message(i++, FAIL, "new_cgroup()", 0, info[NOMESSAGE]); > - > - ret = cgroup_get_cgroup(cgroup_filled); > - if (!ret) > - message(i++, PASS, "get_cgroup()", ret, > - info[NOMESSAGE]); > - else > - message(i++, FAIL, "get_cgroup()", ret, > - info[NOMESSAGE]); > - } > - > - /* MULTIMOUNT: Create, get and compare a cgroup under both mounts */ > - > - /* get cgroup_a ds and create group_a in filesystem */ > - cgroup_a = create_new_cgroup_ds(ctl1, "group_a", STRING, cval, ids, 0); > - if (fs_mounted == FS_MULTI_MOUNTED) { > - /* Create under another controller also */ > - ret = set_controller(ctl2, controller_name, control_file); > - controller = cgroup_add_controller(cgroup_a, controller_name); > - } > - test_cgroup_create_cgroup(0, cgroup_a, "group_a", 0, 1, 1, 00); > - > - /* create group_b ds to be filled by cgroup_get_cgroup */ > - cgroup_b = cgroup_new_cgroup("group_a"); > - if (!cgroup_b) > - message(i++, FAIL, "new_cgroup()", 0, info[NOMESSAGE]); > - /* Fill the ds and compare the two */ > - ret = cgroup_get_cgroup(cgroup_b); > - if (!ret) { > - ret = cgroup_compare_cgroup(cgroup_a, cgroup_b); > - if (ret == 0) > - message(i++, PASS, "get_cgroup()", ret, info[SAMEGRP]); > - else > - message(i++, FAIL, "get_cgroup()", ret, > - info[NOMESSAGE]); > - } else { > - message(i++, FAIL, "get_cgroup()", ret, info[NOMESSAGE]); > - } > - > - cgroup_free(&cgroup_a); > - cgroup_free(&cgroup_b); > - cgroup_free(&cgroup_filled); > -} > - > -void test_cgroup_add_free_controller(int i) > -{ > - struct cgroup *cgroup1 = NULL, *cgroup2 = NULL; > - struct cgroup_controller *cgctl1, *cgctl2; > - > - /* Test with a Null cgroup */ > - cgctl1 = cgroup_add_controller(cgroup1, "cpu"); > - if (!cgctl1) > - message(i++, PASS, "add_controller()", 0, info[NOMESSAGE]); > - else > - message(i++, FAIL, "add_controller()", -1, info[NOMESSAGE]); > - > - cgroup1 = cgroup_new_cgroup("testgroup"); > - cgctl1 = cgroup_add_controller(cgroup1, "cpuset"); > - if (cgctl1) > - message(i++, PASS, "add_controller()", 0, info[NOMESSAGE]); > - else > - message(i++, FAIL, "add_controller()", -1, info[NOMESSAGE]); > - > - cgctl2 = cgroup_add_controller(cgroup1, "cpu"); > - if (cgctl2) > - message(i++, PASS, "add_controller()", 0, info[NOMESSAGE]); > - else > - message(i++, FAIL, "add_controller()", -1, info[NOMESSAGE]); > - > - cgroup_free(&cgroup1); > - cgroup_free_controllers(cgroup2); > - > -} > -- regards, Dhaval ------------------------------------------------------------------------------ Check out the new SourceForge.net Marketplace. It is the best place to buy or sell services for just about anything Open Source. http://p.sf.net/sfu/Xq1LFB _______________________________________________ Libcg-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/libcg-devel
