diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a7b017b..28232d96 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -361,6 +361,15 @@ target_link_modules(toxencryptsave toxcore) find_program(SPECTEST NAMES tox-spectest) +if(NOT SPECTEST) + find_program(STACK NAMES stack) + if(STACK) + set(SPECTEST + ${STACK} --stack-yaml ${toxcore_SOURCE_DIR}/../stack.yaml exec -- + tox-spectest) + endif() +endif() + if(SPECTEST AND MSGPACK_FOUND) add_c_executable(toxcore-sut testing/hstox/binary_decode.c diff --git a/other/travis/hstox-install b/other/travis/hstox-install index fccae0be..773bf388 100755 --- a/other/travis/hstox-install +++ b/other/travis/hstox-install @@ -12,8 +12,11 @@ cabal install happy git clone --recursive --depth=1 https://github.com/TokTok/hs-toxcore ../hs-toxcore git clone --depth=1 https://github.com/msgpack/msgpack-c testing/hstox/msgpack-c -# Install the hstox test runner. -(cd ../hs-toxcore && cabal install --disable-library-profiling) - -# Install toxcore dependencies. +# Install toxcore dependencies before hstox, as hstox needs libsodium. . other/travis/toxcore-linux-install + +# Install the hstox test runner. +CABAL_FLAGS="--disable-library-profiling" +CABAL_FLAGS="$CABAL_FLAGS --extra-include-dirs=$CACHE_DIR/include" +CABAL_FLAGS="$CABAL_FLAGS --extra-lib-dirs=$CACHE_DIR/lib" +(cd ../hs-toxcore && cabal install $CABAL_FLAGS) diff --git a/testing/hstox/binary_decode.c b/testing/hstox/binary_decode.c index fb3bca43..588b9a7c 100644 --- a/testing/hstox/binary_decode.c +++ b/testing/hstox/binary_decode.c @@ -1,3 +1,4 @@ +#define _BSD_SOURCE #include "methods.h" #include "byteswap.h" @@ -9,19 +10,17 @@ static void decode_bytestring(msgpack_object_bin args, msgpack_packer *res, int64_t min_length) { - int64_t length; - uint64_t tmp; - SUCCESS { if (args.size < sizeof(uint64_t)) { // Not enough space to even fit the size. - msgpack_pack_nil(res); + msgpack_pack_uint8(res, 0); return; } + uint64_t tmp; memcpy(&tmp, args.ptr, sizeof(uint64_t)); - length = be64toh(tmp); + int64_t length = be64toh(tmp); // TODO(iphydf): Get rid of this case if/when // https://github.com/kolmodin/binary/issues/127 is fixed. This is a @@ -37,14 +36,17 @@ static void decode_bytestring(msgpack_object_bin args, msgpack_packer *res, { if (length < min_length) { // CipherTexts need at least a MAC. - msgpack_pack_nil(res); + msgpack_pack_uint8(res, 0); return; } + msgpack_pack_array(res, 2); + msgpack_pack_uint8(res, 1); + msgpack_pack_bin(res, args.size - sizeof(uint64_t)); msgpack_pack_bin_body(res, args.ptr + sizeof(uint64_t), args.size - sizeof(uint64_t)); } else { - msgpack_pack_nil(res); + msgpack_pack_uint8(res, 0); } } } @@ -61,6 +63,11 @@ METHOD(bin, Binary_decode, DhtPacket) return pending; } +METHOD(bin, Binary_decode, DhtRequestPacket) +{ + return pending; +} + METHOD(bin, Binary_decode, HostAddress) { return pending; @@ -81,8 +88,11 @@ METHOD(bin, Binary_decode, KeyPair) SUCCESS { if (args.size != 64) { - msgpack_pack_nil(res); + msgpack_pack_uint8(res, 0); } else { + msgpack_pack_array(res, 2); + msgpack_pack_uint8(res, 1); + msgpack_pack_array(res, 2); msgpack_pack_bin(res, 32); msgpack_pack_bin_body(res, args.ptr, 32); @@ -113,6 +123,9 @@ METHOD(bin, Binary_decode, NodeInfo) SUCCESS { if (len > 0 && data_processed > 0 && data_processed == args.size) { + msgpack_pack_array(res, 2); + msgpack_pack_uint8(res, 1); + msgpack_pack_array(res, 3); msgpack_pack_uint8(res, tcp); msgpack_pack_array(res, 2); @@ -133,7 +146,7 @@ METHOD(bin, Binary_decode, NodeInfo) msgpack_pack_bin(res, CRYPTO_PUBLIC_KEY_SIZE); msgpack_pack_bin_body(res, &node.public_key, CRYPTO_PUBLIC_KEY_SIZE); } else { - msgpack_pack_nil(res); + msgpack_pack_uint8(res, 0); } } @@ -160,7 +173,7 @@ METHOD(bin, Binary_decode, PacketKind) SUCCESS { if (args.size != 1) { - msgpack_pack_nil(res); + msgpack_pack_uint8(res, 0); } else { uint8_t kind = args.ptr[0]; size_t i; @@ -168,13 +181,15 @@ METHOD(bin, Binary_decode, PacketKind) for (i = 0; i < sizeof packet_kinds / sizeof *packet_kinds; i++) { if (packet_kinds[i] == kind) { + msgpack_pack_array(res, 2); + msgpack_pack_uint8(res, 1); msgpack_pack_fix_uint8(res, i); return 0; } } // Packet kind not found => error. - msgpack_pack_nil(res); + msgpack_pack_uint8(res, 0); } } return 0; @@ -199,9 +214,11 @@ METHOD(bin, Binary_decode, PortNumber) uint16_t tmp; memcpy(&tmp, args.ptr, 2); uint16_t port = ntohs(tmp); + msgpack_pack_array(res, 2); + msgpack_pack_uint8(res, 1); msgpack_pack_uint16(res, port); } else { - msgpack_pack_nil(res); + msgpack_pack_uint8(res, 0); } } @@ -235,6 +252,7 @@ METHOD(array, Binary, decode) return Binary_decode_##TYPE(args.ptr[1].via.bin, res) DISPATCH(CipherText); DISPATCH(DhtPacket); + DISPATCH(DhtRequestPacket); DISPATCH(HostAddress); DISPATCH(Word64); DISPATCH(Key_PublicKey); diff --git a/testing/hstox/binary_encode.c b/testing/hstox/binary_encode.c index 8809be28..aad94f5f 100644 --- a/testing/hstox/binary_encode.c +++ b/testing/hstox/binary_encode.c @@ -1,3 +1,4 @@ +#define _BSD_SOURCE #include "methods.h" #include "byteswap.h" @@ -22,6 +23,11 @@ METHOD(array, Binary_encode, DhtPacket) return pending; } +METHOD(array, Binary_encode, DhtRequestPacket) +{ + return pending; +} + METHOD(array, Binary_encode, HostAddress) { return pending; @@ -231,6 +237,7 @@ METHOD(array, Binary, encode) } while (0) DISPATCH(CipherText, BIN, bin); DISPATCH(DhtPacket, ARRAY, array); + DISPATCH(DhtRequestPacket, ARRAY, array); DISPATCH(HostAddress, ARRAY, array); DISPATCH(Word64, POSITIVE_INTEGER, u64); DISPATCH(Key_PublicKey, BIN, bin); diff --git a/testing/hstox/driver.c b/testing/hstox/driver.c index 7a9a907e..2ae68f1b 100644 --- a/testing/hstox/driver.c +++ b/testing/hstox/driver.c @@ -1,3 +1,5 @@ +#define _XOPEN_SOURCE 600 + #include #include #include @@ -19,7 +21,7 @@ static void __attribute__((__noreturn__)) handle_interrupt(int signum) { - printf("Caught signal %d; exiting cleanly.\n", signum); + fprintf(stderr, "caught signal %d; exiting cleanly.\n", signum); exit(0); } @@ -92,6 +94,12 @@ static int write_sample_input(msgpack_object req) static int handle_request(struct settings cfg, int write_fd, msgpack_object req) { + if (cfg.trace) { + fprintf(stderr, "input: "); + msgpack_object_print(stderr, req); + fprintf(stderr, "\n"); + } + msgpack_sbuffer sbuf __attribute__((__cleanup__(msgpack_sbuffer_destroy))); /* buffer */ msgpack_sbuffer_init(&sbuf); /* initialize buffer */ @@ -121,7 +129,7 @@ static int handle_request(struct settings cfg, int write_fd, msgpack_object req) if (name.size == (sizeof "rpc.capabilities") - 1 && memcmp(name.ptr, "rpc.capabilities", name.size) == 0) { // 3. Error. - msgpack_pack_string(&pk, "Capabilities negiotiation not implemented"); + msgpack_pack_string(&pk, "capabilities negiotiation not implemented"); // 4. No result. msgpack_pack_nil(&pk); } else { @@ -131,9 +139,9 @@ static int handle_request(struct settings cfg, int write_fd, msgpack_object req) if (error) { if (cfg.debug) { - printf("Error '%s' in request: ", error); - msgpack_object_print(stdout, req); - printf("\n"); + fprintf(stderr, "error '%s' in request: ", error); + msgpack_object_print(stderr, req); + fprintf(stderr, "\n"); } msgpack_pack_string(&pk, error); @@ -144,6 +152,15 @@ static int handle_request(struct settings cfg, int write_fd, msgpack_object req) check_return(E_WRITE, write(write_fd, sbuf.data, sbuf.size)); + if (cfg.trace) { + fprintf(stderr, "result: "); + msgpack_unpacked res __attribute__((__cleanup__(msgpack_unpacked_destroy))); + msgpack_unpacked_init(&res); + msgpack_unpack_next(&res, sbuf.data, sbuf.size, NULL); + msgpack_object_print(stderr, res.data); + fprintf(stderr, "\n"); + } + return E_OK; } @@ -177,7 +194,7 @@ int communicate(struct settings cfg, int read_fd, int write_fd) break; case MSGPACK_UNPACK_EXTRA_BYTES: - printf("EXTRA_BYTES\n"); + fprintf(stderr, "EXTRA_BYTES\n"); break; case MSGPACK_UNPACK_CONTINUE: diff --git a/testing/hstox/driver.h b/testing/hstox/driver.h index 219df8a1..150d5cdd 100644 --- a/testing/hstox/driver.h +++ b/testing/hstox/driver.h @@ -7,6 +7,8 @@ struct settings { // Print the msgpack object on test failure. bool debug; + // Print all inputs and outputs to stderr. + bool trace; // Write test sample files into test-inputs/. These files, one per test // method, are used to seed the fuzzer. bool collect_samples; diff --git a/testing/hstox/fuzz_main.c b/testing/hstox/fuzz_main.c index ff66a166..6f223eb2 100644 --- a/testing/hstox/fuzz_main.c +++ b/testing/hstox/fuzz_main.c @@ -12,7 +12,7 @@ #endif int main(int argc, char **argv) { - struct settings cfg = {false, false}; + struct settings cfg = {false, false, false}; #ifdef __AFL_LOOP while (__AFL_LOOP(ITERATIONS)) diff --git a/testing/hstox/test_main.c b/testing/hstox/test_main.c index 7ac18da0..70f0b95c 100644 --- a/testing/hstox/test_main.c +++ b/testing/hstox/test_main.c @@ -57,7 +57,7 @@ static char const *error_desc(int code) #endif int main(void) { - struct settings cfg = {true, true}; + struct settings cfg = {true, false, true}; uint32_t result = network_main(cfg, PORT, TIMEOUT); int line = result >> 16; int error = (result >> 8) & 0xff; diff --git a/testing/hstox/util.h b/testing/hstox/util.h index c00578a2..c4095994 100644 --- a/testing/hstox/util.h +++ b/testing/hstox/util.h @@ -1,5 +1,7 @@ #pragma once +#include + #include #define check_return(err, expr) \