ARB
command_output.h
Go to the documentation of this file.
1 // ============================================================= //
2 // //
3 // File : command_output.h //
4 // Purpose : //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in March 2012 //
7 // Institute of Microbiology (Technical University Munich) //
8 // http://www.arb-home.de/ //
9 // //
10 // ============================================================= //
11 
12 #ifndef COMMAND_OUTPUT_H
13 #define COMMAND_OUTPUT_H
14 
15 #ifndef UNIT_TESTS
16 #error currently only used inside unittest-code. need refactoring to be used generally
17 #endif
18 
19 #ifndef ARB_FILE_H
20 #include <arb_file.h>
21 #endif
22 #ifndef ARBDBT_H
23 #include <arbdbt.h>
24 #endif
25 #ifndef UT_VALGRINDED_H
26 #include <ut_valgrinded.h>
27 #endif
28 #ifndef _UNISTD_H
29 #include <unistd.h>
30 #endif
31 
32 // --------------------------------------------------------------------------------
33 
34 class CommandOutput : virtual Noncopyable {
35  // support class to test CLI of arb-tools
36 
37  char *stdoutput; // output from command
38  char *stderrput;
39  GB_ERROR error;
40  bool expect_failure;
41 
42  void appendError(GB_ERROR err) {
43  if (!error) error = err;
44  else error = GBS_global_string("%s\n%s", error, err);
45  }
46 
47  char *readAndUnlink(const char *file) {
48  char *content = GB_read_file(file);
49  if (!content) appendError(GB_await_error());
50  int res = GB_unlink(file);
51  if (res == -1) appendError(GB_await_error());
52  return content;
53  }
54  void add_failure_expection(arb_test::expectation_group& expected) {
55  using namespace arb_test;
56  if (expect_failure) expected.add(that(error).does_differ_from_NULL());
57  else expected.add(that(error).is_equal_to_NULL());
58  }
59 
60 public:
61  CommandOutput(const char *command, bool try_valgrind, bool expect_failure_ = false) : // @@@ remove parameter try_valgrind - see ./ut_valgrinded.h@make_valgrinded_call
62  stdoutput(NULp),
63  stderrput(NULp),
64  error(NULp),
65  expect_failure(expect_failure_)
66  {
67  char *escaped = GBS_string_eval(command, "'=\\\\'"); // @@@ use GBK_singlequote?
68  if (!escaped) {
69  appendError(GB_await_error());
70  }
71  else {
72  if (try_valgrind) make_valgrinded_call(escaped); // @@@ extract part of valgrinded_system to create command
73 
74  pid_t pid = getpid();
75 
76  char *stdout_log = GBS_global_string_copy("stdout_%i.log", pid);
77  char *stderr_log = GBS_global_string_copy("stderr_%i.log", pid);
78 
79  char *cmd = GBS_global_string_copy("bash -c '%s >%s 2>%s'", escaped, stdout_log, stderr_log);
80 
81  appendError(GBK_system(cmd));
82  free(cmd);
83 
84  stdoutput = readAndUnlink(stdout_log);
85  stderrput = readAndUnlink(stderr_log);
86 
87  free(stderr_log);
88  free(stdout_log);
89  }
90  if (error) {
91  printf("command '%s'\n"
92  "escaped command '%s'\n"
93  "stdout='%s'\n"
94  "stderr='%s'\n",
95  command, escaped, stdoutput, stderrput);
96  }
97  free(escaped);
98  }
100  free(stderrput);
101  free(stdoutput);
102  }
103 
104  const char *get_stdoutput() const { return stdoutput; }
105  const char *get_stderrput() const { return stderrput; }
106  GB_ERROR get_error() const { return error; }
107 
108  arb_test::match_expectation Equals(const char *expected_std, const char *expected_err) {
109  using namespace arb_test;
110  expectation_group expected; add_failure_expection(expected);
111  if (expected_std) expected.add(that(stdoutput).is_equal_to(expected_std));
112  if (expected_err) expected.add(that(stderrput).is_equal_to(expected_err));
113  return all().ofgroup(expected);
114  }
115  arb_test::match_expectation Contains(const char *expected_std, const char *expected_err) {
116  using namespace arb_test;
117  expectation_group expected; add_failure_expection(expected);
118  if (expected_std) expected.add(that(stdoutput).does_contain(expected_std));
119  if (expected_err) expected.add(that(stderrput).does_contain(expected_err));
120  return all().ofgroup(expected);
121  }
122  arb_test::match_expectation has_checksum(uint32_t expected_checksum) {
123  uint32_t css = GBS_checksum(stdoutput, false, "");
124  uint32_t cse = GBS_checksum(stderrput, false, "");
125  uint32_t checksum = css^cse;
126 
127  using namespace arb_test;
128  expectation_group expected; add_failure_expection(expected);
129  expected.add(that(checksum).is_equal_to(expected_checksum));
130  return all().ofgroup(expected);
131  }
132 };
133 
134 // --------------------------------------------------------------------------------
135 
136 #define TEST_OUTPUT_EQUALS(cmd, expected_std, expected_err) \
137  do { \
138  bool try_valgrind = false; \
139  TEST_EXPECTATION(CommandOutput(cmd, try_valgrind).Equals(expected_std, expected_err)); \
140  } while(0)
141 
142 #define TEST_OUTPUT_EQUALS__BROKEN(cmd, expected_std, expected_err) \
143  do { \
144  bool try_valgrind = false; \
145  TEST_EXPECTATION__BROKEN_SIMPLE(CommandOutput(cmd, try_valgrind).Equals(expected_std, expected_err)); \
146  } while(0)
147 
148 #define TEST_OUTPUT_CONTAINS(cmd, expected_std, expected_err) \
149  do { \
150  bool try_valgrind = false; \
151  TEST_EXPECTATION(CommandOutput(cmd, try_valgrind).Contains(expected_std, expected_err)); \
152  } while(0)
153 
154 #define TEST_OUTPUT_CONTAINS__BROKEN(cmd, expected_std, expected_err) \
155  do { \
156  bool try_valgrind = false; \
157  TEST_EXPECTATION__BROKEN_SIMPLE(CommandOutput(cmd, try_valgrind).Contains(expected_std, expected_err)); \
158  } while(0)
159 
160 #define TEST_FAILURE_OUTPUT_CONTAINS(cmd, expected_std, expected_err) \
161  do { \
162  TEST_EXPECTATION(CommandOutput(cmd, false, true).Contains(expected_std, expected_err)); \
163  } while(0)
164 
165 #define TEST_FAILURE_OUTPUT_CONTAINS__BROKEN(cmd, expected_std, expected_err) \
166  do { \
167  TEST_EXPECTATION__BROKEN_SIMPLE(CommandOutput(cmd, false, true).Contains(expected_std, expected_err)); \
168  } while(0)
169 
170 
171 #define TEST_OUTPUT_HAS_CHECKSUM(cmd,checksum) TEST_EXPECTATION (CommandOutput(cmd, false).has_checksum(checksum))
172 #define TEST_OUTPUT_HAS_CHECKSUM__BROKEN(cmd,checksum) TEST_EXPECTATION__BROKEN_SIMPLE(CommandOutput(cmd, false).has_checksum(checksum))
173 
174 #define TEST_STDOUT_EQUALS(cmd, expected_std) TEST_OUTPUT_EQUALS(cmd, expected_std, (const char *)NULp)
175 #define TEST_STDERR_EQUALS(cmd, expected_err) TEST_OUTPUT_EQUALS(cmd, (const char *)NULp, expected_err)
176 
177 #define TEST_STDOUT_CONTAINS(cmd, part) TEST_OUTPUT_CONTAINS(cmd, part, (const char *)NULp)
178 #define TEST_STDERR_CONTAINS(cmd, part) TEST_OUTPUT_CONTAINS(cmd, (const char *)NULp, part)
179 
180 #else
181 #error command_output.h included twice
182 #endif // COMMAND_OUTPUT_H
GB_ERROR GBK_system(const char *system_command)
Definition: arb_msg.cxx:519
group_matcher all()
Definition: test_unit.h:1000
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:204
char * GBS_string_eval(const char *insource, const char *icommand)
Definition: admatch.cxx:699
int GB_unlink(const char *path)
Definition: arb_file.cxx:188
const char * get_stdoutput() const
arb_test::match_expectation has_checksum(uint32_t expected_checksum)
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:353
#define is_equal_to_NULL()
Definition: test_unit.h:1017
expectation_group & add(const expectation &e)
Definition: test_unit.h:801
#define that(thing)
Definition: test_unit.h:1032
arb_test::match_expectation Contains(const char *expected_std, const char *expected_err)
#define does_differ_from_NULL()
Definition: test_unit.h:1018
const char * get_stderrput() const
GB_ERROR get_error() const
#define is_equal_to(val)
Definition: test_unit.h:1014
#define does_contain(val)
Definition: test_unit.h:1029
#define make_valgrinded_call(command)
CommandOutput(const char *command, bool try_valgrind, bool expect_failure_=false)
uint32_t GBS_checksum(const char *seq, int ignore_case, const char *exclude)
Definition: adstring.cxx:353
#define NULp
Definition: cxxforward.h:97
arb_test::match_expectation Equals(const char *expected_std, const char *expected_err)
static char * command
Definition: arb_a2ps.c:319
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:195
char * GB_read_file(const char *path)
Definition: adsocket.cxx:287