1*be771a7bSCy Schubert /* 2*be771a7bSCy Schubert * testcode/unitldns.c - unit test for ldns routines. 3*be771a7bSCy Schubert * 4*be771a7bSCy Schubert * Copyright (c) 2014, NLnet Labs. All rights reserved. 5*be771a7bSCy Schubert * 6*be771a7bSCy Schubert * This software is open source. 7*be771a7bSCy Schubert * 8*be771a7bSCy Schubert * Redistribution and use in source and binary forms, with or without 9*be771a7bSCy Schubert * modification, are permitted provided that the following conditions 10*be771a7bSCy Schubert * are met: 11*be771a7bSCy Schubert * 12*be771a7bSCy Schubert * Redistributions of source code must retain the above copyright notice, 13*be771a7bSCy Schubert * this list of conditions and the following disclaimer. 14*be771a7bSCy Schubert * 15*be771a7bSCy Schubert * Redistributions in binary form must reproduce the above copyright notice, 16*be771a7bSCy Schubert * this list of conditions and the following disclaimer in the documentation 17*be771a7bSCy Schubert * and/or other materials provided with the distribution. 18*be771a7bSCy Schubert * 19*be771a7bSCy Schubert * Neither the name of the NLNET LABS nor the names of its contributors may 20*be771a7bSCy Schubert * be used to endorse or promote products derived from this software without 21*be771a7bSCy Schubert * specific prior written permission. 22*be771a7bSCy Schubert * 23*be771a7bSCy Schubert * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24*be771a7bSCy Schubert * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25*be771a7bSCy Schubert * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26*be771a7bSCy Schubert * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27*be771a7bSCy Schubert * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28*be771a7bSCy Schubert * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29*be771a7bSCy Schubert * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30*be771a7bSCy Schubert * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31*be771a7bSCy Schubert * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32*be771a7bSCy Schubert * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33*be771a7bSCy Schubert * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34*be771a7bSCy Schubert * 35*be771a7bSCy Schubert */ 36*be771a7bSCy Schubert /** 37*be771a7bSCy Schubert * \file 38*be771a7bSCy Schubert * Calls ldns unit tests. Exits with code 1 on a failure. 39*be771a7bSCy Schubert */ 40*be771a7bSCy Schubert 41*be771a7bSCy Schubert #include "config.h" 42*be771a7bSCy Schubert #include "util/log.h" 43*be771a7bSCy Schubert #include "testcode/unitmain.h" 44*be771a7bSCy Schubert #include "sldns/sbuffer.h" 45*be771a7bSCy Schubert #include "sldns/str2wire.h" 46*be771a7bSCy Schubert #include "sldns/wire2str.h" 47*be771a7bSCy Schubert #include "sldns/parseutil.h" 48*be771a7bSCy Schubert 49*be771a7bSCy Schubert /** verbose this unit test */ 50*be771a7bSCy Schubert static int vbmp = 0; 51*be771a7bSCy Schubert 52*be771a7bSCy Schubert /** print buffer to hex into string */ 53*be771a7bSCy Schubert static void 54*be771a7bSCy Schubert buf_to_hex(uint8_t* b, size_t blen, char* s, size_t slen) 55*be771a7bSCy Schubert { 56*be771a7bSCy Schubert const char* h = "0123456789ABCDEF"; 57*be771a7bSCy Schubert size_t i; 58*be771a7bSCy Schubert if(slen < blen*2+2 && vbmp) printf("hexstring buffer too small\n"); 59*be771a7bSCy Schubert unit_assert(slen >= blen*2+2); 60*be771a7bSCy Schubert for(i=0; i<blen; i++) { 61*be771a7bSCy Schubert s[i*2] = h[(b[i]&0xf0)>>4]; 62*be771a7bSCy Schubert s[i*2+1] = h[b[i]&0x0f]; 63*be771a7bSCy Schubert } 64*be771a7bSCy Schubert s[blen*2] = '\n'; 65*be771a7bSCy Schubert s[blen*2+1] = 0; 66*be771a7bSCy Schubert } 67*be771a7bSCy Schubert 68*be771a7bSCy Schubert /** Transform input. 69*be771a7bSCy Schubert * @param txt_in: input text format. 70*be771a7bSCy Schubert * @param wire1: output wireformat in hex (txt_in converted to wire). 71*be771a7bSCy Schubert * @param txt_out: output text format (converted from wire_out). 72*be771a7bSCy Schubert * @param wire2: output wireformat in hex, txt_out converted back to wireformat. 73*be771a7bSCy Schubert * @param bufs: size of the text buffers. 74*be771a7bSCy Schubert */ 75*be771a7bSCy Schubert static void 76*be771a7bSCy Schubert rr_transform(char* txt_in, char* wire1, char* txt_out, char* wire2, 77*be771a7bSCy Schubert size_t bufs) 78*be771a7bSCy Schubert { 79*be771a7bSCy Schubert uint8_t b[65536]; 80*be771a7bSCy Schubert size_t len; 81*be771a7bSCy Schubert int err; 82*be771a7bSCy Schubert 83*be771a7bSCy Schubert len = sizeof(b); 84*be771a7bSCy Schubert err = sldns_str2wire_rr_buf(txt_in, b, &len, NULL, 3600, 85*be771a7bSCy Schubert NULL, 0, NULL, 0); 86*be771a7bSCy Schubert if(err != 0) { 87*be771a7bSCy Schubert if(vbmp) printf("sldns_str2wire_rr_buf, pos %d: %s\n", 88*be771a7bSCy Schubert LDNS_WIREPARSE_OFFSET(err), 89*be771a7bSCy Schubert sldns_get_errorstr_parse(err)); 90*be771a7bSCy Schubert } 91*be771a7bSCy Schubert unit_assert(err == 0); 92*be771a7bSCy Schubert buf_to_hex(b, len, wire1, bufs); 93*be771a7bSCy Schubert if(vbmp) printf("wire1: %s", wire1); 94*be771a7bSCy Schubert 95*be771a7bSCy Schubert err = sldns_wire2str_rr_buf(b, len, txt_out, bufs); 96*be771a7bSCy Schubert unit_assert(err < (int)bufs && err > 0); 97*be771a7bSCy Schubert if(vbmp) printf("txt: %s", txt_out); 98*be771a7bSCy Schubert 99*be771a7bSCy Schubert len = sizeof(b); 100*be771a7bSCy Schubert err = sldns_str2wire_rr_buf(txt_out, b, &len, NULL, 3600, 101*be771a7bSCy Schubert NULL, 0, NULL, 0); 102*be771a7bSCy Schubert if(err != 0) { 103*be771a7bSCy Schubert if(vbmp) printf("sldns_str2wire_rr_buf-2, pos %d: %s\n", 104*be771a7bSCy Schubert LDNS_WIREPARSE_OFFSET(err), 105*be771a7bSCy Schubert sldns_get_errorstr_parse(err)); 106*be771a7bSCy Schubert } 107*be771a7bSCy Schubert unit_assert(err == 0); 108*be771a7bSCy Schubert buf_to_hex(b, len, wire2, bufs); 109*be771a7bSCy Schubert if(vbmp) printf("wire2: %s", wire2); 110*be771a7bSCy Schubert } 111*be771a7bSCy Schubert 112*be771a7bSCy Schubert /** Check if results are correct */ 113*be771a7bSCy Schubert static void 114*be771a7bSCy Schubert rr_checks(char* wire_chk, char* txt_chk, char* txt_out, char* wire_out, 115*be771a7bSCy Schubert char* back) 116*be771a7bSCy Schubert { 117*be771a7bSCy Schubert #ifdef __APPLE__ 118*be771a7bSCy Schubert /* the wiretostr on ipv6 is weird on apple, we cannot check it. 119*be771a7bSCy Schubert * skip AAAA on OSX */ 120*be771a7bSCy Schubert if(strstr(txt_out, "IN AAAA")) 121*be771a7bSCy Schubert txt_out = txt_chk; /* skip this test, but test wirefmt */ 122*be771a7bSCy Schubert /* so we know that txt_out back to wire is the same */ 123*be771a7bSCy Schubert #endif 124*be771a7bSCy Schubert 125*be771a7bSCy Schubert if(strcmp(txt_chk, txt_out) != 0 && vbmp) 126*be771a7bSCy Schubert printf("txt different\n"); 127*be771a7bSCy Schubert if(strcmp(wire_chk, wire_out) != 0 && vbmp) 128*be771a7bSCy Schubert printf("wire1 different\n"); 129*be771a7bSCy Schubert if(strcmp(wire_chk, back) != 0 && vbmp) 130*be771a7bSCy Schubert printf("wire2 different\n"); 131*be771a7bSCy Schubert 132*be771a7bSCy Schubert unit_assert(strcmp(txt_chk, txt_out) == 0); 133*be771a7bSCy Schubert unit_assert(strcmp(wire_chk, wire_out) == 0); 134*be771a7bSCy Schubert unit_assert(strcmp(wire_chk, back) == 0); 135*be771a7bSCy Schubert } 136*be771a7bSCy Schubert 137*be771a7bSCy Schubert /** read rrs to and from string, and wireformat 138*be771a7bSCy Schubert * Skips empty lines and comments. 139*be771a7bSCy Schubert * @param input: input file with text format. 140*be771a7bSCy Schubert * @param check: check file with hex and then textformat 141*be771a7bSCy Schubert */ 142*be771a7bSCy Schubert static void 143*be771a7bSCy Schubert rr_test_file(const char* input, const char* check) 144*be771a7bSCy Schubert { 145*be771a7bSCy Schubert size_t bufs = 131072; 146*be771a7bSCy Schubert FILE* inf, *chf, *of; 147*be771a7bSCy Schubert int lineno = 0, chlineno = 0; 148*be771a7bSCy Schubert char* txt_in = (char*)malloc(bufs); 149*be771a7bSCy Schubert char* txt_out = (char*)malloc(bufs); 150*be771a7bSCy Schubert char* txt_chk = (char*)malloc(bufs); 151*be771a7bSCy Schubert char* wire_out = (char*)malloc(bufs); 152*be771a7bSCy Schubert char* wire_chk = (char*)malloc(bufs); 153*be771a7bSCy Schubert char* back = (char*)malloc(bufs); 154*be771a7bSCy Schubert if(!txt_in || !txt_out || !txt_chk || !wire_out || !wire_chk || !back) 155*be771a7bSCy Schubert fatal_exit("malloc failure"); 156*be771a7bSCy Schubert inf = fopen(input, "r"); 157*be771a7bSCy Schubert if(!inf) fatal_exit("cannot open %s: %s", input, strerror(errno)); 158*be771a7bSCy Schubert chf = fopen(check, "r"); 159*be771a7bSCy Schubert if(!chf) fatal_exit("cannot open %s: %s", check, strerror(errno)); 160*be771a7bSCy Schubert 161*be771a7bSCy Schubert of = NULL; 162*be771a7bSCy Schubert if(0) { 163*be771a7bSCy Schubert /* debug: create check file */ 164*be771a7bSCy Schubert of = fopen("outputfile", "w"); 165*be771a7bSCy Schubert if(!of) fatal_exit("cannot write output: %s", strerror(errno)); 166*be771a7bSCy Schubert } 167*be771a7bSCy Schubert 168*be771a7bSCy Schubert while(fgets(txt_in, (int)bufs, inf)) { 169*be771a7bSCy Schubert lineno++; 170*be771a7bSCy Schubert if(vbmp) printf("\n%s:%d %s", input, lineno, txt_in); 171*be771a7bSCy Schubert /* skip empty lines and comments */ 172*be771a7bSCy Schubert if(txt_in[0] == 0 || txt_in[0] == '\n' || txt_in[0] == ';') 173*be771a7bSCy Schubert continue; 174*be771a7bSCy Schubert /* read check lines */ 175*be771a7bSCy Schubert if(!fgets(wire_chk, (int)bufs, chf)) { 176*be771a7bSCy Schubert printf("%s too short\n", check); 177*be771a7bSCy Schubert unit_assert(0); 178*be771a7bSCy Schubert } 179*be771a7bSCy Schubert if(!fgets(txt_chk, (int)bufs, chf)) { 180*be771a7bSCy Schubert printf("%s too short\n", check); 181*be771a7bSCy Schubert unit_assert(0); 182*be771a7bSCy Schubert } 183*be771a7bSCy Schubert chlineno += 2; 184*be771a7bSCy Schubert if(vbmp) printf("%s:%d %s", check, chlineno-1, wire_chk); 185*be771a7bSCy Schubert if(vbmp) printf("%s:%d %s", check, chlineno, txt_chk); 186*be771a7bSCy Schubert /* generate results */ 187*be771a7bSCy Schubert rr_transform(txt_in, wire_out, txt_out, back, bufs); 188*be771a7bSCy Schubert /* checks */ 189*be771a7bSCy Schubert if(of) { 190*be771a7bSCy Schubert fprintf(of, "%s%s", wire_out, txt_out); 191*be771a7bSCy Schubert } else { 192*be771a7bSCy Schubert rr_checks(wire_chk, txt_chk, txt_out, wire_out, back); 193*be771a7bSCy Schubert } 194*be771a7bSCy Schubert } 195*be771a7bSCy Schubert 196*be771a7bSCy Schubert if(of) fclose(of); 197*be771a7bSCy Schubert fclose(inf); 198*be771a7bSCy Schubert fclose(chf); 199*be771a7bSCy Schubert free(txt_in); 200*be771a7bSCy Schubert free(txt_out); 201*be771a7bSCy Schubert free(txt_chk); 202*be771a7bSCy Schubert free(wire_out); 203*be771a7bSCy Schubert free(wire_chk); 204*be771a7bSCy Schubert free(back); 205*be771a7bSCy Schubert } 206*be771a7bSCy Schubert 207*be771a7bSCy Schubert #define xstr(s) str(s) 208*be771a7bSCy Schubert #define str(s) #s 209*be771a7bSCy Schubert 210*be771a7bSCy Schubert #define SRCDIRSTR xstr(SRCDIR) 211*be771a7bSCy Schubert 212*be771a7bSCy Schubert /** read rrs to and from string, to and from wireformat */ 213*be771a7bSCy Schubert static void 214*be771a7bSCy Schubert rr_tests(void) 215*be771a7bSCy Schubert { 216*be771a7bSCy Schubert rr_test_file(SRCDIRSTR "/testdata/test_ldnsrr.1", 217*be771a7bSCy Schubert SRCDIRSTR "/testdata/test_ldnsrr.c1"); 218*be771a7bSCy Schubert rr_test_file(SRCDIRSTR "/testdata/test_ldnsrr.2", 219*be771a7bSCy Schubert SRCDIRSTR "/testdata/test_ldnsrr.c2"); 220*be771a7bSCy Schubert rr_test_file(SRCDIRSTR "/testdata/test_ldnsrr.3", 221*be771a7bSCy Schubert SRCDIRSTR "/testdata/test_ldnsrr.c3"); 222*be771a7bSCy Schubert rr_test_file(SRCDIRSTR "/testdata/test_ldnsrr.4", 223*be771a7bSCy Schubert SRCDIRSTR "/testdata/test_ldnsrr.c4"); 224*be771a7bSCy Schubert rr_test_file(SRCDIRSTR "/testdata/test_ldnsrr.5", 225*be771a7bSCy Schubert SRCDIRSTR "/testdata/test_ldnsrr.c5"); 226*be771a7bSCy Schubert } 227*be771a7bSCy Schubert 228*be771a7bSCy Schubert /** test various base64 decoding options */ 229*be771a7bSCy Schubert static void 230*be771a7bSCy Schubert b64_test(void) 231*be771a7bSCy Schubert { 232*be771a7bSCy Schubert /* "normal" b64 alphabet, with padding */ 233*be771a7bSCy Schubert char* p1 = "aGVsbG8="; /* "hello" */ 234*be771a7bSCy Schubert char* p2 = "aGVsbG8+"; /* "hello>" */ 235*be771a7bSCy Schubert char* p3 = "aGVsbG8/IQ=="; /* "hello?!" */ 236*be771a7bSCy Schubert char* p4 = "aGVsbG8"; /* "hel" + extra garbage */ 237*be771a7bSCy Schubert 238*be771a7bSCy Schubert /* base64 url, without padding */ 239*be771a7bSCy Schubert char* u1 = "aGVsbG8"; /* "hello" */ 240*be771a7bSCy Schubert char* u2 = "aGVsbG8-"; /* "hello>" */ 241*be771a7bSCy Schubert char* u3 = "aGVsbG8_IQ"; /* "hello?!" */ 242*be771a7bSCy Schubert char* u4 = "aaaaa"; /* garbage */ 243*be771a7bSCy Schubert 244*be771a7bSCy Schubert char target[128]; 245*be771a7bSCy Schubert size_t tarsize = 128; 246*be771a7bSCy Schubert int result; 247*be771a7bSCy Schubert 248*be771a7bSCy Schubert memset(target, 0, sizeof(target)); 249*be771a7bSCy Schubert result = sldns_b64_pton(p1, (uint8_t*)target, tarsize); 250*be771a7bSCy Schubert unit_assert(result == (int)strlen("hello") && strcmp(target, "hello") == 0); 251*be771a7bSCy Schubert memset(target, 0, sizeof(target)); 252*be771a7bSCy Schubert result = sldns_b64_pton(p2, (uint8_t*)target, tarsize); 253*be771a7bSCy Schubert unit_assert(result == (int)strlen("hello>") && strcmp(target, "hello>") == 0); 254*be771a7bSCy Schubert memset(target, 0, sizeof(target)); 255*be771a7bSCy Schubert result = sldns_b64_pton(p3, (uint8_t*)target, tarsize); 256*be771a7bSCy Schubert unit_assert(result == (int)strlen("hello?!") && strcmp(target, "hello?!") == 0); 257*be771a7bSCy Schubert memset(target, 0, sizeof(target)); 258*be771a7bSCy Schubert result = sldns_b64_pton(p4, (uint8_t*)target, tarsize); 259*be771a7bSCy Schubert /* when padding is used everything that is not a block of 4 will be 260*be771a7bSCy Schubert * ignored */ 261*be771a7bSCy Schubert unit_assert(result == (int)strlen("hel") && strcmp(target, "hel") == 0); 262*be771a7bSCy Schubert 263*be771a7bSCy Schubert memset(target, 0, sizeof(target)); 264*be771a7bSCy Schubert result = sldns_b64url_pton(u1, strlen(u1), (uint8_t*)target, tarsize); 265*be771a7bSCy Schubert unit_assert(result == (int)strlen("hello") && strcmp(target, "hello") == 0); 266*be771a7bSCy Schubert memset(target, 0, sizeof(target)); 267*be771a7bSCy Schubert result = sldns_b64url_pton(u2, strlen(u2), (uint8_t*)target, tarsize); 268*be771a7bSCy Schubert unit_assert(result == (int)strlen("hello>") && strcmp(target, "hello>") == 0); 269*be771a7bSCy Schubert memset(target, 0, sizeof(target)); 270*be771a7bSCy Schubert result = sldns_b64url_pton(u3, strlen(u3), (uint8_t*)target, tarsize); 271*be771a7bSCy Schubert unit_assert(result == (int)strlen("hello+/") && strcmp(target, "hello?!") == 0); 272*be771a7bSCy Schubert /* one item in block of four is not allowed */ 273*be771a7bSCy Schubert memset(target, 0, sizeof(target)); 274*be771a7bSCy Schubert result = sldns_b64url_pton(u4, strlen(u4), (uint8_t*)target, tarsize); 275*be771a7bSCy Schubert unit_assert(result == -1); 276*be771a7bSCy Schubert } 277*be771a7bSCy Schubert 278*be771a7bSCy Schubert void 279*be771a7bSCy Schubert ldns_test(void) 280*be771a7bSCy Schubert { 281*be771a7bSCy Schubert unit_show_feature("sldns"); 282*be771a7bSCy Schubert rr_tests(); 283*be771a7bSCy Schubert b64_test(); 284*be771a7bSCy Schubert } 285