diff --git a/Makefile b/Makefile index ff77c68..ee3e80a 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # IPXWrapper - Makefile -# Copyright (C) 2011-2013 Daniel Collins +# Copyright (C) 2011-2014 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 @@ -63,12 +63,17 @@ dist: all zip -r ipxwrapper-$(VERSION)-src.zip ipxwrapper-$(VERSION)-src/ rm -r ipxwrapper-$(VERSION)-src/ -test: $(TEST_DLLS) tests/bind.exe +test: $(TEST_DLLS) tests/addr.exe tests/bind.exe + ./tests/addr.exe + cp $(TEST_DLLS) tests/ cd tests; perl bind.pl -tests/%.exe: tests/%.c - $(CC) $(CFLAGS) -o $@ $< -lwsock32 +tests/addr.exe: tests/addr.c src/addr.o +tests/bind.exe: tests/bind.c + +tests/%.exe: + $(CC) $(CFLAGS) -I./src/ -o $@ $^ -lwsock32 .SECONDARY: .PHONY: all clean dist depend test diff --git a/manifest.src.txt b/manifest.src.txt index a84ce6d..b2ca92e 100644 --- a/manifest.src.txt +++ b/manifest.src.txt @@ -55,6 +55,7 @@ include/wsnwlink.h directplay-win32.reg directplay-win64.reg +tests/addr.c tests/bind.c tests/bind.pl tests/ipxtest.pm diff --git a/src/addr.c b/src/addr.c index 05aaa51..2eaee1d 100644 --- a/src/addr.c +++ b/src/addr.c @@ -1,5 +1,5 @@ /* ipxwrapper - Address manipulation functions - * Copyright (C) 2012 Daniel Collins + * Copyright (C) 2012-2014 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 @@ -87,7 +87,7 @@ char *addr32_string(char *buf, addr32_t addr) */ bool addr32_from_string(addr32_t *dest, const char *src) { - return _addr_from_string((unsigned char*)&dest, src, 4); + return _addr_from_string((unsigned char*)(dest), src, 4); } addr48_t addr48_in(const void *src) @@ -131,7 +131,7 @@ char *addr48_string(char *buf, addr48_t addr) */ bool addr48_from_string(addr48_t *dest, const char *src) { - return _addr_from_string(((unsigned char*)&dest) + 2, src, 6); + return _addr_from_string((unsigned char*)(dest) + 2, src, 6); } /* Format an IPX address as a string. diff --git a/tests/addr.c b/tests/addr.c new file mode 100644 index 0000000..51f58a6 --- /dev/null +++ b/tests/addr.c @@ -0,0 +1,279 @@ +/* IPXWrapper - Address manipulation unit tests + * Copyright (C) 2014 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 "addr.h" + +static int failed = 0; + +static char *dump32(const void *p) +{ + static char buf[32]; + + sprintf(buf, "%02X:%02X:%02X:%02X", + (unsigned int)(*((unsigned char*)(p) + 0)), + (unsigned int)(*((unsigned char*)(p) + 1)), + (unsigned int)(*((unsigned char*)(p) + 2)), + (unsigned int)(*((unsigned char*)(p) + 3))); + + return buf; +} + +static void test_a32_bin(const unsigned char *bin_in, const char *expect_text) +{ + { + printf("addr32_in(%s) => addr32_out()... ", dump32(bin_in)); + + unsigned char got_bin[4]; + addr32_out(got_bin, addr32_in(bin_in)); + + if(memcmp(got_bin, bin_in, 4) == 0) + { + printf("OK\n"); + } + else{ + printf("FAILED\n"); + ++failed; + + printf("Got: %s\n", dump32(got_bin)); + printf("Expected: %s\n", dump32(bin_in)); + } + } + + { + printf("addr32_in(%s) => addr32_string()... ", dump32(bin_in)); + + char got_text[256]; + memset(got_text, '\0', 256); + + addr32_string(got_text, addr32_in(bin_in)); + + if(strcmp(got_text, expect_text) == 0) + { + printf("OK\n"); + } + else{ + printf("FAILED\n"); + ++failed; + + printf("Got: %s\n", got_text); + printf("Expected: %s\n", expect_text); + } + } +} + +static void test_valid_a32_text(const char *text_in, const unsigned char *expect_bin) +{ + printf("addr32_from_string(%s) => addr32_out()... ", text_in); + + addr32_t a32; + if(!addr32_from_string(&a32, text_in)) + { + printf("FAILED\n"); + ++failed; + + printf("addr32_from_string() returned false\n"); + + return; + } + + unsigned char got_bin[4]; + addr32_out(got_bin, a32); + + if(memcmp(got_bin, expect_bin, 4)) + { + printf("FAILED\n"); + ++failed; + + printf("Got: %s\n", dump32(got_bin)); + printf("Expected: %s\n", dump32(expect_bin)); + + return; + } + + printf("OK\n"); +} + +static void test_bad_a32_text(const char *text_in) +{ + printf("!addr32_from_string(%s)... ", text_in); + + addr32_t a32; + if(addr32_from_string(&a32, text_in)) + { + printf("FAILED\n"); + ++failed; + } + else{ + printf("OK\n"); + } +} + +static char *dump48(const void *p) +{ + static char buf[32]; + + sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", + (unsigned int)(*((unsigned char*)(p) + 0)), + (unsigned int)(*((unsigned char*)(p) + 1)), + (unsigned int)(*((unsigned char*)(p) + 2)), + (unsigned int)(*((unsigned char*)(p) + 3)), + (unsigned int)(*((unsigned char*)(p) + 4)), + (unsigned int)(*((unsigned char*)(p) + 5))); + + return buf; +} + +static void test_a48_bin(const unsigned char *bin_in, const char *expect_text) +{ + { + printf("addr48_in(%s) => addr48_out()... ", dump48(bin_in)); + + unsigned char got_bin[6]; + addr48_out(got_bin, addr48_in(bin_in)); + + if(memcmp(got_bin, bin_in, 6) == 0) + { + printf("OK\n"); + } + else{ + printf("FAILED\n"); + ++failed; + + printf("Got: %s\n", dump48(got_bin)); + printf("Expected: %s\n", dump48(bin_in)); + } + } + + { + printf("addr48_in(%s) => addr48_string()... ", dump48(bin_in)); + + char got_text[256]; + memset(got_text, '\0', 256); + + addr48_string(got_text, addr48_in(bin_in)); + + if(strcmp(got_text, expect_text) == 0) + { + printf("OK\n"); + } + else{ + printf("FAILED\n"); + ++failed; + + printf("Got: %s\n", got_text); + printf("Expected: %s\n", expect_text); + } + } +} + +static void test_valid_a48_text(const char *text_in, const unsigned char *expect_bin) +{ + printf("addr48_from_string(%s) => addr48_out()... ", text_in); + + addr48_t a48; + if(!addr48_from_string(&a48, text_in)) + { + printf("FAILED\n"); + ++failed; + + printf("addr48_from_string() returned false\n"); + + return; + } + + unsigned char got_bin[6]; + addr48_out(got_bin, a48); + + if(memcmp(got_bin, expect_bin, 6)) + { + printf("FAILED\n"); + ++failed; + + printf("Got: %s\n", dump48(&got_bin)); + printf("Expected: %s\n", dump48(expect_bin)); + + return; + } + + printf("OK\n"); +} + +static void test_bad_a48_text(const char *text_in) +{ + printf("!addr48_from_string(%s)... ", text_in); + + addr48_t a48; + if(addr48_from_string(&a48, text_in)) + { + printf("FAILED\n"); + ++failed; + } + else{ + printf("OK\n"); + } +} + +int main() +{ + test_a32_bin((unsigned char[]){0x00, 0x00, 0x00, 0x00}, "00:00:00:00"); + test_a32_bin((unsigned char[]){0x12, 0x34, 0x56, 0x78}, "12:34:56:78"); + test_a32_bin((unsigned char[]){0xFF, 0xFF, 0xFF, 0xFF}, "FF:FF:FF:FF"); + + test_valid_a32_text("00:00:00:00", (unsigned char[]){0x00, 0x00, 0x00, 0x00}); + test_valid_a32_text("0:0:0:0", (unsigned char[]){0x00, 0x00, 0x00, 0x00}); + test_valid_a32_text("00:0:00:0", (unsigned char[]){0x00, 0x00, 0x00, 0x00}); + test_valid_a32_text("12:34:56:78", (unsigned char[]){0x12, 0x34, 0x56, 0x78}); + test_valid_a32_text("12:03:56:07", (unsigned char[]){0x12, 0x03, 0x56, 0x07}); + test_valid_a32_text("12:3:56:7", (unsigned char[]){0x12, 0x03, 0x56, 0x07}); + test_valid_a32_text("FF:FF:FF:FF", (unsigned char[]){0xFF, 0xFF, 0xFF, 0xFF}); + test_valid_a32_text("0F:F0:0F:FF", (unsigned char[]){0x0F, 0xF0, 0x0F, 0xFF}); + + test_bad_a32_text(""); + test_bad_a32_text("00:00:00"); + test_bad_a32_text("00:00:00:"); + test_bad_a32_text("00:00::00"); + test_bad_a32_text("000:00:00:00"); + test_bad_a32_text("00:00:001:00"); + test_bad_a32_text("00:00:00:0G"); + test_bad_a32_text("00:00:00:00:00"); + + test_a48_bin((unsigned char[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, "00:00:00:00:00:00"); + test_a48_bin((unsigned char[]){0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}, "12:34:56:78:9A:BC"); + test_a48_bin((unsigned char[]){0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, "FF:FF:FF:FF:FF:FF"); + + test_valid_a48_text("00:00:00:00:00:00", (unsigned char[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + test_valid_a48_text("0:0:0:0:0:0", (unsigned char[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + test_valid_a48_text("00:0:00:00:0:0", (unsigned char[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + test_valid_a48_text("FF:0:C:00:0B:AA", (unsigned char[]){0xFF, 0x00, 0x0C, 0x00, 0x0B, 0xAA}); + test_valid_a48_text("FF:FF:FF:FF:FF:FF", (unsigned char[]){0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}); + + test_bad_a48_text(""); + test_bad_a48_text("00:00:00:00:00"); + test_bad_a48_text("00:00:00:00:00:00:00"); + test_bad_a48_text("00:00:00:00:00:"); + test_bad_a48_text("00:00:00:00::00"); + test_bad_a48_text("001:00:00:00:00:00"); + test_bad_a48_text("00:00:00:00:000:00"); + test_bad_a48_text("G0:00:00:00:00:00"); + test_bad_a48_text("000000000000"); + test_bad_a48_text("00-00-00-00-00-00"); + + return failed; +}