source: branches/stable/TEMPLATES/command_output.h

Last change on this file was 17729, checked in by westram, 5 years ago
  • fix test condition "contains":
    • checking for empty part
      • always returned 'true'
      • now fails assertion and returns 'false' (it is unwanted to test that)
    • fix callers
File size: 8.1 KB
Line 
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
34class 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
60public:
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    }
99    ~CommandOutput() {
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
Note: See TracBrowser for help on using the repository browser.