anntp

a nntp implementation in pure C99
Log | Files | Refs | README | LICENSE

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