* [LTP] [PATCH] [syscalls] getrusage03: test ru_maxrss
@ 2011-05-16 15:05 Caspar Zhang
2011-05-16 15:08 ` Caspar Zhang
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Caspar Zhang @ 2011-05-16 15:05 UTC (permalink / raw)
To: LTP List
[-- Attachment #1: Type: text/plain, Size: 770 bytes --]
getrusage03 - test ru_maxrss behaviors in struct rusage
This test program is backported from upstream commit:
1f10206cf8e945220f7220a809d8bfc15c21f9a5, which fills ru_maxrss
value in struct rusage according to rss hiwater mark. To make sure
this feature works correctly, a series of tests are executed in
this program.
Signed-off-by: Caspar Zhang <czhang@redhat.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/getrusage/child.c | 165 ++++++++++
testcases/kernel/syscalls/getrusage/getrusage03.c | 341 +++++++++++++++++++++
3 files changed, 507 insertions(+), 0 deletions(-)
create mode 100644 testcases/kernel/syscalls/getrusage/child.c
create mode 100644 testcases/kernel/syscalls/getrusage/getrusage03.c
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-syscalls-getrusage03-test-ru_maxrss.patch --]
[-- Type: text/x-patch; name="0001-syscalls-getrusage03-test-ru_maxrss.patch", Size: 15727 bytes --]
diff --git a/runtest/syscalls b/runtest/syscalls
index 4294d07..7989764 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -399,6 +399,7 @@ get_robust_list01 get_robust_list01
getrusage01 getrusage01
getrusage02 getrusage02
+getrusage03 getrusage03
getsid01 getsid01
getsid02 getsid02
diff --git a/testcases/kernel/syscalls/getrusage/child.c b/testcases/kernel/syscalls/getrusage/child.c
new file mode 100644
index 0000000..4f81241
--- /dev/null
+++ b/testcases/kernel/syscalls/getrusage/child.c
@@ -0,0 +1,165 @@
+/*
+ * child.c - a child program executed by getrusage03
+ *
+ * Copyright (C) 2011 Red Hat, Inc.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU 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.
+ *
+ * Further, this software is distributed without any warranty that it
+ * is free of the rightful claim of any third person regarding
+ * infringement or the like. Any license provided herein, whether
+ * implied or otherwise, applies only to this software file. Patent
+ * licenses, if any, provided herein do not apply to combinations of
+ * this program with other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "test.h"
+#include "usctest.h"
+
+char *TCID = "child_proc ";
+int TST_TOTAL = 1;
+
+#define DELTA_MAX 10240
+
+static int opt_consume, opt_grand, opt_show, opt_self, opt_child;
+static char *consume_str, *grand_consume_str, *self_str, *child_str;
+
+option_t child_options[] = {
+ { "n:", &opt_consume, &consume_str },
+ { "g:", &opt_grand, &grand_consume_str },
+ { "v", &opt_show, NULL },
+ { "s:", &opt_self, &self_str },
+ { "l:", &opt_child, &child_str }
+};
+
+static void usage(void);
+static void consume(int mega);
+static void setup(void);
+static void cleanup(void);
+
+int main(int argc, char *argv[])
+{
+ int lc;
+ pid_t pid;
+ long maxrss_self, maxrss_children, delta;
+ struct rusage ru;
+ char *msg;
+
+ msg = parse_opts(argc, argv, child_options, usage);
+ if (msg != NULL)
+ tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
+
+ setup();
+
+ for (lc = 0; TEST_LOOPING(lc); lc++) {
+ Tst_count = 0;
+
+ if (opt_consume) {
+ tst_resm(TINFO, "child allocate %sMB", consume_str);
+ consume(atol(consume_str));
+ }
+
+ if (opt_grand) {
+ tst_resm(TINFO, "grandchild allocate %sMB",
+ grand_consume_str);
+ switch (pid = fork()) {
+ case -1:
+ tst_brkm(TBROK, cleanup, "fork");
+ case 0:
+ consume(atol(grand_consume_str));
+ exit(0);
+ default:
+ break;
+ }
+ while (waitpid(-1, &pid, WUNTRACED|WCONTINUED) > 0)
+ if (WEXITSTATUS(pid) != 0)
+ tst_brkm(TBROK|TERRNO, cleanup,
+ "child exit status is not 0");
+ }
+
+ if (opt_show) {
+ if (getrusage(RUSAGE_SELF, &ru) == -1)
+ tst_brkm(TBROK|TERRNO, cleanup,
+ "exec getrusage");
+ maxrss_self = ru.ru_maxrss;
+ if (getrusage(RUSAGE_CHILDREN, &ru) == -1)
+ tst_brkm(TBROK|TERRNO, cleanup,
+ "exec getrusage");
+ maxrss_children = ru.ru_maxrss;
+ tst_resm(TINFO, "exec.self = %ld, exec.children = %ld",
+ maxrss_self, maxrss_children);
+ if (opt_self) {
+ delta = maxrss_self - atol(self_str);
+ if (delta >= -DELTA_MAX && delta <= DELTA_MAX)
+ tst_resm(TPASS,
+ "initial.self ~= exec.self");
+ else
+ tst_resm(TFAIL,
+ "initial.self !~= exec.self");
+ }
+ if (opt_child) {
+ delta = maxrss_children - atol(child_str);
+ if (delta >= -DELTA_MAX && delta <= DELTA_MAX)
+ tst_resm(TPASS,
+ "initial.children ~= exec.children");
+ else
+ tst_resm(TFAIL,
+ "initial.children !~= exec.children");
+ }
+ }
+ }
+
+ cleanup();
+ tst_exit();
+}
+
+static void usage(void)
+{
+ printf(" -n consume size (MB)\n");
+ printf(" -g grandchild consume size (MB)\n");
+ printf(" -v verbose mode, show rusage info\n");
+ printf(" -s compare rusage_self.maxrss with given number\n");
+ printf(" -l compare rusage_children.maxrss with given number\n");
+}
+
+static void consume(int mega)
+{
+ size_t sz;
+ void *ptr;
+
+ sz = mega * 1024 * 1024;
+ ptr = malloc(sz);
+ memset(ptr, 0, sz);
+}
+
+static void setup()
+{
+ tst_sig(FORK, DEF_HANDLER, cleanup);
+
+ TEST_PAUSE;
+}
+
+static void cleanup()
+{
+ TEST_CLEANUP;
+}
diff --git a/testcases/kernel/syscalls/getrusage/getrusage03.c b/testcases/kernel/syscalls/getrusage/getrusage03.c
new file mode 100644
index 0000000..c1d8108
--- /dev/null
+++ b/testcases/kernel/syscalls/getrusage/getrusage03.c
@@ -0,0 +1,341 @@
+/*
+ * getrusage03 - test ru_maxrss behaviors in struct rusage
+ *
+ * This test program is backported from upstream commit:
+ * 1f10206cf8e945220f7220a809d8bfc15c21f9a5, which fills ru_maxrss
+ * value in struct rusage according to rss hiwater mark. To make sure
+ * this feature works correctly, a series of tests are executed in
+ * this program.
+ *
+ * Copyright (C) 2011 Red Hat, Inc.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU 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.
+ *
+ * Further, this software is distributed without any warranty that it
+ * is free of the rightful claim of any third person regarding
+ * infringement or the like. Any license provided herein, whether
+ * implied or otherwise, applies only to this software file. Patent
+ * licenses, if any, provided herein do not apply to combinations of
+ * this program with other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "test.h"
+#include "usctest.h"
+
+char *TCID = "getrusage03";
+int TST_TOTAL = 7, Tst_count;
+
+#define DELTA_MAX 10240
+#define ERR(x) perror(x), cleanup(), exit(-1);
+
+static struct rusage ru;
+static long maxrss_init;
+
+static void check_return(int status, char *pass_msg, char *fail_msg);
+static void consume(int mega);
+static void setup(void);
+static void cleanup(void);
+
+int main(int argc, char *argv[])
+{
+ int lc;
+ long delta;
+ int retval;
+ pid_t pid;
+ char *msg;
+ long maxrss_self, maxrss_child;
+ char str_maxrss_self[BUFSIZ], str_maxrss_child[BUFSIZ];
+
+ msg = parse_opts(argc, argv, NULL, NULL);
+ if (msg != NULL)
+ tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
+
+ setup();
+
+ for (lc = 0; TEST_LOOPING(lc); lc++) {
+ Tst_count = 0;
+
+ tst_resm(TINFO, "allocate 100MB");
+ consume(100);
+
+ /* Testcase #01: fork inherit
+ * expect: initial.self ~= child.self */
+ tst_resm(TINFO, "Testcase #01: fork inherit");
+ if (getrusage(RUSAGE_SELF, &ru) == -1)
+ tst_brkm(TBROK|TERRNO, cleanup, "getrusage #1");
+ tst_resm(TINFO, "initial.self = %ld", ru.ru_maxrss);
+
+ switch (pid = fork()) {
+ case -1:
+ tst_brkm(TBROK|TERRNO, cleanup, "fork #1");
+ case 0:
+ maxrss_init = ru.ru_maxrss;
+ if (getrusage(RUSAGE_SELF, &ru) == -1)
+ ERR("child: getrusage #1");
+ printf("%-8s %4d TINFO : child.self = %ld\n",
+ "child_proc ", 0, ru.ru_maxrss);
+ delta = maxrss_init - ru.ru_maxrss;
+ retval = (delta >= -DELTA_MAX &&
+ delta <= DELTA_MAX) ? 0 : 1;
+ exit(retval);
+ default:
+ break;
+ }
+ while (waitpid(-1, &pid, WUNTRACED|WCONTINUED) > 0)
+ check_return(WEXITSTATUS(pid),
+ "initial.self ~= child.self",
+ "initial.self !~= child.self");
+
+ /*
+ * Testcase #02: fork inherit (cont.)
+ * expect: initial.children ~= 100MB,
+ * child.children = 0
+ */
+ tst_resm(TINFO, "Testcase #02: fork inherit(cont.)");
+ if (getrusage(RUSAGE_CHILDREN, &ru) == -1)
+ tst_brkm(TBROK|TERRNO, cleanup, "getrusage #2");
+ tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss);
+ delta = ru.ru_maxrss - 102400;
+ if (delta >= -DELTA_MAX && delta <= DELTA_MAX)
+ tst_resm(TPASS, "initial.children ~= 100MB");
+ else
+ tst_resm(TFAIL, "initial.children !~= 100MB");
+
+ switch (pid = fork()) {
+ case -1:
+ tst_brkm(TBROK|TERRNO, cleanup, "fork #2");
+ case 0:
+ if (getrusage(RUSAGE_CHILDREN, &ru) == -1)
+ ERR("child: getrusage #2");
+ printf("%-8s %4d TINFO : child.children = %ld\n",
+ "child_proc ", 0, ru.ru_maxrss);
+ retval = (ru.ru_maxrss == 0) ? 0 : 1;
+ exit(retval);
+ default:
+ break;
+ }
+ while (waitpid(-1, &pid, WUNTRACED|WCONTINUED) > 0)
+ check_return(WEXITSTATUS(pid),
+ "child.children == 0",
+ "child.children != 0");
+
+ /* Testcase #03: fork + malloc
+ * expect: initial.self + 50MB ~= child.self */
+ tst_resm(TINFO, "Testcase #03: fork + malloc");
+ if (getrusage(RUSAGE_SELF, &ru) == -1)
+ tst_brkm(TBROK|TERRNO, cleanup, "getrusage #3");
+ tst_resm(TINFO, "initial.self = %ld", ru.ru_maxrss);
+
+ switch (pid = fork()) {
+ case -1:
+ tst_brkm(TBROK|TERRNO, cleanup, "fork #3");
+ case 0:
+ maxrss_init = ru.ru_maxrss;
+ printf("%-8s %4d TINFO : child allocate +50MB\n",
+ "child_proc ", 0);
+ consume(50);
+ if (getrusage(RUSAGE_SELF, &ru) == -1)
+ ERR("child getrusage #3");
+ printf("%-8s %4d TINFO : child.self = %ld\n",
+ "child_proc ", 0, ru.ru_maxrss);
+ delta = maxrss_init + 51200 - ru.ru_maxrss;
+ retval = (delta >= -DELTA_MAX &&
+ delta <= DELTA_MAX) ? 0 : 1;
+ exit(retval);
+ default:
+ break;
+ }
+ while (waitpid(-1, &pid, WUNTRACED|WCONTINUED) > 0)
+ check_return(WEXITSTATUS(pid),
+ "initial.self + 50MB ~= child.self",
+ "initial.self + 50MB !~= child.self");
+
+ /* Testcase #04: grandchild maxrss
+ * expect: post_wait.children ~= 300MB */
+ tst_resm(TINFO, "Testcase #04: grandchild maxrss");
+ if (getrusage(RUSAGE_CHILDREN, &ru) == -1)
+ tst_brkm(TBROK|TERRNO, cleanup, "getrusage #4");
+ tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss);
+
+ switch (pid = fork()) {
+ case -1:
+ tst_brkm(TBROK|TERRNO, cleanup, "fork #4");
+ case 0:
+ retval = system("./child -g 300");
+ if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0))
+ ERR("system");
+ exit(0);
+ default:
+ break;
+ }
+ while (waitpid(-1, &pid, WUNTRACED|WCONTINUED) > 0)
+ if (WEXITSTATUS(pid) != 0)
+ tst_brkm(TBROK|TERRNO, cleanup,
+ "child exit status is not 0");
+ if (getrusage(RUSAGE_CHILDREN, &ru) == -1)
+ tst_brkm(TBROK|TERRNO, cleanup,
+ "post_wait getrusage #4");
+ tst_resm(TINFO, "post_wait.children = %ld",
+ ru.ru_maxrss);
+ delta = ru.ru_maxrss - 307200;
+ if (delta >= -DELTA_MAX && delta <= DELTA_MAX)
+ tst_resm(TPASS, "child.children ~= 300MB");
+ else
+ tst_resm(TFAIL, "child.children !~= 300MB");
+
+ /* Testcase #05: zombie
+ * expect: initial ~= pre_wait, post_wait ~= 400MB */
+ tst_resm(TINFO, "Testcase #05: zombie");
+ if (getrusage(RUSAGE_CHILDREN, &ru) == -1)
+ tst_brkm(TBROK|TERRNO, cleanup, "getrusage #5");
+ tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss);
+ maxrss_init = ru.ru_maxrss;
+ switch (pid = fork()) {
+ case -1:
+ tst_brkm(TBROK, cleanup, "fork #5");
+ case 0:
+ retval = system("./child -n 400");
+ if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0))
+ ERR("system");
+ exit(0);
+ default:
+ break;
+ }
+ sleep(1); /* children become zombie */
+ if (getrusage(RUSAGE_CHILDREN, &ru) == -1)
+ tst_brkm(TBROK|TERRNO, cleanup,
+ "pre_wait getrusage #5");
+ tst_resm(TINFO, "pre_wait.children = %ld", ru.ru_maxrss);
+ delta = ru.ru_maxrss - maxrss_init;
+ if (delta >= -DELTA_MAX && delta <= DELTA_MAX)
+ tst_resm(TPASS,
+ "initial.children ~= pre_wait.children");
+ else
+ tst_resm(TFAIL,
+ "initial.children !~= pre_wait.children");
+ while (waitpid(-1, &pid, WUNTRACED|WCONTINUED) > 0)
+ if (WEXITSTATUS(pid) != 0)
+ tst_brkm(TBROK|TERRNO, cleanup,
+ "child exit status is not 0");
+ if (getrusage(RUSAGE_CHILDREN, &ru) == -1)
+ tst_brkm(TBROK|TERRNO, cleanup,
+ "post_wait getrusage #5");
+ tst_resm(TINFO, "post_wait.children = %ld", ru.ru_maxrss);
+ delta = ru.ru_maxrss - 409600;
+ if (delta >= -DELTA_MAX && delta <= DELTA_MAX)
+ tst_resm(TPASS, "post_wait.children ~= 400MB");
+ else
+ tst_resm(TFAIL, "post_wait.children !~= 400MB");
+
+ /* Testcase #06: SIG_IGN
+ * expect: initial ~= after_zombie */
+ tst_resm(TINFO, "Testcase #06: SIG_IGN");
+ if (getrusage(RUSAGE_CHILDREN, &ru) == -1)
+ tst_brkm(TBROK|TERRNO, cleanup, "getrusage #6");
+ tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss);
+ signal(SIGCHLD, SIG_IGN);
+ maxrss_init = ru.ru_maxrss;
+ switch (pid = fork()) {
+ case -1:
+ tst_brkm(TBROK, cleanup, "fork #6");
+ case 0:
+ retval = system("./child -n 500");
+ if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0))
+ ERR("system");
+ exit(0);
+ default:
+ break;
+ }
+ sleep(1); /* children become zombie */
+ if (getrusage(RUSAGE_CHILDREN, &ru) == -1)
+ tst_brkm(TBROK|TERRNO, cleanup,
+ "after_zombie getrusage #6");
+ tst_resm(TINFO, "after_zombie.children = %ld",
+ ru.ru_maxrss);
+ delta = ru.ru_maxrss - maxrss_init;
+ if (delta >= -DELTA_MAX && delta <= DELTA_MAX)
+ tst_resm(TPASS,
+ "initial.children ~= after_zombie.children");
+ else
+ tst_resm(TFAIL,
+ "initial.children !~= after_zombie.children");
+ signal(SIGCHLD, SIG_DFL);
+
+ /* Testcase #07: exec without fork
+ * expect: initial ~= fork */
+ tst_resm(TINFO, "Testcase #07: exec without fork");
+ if (getrusage(RUSAGE_SELF, &ru) == -1)
+ tst_brkm(TBROK|TERRNO, cleanup, "getrusage #7");
+ maxrss_self = ru.ru_maxrss;
+ if (getrusage(RUSAGE_CHILDREN, &ru) == -1)
+ tst_brkm(TBROK|TERRNO, cleanup, "getrusage #7");
+ maxrss_child = ru.ru_maxrss;
+ tst_resm(TINFO, "initial.self = %ld, initial.children = %ld",
+ maxrss_self, maxrss_child);
+ sprintf(str_maxrss_self, "%ld", maxrss_self);
+ sprintf(str_maxrss_child, "%ld", maxrss_child);
+ if (execl("./child", "child", "-v",
+ "-s", str_maxrss_self,
+ "-l", str_maxrss_child, NULL) == -1)
+ tst_brkm(TBROK|TERRNO, cleanup, "execl");
+ }
+ cleanup();
+ tst_exit();
+}
+
+static void check_return(int status, char *pass_msg, char *fail_msg)
+{
+ switch (status) {
+ case 0:
+ tst_resm(TPASS, "%s", pass_msg);
+ break;
+ case 1:
+ tst_resm(TFAIL, "%s", fail_msg);
+ break;
+ default:
+ tst_resm(TFAIL, "child exit status is %d", status);
+ break;
+ }
+}
+
+static void consume(int mega)
+{
+ size_t sz;
+ void *ptr;
+
+ sz = mega * 1024 * 1024;
+ ptr = malloc(sz);
+ memset(ptr, 0, sz);
+}
+
+static void setup(void)
+{
+ tst_sig(FORK, DEF_HANDLER, cleanup);
+
+ TEST_PAUSE;
+}
+
+static void cleanup(void)
+{
+ TEST_CLEANUP;
+}
[-- Attachment #3: Type: text/plain, Size: 350 bytes --]
------------------------------------------------------------------------------
Achieve unprecedented app performance and reliability
What every C/C++ and Fortran developer should know.
Learn how Intel has extended the reach of its next-generation tools
to help boost performance applications - inlcuding clusters.
http://p.sf.net/sfu/intel-dev2devmay
[-- Attachment #4: Type: text/plain, Size: 155 bytes --]
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [LTP] [PATCH] [syscalls] getrusage03: test ru_maxrss 2011-05-16 15:05 [LTP] [PATCH] [syscalls] getrusage03: test ru_maxrss Caspar Zhang @ 2011-05-16 15:08 ` Caspar Zhang 2011-05-19 17:40 ` Cyril Hrubis 2011-06-13 13:12 ` [LTP] [PATCH v2] " Caspar Zhang 2 siblings, 0 replies; 10+ messages in thread From: Caspar Zhang @ 2011-05-16 15:08 UTC (permalink / raw) To: LTP List On 05/16/2011 11:05 PM, Caspar Zhang wrote: > > getrusage03 - test ru_maxrss behaviors in struct rusage > > This test program is backported from upstream commit: > 1f10206cf8e945220f7220a809d8bfc15c21f9a5, which fills ru_maxrss > value in struct rusage according to rss hiwater mark. To make sure > this feature works correctly, a series of tests are executed in > this program. > > Signed-off-by: Caspar Zhang <czhang@redhat.com> > --- > runtest/syscalls | 1 + > testcases/kernel/syscalls/getrusage/child.c | 165 ++++++++++ > testcases/kernel/syscalls/getrusage/getrusage03.c | 341 +++++++++++++++++++++ > 3 files changed, 507 insertions(+), 0 deletions(-) > create mode 100644 testcases/kernel/syscalls/getrusage/child.c > create mode 100644 testcases/kernel/syscalls/getrusage/getrusage03.c > PASS/FAIL Criteria ================== This test PASS when all sub-tests executed successfully and return code is 0. The test gets FAIL when any TFAIL/TBROK information occurs on output or/and the return code is a non-zero value. EXAMPLE OUTPUT ============== getrusage03 0 TINFO : allocate 100MB getrusage03 0 TINFO : Testcase #01: fork inherit getrusage03 0 TINFO : initial.self = 108456 child_proc 0 TINFO : child.self = 103632 getrusage03 1 TPASS : initial.self ~= child.self getrusage03 0 TINFO : Testcase #02: fork inherit(cont.) getrusage03 0 TINFO : initial.children = 105244 getrusage03 2 TPASS : initial.children ~= 100MB child_proc 0 TINFO : child.children = 0 getrusage03 3 TPASS : child.children == 0 getrusage03 0 TINFO : Testcase #03: fork + malloc getrusage03 0 TINFO : initial.self = 108716 child_proc 0 TINFO : child allocate +50MB child_proc 0 TINFO : child.self = 154744 getrusage03 4 TPASS : initial.self + 50MB ~= child.self getrusage03 0 TINFO : Testcase #04: grandchild maxrss getrusage03 0 TINFO : initial.children = 156460 child_proc 0 TINFO : grandchild allocate 300MB getrusage03 0 TINFO : post_wait.children = 310028 getrusage03 5 TPASS : child.children ~= 300MB getrusage03 0 TINFO : Testcase #05: zombie getrusage03 0 TINFO : initial.children = 310028 child_proc 0 TINFO : child allocate 400MB getrusage03 0 TINFO : pre_wait.children = 310028 getrusage03 6 TPASS : initial.children ~= pre_wait.children getrusage03 0 TINFO : post_wait.children = 415972 getrusage03 7 TPASS : post_wait.children ~= 400MB getrusage03 0 TINFO : Testcase #06: SIG_IGN getrusage03 0 TINFO : initial.children = 415972 child_proc 0 TINFO : child allocate 500MB getrusage03 0 TINFO : after_zombie.children = 415972 getrusage03 8 TPASS : initial.children ~= after_zombie.children getrusage03 0 TINFO : Testcase #07: exec without fork getrusage03 0 TINFO : initial.self = 108720, initial.children = 415972 child_proc 0 TINFO : exec.self = 108732, exec.children = 415972 child_proc 1 TPASS : initial.self ~= exec.self child_proc 2 TPASS : initial.children ~= exec.children # echo $? 0 ------------------------------------------------------------------------------ Achieve unprecedented app performance and reliability What every C/C++ and Fortran developer should know. Learn how Intel has extended the reach of its next-generation tools to help boost performance applications - inlcuding clusters. http://p.sf.net/sfu/intel-dev2devmay _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [LTP] [PATCH] [syscalls] getrusage03: test ru_maxrss 2011-05-16 15:05 [LTP] [PATCH] [syscalls] getrusage03: test ru_maxrss Caspar Zhang 2011-05-16 15:08 ` Caspar Zhang @ 2011-05-19 17:40 ` Cyril Hrubis [not found] ` <BANLkTi=m96RBZeFuRaOA5Sb_QANhgo4yCA@mail.gmail.com> 2011-06-13 13:12 ` [LTP] [PATCH v2] " Caspar Zhang 2 siblings, 1 reply; 10+ messages in thread From: Cyril Hrubis @ 2011-05-19 17:40 UTC (permalink / raw) To: Caspar Zhang; +Cc: LTP List Hi! > +char *TCID = "child_proc "; Is this whitespace at the end of child_proc intentional? > +int TST_TOTAL = 1; > + > +#define DELTA_MAX 10240 > + > +static int opt_consume, opt_grand, opt_show, opt_self, opt_child; > +static char *consume_str, *grand_consume_str, *self_str, *child_str; > + > +option_t child_options[] = { > + { "n:", &opt_consume, &consume_str }, > + { "g:", &opt_grand, &grand_consume_str }, > + { "v", &opt_show, NULL }, > + { "s:", &opt_self, &self_str }, > + { "l:", &opt_child, &child_str } > +}; > + > +static void usage(void); > +static void consume(int mega); > +static void setup(void); > +static void cleanup(void); > + > +int main(int argc, char *argv[]) > +{ > + int lc; > + pid_t pid; > + long maxrss_self, maxrss_children, delta; > + struct rusage ru; > + char *msg; > + > + msg = parse_opts(argc, argv, child_options, usage); > + if (msg != NULL) > + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); > + > + setup(); > + > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + Tst_count = 0; > + > + if (opt_consume) { > + tst_resm(TINFO, "child allocate %sMB", consume_str); > + consume(atol(consume_str)); I would rather use strtol() here and print errors when invalid parameters were given. > + } > + > + if (opt_grand) { > + tst_resm(TINFO, "grandchild allocate %sMB", > + grand_consume_str); > + switch (pid = fork()) { > + case -1: > + tst_brkm(TBROK, cleanup, "fork"); > + case 0: > + consume(atol(grand_consume_str)); Here too. > + exit(0); > + default: > + break; > + } > + while (waitpid(-1, &pid, WUNTRACED|WCONTINUED) > 0) > + if (WEXITSTATUS(pid) != 0) > + tst_brkm(TBROK|TERRNO, cleanup, > + "child exit status is not 0"); > + } > + > + if (opt_show) { > + if (getrusage(RUSAGE_SELF, &ru) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, > + "exec getrusage"); > + maxrss_self = ru.ru_maxrss; > + if (getrusage(RUSAGE_CHILDREN, &ru) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, > + "exec getrusage"); > + maxrss_children = ru.ru_maxrss; > + tst_resm(TINFO, "exec.self = %ld, exec.children = %ld", > + maxrss_self, maxrss_children); > + if (opt_self) { > + delta = maxrss_self - atol(self_str); > + if (delta >= -DELTA_MAX && delta <= DELTA_MAX) > + tst_resm(TPASS, > + "initial.self ~= exec.self"); > + else > + tst_resm(TFAIL, > + "initial.self !~= exec.self"); > + } > + if (opt_child) { > + delta = maxrss_children - atol(child_str); > + if (delta >= -DELTA_MAX && delta <= DELTA_MAX) > + tst_resm(TPASS, > + "initial.children ~= exec.children"); > + else > + tst_resm(TFAIL, > + "initial.children !~= exec.children"); > + } > + } > + } > + > + cleanup(); > + tst_exit(); > +} > + > +static void usage(void) > +{ > + printf(" -n consume size (MB)\n"); > + printf(" -g grandchild consume size (MB)\n"); > + printf(" -v verbose mode, show rusage info\n"); > + printf(" -s compare rusage_self.maxrss with given number\n"); > + printf(" -l compare rusage_children.maxrss with given number\n"); > +} > + > +static void consume(int mega) > +{ > + size_t sz; > + void *ptr; > + > + sz = mega * 1024 * 1024; > + ptr = malloc(sz); > + memset(ptr, 0, sz); > +} > + > +static void setup() > +{ > + tst_sig(FORK, DEF_HANDLER, cleanup); > + > + TEST_PAUSE; > +} > + > +static void cleanup() > +{ > + TEST_CLEANUP; > +} Also naming the file simple child.c is not wise idea as it likely will collide after installation. I would suggest getrusage03_child.c here. It seems that there isn't child binary just now, but even then, somebody will burn because of that sooner or later. > diff --git a/testcases/kernel/syscalls/getrusage/getrusage03.c b/testcases/kernel/syscalls/getrusage/getrusage03.c > new file mode 100644 > index 0000000..c1d8108 > --- /dev/null > +++ b/testcases/kernel/syscalls/getrusage/getrusage03.c > @@ -0,0 +1,341 @@ > +/* > + * getrusage03 - test ru_maxrss behaviors in struct rusage > + * > + * This test program is backported from upstream commit: > + * 1f10206cf8e945220f7220a809d8bfc15c21f9a5, which fills ru_maxrss > + * value in struct rusage according to rss hiwater mark. To make sure > + * this feature works correctly, a series of tests are executed in > + * this program. > + * > + * Copyright (C) 2011 Red Hat, Inc. > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of version 2 of the GNU 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. > + * > + * Further, this software is distributed without any warranty that it > + * is free of the rightful claim of any third person regarding > + * infringement or the like. Any license provided herein, whether > + * implied or otherwise, applies only to this software file. Patent > + * licenses, if any, provided herein do not apply to combinations of > + * this program with other software, or any other product whatsoever. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA > + * 02110-1301, USA. > + */ > +#include <sys/types.h> > +#include <sys/mman.h> > +#include <sys/resource.h> > +#include <sys/time.h> > +#include <sys/wait.h> > +#include <unistd.h> > +#include <signal.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > + > +#include "test.h" > +#include "usctest.h" > + > +char *TCID = "getrusage03"; > +int TST_TOTAL = 7, Tst_count; > + > +#define DELTA_MAX 10240 > +#define ERR(x) perror(x), cleanup(), exit(-1); > + > +static struct rusage ru; > +static long maxrss_init; > + > +static void check_return(int status, char *pass_msg, char *fail_msg); > +static void consume(int mega); > +static void setup(void); > +static void cleanup(void); > + > +int main(int argc, char *argv[]) > +{ > + int lc; > + long delta; > + int retval; > + pid_t pid; > + char *msg; > + long maxrss_self, maxrss_child; > + char str_maxrss_self[BUFSIZ], str_maxrss_child[BUFSIZ]; > + > + msg = parse_opts(argc, argv, NULL, NULL); > + if (msg != NULL) > + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); > + > + setup(); > + > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + Tst_count = 0; > + > + tst_resm(TINFO, "allocate 100MB"); > + consume(100); > + > + /* Testcase #01: fork inherit > + * expect: initial.self ~= child.self */ > + tst_resm(TINFO, "Testcase #01: fork inherit"); > + if (getrusage(RUSAGE_SELF, &ru) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "getrusage #1"); > + tst_resm(TINFO, "initial.self = %ld", ru.ru_maxrss); > + > + switch (pid = fork()) { > + case -1: > + tst_brkm(TBROK|TERRNO, cleanup, "fork #1"); > + case 0: > + maxrss_init = ru.ru_maxrss; > + if (getrusage(RUSAGE_SELF, &ru) == -1) > + ERR("child: getrusage #1"); > + printf("%-8s %4d TINFO : child.self = %ld\n", > + "child_proc ", 0, ru.ru_maxrss); > + delta = maxrss_init - ru.ru_maxrss; > + retval = (delta >= -DELTA_MAX && > + delta <= DELTA_MAX) ? 0 : 1; > + exit(retval); > + default: > + break; > + } > + while (waitpid(-1, &pid, WUNTRACED|WCONTINUED) > 0) > + check_return(WEXITSTATUS(pid), > + "initial.self ~= child.self", > + "initial.self !~= child.self"); > + > + /* > + * Testcase #02: fork inherit (cont.) > + * expect: initial.children ~= 100MB, > + * child.children = 0 > + */ > + tst_resm(TINFO, "Testcase #02: fork inherit(cont.)"); > + if (getrusage(RUSAGE_CHILDREN, &ru) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "getrusage #2"); > + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); > + delta = ru.ru_maxrss - 102400; > + if (delta >= -DELTA_MAX && delta <= DELTA_MAX) > + tst_resm(TPASS, "initial.children ~= 100MB"); > + else > + tst_resm(TFAIL, "initial.children !~= 100MB"); > + > + switch (pid = fork()) { > + case -1: > + tst_brkm(TBROK|TERRNO, cleanup, "fork #2"); > + case 0: > + if (getrusage(RUSAGE_CHILDREN, &ru) == -1) > + ERR("child: getrusage #2"); > + printf("%-8s %4d TINFO : child.children = %ld\n", > + "child_proc ", 0, ru.ru_maxrss); > + retval = (ru.ru_maxrss == 0) ? 0 : 1; > + exit(retval); > + default: > + break; > + } > + while (waitpid(-1, &pid, WUNTRACED|WCONTINUED) > 0) > + check_return(WEXITSTATUS(pid), > + "child.children == 0", > + "child.children != 0"); > + > + /* Testcase #03: fork + malloc > + * expect: initial.self + 50MB ~= child.self */ > + tst_resm(TINFO, "Testcase #03: fork + malloc"); > + if (getrusage(RUSAGE_SELF, &ru) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "getrusage #3"); > + tst_resm(TINFO, "initial.self = %ld", ru.ru_maxrss); > + > + switch (pid = fork()) { > + case -1: > + tst_brkm(TBROK|TERRNO, cleanup, "fork #3"); > + case 0: > + maxrss_init = ru.ru_maxrss; > + printf("%-8s %4d TINFO : child allocate +50MB\n", > + "child_proc ", 0); > + consume(50); > + if (getrusage(RUSAGE_SELF, &ru) == -1) > + ERR("child getrusage #3"); > + printf("%-8s %4d TINFO : child.self = %ld\n", > + "child_proc ", 0, ru.ru_maxrss); > + delta = maxrss_init + 51200 - ru.ru_maxrss; > + retval = (delta >= -DELTA_MAX && > + delta <= DELTA_MAX) ? 0 : 1; > + exit(retval); > + default: > + break; > + } > + while (waitpid(-1, &pid, WUNTRACED|WCONTINUED) > 0) > + check_return(WEXITSTATUS(pid), > + "initial.self + 50MB ~= child.self", > + "initial.self + 50MB !~= child.self"); > + > + /* Testcase #04: grandchild maxrss > + * expect: post_wait.children ~= 300MB */ > + tst_resm(TINFO, "Testcase #04: grandchild maxrss"); > + if (getrusage(RUSAGE_CHILDREN, &ru) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "getrusage #4"); > + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); > + > + switch (pid = fork()) { > + case -1: > + tst_brkm(TBROK|TERRNO, cleanup, "fork #4"); > + case 0: > + retval = system("./child -g 300"); > + if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0)) > + ERR("system"); > + exit(0); > + default: > + break; > + } > + while (waitpid(-1, &pid, WUNTRACED|WCONTINUED) > 0) > + if (WEXITSTATUS(pid) != 0) > + tst_brkm(TBROK|TERRNO, cleanup, > + "child exit status is not 0"); > + if (getrusage(RUSAGE_CHILDREN, &ru) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, > + "post_wait getrusage #4"); > + tst_resm(TINFO, "post_wait.children = %ld", > + ru.ru_maxrss); > + delta = ru.ru_maxrss - 307200; > + if (delta >= -DELTA_MAX && delta <= DELTA_MAX) > + tst_resm(TPASS, "child.children ~= 300MB"); > + else > + tst_resm(TFAIL, "child.children !~= 300MB"); > + > + /* Testcase #05: zombie > + * expect: initial ~= pre_wait, post_wait ~= 400MB */ > + tst_resm(TINFO, "Testcase #05: zombie"); > + if (getrusage(RUSAGE_CHILDREN, &ru) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "getrusage #5"); > + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); > + maxrss_init = ru.ru_maxrss; > + switch (pid = fork()) { > + case -1: > + tst_brkm(TBROK, cleanup, "fork #5"); > + case 0: > + retval = system("./child -n 400"); > + if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0)) > + ERR("system"); > + exit(0); > + default: > + break; > + } > + sleep(1); /* children become zombie */ > + if (getrusage(RUSAGE_CHILDREN, &ru) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, > + "pre_wait getrusage #5"); > + tst_resm(TINFO, "pre_wait.children = %ld", ru.ru_maxrss); > + delta = ru.ru_maxrss - maxrss_init; > + if (delta >= -DELTA_MAX && delta <= DELTA_MAX) > + tst_resm(TPASS, > + "initial.children ~= pre_wait.children"); > + else > + tst_resm(TFAIL, > + "initial.children !~= pre_wait.children"); > + while (waitpid(-1, &pid, WUNTRACED|WCONTINUED) > 0) > + if (WEXITSTATUS(pid) != 0) > + tst_brkm(TBROK|TERRNO, cleanup, > + "child exit status is not 0"); > + if (getrusage(RUSAGE_CHILDREN, &ru) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, > + "post_wait getrusage #5"); > + tst_resm(TINFO, "post_wait.children = %ld", ru.ru_maxrss); > + delta = ru.ru_maxrss - 409600; > + if (delta >= -DELTA_MAX && delta <= DELTA_MAX) > + tst_resm(TPASS, "post_wait.children ~= 400MB"); > + else > + tst_resm(TFAIL, "post_wait.children !~= 400MB"); > + > + /* Testcase #06: SIG_IGN > + * expect: initial ~= after_zombie */ > + tst_resm(TINFO, "Testcase #06: SIG_IGN"); > + if (getrusage(RUSAGE_CHILDREN, &ru) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "getrusage #6"); > + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); > + signal(SIGCHLD, SIG_IGN); > + maxrss_init = ru.ru_maxrss; > + switch (pid = fork()) { > + case -1: > + tst_brkm(TBROK, cleanup, "fork #6"); > + case 0: > + retval = system("./child -n 500"); > + if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0)) > + ERR("system"); > + exit(0); > + default: > + break; > + } > + sleep(1); /* children become zombie */ > + if (getrusage(RUSAGE_CHILDREN, &ru) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, > + "after_zombie getrusage #6"); > + tst_resm(TINFO, "after_zombie.children = %ld", > + ru.ru_maxrss); > + delta = ru.ru_maxrss - maxrss_init; > + if (delta >= -DELTA_MAX && delta <= DELTA_MAX) > + tst_resm(TPASS, > + "initial.children ~= after_zombie.children"); > + else > + tst_resm(TFAIL, > + "initial.children !~= after_zombie.children"); > + signal(SIGCHLD, SIG_DFL); > + > + /* Testcase #07: exec without fork > + * expect: initial ~= fork */ > + tst_resm(TINFO, "Testcase #07: exec without fork"); > + if (getrusage(RUSAGE_SELF, &ru) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "getrusage #7"); > + maxrss_self = ru.ru_maxrss; > + if (getrusage(RUSAGE_CHILDREN, &ru) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "getrusage #7"); > + maxrss_child = ru.ru_maxrss; > + tst_resm(TINFO, "initial.self = %ld, initial.children = %ld", > + maxrss_self, maxrss_child); > + sprintf(str_maxrss_self, "%ld", maxrss_self); > + sprintf(str_maxrss_child, "%ld", maxrss_child); > + if (execl("./child", "child", "-v", > + "-s", str_maxrss_self, > + "-l", str_maxrss_child, NULL) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "execl"); Executing binaries from local directory likely won't work after the test is installed. Do we have some helper fuctions for that; Garrett? > + } > + cleanup(); > + tst_exit(); > +} Aaargh, the main is too long, could you split the testcases into individual functions. Also creating SAFE_GETRUSAGE() (as it is done in include/safe_macros.h) would probably make the code simplier. And creating function to handle the delta may help too, then you can just easily write: if (is_in_delta(ru.ru_maxrss - maxrss_init)) { ... or: exit(is_in_delta(maxrss_init - ru.ru_maxrss)); > +static void check_return(int status, char *pass_msg, char *fail_msg) > +{ > + switch (status) { > + case 0: > + tst_resm(TPASS, "%s", pass_msg); > + break; > + case 1: > + tst_resm(TFAIL, "%s", fail_msg); > + break; > + default: > + tst_resm(TFAIL, "child exit status is %d", status); > + break; > + } > +} > + > +static void consume(int mega) > +{ > + size_t sz; > + void *ptr; > + > + sz = mega * 1024 * 1024; > + ptr = malloc(sz); > + memset(ptr, 0, sz); > +} I would rather check the return value here. You know, there may be strange linux system where this may segfault here. Or even better, use SAFE_MALLOC() from safe_macros.h. > +static void setup(void) > +{ > + tst_sig(FORK, DEF_HANDLER, cleanup); > + > + TEST_PAUSE; > +} > + > +static void cleanup(void) > +{ > + TEST_CLEANUP; > +} -- Cyril Hrubis chrubis@suse.cz ------------------------------------------------------------------------------ What Every C/C++ and Fortran developer Should Know! Read this article and learn how Intel has extended the reach of its next-generation tools to help Windows* and Linux* C/C++ and Fortran developers boost performance applications - including clusters. http://p.sf.net/sfu/intel-dev2devmay _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply [flat|nested] 10+ messages in thread
[parent not found: <BANLkTi=m96RBZeFuRaOA5Sb_QANhgo4yCA@mail.gmail.com>]
* Re: [LTP] [PATCH] [syscalls] getrusage03: test ru_maxrss [not found] ` <BANLkTi=m96RBZeFuRaOA5Sb_QANhgo4yCA@mail.gmail.com> @ 2011-05-20 13:29 ` Cyril Hrubis 0 siblings, 0 replies; 10+ messages in thread From: Cyril Hrubis @ 2011-05-20 13:29 UTC (permalink / raw) To: Garrett Cooper; +Cc: LTP List Hi! > [Un]fortunately we don't (I say that because writing something > functional would be kind of a pain because we'd need to replicate what > tar does with that file mode, permissions bits, and other fun security > attributes in order to be complete). > Does this need to be run from the current working directory, or > can it be picked up from $PATH ? If the latter is ok, then all you > need to do is add $LTPROOT/testcases/bin to $PATH (which should be > done already by runltp) and use execvp, or you could play tricks and > lookup the dirname of the realpath, etc of the testcase (argv[0]), and > use that in the execle, etc call. All the child does here is allocating memory, so I would say execvp() is good enough in this case. (And adding note about this into style-guide would be great). -- Cyril Hrubis chrubis@suse.cz ------------------------------------------------------------------------------ What Every C/C++ and Fortran developer Should Know! Read this article and learn how Intel has extended the reach of its next-generation tools to help Windows* and Linux* C/C++ and Fortran developers boost performance applications - including clusters. http://p.sf.net/sfu/intel-dev2devmay _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply [flat|nested] 10+ messages in thread
* [LTP] [PATCH v2] [syscalls] getrusage03: test ru_maxrss 2011-05-16 15:05 [LTP] [PATCH] [syscalls] getrusage03: test ru_maxrss Caspar Zhang 2011-05-16 15:08 ` Caspar Zhang 2011-05-19 17:40 ` Cyril Hrubis @ 2011-06-13 13:12 ` Caspar Zhang 2011-06-29 14:14 ` Cyril Hrubis 2011-06-29 15:36 ` [LTP] [PATCH v3] " Caspar Zhang 2 siblings, 2 replies; 10+ messages in thread From: Caspar Zhang @ 2011-06-13 13:12 UTC (permalink / raw) To: LTP List [-- Attachment #1: Type: text/plain, Size: 906 bytes --] getrusage03 - test ru_maxrss behaviors in struct rusage This test program is backported from upstream commit: 1f10206cf8e945220f7220a809d8bfc15c21f9a5, which fills ru_maxrss value in struct rusage according to rss hiwater mark. To make sure this feature works correctly, a series of tests are executed in this program. Signed-off-by: Caspar Zhang <czhang@redhat.com> --- include/safe_macros.h | 5 + lib/safe_macros.c | 15 + runtest/syscalls | 1 + testcases/kernel/syscalls/getrusage/getrusage03.c | 359 ++++++++++++++++++++ .../kernel/syscalls/getrusage/getrusage03_child.c | 183 ++++++++++ 5 files changed, 563 insertions(+), 0 deletions(-) create mode 100644 testcases/kernel/syscalls/getrusage/getrusage03.c create mode 100644 testcases/kernel/syscalls/getrusage/getrusage03_child.c [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-syscalls-getrusage03-test-ru_maxrss.patch --] [-- Type: text/x-patch; name="0001-syscalls-getrusage03-test-ru_maxrss.patch", Size: 17617 bytes --] diff --git a/include/safe_macros.h b/include/safe_macros.h index 7c99c66..3753b7f 100644 --- a/include/safe_macros.h +++ b/include/safe_macros.h @@ -58,6 +58,11 @@ struct passwd* safe_getpwnam(const char *file, const int lineno, #define SAFE_GETPWNAM(cleanup_fn, name) \ safe_getpwnam(__FILE__, __LINE__, cleanup_fn, (name)) +int safe_getrusage(const char *file, const int lineno, + void (*cleanup_fn)(void), int who, struct rusage *usage); +#define SAFE_GETRUSAGE(cleanup_fn, who, usage) \ + safe_getrusage(__FILE__, __LINE__, (cleanup_fn), (who), (usage)) + void* safe_malloc(const char *file, const int lineno, void (*cleanup_fn)(void), size_t size); #define SAFE_MALLOC(cleanup_fn, size) \ diff --git a/lib/safe_macros.c b/lib/safe_macros.c index c98376d..11f5fe6 100644 --- a/lib/safe_macros.c +++ b/lib/safe_macros.c @@ -1,5 +1,6 @@ #include <sys/types.h> #include <sys/mman.h> +#include <sys/resource.h> #include <sys/stat.h> #include <fcntl.h> #include <libgen.h> @@ -108,6 +109,20 @@ safe_getpwnam(const char *file, const int lineno, void (*cleanup_fn)(void), return (rval); } +int +safe_getrusage(const char *file, const int lineno, void (*cleanup_fn)(void), + int who, struct rusage *usage) +{ + int rval; + + rval = getrusage(who, usage); + if (rval == -1) + tst_brkm(TBROK|TERRNO, cleanup_fn, "getrusage failed at %s:%d", + file, lineno); + + return rval; +} + void* safe_malloc(const char *file, const int lineno, void (*cleanup_fn)(void), size_t size) diff --git a/runtest/syscalls b/runtest/syscalls index 4294d07..7989764 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -399,6 +399,7 @@ get_robust_list01 get_robust_list01 getrusage01 getrusage01 getrusage02 getrusage02 +getrusage03 getrusage03 getsid01 getsid01 getsid02 getsid02 diff --git a/testcases/kernel/syscalls/getrusage/getrusage03.c b/testcases/kernel/syscalls/getrusage/getrusage03.c new file mode 100644 index 0000000..79c7508 --- /dev/null +++ b/testcases/kernel/syscalls/getrusage/getrusage03.c @@ -0,0 +1,359 @@ +/* + * getrusage03 - test ru_maxrss behaviors in struct rusage + * + * This test program is backported from upstream commit: + * 1f10206cf8e945220f7220a809d8bfc15c21f9a5, which fills ru_maxrss + * value in struct rusage according to rss hiwater mark. To make sure + * this feature works correctly, a series of tests are executed in + * this program. + * + * Copyright (C) 2011 Red Hat, Inc. + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU 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. + * + * Further, this software is distributed without any warranty that it + * is free of the rightful claim of any third person regarding + * infringement or the like. Any license provided herein, whether + * implied or otherwise, applies only to this software file. Patent + * licenses, if any, provided herein do not apply to combinations of + * this program with other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/resource.h> +#include <sys/time.h> +#include <sys/wait.h> +#include <unistd.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "test.h" +#include "usctest.h" +#include "safe_macros.h" + +char *TCID = "getrusage03"; +int TST_TOTAL = 1; + +#define DELTA_MAX 10240 + +static struct rusage ru; +static long maxrss_init; +static int retval, status; +static pid_t pid; + +static void inherit_fork(void); +static void inherit_fork2(void); +static void fork_malloc(void); +static void grandchild_maxrss(void); +static void zombie(void); +static void sig_ign(void); +static void exec_without_fork(void); +static void check_return(int status, char *pass_msg, char *fail_msg); +static int is_in_delta(long value); +static void consume(int mega); +static void setup(void); +static void cleanup(void); + +int main(int argc, char *argv[]) +{ + int lc; + char *msg; + + msg = parse_opts(argc, argv, NULL, NULL); + if (msg != NULL) + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + Tst_count = 0; + + tst_resm(TINFO, "allocate 100MB"); + consume(100); + + inherit_fork(); + inherit_fork2(); + fork_malloc(); + grandchild_maxrss(); + zombie(); + sig_ign(); + exec_without_fork(); + } + cleanup(); + tst_exit(); +} + +/* Testcase #01: fork inherit + * expect: initial.self ~= child.self */ +static void inherit_fork(void) +{ + tst_resm(TINFO, "Testcase #01: fork inherit"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + tst_resm(TINFO, "initial.self = %ld", ru.ru_maxrss); + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK|TERRNO, cleanup, "fork #1"); + case 0: + maxrss_init = ru.ru_maxrss; + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + tst_resm(TINFO, "child.self = %ld", ru.ru_maxrss); + exit(is_in_delta(maxrss_init - ru.ru_maxrss)); + default: + break; + } + + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + check_return(WEXITSTATUS(status), "initial.self ~= child.self", + "initial.self !~= child.self"); +} + +/* Testcase #02: fork inherit (cont.) + * expect: initial.children ~= 100MB, child.children = 0 */ +static void inherit_fork2(void) +{ + tst_resm(TINFO, "Testcase #02: fork inherit(cont.)"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); + if (is_in_delta(ru.ru_maxrss - 102400) == 0) + tst_resm(TPASS, "initial.children ~= 100MB"); + else + tst_resm(TFAIL, "initial.children !~= 100MB"); + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK|TERRNO, cleanup, "fork #2"); + case 0: + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "child.children = %ld", ru.ru_maxrss); + exit((ru.ru_maxrss == 0) ? 0 : 1); + default: + break; + } + + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + check_return(WEXITSTATUS(status), "child.children == 0", + "child.children != 0"); +} + +/* Testcase #03: fork + malloc + * expect: initial.self + 50MB ~= child.self */ +static void fork_malloc(void) +{ + tst_resm(TINFO, "Testcase #03: fork + malloc"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + tst_resm(TINFO, "initial.self = %ld", ru.ru_maxrss); + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK|TERRNO, cleanup, "fork #3"); + case 0: + maxrss_init = ru.ru_maxrss; + tst_resm(TINFO, "child allocate +50MB"); + consume(50); + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + tst_resm(TINFO, "child.self = %ld", ru.ru_maxrss); + exit(is_in_delta(maxrss_init + 51200 - ru.ru_maxrss)); + default: + break; + } + + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + check_return(WEXITSTATUS(status), "initial.self + 50MB ~= child.self", + "initial.self + 50MB !~= child.self"); +} + +/* Testcase #04: grandchild maxrss + * expect: post_wait.children ~= 300MB */ +static void grandchild_maxrss(void) +{ + tst_resm(TINFO, "Testcase #04: grandchild maxrss"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK|TERRNO, cleanup, "fork #4"); + case 0: + retval = system("getrusage03_child -g 300"); + if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0)) + tst_brkm(TBROK|TERRNO, cleanup, "system"); + exit(0); + default: + break; + } + + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + if (WEXITSTATUS(status) != 0) + tst_brkm(TBROK|TERRNO, cleanup, "child exit status is not 0"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "post_wait.children = %ld", ru.ru_maxrss); + if (is_in_delta(ru.ru_maxrss - 307200) == 0) + tst_resm(TPASS, "child.children ~= 300MB"); + else + tst_resm(TFAIL, "child.children !~= 300MB"); +} + +/* Testcase #05: zombie + * expect: initial ~= pre_wait, post_wait ~= 400MB */ +static void zombie(void) +{ + tst_resm(TINFO, "Testcase #05: zombie"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); + maxrss_init = ru.ru_maxrss; + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK, cleanup, "fork #5"); + case 0: + retval = system("getrusage03_child -n 400"); + if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0)) + tst_brkm(TBROK|TERRNO, cleanup, "system"); + exit(0); + default: + break; + } + + sleep(1); /* children become zombie */ + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "pre_wait.children = %ld", ru.ru_maxrss); + if (is_in_delta(ru.ru_maxrss - maxrss_init) == 0) + tst_resm(TPASS, "initial.children ~= pre_wait.children"); + else + tst_resm(TFAIL, "initial.children !~= pre_wait.children"); + + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + if (WEXITSTATUS(status) != 0) + tst_brkm(TBROK|TERRNO, cleanup, "child exit status is not 0"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "post_wait.children = %ld", ru.ru_maxrss); + if (is_in_delta(ru.ru_maxrss - 409600) == 0) + tst_resm(TPASS, "post_wait.children ~= 400MB"); + else + tst_resm(TFAIL, "post_wait.children !~= 400MB"); +} + +/* Testcase #06: SIG_IGN + * expect: initial ~= after_zombie */ +static void sig_ign(void) +{ + tst_resm(TINFO, "Testcase #06: SIG_IGN"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); + signal(SIGCHLD, SIG_IGN); + maxrss_init = ru.ru_maxrss; + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK, cleanup, "fork #6"); + case 0: + retval = system("getrusage03_child -n 500"); + if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0)) + tst_brkm(TBROK|TERRNO, cleanup, "system"); + exit(0); + default: + break; + } + + sleep(1); /* children become zombie */ + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "after_zombie.children = %ld", ru.ru_maxrss); + if (is_in_delta(ru.ru_maxrss - maxrss_init) == 0) + tst_resm(TPASS, "initial.children ~= after_zombie.children"); + else + tst_resm(TFAIL, "initial.children !~= after_zombie.children"); + signal(SIGCHLD, SIG_DFL); +} + +/* Testcase #07: exec without fork + * expect: initial ~= fork */ +static void exec_without_fork(void) +{ + char str_maxrss_self[BUFSIZ], str_maxrss_child[BUFSIZ]; + long maxrss_self, maxrss_child; + + tst_resm(TINFO, "Testcase #07: exec without fork"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + maxrss_self = ru.ru_maxrss; + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + maxrss_child = ru.ru_maxrss; + tst_resm(TINFO, "initial.self = %ld, initial.children = %ld", + maxrss_self, maxrss_child); + + sprintf(str_maxrss_self, "%ld", maxrss_self); + sprintf(str_maxrss_child, "%ld", maxrss_child); + if (execlp("getrusage03_child", "getrusage03_child", "-v", + "-s", str_maxrss_self, + "-l", str_maxrss_child, NULL) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "execlp"); +} + +static int is_in_delta(long value) +{ + return ((value >= -DELTA_MAX && value <= DELTA_MAX) ? 0 : 1); +} + +static void check_return(int status, char *pass_msg, char *fail_msg) +{ + switch (status) { + case 0: + tst_resm(TPASS, "%s", pass_msg); + break; + case 1: + tst_resm(TFAIL, "%s", fail_msg); + break; + default: + tst_resm(TFAIL, "child exit status is %d", status); + break; + } +} + +static void consume(int mega) +{ + size_t sz; + void *ptr; + + sz = mega * 1024 * 1024; + ptr = SAFE_MALLOC(cleanup, sz); + if (memset(ptr, 0, sz) == NULL) + tst_brkm(TBROK|TERRNO, cleanup, "memset"); +} + +static void setup(void) +{ + tst_sig(FORK, DEF_HANDLER, cleanup); + + TEST_PAUSE; +} + +static void cleanup(void) +{ + TEST_CLEANUP; +} diff --git a/testcases/kernel/syscalls/getrusage/getrusage03_child.c b/testcases/kernel/syscalls/getrusage/getrusage03_child.c new file mode 100644 index 0000000..6127fd2 --- /dev/null +++ b/testcases/kernel/syscalls/getrusage/getrusage03_child.c @@ -0,0 +1,183 @@ +/* + * getrusage03_child.c - a child program executed by getrusage03 + * + * Copyright (C) 2011 Red Hat, Inc. + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU 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. + * + * Further, this software is distributed without any warranty that it + * is free of the rightful claim of any third person regarding + * infringement or the like. Any license provided herein, whether + * implied or otherwise, applies only to this software file. Patent + * licenses, if any, provided herein do not apply to combinations of + * this program with other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include <sys/types.h> +#include <sys/resource.h> +#include <sys/time.h> +#include <sys/wait.h> +#include <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "test.h" +#include "usctest.h" +#include "safe_macros.h" + +char *TCID = "getrusage03_child"; +int TST_TOTAL = 1; + +#define DELTA_MAX 10240 + +static int opt_consume, opt_grand, opt_show, opt_self, opt_child; +static char *consume_str, *grand_consume_str, *self_str, *child_str; + +option_t child_options[] = { + { "n:", &opt_consume, &consume_str }, + { "g:", &opt_grand, &grand_consume_str }, + { "v", &opt_show, NULL }, + { "s:", &opt_self, &self_str }, + { "l:", &opt_child, &child_str } +}; + +static void usage(void); +static void consume(int mega); +static long get_long(const char *str); +static void setup(void); +static void cleanup(void); + +int main(int argc, char *argv[]) +{ + int lc; + pid_t pid; + long maxrss_self, maxrss_children, delta; + long consume_nr, grand_consume_nr, self_nr, child_nr; + struct rusage ru; + char *msg; + + msg = parse_opts(argc, argv, child_options, usage); + if (msg != NULL) + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + Tst_count = 0; + + if (opt_consume) { + consume_nr = get_long(consume_str); + tst_resm(TINFO, "child allocate %ldMB", consume_nr); + consume(consume_nr); + } + + if (opt_grand) { + grand_consume_nr = get_long(grand_consume_str); + tst_resm(TINFO, "grandchild allocate %ldMB", + grand_consume_nr); + switch (pid = fork()) { + case -1: + tst_brkm(TBROK, cleanup, "fork"); + case 0: + consume(grand_consume_nr); + exit(0); + default: + break; + } + while (waitpid(-1, &pid, WUNTRACED|WCONTINUED) > 0) + if (WEXITSTATUS(pid) != 0) + tst_brkm(TBROK|TERRNO, cleanup, + "child exit status is not 0"); + } + + if (opt_show) { + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + maxrss_self = ru.ru_maxrss; + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + maxrss_children = ru.ru_maxrss; + tst_resm(TINFO, "exec.self = %ld, exec.children = %ld", + maxrss_self, maxrss_children); + if (opt_self) { + self_nr = get_long(self_str); + delta = maxrss_self - self_nr; + if (delta >= -DELTA_MAX && delta <= DELTA_MAX) + tst_resm(TPASS, + "initial.self ~= exec.self"); + else + tst_resm(TFAIL, + "initial.self !~= exec.self"); + } + if (opt_child) { + child_nr = get_long(child_str); + delta = maxrss_children - child_nr; + if (delta >= -DELTA_MAX && delta <= DELTA_MAX) + tst_resm(TPASS, + "initial.children ~= exec.children"); + else + tst_resm(TFAIL, + "initial.children !~= exec.children"); + } + } + } + + cleanup(); + tst_exit(); +} + +static void usage(void) +{ + printf(" -n NUM consume NUM MB size\n"); + printf(" -g NUM grandchild consume NUM MB size\n"); + printf(" -v verbose mode, show rusage info\n"); + printf(" -s NUM compare rusage_self.maxrss with given NUM\n"); + printf(" -l NUM compare rusage_children.maxrss with given NUM\n"); +} + +static void consume(int mega) +{ + size_t sz; + void *ptr; + + sz = mega * 1024 * 1024; + ptr = SAFE_MALLOC(cleanup, sz); + if (memset(ptr, 0, sz) == NULL) + tst_brkm(TBROK|TERRNO, cleanup, "memset"); +} + +static long get_long(const char *str) +{ + long val; + char *endptr; + + val = strtol(str, &endptr, 10); + if (((val == LONG_MAX || val == LONG_MIN) && errno == ERANGE) || + (errno != 0 && val == 0)) + tst_brkm(TBROK|TERRNO, cleanup, "strtol"); + if (endptr == str) + tst_brkm(TBROK, cleanup, "No digits were found."); + + return val; +} + +static void setup() +{ + tst_sig(FORK, DEF_HANDLER, cleanup); + + TEST_PAUSE; +} + +static void cleanup() +{ + TEST_CLEANUP; +} [-- Attachment #3: Type: text/plain, Size: 318 bytes --] ------------------------------------------------------------------------------ EditLive Enterprise is the world's most technically advanced content authoring tool. Experience the power of Track Changes, Inline Image Editing and ensure content is compliant with Accessibility Checking. http://p.sf.net/sfu/ephox-dev2dev [-- Attachment #4: Type: text/plain, Size: 155 bytes --] _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [LTP] [PATCH v2] [syscalls] getrusage03: test ru_maxrss 2011-06-13 13:12 ` [LTP] [PATCH v2] " Caspar Zhang @ 2011-06-29 14:14 ` Cyril Hrubis 2011-06-29 15:36 ` [LTP] [PATCH v3] " Caspar Zhang 1 sibling, 0 replies; 10+ messages in thread From: Cyril Hrubis @ 2011-06-29 14:14 UTC (permalink / raw) To: Caspar Zhang; +Cc: LTP List Hi! > +int main(int argc, char *argv[]) > +{ > + int lc; > + char *msg; > + > + msg = parse_opts(argc, argv, NULL, NULL); > + if (msg != NULL) > + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); > + > + setup(); > + > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + Tst_count = 0; > + > + tst_resm(TINFO, "allocate 100MB"); > + consume(100); > + > + inherit_fork(); > + inherit_fork2(); > + fork_malloc(); > + grandchild_maxrss(); > + zombie(); > + sig_ign(); > + exec_without_fork(); > + } > + cleanup(); > + tst_exit(); > +} > + > +/* Testcase #01: fork inherit > + * expect: initial.self ~= child.self */ > +static void inherit_fork(void) > +{ > + tst_resm(TINFO, "Testcase #01: fork inherit"); > + > + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); > + tst_resm(TINFO, "initial.self = %ld", ru.ru_maxrss); > + > + switch (pid = fork()) { > + case -1: > + tst_brkm(TBROK|TERRNO, cleanup, "fork #1"); > + case 0: > + maxrss_init = ru.ru_maxrss; > + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); > + tst_resm(TINFO, "child.self = %ld", ru.ru_maxrss); > + exit(is_in_delta(maxrss_init - ru.ru_maxrss)); > + default: > + break; > + } > + > + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); > + check_return(WEXITSTATUS(status), "initial.self ~= child.self", > + "initial.self !~= child.self"); > +} > + > +/* Testcase #02: fork inherit (cont.) > + * expect: initial.children ~= 100MB, child.children = 0 */ > +static void inherit_fork2(void) > +{ > + tst_resm(TINFO, "Testcase #02: fork inherit(cont.)"); > + > + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); > + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); > + if (is_in_delta(ru.ru_maxrss - 102400) == 0) > + tst_resm(TPASS, "initial.children ~= 100MB"); > + else > + tst_resm(TFAIL, "initial.children !~= 100MB"); > + > + switch (pid = fork()) { > + case -1: > + tst_brkm(TBROK|TERRNO, cleanup, "fork #2"); > + case 0: > + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); > + tst_resm(TINFO, "child.children = %ld", ru.ru_maxrss); > + exit((ru.ru_maxrss == 0) ? 0 : 1); > + default: > + break; > + } > + > + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); > + check_return(WEXITSTATUS(status), "child.children == 0", > + "child.children != 0"); > +} > + > +/* Testcase #03: fork + malloc > + * expect: initial.self + 50MB ~= child.self */ > +static void fork_malloc(void) > +{ > + tst_resm(TINFO, "Testcase #03: fork + malloc"); > + > + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); > + tst_resm(TINFO, "initial.self = %ld", ru.ru_maxrss); > + > + switch (pid = fork()) { > + case -1: > + tst_brkm(TBROK|TERRNO, cleanup, "fork #3"); > + case 0: > + maxrss_init = ru.ru_maxrss; > + tst_resm(TINFO, "child allocate +50MB"); > + consume(50); > + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); > + tst_resm(TINFO, "child.self = %ld", ru.ru_maxrss); > + exit(is_in_delta(maxrss_init + 51200 - ru.ru_maxrss)); > + default: > + break; > + } > + > + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); > + check_return(WEXITSTATUS(status), "initial.self + 50MB ~= child.self", > + "initial.self + 50MB !~= child.self"); > +} > + > +/* Testcase #04: grandchild maxrss > + * expect: post_wait.children ~= 300MB */ > +static void grandchild_maxrss(void) > +{ > + tst_resm(TINFO, "Testcase #04: grandchild maxrss"); > + > + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); > + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); > + > + switch (pid = fork()) { > + case -1: > + tst_brkm(TBROK|TERRNO, cleanup, "fork #4"); > + case 0: > + retval = system("getrusage03_child -g 300"); > + if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0)) > + tst_brkm(TBROK|TERRNO, cleanup, "system"); > + exit(0); > + default: > + break; > + } > + > + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); > + if (WEXITSTATUS(status) != 0) > + tst_brkm(TBROK|TERRNO, cleanup, "child exit status is not 0"); > + > + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); > + tst_resm(TINFO, "post_wait.children = %ld", ru.ru_maxrss); > + if (is_in_delta(ru.ru_maxrss - 307200) == 0) > + tst_resm(TPASS, "child.children ~= 300MB"); > + else > + tst_resm(TFAIL, "child.children !~= 300MB"); > +} > + > +/* Testcase #05: zombie > + * expect: initial ~= pre_wait, post_wait ~= 400MB */ > +static void zombie(void) > +{ > + tst_resm(TINFO, "Testcase #05: zombie"); > + > + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); > + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); > + maxrss_init = ru.ru_maxrss; > + > + switch (pid = fork()) { > + case -1: > + tst_brkm(TBROK, cleanup, "fork #5"); > + case 0: > + retval = system("getrusage03_child -n 400"); > + if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0)) > + tst_brkm(TBROK|TERRNO, cleanup, "system"); > + exit(0); > + default: > + break; > + } > + > + sleep(1); /* children become zombie */ > + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); > + tst_resm(TINFO, "pre_wait.children = %ld", ru.ru_maxrss); > + if (is_in_delta(ru.ru_maxrss - maxrss_init) == 0) > + tst_resm(TPASS, "initial.children ~= pre_wait.children"); > + else > + tst_resm(TFAIL, "initial.children !~= pre_wait.children"); > + > + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); > + if (WEXITSTATUS(status) != 0) > + tst_brkm(TBROK|TERRNO, cleanup, "child exit status is not 0"); > + > + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); > + tst_resm(TINFO, "post_wait.children = %ld", ru.ru_maxrss); > + if (is_in_delta(ru.ru_maxrss - 409600) == 0) > + tst_resm(TPASS, "post_wait.children ~= 400MB"); > + else > + tst_resm(TFAIL, "post_wait.children !~= 400MB"); > +} > + > +/* Testcase #06: SIG_IGN > + * expect: initial ~= after_zombie */ > +static void sig_ign(void) > +{ > + tst_resm(TINFO, "Testcase #06: SIG_IGN"); > + > + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); > + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); > + signal(SIGCHLD, SIG_IGN); > + maxrss_init = ru.ru_maxrss; > + > + switch (pid = fork()) { > + case -1: > + tst_brkm(TBROK, cleanup, "fork #6"); > + case 0: > + retval = system("getrusage03_child -n 500"); > + if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0)) > + tst_brkm(TBROK|TERRNO, cleanup, "system"); > + exit(0); > + default: > + break; > + } > + > + sleep(1); /* children become zombie */ > + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); > + tst_resm(TINFO, "after_zombie.children = %ld", ru.ru_maxrss); > + if (is_in_delta(ru.ru_maxrss - maxrss_init) == 0) > + tst_resm(TPASS, "initial.children ~= after_zombie.children"); > + else > + tst_resm(TFAIL, "initial.children !~= after_zombie.children"); > + signal(SIGCHLD, SIG_DFL); > +} > + > +/* Testcase #07: exec without fork > + * expect: initial ~= fork */ > +static void exec_without_fork(void) > +{ > + char str_maxrss_self[BUFSIZ], str_maxrss_child[BUFSIZ]; > + long maxrss_self, maxrss_child; > + > + tst_resm(TINFO, "Testcase #07: exec without fork"); > + > + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); > + maxrss_self = ru.ru_maxrss; > + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); > + maxrss_child = ru.ru_maxrss; > + tst_resm(TINFO, "initial.self = %ld, initial.children = %ld", > + maxrss_self, maxrss_child); > + > + sprintf(str_maxrss_self, "%ld", maxrss_self); > + sprintf(str_maxrss_child, "%ld", maxrss_child); > + if (execlp("getrusage03_child", "getrusage03_child", "-v", > + "-s", str_maxrss_self, > + "-l", str_maxrss_child, NULL) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "execlp"); > +} > + > +static int is_in_delta(long value) > +{ > + return ((value >= -DELTA_MAX && value <= DELTA_MAX) ? 0 : 1); > +} Hmm, this is really confusing. The function name suggests that value is "value is in delta range" but it actually returns 0 which is same as false in C. The 0 == success approach makes sence only for C functions that actually returns error codes otherwise, but not for functions whose name suggests boolean return value. I would drop the ? 0:1 part and remove == 0 from the if() statements abowe. > +static void check_return(int status, char *pass_msg, char *fail_msg) > +{ > + switch (status) { > + case 0: > + tst_resm(TPASS, "%s", pass_msg); > + break; > + case 1: > + tst_resm(TFAIL, "%s", fail_msg); > + break; > + default: > + tst_resm(TFAIL, "child exit status is %d", status); > + break; > + } > +} > + > +static void consume(int mega) > +{ > + size_t sz; > + void *ptr; > + > + sz = mega * 1024 * 1024; > + ptr = SAFE_MALLOC(cleanup, sz); > + if (memset(ptr, 0, sz) == NULL) > + tst_brkm(TBROK|TERRNO, cleanup, "memset"); > +} The memset() can't fail, it just returns pointer to the passed buffer. > +static void setup(void) > +{ > + tst_sig(FORK, DEF_HANDLER, cleanup); > + > + TEST_PAUSE; > +} > + > +static void cleanup(void) > +{ > + TEST_CLEANUP; > +} > diff --git a/testcases/kernel/syscalls/getrusage/getrusage03_child.c b/testcases/kernel/syscalls/getrusage/getrusage03_child.c > new file mode 100644 > index 0000000..6127fd2 > --- /dev/null > +++ b/testcases/kernel/syscalls/getrusage/getrusage03_child.c > @@ -0,0 +1,183 @@ > +/* > + * getrusage03_child.c - a child program executed by getrusage03 > + * > + * Copyright (C) 2011 Red Hat, Inc. > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of version 2 of the GNU 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. > + * > + * Further, this software is distributed without any warranty that it > + * is free of the rightful claim of any third person regarding > + * infringement or the like. Any license provided herein, whether > + * implied or otherwise, applies only to this software file. Patent > + * licenses, if any, provided herein do not apply to combinations of > + * this program with other software, or any other product whatsoever. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA > + * 02110-1301, USA. > + */ > +#include <sys/types.h> > +#include <sys/resource.h> > +#include <sys/time.h> > +#include <sys/wait.h> > +#include <errno.h> > +#include <unistd.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > + > +#include "test.h" > +#include "usctest.h" > +#include "safe_macros.h" > + > +char *TCID = "getrusage03_child"; > +int TST_TOTAL = 1; > + > +#define DELTA_MAX 10240 > + > +static int opt_consume, opt_grand, opt_show, opt_self, opt_child; > +static char *consume_str, *grand_consume_str, *self_str, *child_str; > + > +option_t child_options[] = { > + { "n:", &opt_consume, &consume_str }, > + { "g:", &opt_grand, &grand_consume_str }, > + { "v", &opt_show, NULL }, > + { "s:", &opt_self, &self_str }, > + { "l:", &opt_child, &child_str } > +}; > + > +static void usage(void); > +static void consume(int mega); > +static long get_long(const char *str); > +static void setup(void); > +static void cleanup(void); > + > +int main(int argc, char *argv[]) > +{ > + int lc; > + pid_t pid; > + long maxrss_self, maxrss_children, delta; > + long consume_nr, grand_consume_nr, self_nr, child_nr; > + struct rusage ru; > + char *msg; > + > + msg = parse_opts(argc, argv, child_options, usage); > + if (msg != NULL) > + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); > + > + setup(); > + > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + Tst_count = 0; > + > + if (opt_consume) { > + consume_nr = get_long(consume_str); > + tst_resm(TINFO, "child allocate %ldMB", consume_nr); > + consume(consume_nr); > + } > + > + if (opt_grand) { > + grand_consume_nr = get_long(grand_consume_str); > + tst_resm(TINFO, "grandchild allocate %ldMB", > + grand_consume_nr); > + switch (pid = fork()) { > + case -1: > + tst_brkm(TBROK, cleanup, "fork"); > + case 0: > + consume(grand_consume_nr); > + exit(0); > + default: > + break; > + } > + while (waitpid(-1, &pid, WUNTRACED|WCONTINUED) > 0) > + if (WEXITSTATUS(pid) != 0) > + tst_brkm(TBROK|TERRNO, cleanup, > + "child exit status is not 0"); > + } > + > + if (opt_show) { > + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); > + maxrss_self = ru.ru_maxrss; > + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); > + maxrss_children = ru.ru_maxrss; > + tst_resm(TINFO, "exec.self = %ld, exec.children = %ld", > + maxrss_self, maxrss_children); > + if (opt_self) { > + self_nr = get_long(self_str); > + delta = maxrss_self - self_nr; > + if (delta >= -DELTA_MAX && delta <= DELTA_MAX) > + tst_resm(TPASS, > + "initial.self ~= exec.self"); > + else > + tst_resm(TFAIL, > + "initial.self !~= exec.self"); > + } > + if (opt_child) { > + child_nr = get_long(child_str); > + delta = maxrss_children - child_nr; > + if (delta >= -DELTA_MAX && delta <= DELTA_MAX) > + tst_resm(TPASS, > + "initial.children ~= exec.children"); > + else > + tst_resm(TFAIL, > + "initial.children !~= exec.children"); > + } > + } > + } > + > + cleanup(); > + tst_exit(); > +} > + > +static void usage(void) > +{ > + printf(" -n NUM consume NUM MB size\n"); > + printf(" -g NUM grandchild consume NUM MB size\n"); > + printf(" -v verbose mode, show rusage info\n"); > + printf(" -s NUM compare rusage_self.maxrss with given NUM\n"); > + printf(" -l NUM compare rusage_children.maxrss with given NUM\n"); > +} > + > +static void consume(int mega) > +{ > + size_t sz; > + void *ptr; > + > + sz = mega * 1024 * 1024; > + ptr = SAFE_MALLOC(cleanup, sz); > + if (memset(ptr, 0, sz) == NULL) > + tst_brkm(TBROK|TERRNO, cleanup, "memset"); Here too. > +} > + > +static long get_long(const char *str) > +{ > + long val; > + char *endptr; > + > + val = strtol(str, &endptr, 10); > + if (((val == LONG_MAX || val == LONG_MIN) && errno == ERANGE) || > + (errno != 0 && val == 0)) > + tst_brkm(TBROK|TERRNO, cleanup, "strtol"); > + if (endptr == str) > + tst_brkm(TBROK, cleanup, "No digits were found."); > + > + return val; > +} This is not 100% correct. The strtol (for converting whole string into number) is successfull if the endptr points to the end of string, eg. *endptr = '\0' and if the value is not LONG_MAX or LONG_MIN both with errno set to ERANGE. This will accept strings like "256foo". > +static void setup() Add void. > +{ > + tst_sig(FORK, DEF_HANDLER, cleanup); > + > + TEST_PAUSE; > +} > + > +static void cleanup() And here. > +{ > + TEST_CLEANUP; > +} -- Cyril Hrubis chrubis@suse.cz ------------------------------------------------------------------------------ All of the data generated in your IT infrastructure is seriously valuable. Why? It contains a definitive record of application performance, security threats, fraudulent activity, and more. Splunk takes this data and makes sense of it. IT sense. And common sense. http://p.sf.net/sfu/splunk-d2d-c2 _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply [flat|nested] 10+ messages in thread
* [LTP] [PATCH v3] [syscalls] getrusage03: test ru_maxrss 2011-06-13 13:12 ` [LTP] [PATCH v2] " Caspar Zhang 2011-06-29 14:14 ` Cyril Hrubis @ 2011-06-29 15:36 ` Caspar Zhang 2011-06-29 17:46 ` Cyril Hrubis 2011-06-29 17:50 ` [LTP] [PATCH v4] " Caspar Zhang 1 sibling, 2 replies; 10+ messages in thread From: Caspar Zhang @ 2011-06-29 15:36 UTC (permalink / raw) To: LTP List [-- Attachment #1: Type: text/plain, Size: 906 bytes --] getrusage03 - test ru_maxrss behaviors in struct rusage This test program is backported from upstream commit: 1f10206cf8e945220f7220a809d8bfc15c21f9a5, which fills ru_maxrss value in struct rusage according to rss hiwater mark. To make sure this feature works correctly, a series of tests are executed in this program. Signed-off-by: Caspar Zhang <czhang@redhat.com> --- include/safe_macros.h | 5 + lib/safe_macros.c | 15 + runtest/syscalls | 1 + testcases/kernel/syscalls/getrusage/getrusage03.c | 358 ++++++++++++++++++++ .../kernel/syscalls/getrusage/getrusage03_child.c | 182 ++++++++++ 5 files changed, 561 insertions(+), 0 deletions(-) create mode 100644 testcases/kernel/syscalls/getrusage/getrusage03.c create mode 100644 testcases/kernel/syscalls/getrusage/getrusage03_child.c [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-syscalls-getrusage03-test-ru_maxrss.patch --] [-- Type: text/x-patch; name="0001-syscalls-getrusage03-test-ru_maxrss.patch", Size: 17484 bytes --] diff --git a/include/safe_macros.h b/include/safe_macros.h index 7c99c66..3753b7f 100644 --- a/include/safe_macros.h +++ b/include/safe_macros.h @@ -58,6 +58,11 @@ struct passwd* safe_getpwnam(const char *file, const int lineno, #define SAFE_GETPWNAM(cleanup_fn, name) \ safe_getpwnam(__FILE__, __LINE__, cleanup_fn, (name)) +int safe_getrusage(const char *file, const int lineno, + void (*cleanup_fn)(void), int who, struct rusage *usage); +#define SAFE_GETRUSAGE(cleanup_fn, who, usage) \ + safe_getrusage(__FILE__, __LINE__, (cleanup_fn), (who), (usage)) + void* safe_malloc(const char *file, const int lineno, void (*cleanup_fn)(void), size_t size); #define SAFE_MALLOC(cleanup_fn, size) \ diff --git a/lib/safe_macros.c b/lib/safe_macros.c index c98376d..11f5fe6 100644 --- a/lib/safe_macros.c +++ b/lib/safe_macros.c @@ -1,5 +1,6 @@ #include <sys/types.h> #include <sys/mman.h> +#include <sys/resource.h> #include <sys/stat.h> #include <fcntl.h> #include <libgen.h> @@ -108,6 +109,20 @@ safe_getpwnam(const char *file, const int lineno, void (*cleanup_fn)(void), return (rval); } +int +safe_getrusage(const char *file, const int lineno, void (*cleanup_fn)(void), + int who, struct rusage *usage) +{ + int rval; + + rval = getrusage(who, usage); + if (rval == -1) + tst_brkm(TBROK|TERRNO, cleanup_fn, "getrusage failed at %s:%d", + file, lineno); + + return rval; +} + void* safe_malloc(const char *file, const int lineno, void (*cleanup_fn)(void), size_t size) diff --git a/runtest/syscalls b/runtest/syscalls index 4294d07..7989764 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -399,6 +399,7 @@ get_robust_list01 get_robust_list01 getrusage01 getrusage01 getrusage02 getrusage02 +getrusage03 getrusage03 getsid01 getsid01 getsid02 getsid02 diff --git a/testcases/kernel/syscalls/getrusage/getrusage03.c b/testcases/kernel/syscalls/getrusage/getrusage03.c new file mode 100644 index 0000000..a50a852 --- /dev/null +++ b/testcases/kernel/syscalls/getrusage/getrusage03.c @@ -0,0 +1,358 @@ +/* + * getrusage03 - test ru_maxrss behaviors in struct rusage + * + * This test program is backported from upstream commit: + * 1f10206cf8e945220f7220a809d8bfc15c21f9a5, which fills ru_maxrss + * value in struct rusage according to rss hiwater mark. To make sure + * this feature works correctly, a series of tests are executed in + * this program. + * + * Copyright (C) 2011 Red Hat, Inc. + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU 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. + * + * Further, this software is distributed without any warranty that it + * is free of the rightful claim of any third person regarding + * infringement or the like. Any license provided herein, whether + * implied or otherwise, applies only to this software file. Patent + * licenses, if any, provided herein do not apply to combinations of + * this program with other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/resource.h> +#include <sys/time.h> +#include <sys/wait.h> +#include <unistd.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "test.h" +#include "usctest.h" +#include "safe_macros.h" + +char *TCID = "getrusage03"; +int TST_TOTAL = 1; + +#define DELTA_MAX 10240 + +static struct rusage ru; +static long maxrss_init; +static int retval, status; +static pid_t pid; + +static void inherit_fork(void); +static void inherit_fork2(void); +static void fork_malloc(void); +static void grandchild_maxrss(void); +static void zombie(void); +static void sig_ign(void); +static void exec_without_fork(void); +static void check_return(int status, char *pass_msg, char *fail_msg); +static int is_in_delta(long value); +static void consume(int mega); +static void setup(void); +static void cleanup(void); + +int main(int argc, char *argv[]) +{ + int lc; + char *msg; + + msg = parse_opts(argc, argv, NULL, NULL); + if (msg != NULL) + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + Tst_count = 0; + + tst_resm(TINFO, "allocate 100MB"); + consume(100); + + inherit_fork(); + inherit_fork2(); + fork_malloc(); + grandchild_maxrss(); + zombie(); + sig_ign(); + exec_without_fork(); + } + cleanup(); + tst_exit(); +} + +/* Testcase #01: fork inherit + * expect: initial.self ~= child.self */ +static void inherit_fork(void) +{ + tst_resm(TINFO, "Testcase #01: fork inherit"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + tst_resm(TINFO, "initial.self = %ld", ru.ru_maxrss); + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK|TERRNO, cleanup, "fork #1"); + case 0: + maxrss_init = ru.ru_maxrss; + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + tst_resm(TINFO, "child.self = %ld", ru.ru_maxrss); + exit(is_in_delta(maxrss_init - ru.ru_maxrss)); + default: + break; + } + + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + check_return(WEXITSTATUS(status), "initial.self ~= child.self", + "initial.self !~= child.self"); +} + +/* Testcase #02: fork inherit (cont.) + * expect: initial.children ~= 100MB, child.children = 0 */ +static void inherit_fork2(void) +{ + tst_resm(TINFO, "Testcase #02: fork inherit(cont.)"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); + if (is_in_delta(ru.ru_maxrss - 102400)) + tst_resm(TPASS, "initial.children ~= 100MB"); + else + tst_resm(TFAIL, "initial.children !~= 100MB"); + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK|TERRNO, cleanup, "fork #2"); + case 0: + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "child.children = %ld", ru.ru_maxrss); + exit(ru.ru_maxrss == 0); + default: + break; + } + + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + check_return(WEXITSTATUS(status), "child.children == 0", + "child.children != 0"); +} + +/* Testcase #03: fork + malloc + * expect: initial.self + 50MB ~= child.self */ +static void fork_malloc(void) +{ + tst_resm(TINFO, "Testcase #03: fork + malloc"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + tst_resm(TINFO, "initial.self = %ld", ru.ru_maxrss); + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK|TERRNO, cleanup, "fork #3"); + case 0: + maxrss_init = ru.ru_maxrss; + tst_resm(TINFO, "child allocate +50MB"); + consume(50); + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + tst_resm(TINFO, "child.self = %ld", ru.ru_maxrss); + exit(is_in_delta(maxrss_init + 51200 - ru.ru_maxrss)); + default: + break; + } + + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + check_return(WEXITSTATUS(status), "initial.self + 50MB ~= child.self", + "initial.self + 50MB !~= child.self"); +} + +/* Testcase #04: grandchild maxrss + * expect: post_wait.children ~= 300MB */ +static void grandchild_maxrss(void) +{ + tst_resm(TINFO, "Testcase #04: grandchild maxrss"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK|TERRNO, cleanup, "fork #4"); + case 0: + retval = system("getrusage03_child -g 300"); + if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0)) + tst_brkm(TBROK|TERRNO, cleanup, "system"); + exit(0); + default: + break; + } + + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + if (WEXITSTATUS(status) != 0) + tst_brkm(TBROK|TERRNO, cleanup, "child exit status is not 0"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "post_wait.children = %ld", ru.ru_maxrss); + if (is_in_delta(ru.ru_maxrss - 307200)) + tst_resm(TPASS, "child.children ~= 300MB"); + else + tst_resm(TFAIL, "child.children !~= 300MB"); +} + +/* Testcase #05: zombie + * expect: initial ~= pre_wait, post_wait ~= 400MB */ +static void zombie(void) +{ + tst_resm(TINFO, "Testcase #05: zombie"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); + maxrss_init = ru.ru_maxrss; + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK, cleanup, "fork #5"); + case 0: + retval = system("getrusage03_child -n 400"); + if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0)) + tst_brkm(TBROK|TERRNO, cleanup, "system"); + exit(0); + default: + break; + } + + sleep(1); /* children become zombie */ + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "pre_wait.children = %ld", ru.ru_maxrss); + if (is_in_delta(ru.ru_maxrss - maxrss_init)) + tst_resm(TPASS, "initial.children ~= pre_wait.children"); + else + tst_resm(TFAIL, "initial.children !~= pre_wait.children"); + + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + if (WEXITSTATUS(status) != 0) + tst_brkm(TBROK|TERRNO, cleanup, "child exit status is not 0"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "post_wait.children = %ld", ru.ru_maxrss); + if (is_in_delta(ru.ru_maxrss - 409600)) + tst_resm(TPASS, "post_wait.children ~= 400MB"); + else + tst_resm(TFAIL, "post_wait.children !~= 400MB"); +} + +/* Testcase #06: SIG_IGN + * expect: initial ~= after_zombie */ +static void sig_ign(void) +{ + tst_resm(TINFO, "Testcase #06: SIG_IGN"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); + signal(SIGCHLD, SIG_IGN); + maxrss_init = ru.ru_maxrss; + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK, cleanup, "fork #6"); + case 0: + retval = system("getrusage03_child -n 500"); + if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0)) + tst_brkm(TBROK|TERRNO, cleanup, "system"); + exit(0); + default: + break; + } + + sleep(1); /* children become zombie */ + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "after_zombie.children = %ld", ru.ru_maxrss); + if (is_in_delta(ru.ru_maxrss - maxrss_init)) + tst_resm(TPASS, "initial.children ~= after_zombie.children"); + else + tst_resm(TFAIL, "initial.children !~= after_zombie.children"); + signal(SIGCHLD, SIG_DFL); +} + +/* Testcase #07: exec without fork + * expect: initial ~= fork */ +static void exec_without_fork(void) +{ + char str_maxrss_self[BUFSIZ], str_maxrss_child[BUFSIZ]; + long maxrss_self, maxrss_child; + + tst_resm(TINFO, "Testcase #07: exec without fork"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + maxrss_self = ru.ru_maxrss; + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + maxrss_child = ru.ru_maxrss; + tst_resm(TINFO, "initial.self = %ld, initial.children = %ld", + maxrss_self, maxrss_child); + + sprintf(str_maxrss_self, "%ld", maxrss_self); + sprintf(str_maxrss_child, "%ld", maxrss_child); + if (execlp("getrusage03_child", "getrusage03_child", "-v", + "-s", str_maxrss_self, + "-l", str_maxrss_child, NULL) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "execlp"); +} + +static int is_in_delta(long value) +{ + return (value >= -DELTA_MAX && value <= DELTA_MAX); +} + +static void check_return(int status, char *pass_msg, char *fail_msg) +{ + switch (status) { + case 1: + tst_resm(TPASS, "%s", pass_msg); + break; + case 0: + tst_resm(TFAIL, "%s", fail_msg); + break; + default: + tst_resm(TFAIL, "child exit status is %d", status); + break; + } +} + +static void consume(int mega) +{ + size_t sz; + void *ptr; + + sz = mega * 1024 * 1024; + ptr = SAFE_MALLOC(cleanup, sz); + memset(ptr, 0, sz); +} + +static void setup(void) +{ + tst_sig(FORK, DEF_HANDLER, cleanup); + + TEST_PAUSE; +} + +static void cleanup(void) +{ + TEST_CLEANUP; +} diff --git a/testcases/kernel/syscalls/getrusage/getrusage03_child.c b/testcases/kernel/syscalls/getrusage/getrusage03_child.c new file mode 100644 index 0000000..0008aea --- /dev/null +++ b/testcases/kernel/syscalls/getrusage/getrusage03_child.c @@ -0,0 +1,182 @@ +/* + * getrusage03_child.c - a child program executed by getrusage03 + * + * Copyright (C) 2011 Red Hat, Inc. + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU 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. + * + * Further, this software is distributed without any warranty that it + * is free of the rightful claim of any third person regarding + * infringement or the like. Any license provided herein, whether + * implied or otherwise, applies only to this software file. Patent + * licenses, if any, provided herein do not apply to combinations of + * this program with other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include <sys/types.h> +#include <sys/resource.h> +#include <sys/time.h> +#include <sys/wait.h> +#include <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "test.h" +#include "usctest.h" +#include "safe_macros.h" + +char *TCID = "getrusage03_child"; +int TST_TOTAL = 1; + +#define DELTA_MAX 10240 + +static int opt_consume, opt_grand, opt_show, opt_self, opt_child; +static char *consume_str, *grand_consume_str, *self_str, *child_str; + +option_t child_options[] = { + { "n:", &opt_consume, &consume_str }, + { "g:", &opt_grand, &grand_consume_str }, + { "v", &opt_show, NULL }, + { "s:", &opt_self, &self_str }, + { "l:", &opt_child, &child_str } +}; + +static void usage(void); +static void consume(int mega); +static long get_long(const char *str); +static void setup(void); +static void cleanup(void); + +int main(int argc, char *argv[]) +{ + int lc; + pid_t pid; + long maxrss_self, maxrss_children, delta; + long consume_nr, grand_consume_nr, self_nr, child_nr; + struct rusage ru; + char *msg; + + msg = parse_opts(argc, argv, child_options, usage); + if (msg != NULL) + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + Tst_count = 0; + + if (opt_consume) { + consume_nr = get_long(consume_str); + tst_resm(TINFO, "child allocate %ldMB", consume_nr); + consume(consume_nr); + } + + if (opt_grand) { + grand_consume_nr = get_long(grand_consume_str); + tst_resm(TINFO, "grandchild allocate %ldMB", + grand_consume_nr); + switch (pid = fork()) { + case -1: + tst_brkm(TBROK, cleanup, "fork"); + case 0: + consume(grand_consume_nr); + exit(0); + default: + break; + } + while (waitpid(-1, &pid, WUNTRACED|WCONTINUED) > 0) + if (WEXITSTATUS(pid) != 0) + tst_brkm(TBROK|TERRNO, cleanup, + "child exit status is not 0"); + } + + if (opt_show) { + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + maxrss_self = ru.ru_maxrss; + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + maxrss_children = ru.ru_maxrss; + tst_resm(TINFO, "exec.self = %ld, exec.children = %ld", + maxrss_self, maxrss_children); + if (opt_self) { + self_nr = get_long(self_str); + delta = maxrss_self - self_nr; + if (delta >= -DELTA_MAX && delta <= DELTA_MAX) + tst_resm(TPASS, + "initial.self ~= exec.self"); + else + tst_resm(TFAIL, + "initial.self !~= exec.self"); + } + if (opt_child) { + child_nr = get_long(child_str); + delta = maxrss_children - child_nr; + if (delta >= -DELTA_MAX && delta <= DELTA_MAX) + tst_resm(TPASS, + "initial.children ~= exec.children"); + else + tst_resm(TFAIL, + "initial.children !~= exec.children"); + } + } + } + + cleanup(); + tst_exit(); +} + +static void usage(void) +{ + printf(" -n NUM consume NUM MB size\n"); + printf(" -g NUM grandchild consume NUM MB size\n"); + printf(" -v verbose mode, show rusage info\n"); + printf(" -s NUM compare rusage_self.maxrss with given NUM\n"); + printf(" -l NUM compare rusage_children.maxrss with given NUM\n"); +} + +static void consume(int mega) +{ + size_t sz; + void *ptr; + + sz = mega * 1024 * 1024; + ptr = SAFE_MALLOC(cleanup, sz); + memset(ptr, 0, sz); +} + +static long get_long(const char *str) +{ + long val; + char *endptr; + + val = strtol(str, &endptr, 10); + if (((val == LONG_MAX || val == LONG_MIN) && errno == ERANGE) || + (errno != 0 && val == 0)) + tst_brkm(TBROK|TERRNO, cleanup, "strtol"); + if (endptr == str || *endptr != '\0') + tst_brkm(TBROK, cleanup, "Non-digits were found."); + + return val; +} + +static void setup(void) +{ + tst_sig(FORK, DEF_HANDLER, cleanup); + + TEST_PAUSE; +} + +static void cleanup(void) +{ + TEST_CLEANUP; +} [-- Attachment #3: Type: text/plain, Size: 377 bytes --] ------------------------------------------------------------------------------ All of the data generated in your IT infrastructure is seriously valuable. Why? It contains a definitive record of application performance, security threats, fraudulent activity, and more. Splunk takes this data and makes sense of it. IT sense. And common sense. http://p.sf.net/sfu/splunk-d2d-c2 [-- Attachment #4: Type: text/plain, Size: 155 bytes --] _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [LTP] [PATCH v3] [syscalls] getrusage03: test ru_maxrss 2011-06-29 15:36 ` [LTP] [PATCH v3] " Caspar Zhang @ 2011-06-29 17:46 ` Cyril Hrubis 2011-06-29 17:50 ` [LTP] [PATCH v4] " Caspar Zhang 1 sibling, 0 replies; 10+ messages in thread From: Cyril Hrubis @ 2011-06-29 17:46 UTC (permalink / raw) To: Caspar Zhang; +Cc: LTP List Hi! > +static void consume(int mega) > +{ > + size_t sz; > + void *ptr; > + > + sz = mega * 1024 * 1024; > + ptr = SAFE_MALLOC(cleanup, sz); > + memset(ptr, 0, sz); > +} > + > +static long get_long(const char *str) > +{ > + long val; > + char *endptr; > + > + val = strtol(str, &endptr, 10); > + if (((val == LONG_MAX || val == LONG_MIN) && errno == ERANGE) || > + (errno != 0 && val == 0)) > + tst_brkm(TBROK|TERRNO, cleanup, "strtol"); > + if (endptr == str || *endptr != '\0') > + tst_brkm(TBROK, cleanup, "Non-digits were found."); > + > + return val; > +} One more thing, please keep the error meesages sweet and to the point. Just imagine you get "Non-digits were found." error from some utility. Which doesn't say much, for example where was these non digits found. I would do something like: tst_brkm(TBROK, "Invalid number parameter '%s'", str); -- Cyril Hrubis chrubis@suse.cz ------------------------------------------------------------------------------ All of the data generated in your IT infrastructure is seriously valuable. Why? It contains a definitive record of application performance, security threats, fraudulent activity, and more. Splunk takes this data and makes sense of it. IT sense. And common sense. http://p.sf.net/sfu/splunk-d2d-c2 _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply [flat|nested] 10+ messages in thread
* [LTP] [PATCH v4] [syscalls] getrusage03: test ru_maxrss 2011-06-29 15:36 ` [LTP] [PATCH v3] " Caspar Zhang 2011-06-29 17:46 ` Cyril Hrubis @ 2011-06-29 17:50 ` Caspar Zhang 2011-07-11 13:16 ` Cyril Hrubis 1 sibling, 1 reply; 10+ messages in thread From: Caspar Zhang @ 2011-06-29 17:50 UTC (permalink / raw) To: LTP List [-- Attachment #1: Type: text/plain, Size: 906 bytes --] getrusage03 - test ru_maxrss behaviors in struct rusage This test program is backported from upstream commit: 1f10206cf8e945220f7220a809d8bfc15c21f9a5, which fills ru_maxrss value in struct rusage according to rss hiwater mark. To make sure this feature works correctly, a series of tests are executed in this program. Signed-off-by: Caspar Zhang <czhang@redhat.com> --- include/safe_macros.h | 5 + lib/safe_macros.c | 15 + runtest/syscalls | 1 + testcases/kernel/syscalls/getrusage/getrusage03.c | 358 ++++++++++++++++++++ .../kernel/syscalls/getrusage/getrusage03_child.c | 182 ++++++++++ 5 files changed, 561 insertions(+), 0 deletions(-) create mode 100644 testcases/kernel/syscalls/getrusage/getrusage03.c create mode 100644 testcases/kernel/syscalls/getrusage/getrusage03_child.c [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-syscalls-getrusage03-test-ru_maxrss.patch --] [-- Type: text/x-patch; name="0001-syscalls-getrusage03-test-ru_maxrss.patch", Size: 17495 bytes --] diff --git a/include/safe_macros.h b/include/safe_macros.h index 7c99c66..3753b7f 100644 --- a/include/safe_macros.h +++ b/include/safe_macros.h @@ -58,6 +58,11 @@ struct passwd* safe_getpwnam(const char *file, const int lineno, #define SAFE_GETPWNAM(cleanup_fn, name) \ safe_getpwnam(__FILE__, __LINE__, cleanup_fn, (name)) +int safe_getrusage(const char *file, const int lineno, + void (*cleanup_fn)(void), int who, struct rusage *usage); +#define SAFE_GETRUSAGE(cleanup_fn, who, usage) \ + safe_getrusage(__FILE__, __LINE__, (cleanup_fn), (who), (usage)) + void* safe_malloc(const char *file, const int lineno, void (*cleanup_fn)(void), size_t size); #define SAFE_MALLOC(cleanup_fn, size) \ diff --git a/lib/safe_macros.c b/lib/safe_macros.c index c98376d..11f5fe6 100644 --- a/lib/safe_macros.c +++ b/lib/safe_macros.c @@ -1,5 +1,6 @@ #include <sys/types.h> #include <sys/mman.h> +#include <sys/resource.h> #include <sys/stat.h> #include <fcntl.h> #include <libgen.h> @@ -108,6 +109,20 @@ safe_getpwnam(const char *file, const int lineno, void (*cleanup_fn)(void), return (rval); } +int +safe_getrusage(const char *file, const int lineno, void (*cleanup_fn)(void), + int who, struct rusage *usage) +{ + int rval; + + rval = getrusage(who, usage); + if (rval == -1) + tst_brkm(TBROK|TERRNO, cleanup_fn, "getrusage failed at %s:%d", + file, lineno); + + return rval; +} + void* safe_malloc(const char *file, const int lineno, void (*cleanup_fn)(void), size_t size) diff --git a/runtest/syscalls b/runtest/syscalls index 4294d07..7989764 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -399,6 +399,7 @@ get_robust_list01 get_robust_list01 getrusage01 getrusage01 getrusage02 getrusage02 +getrusage03 getrusage03 getsid01 getsid01 getsid02 getsid02 diff --git a/testcases/kernel/syscalls/getrusage/getrusage03.c b/testcases/kernel/syscalls/getrusage/getrusage03.c new file mode 100644 index 0000000..a50a852 --- /dev/null +++ b/testcases/kernel/syscalls/getrusage/getrusage03.c @@ -0,0 +1,358 @@ +/* + * getrusage03 - test ru_maxrss behaviors in struct rusage + * + * This test program is backported from upstream commit: + * 1f10206cf8e945220f7220a809d8bfc15c21f9a5, which fills ru_maxrss + * value in struct rusage according to rss hiwater mark. To make sure + * this feature works correctly, a series of tests are executed in + * this program. + * + * Copyright (C) 2011 Red Hat, Inc. + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU 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. + * + * Further, this software is distributed without any warranty that it + * is free of the rightful claim of any third person regarding + * infringement or the like. Any license provided herein, whether + * implied or otherwise, applies only to this software file. Patent + * licenses, if any, provided herein do not apply to combinations of + * this program with other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/resource.h> +#include <sys/time.h> +#include <sys/wait.h> +#include <unistd.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "test.h" +#include "usctest.h" +#include "safe_macros.h" + +char *TCID = "getrusage03"; +int TST_TOTAL = 1; + +#define DELTA_MAX 10240 + +static struct rusage ru; +static long maxrss_init; +static int retval, status; +static pid_t pid; + +static void inherit_fork(void); +static void inherit_fork2(void); +static void fork_malloc(void); +static void grandchild_maxrss(void); +static void zombie(void); +static void sig_ign(void); +static void exec_without_fork(void); +static void check_return(int status, char *pass_msg, char *fail_msg); +static int is_in_delta(long value); +static void consume(int mega); +static void setup(void); +static void cleanup(void); + +int main(int argc, char *argv[]) +{ + int lc; + char *msg; + + msg = parse_opts(argc, argv, NULL, NULL); + if (msg != NULL) + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + Tst_count = 0; + + tst_resm(TINFO, "allocate 100MB"); + consume(100); + + inherit_fork(); + inherit_fork2(); + fork_malloc(); + grandchild_maxrss(); + zombie(); + sig_ign(); + exec_without_fork(); + } + cleanup(); + tst_exit(); +} + +/* Testcase #01: fork inherit + * expect: initial.self ~= child.self */ +static void inherit_fork(void) +{ + tst_resm(TINFO, "Testcase #01: fork inherit"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + tst_resm(TINFO, "initial.self = %ld", ru.ru_maxrss); + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK|TERRNO, cleanup, "fork #1"); + case 0: + maxrss_init = ru.ru_maxrss; + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + tst_resm(TINFO, "child.self = %ld", ru.ru_maxrss); + exit(is_in_delta(maxrss_init - ru.ru_maxrss)); + default: + break; + } + + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + check_return(WEXITSTATUS(status), "initial.self ~= child.self", + "initial.self !~= child.self"); +} + +/* Testcase #02: fork inherit (cont.) + * expect: initial.children ~= 100MB, child.children = 0 */ +static void inherit_fork2(void) +{ + tst_resm(TINFO, "Testcase #02: fork inherit(cont.)"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); + if (is_in_delta(ru.ru_maxrss - 102400)) + tst_resm(TPASS, "initial.children ~= 100MB"); + else + tst_resm(TFAIL, "initial.children !~= 100MB"); + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK|TERRNO, cleanup, "fork #2"); + case 0: + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "child.children = %ld", ru.ru_maxrss); + exit(ru.ru_maxrss == 0); + default: + break; + } + + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + check_return(WEXITSTATUS(status), "child.children == 0", + "child.children != 0"); +} + +/* Testcase #03: fork + malloc + * expect: initial.self + 50MB ~= child.self */ +static void fork_malloc(void) +{ + tst_resm(TINFO, "Testcase #03: fork + malloc"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + tst_resm(TINFO, "initial.self = %ld", ru.ru_maxrss); + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK|TERRNO, cleanup, "fork #3"); + case 0: + maxrss_init = ru.ru_maxrss; + tst_resm(TINFO, "child allocate +50MB"); + consume(50); + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + tst_resm(TINFO, "child.self = %ld", ru.ru_maxrss); + exit(is_in_delta(maxrss_init + 51200 - ru.ru_maxrss)); + default: + break; + } + + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + check_return(WEXITSTATUS(status), "initial.self + 50MB ~= child.self", + "initial.self + 50MB !~= child.self"); +} + +/* Testcase #04: grandchild maxrss + * expect: post_wait.children ~= 300MB */ +static void grandchild_maxrss(void) +{ + tst_resm(TINFO, "Testcase #04: grandchild maxrss"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK|TERRNO, cleanup, "fork #4"); + case 0: + retval = system("getrusage03_child -g 300"); + if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0)) + tst_brkm(TBROK|TERRNO, cleanup, "system"); + exit(0); + default: + break; + } + + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + if (WEXITSTATUS(status) != 0) + tst_brkm(TBROK|TERRNO, cleanup, "child exit status is not 0"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "post_wait.children = %ld", ru.ru_maxrss); + if (is_in_delta(ru.ru_maxrss - 307200)) + tst_resm(TPASS, "child.children ~= 300MB"); + else + tst_resm(TFAIL, "child.children !~= 300MB"); +} + +/* Testcase #05: zombie + * expect: initial ~= pre_wait, post_wait ~= 400MB */ +static void zombie(void) +{ + tst_resm(TINFO, "Testcase #05: zombie"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); + maxrss_init = ru.ru_maxrss; + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK, cleanup, "fork #5"); + case 0: + retval = system("getrusage03_child -n 400"); + if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0)) + tst_brkm(TBROK|TERRNO, cleanup, "system"); + exit(0); + default: + break; + } + + sleep(1); /* children become zombie */ + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "pre_wait.children = %ld", ru.ru_maxrss); + if (is_in_delta(ru.ru_maxrss - maxrss_init)) + tst_resm(TPASS, "initial.children ~= pre_wait.children"); + else + tst_resm(TFAIL, "initial.children !~= pre_wait.children"); + + if (waitpid(pid, &status, WUNTRACED|WCONTINUED) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + if (WEXITSTATUS(status) != 0) + tst_brkm(TBROK|TERRNO, cleanup, "child exit status is not 0"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "post_wait.children = %ld", ru.ru_maxrss); + if (is_in_delta(ru.ru_maxrss - 409600)) + tst_resm(TPASS, "post_wait.children ~= 400MB"); + else + tst_resm(TFAIL, "post_wait.children !~= 400MB"); +} + +/* Testcase #06: SIG_IGN + * expect: initial ~= after_zombie */ +static void sig_ign(void) +{ + tst_resm(TINFO, "Testcase #06: SIG_IGN"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "initial.children = %ld", ru.ru_maxrss); + signal(SIGCHLD, SIG_IGN); + maxrss_init = ru.ru_maxrss; + + switch (pid = fork()) { + case -1: + tst_brkm(TBROK, cleanup, "fork #6"); + case 0: + retval = system("getrusage03_child -n 500"); + if ((WIFEXITED(retval) && WEXITSTATUS(retval) != 0)) + tst_brkm(TBROK|TERRNO, cleanup, "system"); + exit(0); + default: + break; + } + + sleep(1); /* children become zombie */ + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + tst_resm(TINFO, "after_zombie.children = %ld", ru.ru_maxrss); + if (is_in_delta(ru.ru_maxrss - maxrss_init)) + tst_resm(TPASS, "initial.children ~= after_zombie.children"); + else + tst_resm(TFAIL, "initial.children !~= after_zombie.children"); + signal(SIGCHLD, SIG_DFL); +} + +/* Testcase #07: exec without fork + * expect: initial ~= fork */ +static void exec_without_fork(void) +{ + char str_maxrss_self[BUFSIZ], str_maxrss_child[BUFSIZ]; + long maxrss_self, maxrss_child; + + tst_resm(TINFO, "Testcase #07: exec without fork"); + + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + maxrss_self = ru.ru_maxrss; + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + maxrss_child = ru.ru_maxrss; + tst_resm(TINFO, "initial.self = %ld, initial.children = %ld", + maxrss_self, maxrss_child); + + sprintf(str_maxrss_self, "%ld", maxrss_self); + sprintf(str_maxrss_child, "%ld", maxrss_child); + if (execlp("getrusage03_child", "getrusage03_child", "-v", + "-s", str_maxrss_self, + "-l", str_maxrss_child, NULL) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "execlp"); +} + +static int is_in_delta(long value) +{ + return (value >= -DELTA_MAX && value <= DELTA_MAX); +} + +static void check_return(int status, char *pass_msg, char *fail_msg) +{ + switch (status) { + case 1: + tst_resm(TPASS, "%s", pass_msg); + break; + case 0: + tst_resm(TFAIL, "%s", fail_msg); + break; + default: + tst_resm(TFAIL, "child exit status is %d", status); + break; + } +} + +static void consume(int mega) +{ + size_t sz; + void *ptr; + + sz = mega * 1024 * 1024; + ptr = SAFE_MALLOC(cleanup, sz); + memset(ptr, 0, sz); +} + +static void setup(void) +{ + tst_sig(FORK, DEF_HANDLER, cleanup); + + TEST_PAUSE; +} + +static void cleanup(void) +{ + TEST_CLEANUP; +} diff --git a/testcases/kernel/syscalls/getrusage/getrusage03_child.c b/testcases/kernel/syscalls/getrusage/getrusage03_child.c new file mode 100644 index 0000000..0008aea --- /dev/null +++ b/testcases/kernel/syscalls/getrusage/getrusage03_child.c @@ -0,0 +1,182 @@ +/* + * getrusage03_child.c - a child program executed by getrusage03 + * + * Copyright (C) 2011 Red Hat, Inc. + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU 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. + * + * Further, this software is distributed without any warranty that it + * is free of the rightful claim of any third person regarding + * infringement or the like. Any license provided herein, whether + * implied or otherwise, applies only to this software file. Patent + * licenses, if any, provided herein do not apply to combinations of + * this program with other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include <sys/types.h> +#include <sys/resource.h> +#include <sys/time.h> +#include <sys/wait.h> +#include <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "test.h" +#include "usctest.h" +#include "safe_macros.h" + +char *TCID = "getrusage03_child"; +int TST_TOTAL = 1; + +#define DELTA_MAX 10240 + +static int opt_consume, opt_grand, opt_show, opt_self, opt_child; +static char *consume_str, *grand_consume_str, *self_str, *child_str; + +option_t child_options[] = { + { "n:", &opt_consume, &consume_str }, + { "g:", &opt_grand, &grand_consume_str }, + { "v", &opt_show, NULL }, + { "s:", &opt_self, &self_str }, + { "l:", &opt_child, &child_str } +}; + +static void usage(void); +static void consume(int mega); +static long get_long(const char *str); +static void setup(void); +static void cleanup(void); + +int main(int argc, char *argv[]) +{ + int lc; + pid_t pid; + long maxrss_self, maxrss_children, delta; + long consume_nr, grand_consume_nr, self_nr, child_nr; + struct rusage ru; + char *msg; + + msg = parse_opts(argc, argv, child_options, usage); + if (msg != NULL) + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + Tst_count = 0; + + if (opt_consume) { + consume_nr = get_long(consume_str); + tst_resm(TINFO, "child allocate %ldMB", consume_nr); + consume(consume_nr); + } + + if (opt_grand) { + grand_consume_nr = get_long(grand_consume_str); + tst_resm(TINFO, "grandchild allocate %ldMB", + grand_consume_nr); + switch (pid = fork()) { + case -1: + tst_brkm(TBROK, cleanup, "fork"); + case 0: + consume(grand_consume_nr); + exit(0); + default: + break; + } + while (waitpid(-1, &pid, WUNTRACED|WCONTINUED) > 0) + if (WEXITSTATUS(pid) != 0) + tst_brkm(TBROK|TERRNO, cleanup, + "child exit status is not 0"); + } + + if (opt_show) { + SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru); + maxrss_self = ru.ru_maxrss; + SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru); + maxrss_children = ru.ru_maxrss; + tst_resm(TINFO, "exec.self = %ld, exec.children = %ld", + maxrss_self, maxrss_children); + if (opt_self) { + self_nr = get_long(self_str); + delta = maxrss_self - self_nr; + if (delta >= -DELTA_MAX && delta <= DELTA_MAX) + tst_resm(TPASS, + "initial.self ~= exec.self"); + else + tst_resm(TFAIL, + "initial.self !~= exec.self"); + } + if (opt_child) { + child_nr = get_long(child_str); + delta = maxrss_children - child_nr; + if (delta >= -DELTA_MAX && delta <= DELTA_MAX) + tst_resm(TPASS, + "initial.children ~= exec.children"); + else + tst_resm(TFAIL, + "initial.children !~= exec.children"); + } + } + } + + cleanup(); + tst_exit(); +} + +static void usage(void) +{ + printf(" -n NUM consume NUM MB size\n"); + printf(" -g NUM grandchild consume NUM MB size\n"); + printf(" -v verbose mode, show rusage info\n"); + printf(" -s NUM compare rusage_self.maxrss with given NUM\n"); + printf(" -l NUM compare rusage_children.maxrss with given NUM\n"); +} + +static void consume(int mega) +{ + size_t sz; + void *ptr; + + sz = mega * 1024 * 1024; + ptr = SAFE_MALLOC(cleanup, sz); + memset(ptr, 0, sz); +} + +static long get_long(const char *str) +{ + long val; + char *endptr; + + val = strtol(str, &endptr, 10); + if (((val == LONG_MAX || val == LONG_MIN) && errno == ERANGE) || + (errno != 0 && val == 0)) + tst_brkm(TBROK|TERRNO, cleanup, "strtol"); + if (endptr == str || *endptr != '\0') + tst_brkm(TBROK, cleanup, "Invalid number parameter: %s", str); + + return val; +} + +static void setup(void) +{ + tst_sig(FORK, DEF_HANDLER, cleanup); + + TEST_PAUSE; +} + +static void cleanup(void) +{ + TEST_CLEANUP; +} [-- Attachment #3: Type: text/plain, Size: 377 bytes --] ------------------------------------------------------------------------------ All of the data generated in your IT infrastructure is seriously valuable. Why? It contains a definitive record of application performance, security threats, fraudulent activity, and more. Splunk takes this data and makes sense of it. IT sense. And common sense. http://p.sf.net/sfu/splunk-d2d-c2 [-- Attachment #4: Type: text/plain, Size: 155 bytes --] _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [LTP] [PATCH v4] [syscalls] getrusage03: test ru_maxrss 2011-06-29 17:50 ` [LTP] [PATCH v4] " Caspar Zhang @ 2011-07-11 13:16 ` Cyril Hrubis 0 siblings, 0 replies; 10+ messages in thread From: Cyril Hrubis @ 2011-07-11 13:16 UTC (permalink / raw) To: Caspar Zhang; +Cc: LTP List Hi! > getrusage03 - test ru_maxrss behaviors in struct rusage > > This test program is backported from upstream commit: > 1f10206cf8e945220f7220a809d8bfc15c21f9a5, which fills ru_maxrss > value in struct rusage according to rss hiwater mark. To make sure > this feature works correctly, a series of tests are executed in > this program. > > Signed-off-by: Caspar Zhang <czhang@redhat.com> Commited, thanks. -- Cyril Hrubis chrubis@suse.cz ------------------------------------------------------------------------------ All of the data generated in your IT infrastructure is seriously valuable. Why? It contains a definitive record of application performance, security threats, fraudulent activity, and more. Splunk takes this data and makes sense of it. IT sense. And common sense. http://p.sf.net/sfu/splunk-d2d-c2 _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-07-11 13:14 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-16 15:05 [LTP] [PATCH] [syscalls] getrusage03: test ru_maxrss Caspar Zhang
2011-05-16 15:08 ` Caspar Zhang
2011-05-19 17:40 ` Cyril Hrubis
[not found] ` <BANLkTi=m96RBZeFuRaOA5Sb_QANhgo4yCA@mail.gmail.com>
2011-05-20 13:29 ` Cyril Hrubis
2011-06-13 13:12 ` [LTP] [PATCH v2] " Caspar Zhang
2011-06-29 14:14 ` Cyril Hrubis
2011-06-29 15:36 ` [LTP] [PATCH v3] " Caspar Zhang
2011-06-29 17:46 ` Cyril Hrubis
2011-06-29 17:50 ` [LTP] [PATCH v4] " Caspar Zhang
2011-07-11 13:16 ` Cyril Hrubis
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox