~ubuntu-branches/ubuntu/lucid/rsyslog/lucid-updates

« back to all changes in this revision

Viewing changes to tests/udptester.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Biebl
  • Date: 2009-06-23 12:12:43 UTC
  • mfrom: (1.1.11 upstream) (3.2.8 sid)
  • Revision ID: james.westby@ubuntu.com-20090623121243-d2fejarzidywnn17
Tags: 4.2.0-1
* New upstream release of the now stable v4 branch.
  - Fix warnings when /etc/rsyslog.d/ is empty. Closes: #530228
* debian/patches/imudp_multiple_udp_sockets.patch
  - Removed, merged upstream.
* debian/rsyslog.default
  - Set default compat mode to '4'.
* debian/rsyslog.logcheck.ignore.server
  - Update logcheck rules files to also ignore rsyslogd and imklog stop
    messages.
* debian/control
  - Bump Standards-Version to 3.8.2. No further changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Runs a test suite on the rsyslog (and later potentially
 
2
 * other things).
 
3
 *
 
4
 * The name of the test suite must be given as argv[1]. In this config,
 
5
 * rsyslogd is loaded with config ./testsuites/<name>.conf and then
 
6
 * test cases ./testsuites/ *.<name> are executed on it. This test driver is
 
7
 * suitable for testing cases where a message sent (via UDP) results in
 
8
 * exactly one response. It can not be used in cases where no response
 
9
 * is expected (that would result in a hang of the test driver).
 
10
 * Note: each test suite can contain many tests, but they all need to work
 
11
 * with the same rsyslog configuration.
 
12
 *
 
13
 * Part of the testbench for rsyslog.
 
14
 *
 
15
 * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
 
16
 *
 
17
 * This file is part of rsyslog.
 
18
 *
 
19
 * Rsyslog is free software: you can redistribute it and/or modify
 
20
 * it under the terms of the GNU General Public License as published by
 
21
 * the Free Software Foundation, either version 3 of the License, or
 
22
 * (at your option) any later version.
 
23
 *
 
24
 * Rsyslog is distributed in the hope that it will be useful,
 
25
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
26
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
27
 * GNU General Public License for more details.
 
28
 *
 
29
 * You should have received a copy of the GNU General Public License
 
30
 * along with Rsyslog.  If not, see <http://www.gnu.org/licenses/>.
 
31
 *
 
32
 * A copy of the GPL can be found in the file "COPYING" in this distribution.
 
33
 */
 
34
#include "config.h"
 
35
#include <stdio.h>
 
36
#include <stdlib.h>
 
37
#include <sys/types.h>
 
38
#include <sys/socket.h>
 
39
#include <sys/wait.h>
 
40
#include <sys/stat.h>
 
41
#include <arpa/inet.h>
 
42
#include <assert.h>
 
43
#include <unistd.h>
 
44
#include <string.h>
 
45
#include <glob.h>
 
46
#include <netinet/in.h>
 
47
 
 
48
#define EXIT_FAILURE 1
 
49
 
 
50
static char *srcdir;    /* global $srcdir, set so that we can run outside of "make check" */
 
51
static char *testSuite; /* name of current test suite */
 
52
 
 
53
 
 
54
void readLine(int fd, char *ln)
 
55
{
 
56
        char c;
 
57
        int lenRead;
 
58
        lenRead = read(fd, &c, 1);
 
59
        while(lenRead == 1 && c != '\n') {
 
60
                *ln++ = c;
 
61
                 lenRead = read(fd, &c, 1);
 
62
        }
 
63
        *ln = '\0';
 
64
}
 
65
 
 
66
 
 
67
/* send a message via UDP
 
68
 * returns 0 if ok, something else otherwise.
 
69
 */
 
70
int
 
71
udpSend(char *buf, int lenBuf)
 
72
{
 
73
        struct sockaddr_in si_other;
 
74
        int s, slen=sizeof(si_other);
 
75
 
 
76
        if((s=socket(AF_INET, SOCK_DGRAM, 0))==-1) {
 
77
                perror("socket()");
 
78
                return(1);
 
79
        }
 
80
 
 
81
        memset((char *) &si_other, 0, sizeof(si_other));
 
82
        si_other.sin_family = AF_INET;
 
83
        si_other.sin_port = htons(12514);
 
84
        if(inet_aton("127.0.0.1", &si_other.sin_addr)==0) {
 
85
                fprintf(stderr, "inet_aton() failed\n");
 
86
                return(1);
 
87
        }
 
88
 
 
89
        if(sendto(s, buf, lenBuf, 0, (struct sockaddr*) &si_other, slen)==-1) {
 
90
                perror("sendto");
 
91
                fprintf(stderr, "sendto() failed\n");
 
92
                return(1);
 
93
        }
 
94
 
 
95
        close(s);
 
96
        return 0;
 
97
}
 
98
 
 
99
 
 
100
/* open pipe to test candidate - so far, this is
 
101
 * always rsyslogd and with a fixed config. Later, we may
 
102
 * change this. Returns 0 if ok, something else otherwise.
 
103
 * rgerhards, 2009-03-31
 
104
 */
 
105
int openPipe(char *configFile, pid_t *pid, int *pfd)
 
106
{
 
107
        int pipefd[2];
 
108
        pid_t cpid;
 
109
        char *newargv[] = {"../tools/rsyslogd", "dummy", "-c4", "-u2", "-n", "-irsyslog.pid",
 
110
                           "-M../runtime//.libs", NULL };
 
111
        char confFile[1024];
 
112
        char *newenviron[] = { NULL };
 
113
 
 
114
 
 
115
        sprintf(confFile, "-f%s/testsuites/%s.conf", srcdir, configFile);
 
116
        newargv[1] = confFile;
 
117
 
 
118
        if (pipe(pipefd) == -1) {
 
119
                perror("pipe");
 
120
                exit(EXIT_FAILURE);
 
121
        }
 
122
 
 
123
        cpid = fork();
 
124
        if (cpid == -1) {
 
125
                perror("fork");
 
126
                exit(EXIT_FAILURE);
 
127
        }
 
128
 
 
129
        if(cpid == 0) {    /* Child reads from pipe */
 
130
                fclose(stdout);
 
131
                dup(pipefd[1]);
 
132
                close(pipefd[1]);
 
133
                close(pipefd[0]);
 
134
                fclose(stdin);
 
135
                execve("../tools/rsyslogd", newargv, newenviron);
 
136
        } else {            
 
137
                close(pipefd[1]);
 
138
                *pid = cpid;
 
139
                *pfd = pipefd[0];
 
140
        }
 
141
 
 
142
        return(0);
 
143
}
 
144
 
 
145
 
 
146
/* Process a specific test case. File name is provided.
 
147
 * Needs to return 0 if all is OK, something else otherwise.
 
148
 */
 
149
int
 
150
processTestFile(int fd, char *pszFileName)
 
151
{
 
152
        FILE *fp;
 
153
        char *testdata = NULL;
 
154
        char *expected = NULL;
 
155
        int ret = 0;
 
156
        size_t lenLn;
 
157
        char buf[4096];
 
158
 
 
159
        if((fp = fopen((char*)pszFileName, "r")) == NULL) {
 
160
                perror((char*)pszFileName);
 
161
                return(2);
 
162
        }
 
163
 
 
164
        /* skip comments at start of file */
 
165
 
 
166
        getline(&testdata, &lenLn, fp);
 
167
        while(!feof(fp)) {
 
168
                if(*testdata == '#')
 
169
                        getline(&testdata, &lenLn, fp);
 
170
                else
 
171
                        break; /* first non-comment */
 
172
        }
 
173
 
 
174
 
 
175
        testdata[strlen(testdata)-1] = '\0'; /* remove \n */
 
176
        /* now we have the test data to send */
 
177
        if(udpSend(testdata, strlen(testdata)) != 0)
 
178
                return(2);
 
179
 
 
180
        /* next line is expected output 
 
181
         * we do not care about EOF here, this will lead to a failure and thus
 
182
         * draw enough attention. -- rgerhards, 2009-03-31
 
183
         */
 
184
        getline(&expected, &lenLn, fp);
 
185
        expected[strlen(expected)-1] = '\0'; /* remove \n */
 
186
 
 
187
        /* pull response from server and then check if it meets our expectation */
 
188
        readLine(fd, buf);
 
189
        if(strcmp(expected, buf)) {
 
190
                printf("\nExpected Response:\n'%s'\nActual Response:\n'%s'\n",
 
191
                        expected, buf);
 
192
                        ret = 1;
 
193
        }
 
194
 
 
195
        free(testdata);
 
196
        free(expected);
 
197
        fclose(fp);
 
198
        return(ret);
 
199
}
 
