ARB
test_runtool.h
Go to the documentation of this file.
1 // ============================================================ //
2 // //
3 // File : test_runtool.h //
4 // Purpose : provides tests for external tools (CLI) //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in June 2017 //
7 // http://www.arb-home.de/ //
8 // //
9 // ============================================================ //
10 
11 #ifndef TEST_RUNTOOL_H
12 #define TEST_RUNTOOL_H
13 
14 #ifndef UT_VALGRINDED_H
15 #include <ut_valgrinded.h>
16 #endif
17 #ifndef ARB_STRARRAY_H
18 #include <arb_strarray.h>
19 #endif
20 #ifndef ARB_STRBUF_H
21 #include <arb_strbuf.h>
22 #endif
23 
24 namespace test_runtool {
25 
26  inline char *make_checked_piped_command(const char *piped_command, int pipeSymbolCount) {
27  // append pipe-check to 'piped_command'
28  // ('piped_command' has to contain 'pipeSymbolCount' pipe symbols)
29  // - wrap command in call to bash (PIPESTATUS is bash-specific)
30 
31  arb_assert(pipeSymbolCount>0);
32 
33  GBS_strstruct cmd_list(500);
34  cmd_list.cat(piped_command);
35  // append bash-expression to check result of each part of the pipe
36  cmd_list.cat(";exit $((");
37  for (int i = 0; i<=pipeSymbolCount; ++i) {
38  if (i) cmd_list.cat(" | ");
39  cmd_list.nprintf(30, "${PIPESTATUS[%i]}", i);
40  }
41  cmd_list.cat("))");
42 
43  // explicitely use bash to execute:
44  char *quotedCommand = GBK_singlequote(cmd_list.get_data());
45  char *checked_cmd = GBS_global_string_copy("bash -c %s", quotedCommand);
46  free(quotedCommand);
47  return checked_cmd;
48  }
49 
50  inline void add_valgrinded_cmd(StrArray& array, char *cmd) {
52  array.put(cmd);
53  }
54 
55  inline char *valgrinded_pipe_command(const char *piped_command, const char *first_pipe) {
56  if (will_valgrind_calls()) {
57  StrArray pipe_cmds;
58 
59  while (first_pipe) {
60  add_valgrinded_cmd(pipe_cmds, ARB_strpartdup(piped_command, first_pipe-1));
61  piped_command = first_pipe+1;
62  first_pipe = find_pipe_symbol(piped_command);
63  }
64  add_valgrinded_cmd(pipe_cmds, strdup(piped_command)); // rest
65 
66  char *repiped_cmd = GBT_join_strings(pipe_cmds, '|');
67  char *checked_repiped_cmd = make_checked_piped_command(repiped_cmd, pipe_cmds.size()-1);
68  free(repiped_cmd);
69 
70  return checked_repiped_cmd;
71  }
72 
73  int pipeCount = 0;
74  while (first_pipe) {
75  ++pipeCount;
76  first_pipe = find_pipe_symbol(first_pipe+1);
77  }
78  return make_checked_piped_command(piped_command, pipeCount);
79  }
80 
81  inline GB_ERROR valgrinded_system(const char *cmdline) { // @@@ rename later (does more)
82  // basically does two things:
83  // - if current binary runs valgrinded => use valgrind to run 'cmdline' (can handle pipes)
84  // - if 'cmdline' is a pipe => check exitcodes of all parts of the pipe
85 
86  char *cmddup = NULp;
87  const char *first_pipe = find_pipe_symbol(cmdline);
88 
89  if (first_pipe) {
90  cmddup = valgrinded_pipe_command(cmdline, first_pipe);
91  }
92  else {
93  cmddup = ARB_strdup(cmdline);
94  make_valgrinded_call(cmddup);
95  }
96 
97  GB_ERROR error = GBK_system(cmddup);
98  free(cmddup);
99  return error;
100  }
101 
102 };
103 
104 #define RUN_TOOL(cmdline) test_runtool::valgrinded_system(cmdline)
105 #define RUN_TOOL_NEVER_VALGRIND(cmdline) GBK_system(cmdline)
106 
107 // expect success or failure running CLI-tool:
108 
109 #define TEST_RUN_TOOL(cmdline) TEST_EXPECT_NO_ERROR(RUN_TOOL(cmdline))
110 #define TEST_RUN_TOOL_NEVER_VALGRIND(cmdline) TEST_EXPECT_NO_ERROR(RUN_TOOL_NEVER_VALGRIND(cmdline))
111 #define TEST_RUN_TOOL_FAILS(cmdline) TEST_EXPECT_ERROR_CONTAINS(RUN_TOOL(cmdline), "System call failed")
112 
113 // Note: more detailed tests are available using TEST_OUTPUT_CONTAINS, TEST_FAILURE_OUTPUT_CONTAINS and related macros
114 
115 #else
116 #error test_runtool.h included twice
117 #endif // TEST_RUNTOOL_H
char * make_checked_piped_command(const char *piped_command, int pipeSymbolCount)
Definition: test_runtool.h:26
GB_ERROR GBK_system(const char *system_command)
Definition: arb_msg.cxx:571
#define arb_assert(cond)
Definition: arb_assert.h:245
GB_ERROR valgrinded_system(const char *cmdline)
Definition: test_runtool.h:81
char * valgrinded_pipe_command(const char *piped_command, const char *first_pipe)
Definition: test_runtool.h:55
char * ARB_strdup(const char *str)
Definition: arb_string.h:27
void add_valgrinded_cmd(StrArray &array, char *cmd)
Definition: test_runtool.h:50
void cat(const char *from)
Definition: arb_strbuf.h:199
char * ARB_strpartdup(const char *start, const char *end)
Definition: arb_string.h:51
const char * find_pipe_symbol(const char *str)
Definition: ut_valgrinded.h:15
static void error(const char *msg)
Definition: mkptypes.cxx:96
char * GBT_join_strings(const CharPtrArray &strings, char separator)
#define make_valgrinded_call(command)
char * GBK_singlequote(const char *arg)
Definition: arb_msg.cxx:599
void nprintf(size_t maxlen, const char *templat,...) __ATTR__FORMAT_MEMBER(2)
Definition: arb_strbuf.cxx:29
bool will_valgrind_calls()
#define NULp
Definition: cxxforward.h:116
const char * get_data() const
Definition: arb_strbuf.h:120
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:194