test.c (6714B)
1 #include <stdbool.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 #define ANNTP_IMPLEMENTATION 7 #include "anntp.h" 8 9 static unsigned int nfailed = 0; 10 static unsigned int ntests = 0; 11 12 static const char* 13 nntp_host(void) 14 { 15 const char* host = getenv("NNTP_HOST"); 16 return host ? host : "news.eternal-september.org"; 17 } 18 19 static const char* 20 nntp_port_plain(void) 21 { 22 const char* port = getenv("NNTP_PORT_PLAIN"); 23 return port ? port : "119"; 24 } 25 26 static const char* 27 nntp_port_tls(void) 28 { 29 const char* port = getenv("NNTP_PORT_TLS"); 30 return port ? port : "563"; 31 } 32 33 static const char* 34 nntp_group(void) 35 { 36 const char* group = getenv("NNTP_GROUP"); 37 return group ? group : "eternal-september.talk"; 38 } 39 40 static AnntpConnection* 41 mktestconn(bool tls) 42 { 43 return anntp_mkconn( 44 nntp_host(), 45 tls ? nntp_port_tls() : nntp_port_plain(), 46 tls 47 ); 48 } 49 50 void 51 require(bool cond, const char* desc) 52 { 53 ntests++; 54 if (!cond) { 55 fprintf(stderr, "> testing `%s'... FAIL!\n", desc); 56 nfailed++; 57 } else { 58 fprintf(stderr, "> testing `%s'... ok\n", desc); 59 } 60 } 61 62 /*********************************************************************************************************************/ 63 64 void 65 test_connection_tcp(void) 66 { 67 AnntpConnection* c = mktestconn(false); 68 require(c != NULL, "plaintext, unencrypted connections"); 69 70 anntp_freeconn(c); 71 } 72 73 void 74 test_connection_tls(void) 75 { 76 #ifdef ANNTP_TLS 77 AnntpConnection* c = mktestconn(true); 78 require(c != NULL, "encrypted connections"); 79 80 anntp_freeconn(c); 81 #else 82 require(true, "skipped [TLS disabled]"); 83 #endif 84 } 85 86 void 87 test_read(void) 88 { 89 AnntpConnection* c = mktestconn(false); 90 91 char l[256] = { 0 }; 92 require(anntp_readline(c, l, 256) > 0, "reading"); 93 94 anntp_freeconn(c); 95 } 96 97 void 98 test_read_tls(void) 99 { 100 #ifdef ANNTP_TLS 101 AnntpConnection* c = mktestconn(true); 102 require(c != NULL, "connection for read tls test"); 103 104 char l[256] = { 0 }; 105 require(anntp_readline(c, l, 255) > 0, "reading line over TLS"); 106 107 anntp_freeconn(c); 108 #else 109 require(true, "skipped [TLS disabled]"); 110 #endif 111 } 112 113 void 114 test_auth(void) 115 { 116 AnntpConnection* c = mktestconn(false); 117 require(c != NULL, "connection for AUTH test"); 118 119 const char* login = getenv("NNTP_LOGIN"); 120 const char* pass = getenv("NNTP_PASS"); 121 if (!login || !pass) { 122 require(true, "skipped auth test, NNTP_LOGIN or NNTP_PASS are unset"); 123 return; 124 } 125 126 char line[256]; 127 anntp_readline(c, line, sizeof(line)); 128 129 int err = anntp_auth(c, login, pass); 130 131 require(err == ANE_OK, "authentication"); 132 133 anntp_freeconn(c); 134 } 135 136 static int 137 count_cb(const char* line, void* extra) 138 { 139 size_t* count = (size_t*)extra; 140 (*count)++; 141 (void)line; 142 return 0; 143 } 144 145 void 146 test_list(void) 147 { 148 AnntpConnection* c = mktestconn(false); 149 require(c != NULL, "connection for LIST test"); 150 151 char line[512]; 152 ssize_t n = anntp_readline(c, line, sizeof(line)); 153 require(n > 0, "read greeting before LIST"); 154 155 n = anntp_writeline(c, "LIST"); 156 require(n > 0, "send LIST"); 157 158 n = anntp_readline(c, line, sizeof(line)); 159 require(n > 0, "read LIST response"); 160 require(strncmp(line, "215", 3) == 0, "LIST response code"); 161 162 size_t count = 0; 163 int err = anntp_readdot_cb(c, count_cb, &count); 164 require(err == ANE_OK, "anntp_readdot_cb"); 165 require(count > 0, "received at least one LIST entry"); 166 167 anntp_freeconn(c); 168 } 169 170 void 171 test_group(void) 172 { 173 AnntpConnection* c = mktestconn(false); 174 require(c != NULL, "connection for GROUP test"); 175 176 char line[256]; 177 anntp_readline(c, line, sizeof(line)); 178 179 AnntpGroup g; 180 int err = anntp_group(c, nntp_group(), &g); 181 require(err == ANE_OK, "groups"); 182 183 anntp_freeconn(c); 184 } 185 186 void 187 test_article(void) 188 { 189 AnntpConnection* c = mktestconn(false); 190 require(c != NULL, "connection for ARTICLE test"); 191 192 char line[256]; 193 anntp_readline(c, line, sizeof(line)); 194 195 AnntpGroup g; 196 int err = anntp_group(c, nntp_group(), &g); 197 require(err == ANE_OK, "group for article"); 198 199 AnntpArticle art; 200 memset(&art, 0, sizeof(art)); 201 202 ssize_t r = anntp_article(c, g.first, &art); 203 204 require(r > 0, "anntp_article fetch"); 205 require(art.body != NULL, "article body present"); 206 207 require(art.from != NULL || art.id != NULL, "some headers parsed"); 208 209 anntp_article_free(&art); 210 anntp_freeconn(c); 211 } 212 213 static int 214 article_count_cb(const char* line, void* extra) 215 { 216 size_t* count = (size_t*)extra; 217 if (line && line[0] != '\0') 218 (*count)++; 219 return 0; 220 } 221 222 void 223 test_article_cb(void) 224 { 225 AnntpConnection* c = mktestconn(false); 226 require(c != NULL, "connection for ARTICLE_CB test"); 227 228 char line[256]; 229 anntp_readline(c, line, sizeof(line)); 230 231 AnntpGroup g; 232 int err = anntp_group(c, nntp_group(), &g); 233 require(err == ANE_OK, "group for article_cb"); 234 235 size_t count = 0; 236 237 err = anntp_article_cb(c, g.first, article_count_cb, &count); 238 239 require(err == ANE_OK, "anntp_article_cb execution"); 240 require(count > 0, "article_cb received lines"); 241 242 anntp_freeconn(c); 243 } 244 245 void 246 test_overview(void) 247 { 248 AnntpConnection* c = mktestconn(false); 249 require(c != NULL, "connection for OVERVIEW test"); 250 251 char line[256]; 252 anntp_readline(c, line, sizeof(line)); 253 254 AnntpGroup g; 255 int err = anntp_group(c, nntp_group(), &g); 256 require(err == ANE_OK, "group for overview"); 257 258 AnntpOverview ov; 259 memset(&ov, 0, sizeof(ov)); 260 261 /* small range to avoid huge downloads */ 262 ssize_t n = anntp_overview(c, g.first, g.first + 10, &ov); 263 264 require(n > 0, "anntp_overview fetch"); 265 require(ov.count > 0, "overview has entries"); 266 require(ov.lines != NULL, "overview lines allocated"); 267 268 /* make sure the server also works */ 269 require(ov.lines[0] != NULL, "first overview line exists"); 270 271 anntp_overview_free(&ov); 272 anntp_freeconn(c); 273 } 274 275 static int 276 overview_count_cb(const char* line, void* extra) 277 { 278 size_t* n = (size_t*)extra; 279 if (line && line[0] != '\0') 280 (*n)++; 281 return 0; 282 } 283 284 void 285 test_overview_cb(void) 286 { 287 AnntpConnection* c = mktestconn(false); 288 require(c != NULL, "connection for OVERVIEW_CB test"); 289 290 char line[256]; 291 anntp_readline(c, line, sizeof(line)); 292 293 AnntpGroup g; 294 int err = anntp_group(c, nntp_group(), &g); 295 require(err == ANE_OK, "group for overview_cb"); 296 297 size_t count = 0; 298 299 err = anntp_overview_cb(c, g.first, g.first + 10, overview_count_cb, &count); 300 301 require(err == ANE_OK, "anntp_overview_cb execution"); 302 require(count > 0, "overview_cb received lines"); 303 304 anntp_freeconn(c); 305 } 306 307 /*********************************************************************************************************************/ 308 309 int 310 main(void) 311 { 312 anntp_init(); 313 314 test_connection_tcp(); 315 test_connection_tls(); 316 test_read(); 317 test_read_tls(); 318 test_auth(); 319 test_group(); 320 test_list(); 321 test_article(); 322 test_article_cb(); 323 test_overview(); 324 test_overview_cb(); 325 326 printf("> INFO: %u out of %u tests failed (%u succeeded).\n", 327 nfailed, ntests, ntests - nfailed); 328 329 return nfailed > 0 ? EXIT_FAILURE : EXIT_SUCCESS; 330 } 331