200
 
 
201
 
 
202
/* carry out all tests. Tests are specified via a file name
 
203
 * wildcard. Each of the files is read and the test carried
 
204
 * out.
 
205
 * Returns the number of tests that failed. Zero means all
 
206
 * success.
 
207
 */
 
208
int
 
209
doTests(int fd, char *files)
 
210
{
 
211
        int iFailed = 0;
 
212
        int iTests = 0;
 
213
        int ret;
 
214
        char *testFile;
 
215
        glob_t testFiles;
 
216
        size_t i = 0;
 
217
        struct stat fileInfo;
 
218
 
 
219
        glob(files, GLOB_MARK, NULL, &testFiles);
 
220
 
 
221
        for(i = 0; i < testFiles.gl_pathc; i++) {
 
222
                testFile = testFiles.gl_pathv[i];
 
223
 
 
224
                if(stat((char*) testFile, &fileInfo) != 0) 
 
225
                        continue; /* continue with the next file if we can't stat() the file */
 
226
 
 
227
                ++iTests;
 
228
                /* all regular files are run through the test logic. Symlinks don't work. */
 
229
                if(S_ISREG(fileInfo.st_mode)) { /* config file */
 
230
                        printf("processing test case '%s' ... ", testFile);
 
231
                        ret = processTestFile(fd, testFile);
 
232
                        if(ret == 0) {
 
233
                                printf("successfully completed\n");
 
234
                        } else {
 
235
                                printf("failed!\n");
 
236
                                ++iFailed;
 
237
                        }
 
238
                }
 
239
        }
 
240
        globfree(&testFiles);
 
241
 
 
242
        if(iTests == 0) {
 
243
                printf("Error: no test cases found, no tests executed.\n");
 
244
                iFailed = 1;
 
245
        } else {
 
246
                printf("Number of tests run: %d, number of failures: %d\n", iTests, iFailed);
 
247
        }
 
248
 
 
249
        return(iFailed);
 
250
}
 
251
 
 
252
 
 
253
/* Run the test suite. This must be called with exactly one parameter, the
 
254
 * name of the test suite. For details, see file header comment at the top
 
255
 * of this file.
 
256
 * rgerhards, 2009-04-03
 
257
 */
 
258
int main(int argc, char *argv[])
 
259
{
 
260
        int fd;
 
261
        pid_t pid;
 
262
        int status;
 
263
        int ret = 0;
 
264
        char buf[4096];
 
265
        char testcases[4096];
 
266
 
 
267
        if(argc != 2) {
 
268
                printf("Invalid call of udptester\n");
 
269
                printf("Usage: udptester testsuite-name\n");
 
270
                exit(1);
 
271
        }
 
272
 
 
273
        testSuite = argv[1];
 
274
 
 
275
        if((srcdir = getenv("srcdir")) == NULL)
 
276
                srcdir = ".";
 
277
 
 
278
        printf("Start of udptester run ($srcdir=%s, testsuite=%s)\n", srcdir, testSuite);
 
279
 
 
280
        openPipe(argv[1], &pid, &fd);
 
281
        readLine(fd, buf);
 
282
 
 
283
        /* generate filename */
 
284
        sprintf(testcases, "%s/testsuites/*.%s", srcdir, testSuite);
 
285
        if(doTests(fd, testcases) != 0)
 
286
                ret = 1;
 
287
 
 
288
        /* cleanup */
 
289
        kill(pid, SIGTERM);
 
290
        waitpid(pid, &status, 0);       /* wait until instance terminates */
 
291
        printf("End of udptester run.\n");
 
292
        exit(ret);
 
293
}