File: command_output.h

package info (click to toggle)
arb 6.0.6-8
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid, trixie
  • size: 66,204 kB
  • sloc: ansic: 394,911; cpp: 250,290; makefile: 19,644; sh: 15,879; perl: 10,473; fortran: 6,019; ruby: 683; xml: 503; python: 53; awk: 32
file content (158 lines) | stat: -rw-r--r-- 6,837 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// ============================================================= //
//                                                               //
//   File      : command_output.h                                //
//   Purpose   :                                                 //
//                                                               //
//   Coded by Ralf Westram (coder@reallysoft.de) in March 2012   //
//   Institute of Microbiology (Technical University Munich)     //
//   http://www.arb-home.de/                                     //
//                                                               //
// ============================================================= //

#ifndef COMMAND_OUTPUT_H
#define COMMAND_OUTPUT_H

#ifndef UNIT_TESTS
#error currently only used inside unittest-code. need refactoring to be used generally
#endif

#ifndef ARB_FILE_H
#include <arb_file.h>
#endif
#ifndef ARBDBT_H
#include <arbdbt.h>
#endif
#ifndef UT_VALGRINDED_H
#include <ut_valgrinded.h>
#endif
#ifndef _UNISTD_H
#include <unistd.h>
#endif

// --------------------------------------------------------------------------------

class CommandOutput : virtual Noncopyable {
    // support class to test CLI of arb-tools

    char     *stdoutput; // output from command
    char     *stderrput;
    GB_ERROR  error;

    void appendError(GB_ERROR err) {
        if (!error) error = err;
        else error = GBS_global_string("%s\n%s", error, err);
    }

    char *readAndUnlink(const char *file) {
        char *content = GB_read_file(file);
        if (!content) appendError(GB_await_error());
        int res = GB_unlink(file);
        if (res == -1) appendError(GB_await_error());
        return content;
    }
public:
    CommandOutput(const char *command, bool try_valgrind)
        : stdoutput(NULL), stderrput(NULL), error(NULL)
    {
        char *escaped = GBS_string_eval(command, "'=\\\\'", NULL);
        if (!escaped) {
            appendError(GB_await_error());
        }
        else {
            if (try_valgrind) make_valgrinded_call(escaped);

            pid_t pid = getpid();

            char *stdout_log = GBS_global_string_copy("stdout_%i.log", pid);
            char *stderr_log = GBS_global_string_copy("stderr_%i.log", pid);

            char *cmd = GBS_global_string_copy("bash -c '%s >%s 2>%s'", escaped, stdout_log, stderr_log);

            appendError(GBK_system(cmd));
            free(cmd);
            free(escaped);

            stdoutput = readAndUnlink(stdout_log);
            stderrput = readAndUnlink(stderr_log);

            free(stderr_log);
            free(stdout_log);
        }
        if (error) {
            printf("command '%s'\n"
                   "escaped command '%s'\n"
                   "stdout='%s'\n"
                   "stderr='%s'\n", 
                   command, escaped, stdoutput, stderrput);
        }
    }
    ~CommandOutput() {
        free(stderrput);
        free(stdoutput);
    }

    const char *get_stdoutput() const { return stdoutput; }
    const char *get_stderrput() const { return stderrput; }
    GB_ERROR get_error() const { return error; }

    arb_test::match_expectation Equals(const char *expected_std, const char *expected_err) {
        using namespace arb_test;
        expectation_group expected(that(error).is_equal_to_NULL());
        if (expected_std) expected.add(that(stdoutput).is_equal_to(expected_std));
        if (expected_err) expected.add(that(stderrput).is_equal_to(expected_err));
        return all().ofgroup(expected);
    }
    arb_test::match_expectation Contains(const char *expected_std, const char *expected_err) {
        using namespace arb_test;
        expectation_group expected(that(error).is_equal_to_NULL());
        if (expected_std) expected.add(that(stdoutput).does_contain(expected_std));
        if (expected_err) expected.add(that(stderrput).does_contain(expected_err));
        return all().ofgroup(expected);
    }
    arb_test::match_expectation has_checksum(uint32_t expected_checksum) {
        uint32_t css      = GBS_checksum(stdoutput, false, "");
        uint32_t cse      = GBS_checksum(stderrput, false, "");
        uint32_t checksum = css^cse;
        using namespace arb_test;
        return all().of(that(error).is_equal_to_NULL(),
                        that(checksum).is_equal_to(expected_checksum));
    }
};

// --------------------------------------------------------------------------------

#define TEST_OUTPUT_EQUALS(cmd, expected_std, expected_err)                                             \
    do {                                                                                                \
        bool try_valgrind = (expected_err == NULL);                                                     \
        TEST_EXPECTATION(CommandOutput(cmd, try_valgrind).Equals(expected_std, expected_err));               \
    } while(0)

#define TEST_OUTPUT_EQUALS__BROKEN(cmd, expected_std, expected_err)                                     \
    do {                                                                                                \
        bool try_valgrind = (expected_err == NULL);                                                     \
        TEST_EXPECTATION__BROKEN(CommandOutput(cmd, try_valgrind).Equals(expected_std, expected_err));       \
    } while(0)

#define TEST_OUTPUT_CONTAINS(cmd, expected_std, expected_err)                                           \
    do {                                                                                                \
        bool try_valgrind = (expected_err == NULL);                                                     \
        TEST_EXPECTATION(CommandOutput(cmd, try_valgrind).Contains(expected_std, expected_err));             \
    } while(0)

#define TEST_OUTPUT_CONTAINS__BROKEN(cmd, expected_std, expected_err)                                   \
    do {                                                                                                \
        bool try_valgrind = (expected_err == NULL);                                                     \
        TEST_EXPECTATION__BROKEN(CommandOutput(cmd, try_valgrind).Contains(expected_std, expected_err));     \
    } while(0)

#define TEST_OUTPUT_HAS_CHECKSUM(cmd,checksum)         TEST_EXPECTATION        (CommandOutput(cmd, false).has_checksum(checksum))
#define TEST_OUTPUT_HAS_CHECKSUM__BROKEN(cmd,checksum) TEST_EXPECTATION__BROKEN(CommandOutput(cmd, false).has_checksum(checksum))

#define TEST_STDOUT_EQUALS(cmd, expected_std) TEST_OUTPUT_EQUALS(cmd, expected_std, (const char *)NULL)
#define TEST_STDERR_EQUALS(cmd, expected_err) TEST_OUTPUT_EQUALS(cmd, (const char *)NULL, expected_err)

#define TEST_STDOUT_CONTAINS(cmd, part) TEST_OUTPUT_CONTAINS(cmd, part, "")

#else
#error command_output.h included twice
#endif // COMMAND_OUTPUT_H