git-svn: trunk@4763
Török Edvin authored on 2009/02/13 03:22:194 | 8 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,212 @@ |
0 |
+#if HAVE_CONFIG_H |
|
1 |
+#include "clamav-config.h" |
|
2 |
+#endif |
|
3 |
+ |
|
4 |
+#include <fcntl.h> |
|
5 |
+#include <stdio.h> |
|
6 |
+#include <stdlib.h> |
|
7 |
+#include <string.h> |
|
8 |
+#include <errno.h> |
|
9 |
+#include <signal.h> |
|
10 |
+#ifdef HAVE_SYS_TYPES_H |
|
11 |
+#include <sys/types.h> |
|
12 |
+#endif |
|
13 |
+#include <sys/socket.h> |
|
14 |
+#include <sys/stat.h> |
|
15 |
+#include <sys/un.h> |
|
16 |
+#include <unistd.h> |
|
17 |
+ |
|
18 |
+#include <check.h> |
|
19 |
+#include "checks_common.h" |
|
20 |
+#include "libclamav/version.h" |
|
21 |
+#include "libclamav/cltypes.h" |
|
22 |
+ |
|
23 |
+#ifdef CHECK_HAVE_LOOPS |
|
24 |
+ |
|
25 |
+static int sockd; |
|
26 |
+#define SOCKET "clamd-test.socket" |
|
27 |
+static void conn_setup(void) |
|
28 |
+{ |
|
29 |
+ int rc; |
|
30 |
+ struct sockaddr_un nixsock; |
|
31 |
+ memset((void *)&nixsock, 0, sizeof(nixsock)); |
|
32 |
+ nixsock.sun_family = AF_UNIX; |
|
33 |
+ strncpy(nixsock.sun_path, SOCKET, sizeof(nixsock.sun_path)); |
|
34 |
+ |
|
35 |
+ sockd = socket(AF_UNIX, SOCK_STREAM, 0); |
|
36 |
+ fail_unless_fmt(sockd != -1, "Unable to create socket: %s\n", strerror(errno)); |
|
37 |
+ |
|
38 |
+ rc = connect(sockd, (struct sockaddr *)&nixsock, sizeof(nixsock)); |
|
39 |
+ fail_unless_fmt(rc != -1, "Unable to connect(): %s\n", strerror(errno)); |
|
40 |
+ |
|
41 |
+ signal(SIGPIPE, SIG_IGN); |
|
42 |
+} |
|
43 |
+ |
|
44 |
+static void conn_teardown(void) |
|
45 |
+{ |
|
46 |
+ if (sockd != -1) |
|
47 |
+ close(sockd); |
|
48 |
+} |
|
49 |
+ |
|
50 |
+#ifndef REPO_VERSION |
|
51 |
+#define REPO_VERSION VERSION |
|
52 |
+#endif |
|
53 |
+ |
|
54 |
+#define SCANFILE BUILDDIR"/../test/clam.exe" |
|
55 |
+#define FOUNDREPLY SCANFILE": ClamAV-Test-File.UNOFFICIAL FOUND" |
|
56 |
+ |
|
57 |
+static struct basic_test { |
|
58 |
+ const char *command; |
|
59 |
+ const char *reply; |
|
60 |
+} basic_tests[] = { |
|
61 |
+ {"PING", "PONG"}, |
|
62 |
+ {"RELOAD","RELOADING"}, |
|
63 |
+ {"VERSION", "ClamAV "REPO_VERSION""VERSION_SUFFIX}, |
|
64 |
+ {"SCAN "SCANFILE, FOUNDREPLY}, |
|
65 |
+ {"CONTSCAN "SCANFILE, FOUNDREPLY}, |
|
66 |
+ {"MULTISCAN "SCANFILE, FOUNDREPLY}, |
|
67 |
+}; |
|
68 |
+ |
|
69 |
+static void *recvfull(int sd, size_t *len) |
|
70 |
+{ |
|
71 |
+ char *buf = NULL; |
|
72 |
+ size_t off = 0; |
|
73 |
+ int rc; |
|
74 |
+ |
|
75 |
+ *len = 0; |
|
76 |
+ do { |
|
77 |
+ if (off + BUFSIZ > *len) { |
|
78 |
+ *len += BUFSIZ+1; |
|
79 |
+ buf = realloc(buf, *len); |
|
80 |
+ fail_unless(!!buf, "Cannot realloc buffer\n"); |
|
81 |
+ } |
|
82 |
+ |
|
83 |
+ rc = recv(sd, buf + off, BUFSIZ, 0); |
|
84 |
+ fail_unless_fmt(rc != -1, "recv() failed: %s\n", strerror(errno)); |
|
85 |
+ off += rc; |
|
86 |
+ } while (rc); |
|
87 |
+ buf[*len] = '\0'; |
|
88 |
+ *len = off; |
|
89 |
+ return buf; |
|
90 |
+} |
|
91 |
+ |
|
92 |
+static void test_command(const char *cmd, size_t len, const char *expect, size_t expect_len) |
|
93 |
+{ |
|
94 |
+ void *recvdata; |
|
95 |
+ int rc; |
|
96 |
+ rc = send(sockd, cmd, len, 0); |
|
97 |
+ fail_unless_fmt(rc == len, "Unable to send(): %s\n", strerror(errno)); |
|
98 |
+ |
|
99 |
+ recvdata = recvfull(sockd, &len); |
|
100 |
+ |
|
101 |
+ fail_unless_fmt(len == expect_len, "Reply has wrong size: %lu, expected %lu, reply: %s\n", |
|
102 |
+ len, expect_len, recvdata); |
|
103 |
+ |
|
104 |
+ rc = memcmp(recvdata, expect, expect_len); |
|
105 |
+ fail_unless_fmt(!rc, "Wrong reply for command %s: |%s|, expected: |%s|\n", cmd, recvdata, expect); |
|
106 |
+ free(recvdata); |
|
107 |
+} |
|
108 |
+ |
|
109 |
+START_TEST (test_basic_commands) |
|
110 |
+{ |
|
111 |
+ int rc; |
|
112 |
+ struct basic_test *test = &basic_tests[_i]; |
|
113 |
+ size_t len; |
|
114 |
+ char nsend[BUFSIZ], nreply[BUFSIZ]; |
|
115 |
+ /* send the command the "old way" */ |
|
116 |
+ conn_setup(); |
|
117 |
+ snprintf(nreply, sizeof(nreply), "%s\n", test->reply); |
|
118 |
+ test_command(test->command, strlen(test->command), nreply, strlen(nreply)); |
|
119 |
+ conn_teardown(); |
|
120 |
+ |
|
121 |
+ /* send nCOMMAND */ |
|
122 |
+ conn_setup(); |
|
123 |
+ snprintf(nsend, sizeof(nsend), "n%s\n", test->command); |
|
124 |
+ test_command(nsend, strlen(nsend), nreply, strlen(nreply)); |
|
125 |
+ conn_teardown(); |
|
126 |
+ |
|
127 |
+ /* send zCOMMAND */ |
|
128 |
+ conn_setup(); |
|
129 |
+ snprintf(nsend, sizeof(nsend), "z%s\0", test->command); |
|
130 |
+ test_command(nsend, strlen(nsend)+1, test->reply, strlen(test->reply)+1); |
|
131 |
+ conn_teardown(); |
|
132 |
+} |
|
133 |
+END_TEST |
|
134 |
+ |
|
135 |
+#define EXPECT_INSTREAM "stream: ClamAV-Test-File.UNOFFICIAL FOUND\n" |
|
136 |
+ |
|
137 |
+START_TEST (tc_instream) |
|
138 |
+{ |
|
139 |
+ int fd, nread, rc; |
|
140 |
+ struct stat stbuf; |
|
141 |
+ uint32_t chunk; |
|
142 |
+ void *recvdata; |
|
143 |
+ size_t len, expect_len; |
|
144 |
+ char buf[4096] = "nINSTREAM\n"; |
|
145 |
+ size_t off = strlen(buf); |
|
146 |
+ |
|
147 |
+ fail_unless_fmt(stat(SCANFILE, &stbuf) != -1, "stat failed for %s: %s", SCANFILE, strerror(errno)); |
|
148 |
+ |
|
149 |
+ fd = open(SCANFILE, O_RDONLY); |
|
150 |
+ fail_unless_fmt(fd != -1, "open failed: %s\n", strerror(errno)); |
|
151 |
+ |
|
152 |
+ chunk = htonl(stbuf.st_size); |
|
153 |
+ memcpy(&buf[off], &chunk, sizeof(chunk)); |
|
154 |
+ off += 4; |
|
155 |
+ nread = read(fd, &buf[off], sizeof(buf)-off-4); |
|
156 |
+ fail_unless_fmt(nread == stbuf.st_size, "read failed: %s\n", strerror(errno)); |
|
157 |
+ off += nread; |
|
158 |
+ buf[off++]=0; |
|
159 |
+ buf[off++]=0; |
|
160 |
+ buf[off++]=0; |
|
161 |
+ buf[off++]=0; |
|
162 |
+ close(fd); |
|
163 |
+ |
|
164 |
+ conn_setup(); |
|
165 |
+ fail_unless(send(sockd, buf, off, 0) == off, "send() failed: %s\n", strerror(errno)); |
|
166 |
+ |
|
167 |
+ recvdata = recvfull(sockd, &len); |
|
168 |
+ |
|
169 |
+ expect_len = strlen(EXPECT_INSTREAM); |
|
170 |
+ fail_unless_fmt(len == expect_len, "Reply has wrong size: %lu, expected %lu, reply: %s\n", |
|
171 |
+ len, expect_len, recvdata); |
|
172 |
+ |
|
173 |
+ rc = memcmp(recvdata, EXPECT_INSTREAM, expect_len); |
|
174 |
+ fail_unless_fmt(!rc, "Wrong reply for command INSTREAM: |%s|, expected: |%s|\n", recvdata, EXPECT_INSTREAM); |
|
175 |
+ free(recvdata); |
|
176 |
+ |
|
177 |
+ conn_teardown(); |
|
178 |
+} |
|
179 |
+END_TEST |
|
180 |
+ |
|
181 |
+static Suite *test_clamd_suite(void) |
|
182 |
+{ |
|
183 |
+ Suite *s = suite_create("clamd"); |
|
184 |
+ TCase *tc_commands = tcase_create("clamd commands"); |
|
185 |
+ suite_add_tcase(s, tc_commands); |
|
186 |
+ tcase_add_loop_test(tc_commands, test_basic_commands, 0, sizeof(basic_tests)/sizeof(basic_tests[0])); |
|
187 |
+ tcase_add_test(tc_commands, tc_instream); |
|
188 |
+ |
|
189 |
+ return s; |
|
190 |
+} |
|
191 |
+ |
|
192 |
+int main(void) |
|
193 |
+{ |
|
194 |
+ int nf; |
|
195 |
+ Suite *s = test_clamd_suite(); |
|
196 |
+ SRunner *sr = srunner_create(s); |
|
197 |
+ srunner_set_log(sr, "test-clamd.log"); |
|
198 |
+ srunner_run_all(sr, CK_NORMAL); |
|
199 |
+ nf = srunner_ntests_failed(sr); |
|
200 |
+ srunner_free(sr); |
|
201 |
+ return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE; |
|
202 |
+} |
|
203 |
+ |
|
204 |
+#else |
|
205 |
+int main(void) |
|
206 |
+{ |
|
207 |
+ puts("\n*** Check version too old, clamd tests not run!\n"); |
|
208 |
+ /* tell automake the test was skipped */ |
|
209 |
+ return 77; |
|
210 |
+} |
|
211 |
+#endif |