diff options
author | Yang Zhang <yang.z.zhang@intel.com> | 2015-08-28 09:58:54 +0800 |
---|---|---|
committer | Yang Zhang <yang.z.zhang@intel.com> | 2015-09-01 12:44:00 +0800 |
commit | e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch) | |
tree | 66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/ipxe/src/tests/dns_test.c | |
parent | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff) |
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/ipxe/src/tests/dns_test.c')
-rw-r--r-- | qemu/roms/ipxe/src/tests/dns_test.c | 605 |
1 files changed, 605 insertions, 0 deletions
diff --git a/qemu/roms/ipxe/src/tests/dns_test.c b/qemu/roms/ipxe/src/tests/dns_test.c new file mode 100644 index 000000000..52f5f19f2 --- /dev/null +++ b/qemu/roms/ipxe/src/tests/dns_test.c @@ -0,0 +1,605 @@ +/* + * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * DNS self-tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <string.h> +#include <assert.h> +#include <ipxe/dns.h> +#include <ipxe/test.h> + +/** Define inline data */ +#define DATA(...) { __VA_ARGS__ } + +/** A DNS encoding test */ +struct dns_encode_test { + /** String */ + const char *string; + /** Encoded string */ + const void *data; + /** Length of encoded string */ + int len; +}; + +/** + * Define a DNS encoding test + * + * @v _name Test name + * @v _string Test string + * @v _data Expected encoded data + * @ret test DNS encoding test + */ +#define DNS_ENCODE( _name, _string, _data ) \ + static const uint8_t _name ## __data[] = _data; \ + static struct dns_encode_test _name = { \ + .string = _string, \ + .data = _name ## __data, \ + .len = sizeof ( _name ## __data ), \ + } + +/** + * Report DNS encoding test result + * + * @v test DNS encoding test + * @v file Test code file + * @v line Test code line + */ +static void dns_encode_okx ( struct dns_encode_test *test, const char *file, + unsigned int line ) { + uint8_t data[ test->len ]; + struct dns_name name; + int len; + + /* Check ability to determine length with no buffer */ + memset ( &name, 0, sizeof ( name ) ); + len = dns_encode ( test->string, &name ); + okx ( len >= 0, file, line ); + okx ( len == test->len, file, line ); + + /* Check encoded name */ + name.data = data; + name.len = sizeof ( data ); + len = dns_encode ( test->string, &name ); + okx ( len >= 0, file, line ); + if ( len >= 0 ) { + okx ( len == test->len, file, line ); + okx ( memcmp ( data, test->data, test->len ) == 0, file, line ); + DBGC ( test, "DNS encoded \"%s\" to:\n", test->string ); + DBGC_HDA ( test, 0, data, len ); + } +} +#define dns_encode_ok( test ) dns_encode_okx ( test, __FILE__, __LINE__ ) + +/** + * Report DNS encoding failure test result + * + * @v test DNS encoding test + * @v file Test code file + * @v line Test code line + */ +static void dns_encode_fail_okx ( struct dns_encode_test *test, + const char *file, unsigned int line ) { + struct dns_name name = { .data = NULL, .len = 0 }; + int len; + + len = dns_encode ( test->string, &name ); + okx ( len < 0, file, line ); +} +#define dns_encode_fail_ok( test ) \ + dns_encode_fail_okx ( test, __FILE__, __LINE__ ) + +/** A DNS decoding test */ +struct dns_decode_test { + /** Name */ + struct dns_name name; + /** Expected string */ + const char *string; +}; + +/** + * Define a DNS decoding test + * + * @v _name Test name + * @v _data RFC1035-encoded data + * @v _offset Starting offset within encoded data + * @v _string Expected decoded string + * @ret test DNS decoding test + */ +#define DNS_DECODE( _name, _data, _offset, _string ) \ + static uint8_t _name ## __data[] = _data; \ + static struct dns_decode_test _name = { \ + .name = { \ + .data = _name ## __data, \ + .offset = _offset, \ + .len = sizeof ( _name ## __data ), \ + }, \ + .string = _string, \ + } + +/** + * Report DNS decoding test result + * + * @v test DNS decoding test + * @v file Test code file + * @v line Test code line + */ +static void dns_decode_okx ( struct dns_decode_test *test, const char *file, + unsigned int line ) { + char string[ strlen ( test->string ) + 1 /* NUL */ ]; + int len; + + /* Check ability to determine length with no buffer */ + len = dns_decode ( &test->name, NULL, 0 ); + okx ( len >= 0, file, line ); + okx ( len == ( ( int ) strlen ( test->string ) ), file, line ); + + /* Check decoded string */ + len = dns_decode ( &test->name, string, sizeof ( string ) ); + okx ( len >= 0, file, line ); + if ( len >= 0 ) { + okx ( strcmp ( string, test->string ) == 0, file, line ); + DBGC ( test, "DNS decoded \"%s\" from offset %#zx in:\n", + string, test->name.offset ); + DBGC_HDA ( test, 0, test->name.data, test->name.len ); + } +} +#define dns_decode_ok( test ) dns_decode_okx ( test, __FILE__, __LINE__ ) + +/** + * Report DNS decoding failure test result + * + * @v test DNS decoding test + * @v file Test code file + * @v line Test code line + */ +static void dns_decode_fail_okx ( struct dns_decode_test *test, + const char *file, unsigned int line ) { + int len; + + len = dns_decode ( &test->name, NULL, 0 ); + okx ( len < 0, file, line ); +} +#define dns_decode_fail_ok( test ) \ + dns_decode_fail_okx ( test, __FILE__, __LINE__ ) + +/** A DNS comparison test */ +struct dns_compare_test { + /** First name */ + struct dns_name first; + /** Second name */ + struct dns_name second; +}; + +/** + * Define a DNS comparison test + * + * @v _name Test name + * @v _first_data First RFC1035-encoded data + * @v _first_offset Starting offset within first encoded data + * @v _second_data Second RFC1035-encoded data + * @v _second_offset Starting offset within second encoded data + * @ret test DNS comparison test + */ +#define DNS_COMPARE( _name, _first_data, _first_offset, _second_data, \ + _second_offset ) \ + static uint8_t _name ## __first_data[] = _first_data; \ + static uint8_t _name ## __second_data[] = _second_data; \ + static struct dns_compare_test _name = { \ + .first = { \ + .data = _name ## __first_data, \ + .offset = _first_offset, \ + .len = sizeof ( _name ## __first_data ), \ + }, \ + .second = { \ + .data = _name ## __second_data, \ + .offset = _second_offset, \ + .len = sizeof ( _name ## __second_data ), \ + }, \ + } + +/** + * Report DNS comparison test result + * + * @v test DNS comparison test + * @v file Test code file + * @v line Test code line + */ +static void dns_compare_okx ( struct dns_compare_test *test, const char *file, + unsigned int line ) { + + okx ( dns_compare ( &test->first, &test->second ) == 0, file, line ); +} +#define dns_compare_ok( test ) dns_compare_okx ( test, __FILE__, __LINE__ ) + +/** + * Report DNS comparison test failure result + * + * @v test DNS comparison test + * @v file Test code file + * @v line Test code line + */ +static void dns_compare_fail_okx ( struct dns_compare_test *test, + const char *file, unsigned int line ) { + + okx ( dns_compare ( &test->first, &test->second ) != 0, file, line ); +} +#define dns_compare_fail_ok( test ) \ + dns_compare_fail_okx ( test, __FILE__, __LINE__ ) + +/** A DNS copying test */ +struct dns_copy_test { + /** Source name */ + struct dns_name src; + /** Expected copied name */ + struct dns_name dst; +}; + +/** + * Define a DNS copying test + * + * @v _name Test name + * @v _src_data Source RFC1035-encoded data + * @v _src_offset Starting offset within source encoded data + * @v _dst_data Expected copied RFC1035-encoded data + * @v _dst_offset Starting offset withint copied encoded data + * @ret test DNS copying test + */ +#define DNS_COPY( _name, _src_data, _src_offset, _dst_data, \ + _dst_offset ) \ + static uint8_t _name ## __src_data[] = _src_data; \ + static uint8_t _name ## __dst_data[] = _dst_data; \ + static struct dns_copy_test _name = { \ + .src = { \ + .data = _name ## __src_data, \ + .offset = _src_offset, \ + .len = sizeof ( _name ## __src_data ), \ + }, \ + .dst = { \ + .data = _name ## __dst_data, \ + .offset = _dst_offset, \ + .len = sizeof ( _name ## __dst_data ), \ + }, \ + } + +/** + * Report a DNS copying test result + * + * @v test DNS copying test + * @v file Test code file + * @v line Test code line + */ +static void dns_copy_okx ( struct dns_copy_test *test, + const char *file, unsigned int line ) { + uint8_t data[ test->dst.len ]; + struct dns_name dst; + int len; + + /* Check ability to determine length with no buffer */ + memset ( &dst, 0, sizeof ( dst ) ); + len = dns_copy ( &test->src, &dst ); + okx ( len >= 0, file, line ); + okx ( len == ( ( int ) ( test->dst.len - test->dst.offset ) ), + file, line ); + + /* Check copied name */ + dst.data = data; + dst.offset = test->dst.offset; + dst.len = sizeof ( data ); + memcpy ( dst.data, test->dst.data, test->dst.offset ); + len = dns_copy ( &test->src, &dst ); + okx ( len >= 0, file, line ); + okx ( len == ( ( int ) ( test->dst.len - test->dst.offset ) ), + file, line ); + okx ( memcmp ( data, test->dst.data, sizeof ( data ) ) == 0, + file, line ); + DBGC ( test, "DNS copied:\n" ); + DBGC_HDA ( test, 0, test->src.data, test->src.len ); + DBGC_HDA ( test, 0, data, ( test->dst.offset + len ) ); +} +#define dns_copy_ok( test ) dns_copy_okx ( test, __FILE__, __LINE__ ) + +/** + * Report a DNS copying failure test result + * + * @v test DNS copying test + * @v file Test code file + * @v line Test code line + */ +static void dns_copy_fail_okx ( struct dns_copy_test *test, + const char *file, unsigned int line ) { + struct dns_name dst; + int len; + + memset ( &dst, 0, sizeof ( dst ) ); + len = dns_copy ( &test->src, &dst ); + okx ( len < 0, file, line ); +} +#define dns_copy_fail_ok( test ) dns_copy_fail_okx ( test, __FILE__, __LINE__ ) + +/** A DNS search list test */ +struct dns_list_test { + /** Search list */ + struct dns_name list; + /** Expected decoded search list */ + const char **strings; + /** Number of expected decoded string */ + unsigned int count; +}; + +/** + * Define a DNS search list test + * + * @v _name Test name + * @v _list RFC1035-encoded data + * @v _strings Expected decoded strings + * @ret test DNS search list test + */ +#define DNS_LIST( _name, _list, _strings ) \ + static uint8_t _name ## __list[] = _list; \ + static const char * _name ## __strings[] = _strings; \ + static struct dns_list_test _name = { \ + .list = { \ + .data = _name ## __list, \ + .offset = 0, \ + .len = sizeof ( _name ## __list ), \ + }, \ + .strings = _name ## __strings, \ + .count = ( sizeof ( _name ## __strings ) / \ + sizeof ( _name ## __strings[0] ) ), \ + } + +/** + * Report DNS search list test result + * + * @v test DNS search list test + * @v file Test code file + * @v line Test code line + */ +static void dns_list_okx ( struct dns_list_test *test, const char *file, + unsigned int line ) { + struct dns_name name; + unsigned int i; + + DBGC ( test, "DNS search list:\n" ); + DBGC_HDA ( test, 0, test->list.data, test->list.len ); + memcpy ( &name, &test->list, sizeof ( name ) ); + for ( i = 0 ; i < test->count ; i++ ) { + char buf[ strlen ( test->strings[i] ) + 1 /* NUL */ ]; + int len; + int offset; + + /* Decode this name */ + len = dns_decode ( &name, buf, sizeof ( buf ) ); + okx ( len >= 0, file, line ); + if ( len >= 0 ) { + okx ( len == ( ( int ) strlen ( test->strings[i] ) ), + file, line ); + okx ( strcmp ( buf, test->strings[i] ) == 0, + file, line ); + DBGC ( test, "DNS search list found \"%s\" at offset " + "%#zx\n", buf, name.offset ); + } + + /* Skip to next name */ + offset = dns_skip ( &name ); + okx ( offset >= 0, file, line ); + name.offset = offset; + } + + /* Check that we have consumed the whole search list */ + okx ( name.offset == name.len, file, line ); +} +#define dns_list_ok( test ) dns_list_okx ( test, __FILE__, __LINE__ ) + +/* Simple encoding test */ +DNS_ENCODE ( encode_simple, "ipxe.org", + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ) ); + +/* Single-word encoding test */ +DNS_ENCODE ( encode_single, "foo", DATA ( 3, 'f', 'o', 'o', 0 ) ); + +/* Absolute encoding test */ +DNS_ENCODE ( encode_absolute, "git.ipxe.org.", + DATA ( 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', + 0 ) ); + +/* Empty string encoding test */ +DNS_ENCODE ( encode_empty, "", DATA ( 0 ) ); + +/* Root domain encoding test */ +DNS_ENCODE ( encode_root, ".", DATA ( 0 ) ); + +/* Invalid initial dot encoding test */ +DNS_ENCODE ( encode_initial_dot, ".foo", DATA() ); + +/* Invalid double dot encoding test */ +DNS_ENCODE ( encode_double_dot, "ipxe..org", DATA() ); + +/* Invalid solo double dot encoding test */ +DNS_ENCODE ( encode_solo_double_dot, "..", DATA() ); + +/* Invalid trailing double dot encoding test */ +DNS_ENCODE ( encode_trailing_double_dot, "ipxe.org..", DATA() ); + +/* Invalid overlength label encoding test */ +DNS_ENCODE ( encode_overlength, + "this-label-is-maliciously-long-in-an-attempt-to-overflow-the-" + "length-field-and-generate-a-length-which-looks-like-a-" + "compression-pointer", DATA() ); + +/* Simple decoding test */ +DNS_DECODE ( decode_simple, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0, + "ipxe.org" ); + +/* Compression pointer decoding test */ +DNS_DECODE ( decode_ptr, + DATA ( 3, 'o', 'r', 'g', 0, 3, 'g', 'i', 't', 4, 'i', 'p', 'x', + 'e', 0xc0, 0x00 ), 5, + "git.ipxe.org" ); + +/* Root decoding test */ +DNS_DECODE ( decode_root, + DATA ( 0 ), 0, "" ); + +/* Incomplete name decoding test */ +DNS_DECODE ( decode_incomplete_name, + DATA ( 4, 'i', 'p', 'x', 'e' ), 0, NULL ); + +/* Incomplete label decoding test */ +DNS_DECODE ( decode_incomplete_label, + DATA ( 4, 'i', 'p', 'x' ), 0, NULL ); + +/* Incomplete compression pointer decoding test */ +DNS_DECODE ( decode_incomplete_ptr, + DATA ( 3, 'o', 'r', 'g', 0, 4, 'i', 'p', 'x', 'e', 0xc0 ), 5, + NULL ); + +/* Forward reference decoding test */ +DNS_DECODE ( decode_forward, + DATA ( 0xc0, 0x02, 3, 'f', 'o', 'o', 0 ), 0, NULL ); + +/* Infinite loop decoding test */ +DNS_DECODE ( decode_infinite, + DATA ( 4, 'i', 'p', 'x', 'e', 0xc0, 0x00 ), 0, NULL ); + +/* Empty decoding test */ +DNS_DECODE ( decode_empty, + DATA (), 0, NULL ); + +/* Simple comparison test */ +DNS_COMPARE ( compare_simple, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0 ); + +/* Compression pointer comparison test */ +DNS_COMPARE ( compare_ptr, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0, + DATA ( 3, 'o', 'r', 'g', 0, 4, 'i', 'p', 'x', 'e', + 0xc0, 0x00 ), 5 ); + +/* Case insensitive comparison test */ +DNS_COMPARE ( compare_case, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'O', 'R', 'G', 0 ), 0 ); + +/* Mismatch comparison test */ +DNS_COMPARE ( compare_mismatch, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0, + DATA ( 4, 'g', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0 ); + +/* Infinite loop comparison test */ +DNS_COMPARE ( compare_infinite, + DATA ( 3, 'f', 'o', 'o', 0xc0, 0x00 ), 0, + DATA ( 3, 'f', 'o', 'o', 0xc0, 0x00 ), 0 ); + +/* Simple copying test */ +DNS_COPY ( copy_simple, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0 ); + +/* Simple copying test with offset */ +DNS_COPY ( copy_offset, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0, + DATA ( 'f', 'o', 'o', 0, 4, 'i', 'p', 'x', 'e', + 3, 'o', 'r', 'g', 0 ), 4 ); + +/* Compression pointer copying test */ +DNS_COPY ( copy_ptr, + DATA ( 3, 'o', 'r', 'g', 0, 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e', + 0xc0, 0x00 ), 5, + DATA ( 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', + 0 ), 0 ); + +/* Infinite loop copying test */ +DNS_COPY ( copy_infinite, + DATA ( 4, 'l', 'o', 'o', 'p', 7, 'f', 'o', 'r', 'e', 'v', 'e', 'r', + 0xc0, 0x05 ), 0, + DATA (), 0 ); + +/* DNS search list test */ +DNS_LIST ( search, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0, + 4, 'b', 'o', 'o', 't', 0xc0, 0x00, + 3, 'd', 'e', 'v', 0xc0, 0x0a, + 11, 'n', 'e', 't', 'w', 'o', 'r', 'k', 'b', 'o', 'o', 't', + 0xc0, 0x05 ), + DATA ( "ipxe.org", "boot.ipxe.org", "dev.boot.ipxe.org", + "networkboot.org" ) ); + +/** + * Perform DNS self-test + * + */ +static void dns_test_exec ( void ) { + + /* Encoding tests */ + dns_encode_ok ( &encode_simple ); + dns_encode_ok ( &encode_single ); + dns_encode_ok ( &encode_absolute ); + dns_encode_ok ( &encode_empty ); + dns_encode_ok ( &encode_root ); + dns_encode_fail_ok ( &encode_initial_dot ); + dns_encode_fail_ok ( &encode_double_dot ); + dns_encode_fail_ok ( &encode_solo_double_dot ); + dns_encode_fail_ok ( &encode_trailing_double_dot ); + dns_encode_fail_ok ( &encode_overlength ); + + /* Decoding tests */ + dns_decode_ok ( &decode_simple ); + dns_decode_ok ( &decode_ptr ); + dns_decode_ok ( &decode_root ); + dns_decode_fail_ok ( &decode_incomplete_name ); + dns_decode_fail_ok ( &decode_incomplete_label ); + dns_decode_fail_ok ( &decode_incomplete_ptr ); + dns_decode_fail_ok ( &decode_forward ); + dns_decode_fail_ok ( &decode_infinite ); + dns_decode_fail_ok ( &decode_empty ); + + /* Comparison tests */ + dns_compare_ok ( &compare_simple ); + dns_compare_ok ( &compare_ptr ); + dns_compare_ok ( &compare_case ); + dns_compare_fail_ok ( &compare_mismatch ); + dns_compare_fail_ok ( &compare_infinite ); + + /* Copying tests */ + dns_copy_ok ( ©_simple ); + dns_copy_ok ( ©_offset ); + dns_copy_ok ( ©_ptr ); + dns_copy_fail_ok ( ©_infinite ); + + /* Search list tets */ + dns_list_ok ( &search ); +} + +/** DNS self-test */ +struct self_test dns_test __self_test = { + .name = "dns", + .exec = dns_test_exec, +}; |