From 659641d436ca349144f150ea088436da303c258e Mon Sep 17 00:00:00 2001 From: Daniel Collins Date: Wed, 29 Mar 2017 20:34:32 +0100 Subject: [PATCH] Added unit tests for Ethernet frame (de)serialising functions. --- Makefile | 5 +- manifest.src.txt | 2 + tests/07-ethernet.t | 29 +++ tests/ethernet.c | 507 ++++++++++++++++++++++++++++++++++++++++++++ tests/tap/basic.c | 37 ++++ tests/tap/basic.h | 2 + 6 files changed, 581 insertions(+), 1 deletion(-) create mode 100644 tests/07-ethernet.t create mode 100644 tests/ethernet.c diff --git a/Makefile b/Makefile index e4fa65e..dbd1d83 100644 --- a/Makefile +++ b/Makefile @@ -77,7 +77,7 @@ dist: all zip -r ipxwrapper-$(VERSION)-src.zip ipxwrapper-$(VERSION)-src/ rm -r ipxwrapper-$(VERSION)-src/ -tools: $(TOOLS) tests/addr.exe ipxwrapper.dll wsock32.dll dpwsockx.dll +tools: $(TOOLS) tests/addr.exe tests/ethernet.exe ipxwrapper.dll wsock32.dll dpwsockx.dll cp ipxwrapper.dll wsock32.dll dpwsockx.dll tools/ tools/%.exe: tools/%.c tools/tools.h src/addr.o @@ -86,6 +86,9 @@ tools/%.exe: tools/%.c tools/tools.h src/addr.o tests/addr.exe: tests/addr.o tests/tap/basic.o src/addr.o $(CC) $(CFLAGS) -I./ -o $@ $^ -lwsock32 +tests/ethernet.exe: tests/ethernet.o tests/tap/basic.o src/ethernet.o src/addr.o + $(CC) $(CFLAGS) -I./ -o $@ $^ -lwsock32 + tests/%.o: tests/%.c $(CC) $(CFLAGS) -I./ -c -o $@ $< diff --git a/manifest.src.txt b/manifest.src.txt index 2de0b9a..4e41654 100644 --- a/manifest.src.txt +++ b/manifest.src.txt @@ -59,6 +59,7 @@ directplay-win32.reg directplay-win64.reg tests/05-addr.t +tests/07-ethernet.t tests/10-socket.t tests/15-interfaces.t tests/20-bind.t @@ -68,6 +69,7 @@ tests/40-ip-spx.t tests/50-dplay.t tests/addr.c tests/config.pm +tests/ethernet.c tests/ptype.pm tests/lib/IPXWrapper/Capture/IPX.pm diff --git a/tests/07-ethernet.t b/tests/07-ethernet.t new file mode 100644 index 0000000..133346a --- /dev/null +++ b/tests/07-ethernet.t @@ -0,0 +1,29 @@ +# IPXWrapper test suite +# Copyright (C) 2017 Daniel Collins +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published by +# the Free Software Foundation. +# +# 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. + +use strict; +use warnings; + +use FindBin; + +require "$FindBin::Bin/config.pm"; +our $remote_ip_a; + +# Unit tests implemented by ethernet.exe, so run it on the test system and pass +# the (TAP) output/exit status to our parent. + +system("ssh", $remote_ip_a, "Z:\\tests\\ethernet.exe"); +exit($? >> 8); diff --git a/tests/ethernet.c b/tests/ethernet.c new file mode 100644 index 0000000..57cd2cd --- /dev/null +++ b/tests/ethernet.c @@ -0,0 +1,507 @@ +/* IPXWrapper test suite + * Copyright (C) 2017 Daniel Collins + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * 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. +*/ + +#include + +#include +#include + +#include "tests/tap/basic.h" +#include "src/ethernet.h" + +#define CHECK_FRAME_SIZE(func, input, output) \ + is_int((output), func(input), #func "(" #input ") returns " #output) + +#define UNPACK_GOOD_FRAME(func, desc, expect_ipx_off, expect_ipx_len, frame_len, ...) \ +{ \ + const unsigned char FRAME[frame_len] = { __VA_ARGS__ }; \ + \ + const novell_ipx_packet *ipx; \ + size_t ipx_len; \ + \ + ok(func(&ipx, &ipx_len, FRAME, frame_len), #func "(<" desc ">) succeeds"); \ + ok((ipx == (FRAME + expect_ipx_off)), #func "(<" desc ">) returns the correct payload address"); \ + is_int(expect_ipx_len, ipx_len, #func "(<" desc ">) returns the correct payload length"); \ +} + +#define UNPACK_BAD_FRAME(func, desc, frame_len, ...) \ +{ \ + const unsigned char FRAME[frame_len] = { __VA_ARGS__ }; \ + \ + const novell_ipx_packet *ipx; \ + size_t ipx_len; \ + \ + ok(!func(&ipx, &ipx_len, FRAME, frame_len), #func "(<" desc ">) fails"); \ +} + +int main() +{ + plan_lazy(); + + /* +------------------+ + * | ethII_frame_size | + * +------------------+ + */ + + CHECK_FRAME_SIZE(ethII_frame_size, 0, 44); + CHECK_FRAME_SIZE(ethII_frame_size, 50, 94); + CHECK_FRAME_SIZE(ethII_frame_size, 2000, 2044); + + /* +------------------+ + * | ethII_frame_pack | + * +------------------+ + */ + + { + uint8_t ptype = 0x42; + + addr32_t src_net = addr32_in((unsigned char[]){ 0xDE, 0xAD, 0xBE, 0xEF }); + addr48_t src_node = addr48_in((unsigned char[]){ 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D }); + uint16_t src_socket = htons(1234); + + addr32_t dst_net = addr32_in((unsigned char[]){ 0xBE, 0xEF, 0x0D, 0xAD }); + addr48_t dst_node = addr48_in((unsigned char[]){ 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00 }); + uint16_t dst_socket = htons(9876); + + static const char payload[] = { 0x00, 0xFF, 0x12, 0x34 }; + + unsigned char buf[1024]; + ethII_frame_pack(&buf, + ptype, + src_net, src_node, src_socket, + dst_net, dst_node, dst_socket, + payload, sizeof(payload)); + + static const unsigned char expect[] = { + /* Ethernet header */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination MAC */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source MAC */ + 0x81, 0x37, /* Ethertype */ + + /* IPX header */ + 0xFF, 0xFF, /* Checksum */ + 0x00, 0x22, /* Length */ + 0x00, /* Hops */ + 0x42, /* Type */ + + 0xBE, 0xEF, 0x0D, 0xAD, /* Destination network */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination node */ + 0x26, 0x94, /* Destination socket */ + + 0xDE, 0xAD, 0xBE, 0xEF, /* Source network */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source node */ + 0x04, 0xD2, /* Source socket */ + + /* Payload */ + 0x00, 0xFF, 0x12, 0x34, + }; + + is_blob(expect, buf, sizeof(expect), "ethII_frame_pack() serialises correctly"); + } + + /* +--------------------+ + * | ethII_frame_unpack | + * +--------------------+ + */ + + /* Frame with smallest possible IPX packet (30 bytes) */ + UNPACK_GOOD_FRAME(ethII_frame_unpack, + "frame with 30 byte packet", + + 14, /* Offset of IPX packet */ + 30, /* Length of IPX packet */ + + /* Frame length */ + 44, + + /* Ethernet header */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination MAC */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source MAC */ + 0x81, 0x37, /* Ethertype */ + + /* IPX header */ + 0xFF, 0xFF, /* Checksum */ + 0x00, 0x1E, /* Length */ + 0x00, /* Hops */ + 0x42, /* Type */ + + 0xBE, 0xEF, 0x0D, 0xAD, /* Destination network */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination node */ + 0x26, 0x94, /* Destination socket */ + + 0xDE, 0xAD, 0xBE, 0xEF, /* Source network */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source node */ + 0x04, 0xD2, /* Source socket */ + ); + + /* Frame with wrong Ethertype (valid raw frame) */ + UNPACK_BAD_FRAME(ethII_frame_unpack, + "frame with wrong Ethertype", + + /* Frame length */ + 44, + + /* Ethernet header */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination MAC */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source MAC */ + 0x00, 0x1E, /* Payload length */ + + /* IPX header */ + 0xFF, 0xFF, /* Checksum */ + 0x00, 0x1E, /* Length */ + 0x00, /* Hops */ + 0x42, /* Type */ + + 0xBE, 0xEF, 0x0D, 0xAD, /* Destination network */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination node */ + 0x26, 0x94, /* Destination socket */ + + 0xDE, 0xAD, 0xBE, 0xEF, /* Source network */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source node */ + 0x04, 0xD2, /* Source socket */ + ); + + /* Frame with 2000 byte IPX packet */ + UNPACK_GOOD_FRAME(ethII_frame_unpack, + "frame with 2000 byte packet", + + 14, /* Offset of IPX packet */ + 2000, /* Length of IPX packet */ + + /* Frame length */ + 2014, + + /* Ethernet header */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination MAC */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source MAC */ + 0x81, 0x37, /* Ethertype */ + + /* IPX header */ + 0xFF, 0xFF, /* Checksum */ + 0x07, 0xD0, /* Length */ + 0x00, /* Hops */ + 0x42, /* Type */ + + 0xBE, 0xEF, 0x0D, 0xAD, /* Destination network */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination node */ + 0x26, 0x94, /* Destination socket */ + + 0xDE, 0xAD, 0xBE, 0xEF, /* Source network */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source node */ + 0x04, 0xD2, /* Source socket */ + + /* IPX payload (uninitialised) */ + ); + + /* Frame too short to hold all the headers */ + UNPACK_BAD_FRAME(ethII_frame_unpack, + "truncated frame - too short", + + /* Frame length */ + 43, + + /* Ethernet header */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination MAC */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source MAC */ + 0x81, 0x37, /* Ethertype */ + + /* IPX header */ + 0xFF, 0xFF, /* Checksum */ + 0x00, 0x1D, /* Length */ + 0x00, /* Hops */ + 0x42, /* Type */ + + 0xBE, 0xEF, 0x0D, 0xAD, /* Destination network */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination node */ + 0x26, 0x94, /* Destination socket */ + + 0xDE, 0xAD, 0xBE, 0xEF, /* Source network */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source node */ + 0x04, /* Source socket (truncated) */ + ); + + /* +-------------------+ + * | novell_frame_size | + * +-------------------+ + */ + + CHECK_FRAME_SIZE(novell_frame_size, 0, 44); + CHECK_FRAME_SIZE(novell_frame_size, 50, 94); + CHECK_FRAME_SIZE(novell_frame_size, 1456, 1500); + CHECK_FRAME_SIZE(novell_frame_size, 1457, 0); + + /* +===================+ + * | novell_frame_pack | + * +===================+ + */ + + { + uint8_t ptype = 0x42; + + addr32_t src_net = addr32_in((unsigned char[]){ 0xDE, 0xAD, 0xBE, 0xEF }); + addr48_t src_node = addr48_in((unsigned char[]){ 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D }); + uint16_t src_socket = htons(1234); + + addr32_t dst_net = addr32_in((unsigned char[]){ 0xBE, 0xEF, 0x0D, 0xAD }); + addr48_t dst_node = addr48_in((unsigned char[]){ 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00 }); + uint16_t dst_socket = htons(9876); + + static const char payload[] = { 0x00, 0xFF, 0x12, 0x34 }; + + unsigned char buf[1024]; + novell_frame_pack(&buf, + ptype, + src_net, src_node, src_socket, + dst_net, dst_node, dst_socket, + payload, sizeof(payload)); + + static const unsigned char expect[] = { + /* Ethernet header */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination MAC */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source MAC */ + 0x00, 0x22, /* Payload length */ + + /* IPX header */ + 0xFF, 0xFF, /* Checksum */ + 0x00, 0x22, /* Length */ + 0x00, /* Hops */ + 0x42, /* Type */ + + 0xBE, 0xEF, 0x0D, 0xAD, /* Destination network */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination node */ + 0x26, 0x94, /* Destination socket */ + + 0xDE, 0xAD, 0xBE, 0xEF, /* Source network */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source node */ + 0x04, 0xD2, /* Source socket */ + + /* Payload */ + 0x00, 0xFF, 0x12, 0x34, + }; + + is_blob(expect, buf, sizeof(expect), "novell_frame_pack() serialises correctly"); + } + + /* +---------------------+ + * | novell_frame_unpack | + * +---------------------+ + */ + + /* Frame with smallest possible IPX packet (30 bytes) */ + UNPACK_GOOD_FRAME(novell_frame_unpack, + "frame with 30 byte packet", + + 14, /* Offset of IPX packet */ + 30, /* Length of IPX packet */ + + /* Frame length */ + 44, + + /* Ethernet header */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination MAC */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source MAC */ + 0x00, 0x1E, /* Payload length */ + + /* IPX header */ + 0xFF, 0xFF, /* Checksum */ + 0x00, 0x1E, /* Length */ + 0x00, /* Hops */ + 0x42, /* Type */ + + 0xBE, 0xEF, 0x0D, 0xAD, /* Destination network */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination node */ + 0x26, 0x94, /* Destination socket */ + + 0xDE, 0xAD, 0xBE, 0xEF, /* Source network */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source node */ + 0x04, 0xD2, /* Source socket */ + ); + + /* Frame with an Ethernet II Ethertype rather than a length */ + UNPACK_BAD_FRAME(novell_frame_unpack, + "frame with 30 byte packet and an Ethertype", + + /* Frame length */ + 44, + + /* Ethernet header */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination MAC */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source MAC */ + 0x81, 0x37, /* Ethertype */ + + /* IPX header */ + 0xFF, 0xFF, /* Checksum */ + 0x00, 0x1E, /* Length */ + 0x00, /* Hops */ + 0x42, /* Type */ + + 0xBE, 0xEF, 0x0D, 0xAD, /* Destination network */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination node */ + 0x26, 0x94, /* Destination socket */ + + 0xDE, 0xAD, 0xBE, 0xEF, /* Source network */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source node */ + 0x04, 0xD2, /* Source socket */ + ); + + /* Frame with largest allowable IPX packet (1500 bytes) */ + UNPACK_GOOD_FRAME(novell_frame_unpack, + "frame with 1500 byte packet", + + 14, /* Offset of IPX packet */ + 1500, /* Length of IPX packet */ + + /* Frame length */ + 1514, + + /* Ethernet header */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination MAC */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source MAC */ + 0x05, 0xDC, /* Payload length */ + + /* IPX header */ + 0xFF, 0xFF, /* Checksum */ + 0x05, 0xDC, /* Length */ + 0x00, /* Hops */ + 0x42, /* Type */ + + 0xBE, 0xEF, 0x0D, 0xAD, /* Destination network */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination node */ + 0x26, 0x94, /* Destination socket */ + + 0xDE, 0xAD, 0xBE, 0xEF, /* Source network */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source node */ + 0x04, 0xD2, /* Source socket */ + + /* IPX payload (uninitialised) */ + ); + + /* Frame with 1501 length header (undefined behaviour) */ + UNPACK_BAD_FRAME(novell_frame_unpack, + "frame with 1501 byte packet", + + /* Frame length */ + 1515, + + /* Ethernet header */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination MAC */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source MAC */ + 0x05, 0xDD, /* Payload length */ + + /* IPX header */ + 0xFF, 0xFF, /* Checksum */ + 0x05, 0xDD, /* Length */ + 0x00, /* Hops */ + 0x42, /* Type */ + + 0xBE, 0xEF, 0x0D, 0xAD, /* Destination network */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination node */ + 0x26, 0x94, /* Destination socket */ + + 0xDE, 0xAD, 0xBE, 0xEF, /* Source network */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source node */ + 0x04, 0xD2, /* Source socket */ + + /* IPX payload (uninitialised) */ + ); + + /* Valid IPX packet within, but Ethernet payload length is too short */ + UNPACK_BAD_FRAME(novell_frame_unpack, + "frame with valid packet but 29 bytes in length header", + + /* Frame length */ + 48, + + /* Ethernet header */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination MAC */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source MAC */ + 0x00, 0x1D, /* Payload length */ + + /* IPX header */ + 0xFF, 0xFF, /* Checksum */ + 0x00, 0x22, /* Length */ + 0x00, /* Hops */ + 0x42, /* Type */ + + 0xBE, 0xEF, 0x0D, 0xAD, /* Destination network */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination node */ + 0x26, 0x94, /* Destination socket */ + + 0xDE, 0xAD, 0xBE, 0xEF, /* Source network */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source node */ + 0x04, 0xD2, /* Source socket */ + + /* IPX payload */ + 0x00, 0xFF, 0x12, 0x34, + ); + + /* Frame too short to hold all the headers */ + UNPACK_BAD_FRAME(novell_frame_unpack, + "truncated frame - too short", + + /* Frame length */ + 43, + + /* Ethernet header */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination MAC */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source MAC */ + 0x00, 0x1D, /* Payload length */ + + /* IPX header */ + 0xFF, 0xFF, /* Checksum */ + 0x00, 0x1D, /* Length */ + 0x00, /* Hops */ + 0x42, /* Type */ + + 0xBE, 0xEF, 0x0D, 0xAD, /* Destination network */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination node */ + 0x26, 0x94, /* Destination socket */ + + 0xDE, 0xAD, 0xBE, 0xEF, /* Source network */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source node */ + 0x04, /* Source socket (truncated) */ + ); + + /* Length runs past frame end */ + UNPACK_BAD_FRAME(novell_frame_unpack, + "truncated frame - length runs past end", + + /* Frame length */ + 44, + + /* Ethernet header */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination MAC */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source MAC */ + 0x00, 0x1F, /* Payload length */ + + /* IPX header */ + 0xFF, 0xFF, /* Checksum */ + 0x00, 0x1F, /* Length */ + 0x00, /* Hops */ + 0x42, /* Type */ + + 0xBE, 0xEF, 0x0D, 0xAD, /* Destination network */ + 0x99, 0xB0, 0x77, 0x1E, 0x50, 0x00, /* Destination node */ + 0x26, 0x94, /* Destination socket */ + + 0xDE, 0xAD, 0xBE, 0xEF, /* Source network */ + 0x0B, 0xAD, 0x0B, 0xEE, 0xF0, 0x0D, /* Source node */ + 0x04, 0xD2, /* Source socket */ + ); + + return 0; +} diff --git a/tests/tap/basic.c b/tests/tap/basic.c index 92a749b..45b664c 100644 --- a/tests/tap/basic.c +++ b/tests/tap/basic.c @@ -568,6 +568,43 @@ is_hex(unsigned long wanted, unsigned long seen, const char *format, ...) } +/* + * Takes pointers to an expected region of memory and a seen region of memory + * and assumes the test passes if the len bytes onwards from them match. + * Otherwise reports any bytes which didn't match. + */ +int +is_blob(const void *wanted, const void *seen, size_t len, const char *format, ...) +{ + int success; + size_t i; + + fflush(stderr); + check_diag_files(); + success = (memcmp(wanted, seen, len) == 0); + if (success) + printf("ok %lu", testnum++); + else { + for(i = 0; i < len; ++i) + { + unsigned char wanted_b = ((unsigned char*)(wanted))[i]; + unsigned char seen_b = ((unsigned char*)(seen))[i]; + + if(wanted_b != seen_b) + { + diag("offset %x: wanted %02x, seen %02x", + (unsigned)(i), (unsigned)(wanted_b), (unsigned)(seen_b)); + } + } + printf("not ok %lu", testnum++); + _failed++; + } + PRINT_DESC(" - ", format); + putchar('\n'); + return success; +} + + /* * Bail out with an error. */ diff --git a/tests/tap/basic.h b/tests/tap/basic.h index c002df9..a32eb2e 100644 --- a/tests/tap/basic.h +++ b/tests/tap/basic.h @@ -95,6 +95,8 @@ int is_string(const char *wanted, const char *seen, const char *format, ...) __attribute__((__format__(printf, 3, 4))); int is_hex(unsigned long wanted, unsigned long seen, const char *format, ...) __attribute__((__format__(printf, 3, 4))); +int is_blob(const void *wanted, const void *seen, size_t len, const char *format, ...) + __attribute__((__format__(printf, 4, 5))); /* Bail out with an error. sysbail appends strerror(errno). */ void bail(const char *format, ...)