Extend test harnish to auto-hexdump on buffer differences
This commit is contained in:
parent
e072a11725
commit
b7a41b932c
2 changed files with 179 additions and 91 deletions
|
@ -26,133 +26,103 @@ TestResult test_vl_int_16384(void) {
|
|||
|
||||
TestResult test_vl_int_data_0(void) {
|
||||
char data[] = { 0 };
|
||||
Buffer *buffer = buffer_allocate(5);
|
||||
Buffer *buffer = buffer_allocate(sizeof(data));
|
||||
variable_length_int_encode(0, buffer);
|
||||
|
||||
TESTASSERT(
|
||||
(
|
||||
(buffer->position == 1)
|
||||
&&
|
||||
(memcmp(buffer->data, data, 1) == 0)
|
||||
),
|
||||
"Variable length int of 0 should result in [0x00]");
|
||||
return TESTMEMCMP(
|
||||
buffer_from_data_copy(data, sizeof(data)),
|
||||
buffer
|
||||
);
|
||||
}
|
||||
|
||||
TestResult test_vl_int_data_127(void) {
|
||||
char data[] = { 127 };
|
||||
Buffer *buffer = buffer_allocate(5);
|
||||
Buffer *buffer = buffer_allocate(sizeof(data));
|
||||
variable_length_int_encode(127, buffer);
|
||||
|
||||
TESTASSERT(
|
||||
(
|
||||
(buffer->position == 1)
|
||||
&&
|
||||
(memcmp(buffer->data, data, 1) == 0)
|
||||
),
|
||||
"Variable length int of 127 should result in [0x7f]");
|
||||
return TESTMEMCMP(
|
||||
buffer_from_data_copy(data, sizeof(data)),
|
||||
buffer
|
||||
);
|
||||
}
|
||||
|
||||
TestResult test_vl_int_data_128(void) {
|
||||
char data[] = { 0x80, 0x01 };
|
||||
Buffer *buffer = buffer_allocate(5);
|
||||
Buffer *buffer = buffer_allocate(sizeof(data));
|
||||
variable_length_int_encode(128, buffer);
|
||||
|
||||
TESTASSERT(
|
||||
(
|
||||
(buffer->position == 2)
|
||||
&&
|
||||
(memcmp(buffer->data, data, 2) == 0)
|
||||
),
|
||||
"Variable length int of 128 should result in [0x80, 0x01]");
|
||||
return TESTMEMCMP(
|
||||
buffer_from_data_copy(data, sizeof(data)),
|
||||
buffer
|
||||
);
|
||||
}
|
||||
|
||||
TestResult test_vl_int_data_16383(void) {
|
||||
char data[] = { 0xff, 0x7f };
|
||||
Buffer *buffer = buffer_allocate(5);
|
||||
Buffer *buffer = buffer_allocate(sizeof(data));
|
||||
variable_length_int_encode(16383, buffer);
|
||||
|
||||
TESTASSERT(
|
||||
(
|
||||
(buffer->position == 2)
|
||||
&&
|
||||
(memcmp(buffer->data, data, 2) == 0)
|
||||
),
|
||||
"Variable length int of 16383 should result in [0xff, 0x7f]");
|
||||
return TESTMEMCMP(
|
||||
buffer_from_data_copy(data, sizeof(data)),
|
||||
buffer
|
||||
);
|
||||
}
|
||||
|
||||
TestResult test_vl_int_data_16384(void) {
|
||||
char data[] = { 0x80, 0x80, 0x01 };
|
||||
Buffer *buffer = buffer_allocate(5);
|
||||
Buffer *buffer = buffer_allocate(sizeof(data));
|
||||
variable_length_int_encode(16384, buffer);
|
||||
|
||||
TESTASSERT(
|
||||
(
|
||||
(buffer->position == 3)
|
||||
&&
|
||||
(memcmp(buffer->data, data, 3) == 0)
|
||||
),
|
||||
"Variable length int of 16384 should result in [0x80, 0x80, 0x01]");
|
||||
return TESTMEMCMP(
|
||||
buffer_from_data_copy(data, sizeof(data)),
|
||||
buffer
|
||||
);
|
||||
}
|
||||
|
||||
TestResult test_vl_int_data_32767(void) {
|
||||
char data[] = { 0xff, 0xff, 0x01 };
|
||||
Buffer *buffer = buffer_allocate(5);
|
||||
Buffer *buffer = buffer_allocate(sizeof(data));
|
||||
variable_length_int_encode(32767, buffer);
|
||||
|
||||
TESTASSERT(
|
||||
(
|
||||
(buffer->position == 3)
|
||||
&&
|
||||
(memcmp(buffer->data, data, 3) == 0)
|
||||
),
|
||||
"Variable length int of 32767 should result in [0xff, 0xff, 0x01]");
|
||||
return TESTMEMCMP(
|
||||
buffer_from_data_copy(data, sizeof(data)),
|
||||
buffer
|
||||
);
|
||||
}
|
||||
|
||||
// UTF-8 String encoding
|
||||
|
||||
TestResult test_utf8_string_null(void) {
|
||||
char data[] = { 0x00, 0x00 };
|
||||
Buffer *buffer = buffer_allocate(5);
|
||||
Buffer *buffer = buffer_allocate(sizeof(data));
|
||||
size_t sz = utf8_string_encode(NULL, buffer);
|
||||
TESTASSERT(
|
||||
(
|
||||
(buffer->position == 2)
|
||||
&&
|
||||
(sz == 2)
|
||||
&&
|
||||
(memcmp(buffer->data, data, 2) == 0)
|
||||
),
|
||||
"NULL String should result in [0x00, 0x00]");
|
||||
|
||||
return TESTMEMCMP(
|
||||
buffer_from_data_copy(data, sizeof(data)),
|
||||
buffer
|
||||
);
|
||||
}
|
||||
|
||||
TestResult test_utf8_string_empty(void) {
|
||||
char data[] = { 0x00, 0x00 };
|
||||
Buffer *buffer = buffer_allocate(5);
|
||||
Buffer *buffer = buffer_allocate(sizeof(data));
|
||||
size_t sz = utf8_string_encode("", buffer);
|
||||
TESTASSERT(
|
||||
(
|
||||
(buffer->position == 2)
|
||||
&&
|
||||
(sz == 2)
|
||||
&&
|
||||
(memcmp(buffer->data, data, 2) == 0)
|
||||
),
|
||||
"Empty String should result in [0x00, 0x00]");
|
||||
|
||||
return TESTMEMCMP(
|
||||
buffer_from_data_copy(data, sizeof(data)),
|
||||
buffer
|
||||
);
|
||||
}
|
||||
|
||||
TestResult test_utf8_string_hello(void) {
|
||||
char data[] = { 0x00, 0x05, 'h', 'e', 'l', 'l', 'o' };
|
||||
Buffer *buffer = buffer_allocate(10);
|
||||
Buffer *buffer = buffer_allocate(sizeof(data));
|
||||
size_t sz = utf8_string_encode("hello", buffer);
|
||||
TESTASSERT(
|
||||
(
|
||||
(buffer->position == 7)
|
||||
&&
|
||||
(sz == 7)
|
||||
&&
|
||||
(memcmp(buffer->data, data, 7) == 0)
|
||||
),
|
||||
"\"hello\" String should result in [0x00, 0x05, 'h', 'e', 'l', 'l', 'o']");
|
||||
|
||||
return TESTMEMCMP(
|
||||
buffer_from_data_copy(data, sizeof(data)),
|
||||
buffer
|
||||
);
|
||||
}
|
||||
|
||||
// make header
|
||||
|
@ -160,17 +130,100 @@ TestResult test_make_header(void) {
|
|||
char data[] = { 0x10, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
Buffer *buffer = make_buffer_for_header(5, PacketTypeConnect);
|
||||
|
||||
TESTASSERT(
|
||||
(
|
||||
(buffer->len == 7)
|
||||
&&
|
||||
(memcmp(buffer->data, data, 7) == 0)
|
||||
&&
|
||||
(buffer->position == 2)
|
||||
),
|
||||
"Header should be valid");
|
||||
return TESTMEMCMP(
|
||||
buffer_from_data_copy(data, sizeof(data)),
|
||||
buffer
|
||||
);
|
||||
}
|
||||
|
||||
TestResult test_encode_connect_simple(void) {
|
||||
char data[] = {
|
||||
0x10, 0x10, // header
|
||||
0x00, 0x04, 'M', 'Q', 'T', 'T', 0x04, 0x02, 0x00, 0x0a, // var header
|
||||
0x00, 0x04, 't', 'e', 's', 't' // client id
|
||||
};
|
||||
ConnectPayload *payload = calloc(1, sizeof(ConnectPayload));
|
||||
|
||||
payload->client_id = "test";
|
||||
payload->protocol_level = 4;
|
||||
payload->keepalive_interval = 10;
|
||||
payload->clean_session = 1;
|
||||
|
||||
Buffer *encoded = encode_connect(payload);
|
||||
free(payload);
|
||||
|
||||
return TESTMEMCMP(
|
||||
buffer_from_data_copy(data, sizeof(data)),
|
||||
encoded
|
||||
);
|
||||
}
|
||||
|
||||
TestResult test_encode_connect_will(void) {
|
||||
char data[] = {
|
||||
0x10, 0x2d, // header
|
||||
0x00, 0x04, 'M', 'Q', 'T', 'T', 0x04, 0x2e, 0x00, 0x0a, // var header
|
||||
0x00, 0x04, 't', 'e', 's', 't', // client id
|
||||
0x00, 0x0d, 't', 'e', 's', 't', '/', 'l', 'a', 's', 't', 'w', 'i', 'l', 'l',
|
||||
0x00, 0x0c, 'd', 'i', 's', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'e', 'd',
|
||||
|
||||
};
|
||||
ConnectPayload *payload = calloc(1, sizeof(ConnectPayload));
|
||||
|
||||
payload->client_id = "test";
|
||||
payload->protocol_level = 4;
|
||||
payload->keepalive_interval = 10;
|
||||
payload->clean_session = 1;
|
||||
|
||||
payload->will_topic = "test/lastwill";
|
||||
payload->will_message = "disconnected";
|
||||
payload->will_qos = MQTT_QOS_1;
|
||||
payload->retain_will = true;
|
||||
|
||||
Buffer *encoded = encode_connect(payload);
|
||||
free(payload);
|
||||
|
||||
return TESTMEMCMP(
|
||||
buffer_from_data_copy(data, sizeof(data)),
|
||||
encoded
|
||||
);
|
||||
}
|
||||
|
||||
TestResult test_encode_connect_auth(void) {
|
||||
char data[] = {
|
||||
0x10, 0x39, // header
|
||||
0x00, 0x04, 'M', 'Q', 'T', 'T', 0x04, 0xee, 0x00, 0x0a, // var header
|
||||
0x00, 0x04, 't', 'e', 's', 't', // client id
|
||||
0x00, 0x0d, 't', 'e', 's', 't', '/', 'l', 'a', 's', 't', 'w', 'i', 'l', 'l',
|
||||
0x00, 0x0c, 'd', 'i', 's', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'e', 'd',
|
||||
0x00, 0x04, 'a', 'n', 'o', 'n', // username
|
||||
0x00, 0x04, 't', 'e', 's', 't' // password
|
||||
};
|
||||
ConnectPayload *payload = calloc(1, sizeof(ConnectPayload));
|
||||
|
||||
payload->client_id = "test";
|
||||
payload->protocol_level = 4;
|
||||
payload->keepalive_interval = 10;
|
||||
payload->clean_session = 1;
|
||||
|
||||
payload->will_topic = "test/lastwill";
|
||||
payload->will_message = "disconnected";
|
||||
payload->will_qos = MQTT_QOS_1;
|
||||
payload->retain_will = true;
|
||||
|
||||
payload->username = "anon";
|
||||
payload->password = "test";
|
||||
|
||||
Buffer *encoded = encode_connect(payload);
|
||||
free(payload);
|
||||
|
||||
return TESTMEMCMP(
|
||||
buffer_from_data_copy(data, sizeof(data)),
|
||||
encoded
|
||||
);
|
||||
}
|
||||
|
||||
// not implemented placeholder
|
||||
|
||||
TestResult not_implemented(void) {
|
||||
TESTRESULT(TestStatusSkipped, "Not implemented");
|
||||
}
|
||||
|
@ -192,7 +245,9 @@ TESTS(
|
|||
TEST("UTF-8 string encode empty string", test_utf8_string_empty),
|
||||
TEST("UTF-8 string encode \"hello\"", test_utf8_string_hello),
|
||||
TEST("Make header", test_make_header),
|
||||
TEST("Encode Connect", not_implemented),
|
||||
TEST("Encode Connect simple", test_encode_connect_simple),
|
||||
TEST("Encode Connect with will", test_encode_connect_will),
|
||||
TEST("Encode Connect with auth", test_encode_connect_auth),
|
||||
TEST("Encode ConnAck", not_implemented),
|
||||
TEST("Encode Publish", not_implemented),
|
||||
TEST("Encode PubAck", not_implemented),
|
||||
|
|
39
tests/test.h
39
tests/test.h
|
@ -7,16 +7,20 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "cputime.h"
|
||||
#include "buffer.h"
|
||||
|
||||
typedef enum {
|
||||
TestStatusSkipped = 0,
|
||||
TestStatusFailure,
|
||||
TestStatusOk,
|
||||
TestStatusFailureHexdump
|
||||
} TestStatus;
|
||||
|
||||
typedef struct {
|
||||
TestStatus status;
|
||||
char *message;
|
||||
Buffer *buffer;
|
||||
Buffer *template;
|
||||
} TestResult;
|
||||
|
||||
typedef TestResult (*TestPointer)(void);
|
||||
|
@ -38,7 +42,8 @@ extern DefinedTest defined_tests[];
|
|||
TEST(NULL, NULL) \
|
||||
}
|
||||
|
||||
#define TESTRESULT(_status, _message) return (TestResult){ _status, _message }
|
||||
#define TESTRESULT(_status, _message) return (TestResult){ _status, _message, NULL, NULL }
|
||||
#define TESTRESULT_BUFFER(_status, _message, _buffer, _template) return (TestResult){ _status, _message, _buffer, _template }
|
||||
|
||||
#ifdef TIMETRIAL
|
||||
# define TESTASSERT(_assertion, _message) return (TestResult){ (_assertion) ? TestStatusOk : TestStatusFailure, NULL }
|
||||
|
@ -46,9 +51,22 @@ extern DefinedTest defined_tests[];
|
|||
# define TESTASSERT(_assertion, _message) return (TestResult){ (_assertion) ? TestStatusOk : TestStatusFailure, _message }
|
||||
#endif
|
||||
|
||||
static inline TestResult TESTMEMCMP(Buffer *template, Buffer *check) {
|
||||
if (template->len != check->len) {
|
||||
TESTRESULT_BUFFER(TestStatusFailureHexdump, "Buffer size differs from template", check, template);
|
||||
}
|
||||
if (memcmp(template->data, check->data, template->len) == 0) {
|
||||
TESTRESULT(TestStatusOk, "Buffer matches template");
|
||||
} else {
|
||||
TESTRESULT_BUFFER(TestStatusFailureHexdump, "Buffer and template differ", check, template);
|
||||
}
|
||||
}
|
||||
|
||||
void timetrial(DefinedTest *test);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
bool failure_seen = false;
|
||||
|
||||
for(DefinedTest *test = defined_tests; test->run != NULL; test++) {
|
||||
TestResult result = test->run();
|
||||
switch (result.status) {
|
||||
|
@ -67,16 +85,31 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
break;
|
||||
case TestStatusFailure:
|
||||
failure_seen = true;
|
||||
fprintf(stderr, "%s:%d: error: Test %s failed\n", test->file, test->line, test->name);
|
||||
if (result.message) {
|
||||
fprintf(stderr, " -> %s\n", result.message);
|
||||
}
|
||||
return 1;
|
||||
break;
|
||||
case TestStatusFailureHexdump:
|
||||
failure_seen = true;
|
||||
fprintf(stderr, "%s:%d: error: Test %s failed\n", test->file, test->line, test->name);
|
||||
if (result.message) {
|
||||
fprintf(stderr, " -> %s\n", result.message);
|
||||
}
|
||||
if (result.template) {
|
||||
fprintf(stderr, " -> Template (%d bytes)\n", result.template->len);
|
||||
buffer_hexdump(result.template, 5);
|
||||
}
|
||||
if (result.buffer) {
|
||||
fprintf(stderr, " -> Buffer (%d bytes)\n", result.buffer->len);
|
||||
buffer_hexdump(result.buffer, 5);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return failure_seen;
|
||||
}
|
||||
|
||||
#ifdef TIMETRIAL
|
||||
|
|
Loading…
Reference in a new issue