Variable Byte Integer reading tests.

This commit is contained in:
Roger A. Light 2018-10-03 11:29:57 +01:00
parent 99a1c0e43a
commit b6b8da1fa6
7 changed files with 342 additions and 14 deletions

18
.gitignore vendored
View File

@ -1,11 +1,15 @@
*.o
*.so
*.exe
*.db
*.gcda
*.gcno
*.exe
*.o
*.old
*.pyc
*.so
*.vglog
c/*.test
cpp/*.test
*.pyc
*.vglog
build/
@ -50,5 +54,9 @@ test/ssl/*.csr
test/lib/c/*.test
test/lib/cpp/*.test
test/unit/coverage.info
test/unit/mosq_test
test/unit/out
www/cache/
__pycache__

View File

@ -174,24 +174,30 @@ void packet__write_uint32(struct mosquitto__packet *packet, uint32_t word)
}
int packet__read_varint(struct mosquitto__packet *packet, int32_t *word, uint8_t *bytes)
int packet__read_varint(struct mosquitto__packet *packet, int32_t *word, int8_t *bytes)
{
int i;
int remaining_mult = 1;
uint8_t byte;
*word = 0;
if(bytes) (*bytes) = 0;
int remaining_mult = 1;
int32_t lword = 0;
uint8_t lbytes = 0;
for(i=0; i<4; i++){
if(packet->pos < packet->remaining_length){
if(bytes) (*bytes)++;
lbytes++;
byte = packet->payload[packet->pos];
*word += (byte & 127) * remaining_mult;
lword += (byte & 127) * remaining_mult;
remaining_mult *= 128;
packet->pos++;
if((byte & 128) == 0){
return MOSQ_ERR_SUCCESS;
if(lbytes > 1 && byte == 0){
/* Catch overlong encodings */
return MOSQ_ERR_PROTOCOL;
}else{
*word = lword;
if(bytes) (*bytes) = lbytes;
return MOSQ_ERR_SUCCESS;
}
}
}else{
return MOSQ_ERR_PROTOCOL;

View File

@ -32,7 +32,7 @@ int packet__read_bytes(struct mosquitto__packet *packet, void *bytes, uint32_t c
int packet__read_string(struct mosquitto__packet *packet, char **str, int *length);
int packet__read_uint16(struct mosquitto__packet *packet, uint16_t *word);
int packet__read_uint32(struct mosquitto__packet *packet, uint32_t *word);
int packet__read_varint(struct mosquitto__packet *packet, int32_t *word, uint8_t *bytes);
int packet__read_varint(struct mosquitto__packet *packet, int32_t *word, int8_t *bytes);
void packet__write_byte(struct mosquitto__packet *packet, uint8_t byte);
void packet__write_bytes(struct mosquitto__packet *packet, const void *bytes, uint32_t count);

View File

@ -14,6 +14,7 @@ all : fake_user msgsps_pub msgsps_sub
test :
$(MAKE) -C broker test
$(MAKE) -C lib test
$(MAKE) -C unit test
ptest :
$(MAKE) -C broker ptest

27
test/unit/Makefile Normal file
View File

@ -0,0 +1,27 @@
include ../../config.mk
.PHONY: all test clean coverage
CFLAGS=-I../.. -I../../lib -coverage
TEST_LDFLAGS=-lcunit -coverage
all : test
packet_datatypes.o : ../../lib/packet_datatypes.c
$(CROSS_COMPILE)$(CC) $(CFLAGS) -c -o $@ $^
memory_mosq.o : ../../lib/memory_mosq.c
$(CROSS_COMPILE)$(CC) $(CFLAGS) -c -o $@ $^
mosq_test : test.o datatypes.o memory_mosq.o packet_datatypes.o
$(CROSS_COMPILE)$(CC) -o $@ $^ ${TEST_LDFLAGS}
test : mosq_test
./mosq_test
clean :
-rm -f test *.o
coverage :
lcov --capture --directory . --output-file coverage.info
genhtml coverage.info --output-directory out

259
test/unit/datatypes.c Normal file
View File

@ -0,0 +1,259 @@
#include <CUnit/CUnit.h>
#include <CUnit/Basic.h>
#include "packet_mosq.h"
static void varint_read_helper(
uint8_t *payload,
int remaining_length,
int rc_expected,
int32_t value_expected,
int8_t bytes_expected)
{
struct mosquitto__packet packet;
int32_t value = -1;
int8_t bytes = -1;
int rc;
memset(&packet, 0, sizeof(struct mosquitto__packet));
packet.payload = payload;
packet.remaining_length = remaining_length;
rc = packet__read_varint(&packet, &value, &bytes);
CU_ASSERT_EQUAL(rc, rc_expected);
CU_ASSERT_EQUAL(value, value_expected);
CU_ASSERT_EQUAL(bytes, bytes_expected);
}
/* This tests reading a Variable Byte Integer from an incoming packet.
*
* It tests:
* * Empty packet
*/
static void TEST_varint_read_empty(void)
{
struct mosquitto__packet packet;
int rc;
/* Empty packet */
varint_read_helper(NULL, 0, MOSQ_ERR_PROTOCOL, -1, -1);
}
/* This tests reading a Variable Byte Integer from an incoming packet.
*
* It tests:
* * Truncated packets (varint encoding is longer than data)
*/
static void TEST_varint_read_truncated(void)
{
struct mosquitto__packet packet;
uint8_t payload[20];
int rc;
/* Varint bigger than packet */
memset(payload, 0, sizeof(payload));
payload[0] = 0x80;
varint_read_helper(payload, 1, MOSQ_ERR_PROTOCOL, -1, -1);
/* Varint bigger than packet */
memset(payload, 1, sizeof(payload));
payload[0] = 0x80;
payload[1] = 0x80;
varint_read_helper(payload, 2, MOSQ_ERR_PROTOCOL, -1, -1);
/* Varint bigger than packet */
memset(payload, 0, sizeof(payload));
payload[0] = 0x80;
payload[1] = 0x80;
payload[2] = 0x80;
varint_read_helper(payload, 3, MOSQ_ERR_PROTOCOL, -1, -1);
/* Varint bigger than packet */
memset(payload, 0, sizeof(payload));
payload[0] = 0x80;
payload[1] = 0x80;
payload[2] = 0x80;
payload[3] = 0x80;
varint_read_helper(payload, 4, MOSQ_ERR_PROTOCOL, -1, -1);
}
/* This tests reading a Variable Byte Integer from an incoming packet.
*
* It tests:
* * Correct values on boundaries of 1, 2, 3, 4 byte encodings
*/
static void TEST_varint_read_boundaries(void)
{
struct mosquitto__packet packet;
uint8_t payload[20];
int rc;
/* Value = 0 */
memset(payload, 0, sizeof(payload));
payload[0] = 0x00;
varint_read_helper(payload, 1, MOSQ_ERR_SUCCESS, 0, 1);
/* Value = 127 (just beneath the crossover to two bytes */
memset(payload, 0, sizeof(payload));
payload[0] = 0x7F;
varint_read_helper(payload, 1, MOSQ_ERR_SUCCESS, 127, 1);
/* Value = 128 (just after the crossover to two bytes */
memset(payload, 0, sizeof(payload));
packet.payload = payload;
payload[0] = 0x80;
payload[1] = 0x01;
varint_read_helper(payload, 2, MOSQ_ERR_SUCCESS, 128, 2);
/* Value = 16383 (just before the crossover to three bytes */
memset(payload, 0, sizeof(payload));
packet.payload = payload;
payload[0] = 0xFF;
payload[1] = 0x7F;
varint_read_helper(payload, 2, MOSQ_ERR_SUCCESS, 16383, 2);
/* Value = 16384 (just after the crossover to three bytes */
memset(payload, 0, sizeof(payload));
packet.payload = payload;
payload[0] = 0x80;
payload[1] = 0x80;
payload[2] = 0x01;
varint_read_helper(payload, 3, MOSQ_ERR_SUCCESS, 16384, 3);
/* Value = 2,097,151 (just before the crossover to four bytes */
memset(payload, 0, sizeof(payload));
packet.payload = payload;
payload[0] = 0xFF;
payload[1] = 0xFF;
payload[2] = 0x7F;
varint_read_helper(payload, 3, MOSQ_ERR_SUCCESS, 2097151, 3);
/* Value = 2,097,152 (just after the crossover to four bytes */
memset(payload, 0, sizeof(payload));
packet.payload = payload;
payload[0] = 0x80;
payload[1] = 0x80;
payload[2] = 0x80;
payload[3] = 0x01;
varint_read_helper(payload, 4, MOSQ_ERR_SUCCESS, 2097152, 4);
/* Value = 268,435,455 (highest value allowed) */
memset(payload, 0, sizeof(payload));
packet.payload = payload;
payload[0] = 0xFF;
payload[1] = 0xFF;
payload[2] = 0xFF;
payload[3] = 0x7F;
varint_read_helper(payload, 4, MOSQ_ERR_SUCCESS, 268435455, 4);
}
/* This tests reading a Variable Byte Integer from an incoming packet.
*
* It tests:
* * Too long encoding (5 bytes)
*/
static void TEST_varint_read_5_bytes(void)
{
struct mosquitto__packet packet;
uint8_t payload[20];
int rc;
/* Value = 268,435,456 (one higher than highest value allowed) */
memset(payload, 0, sizeof(payload));
packet.payload = payload;
payload[0] = 0x80;
payload[1] = 0x80;
payload[2] = 0x80;
payload[3] = 0x80;
payload[4] = 0x01;
varint_read_helper(payload, 5, MOSQ_ERR_PROTOCOL, -1, -1);
}
/* This tests reading a Variable Byte Integer from an incoming packet.
*
* It tests:
* * Overlong encodings (e.g. 2 bytes to encode "1")
*/
static void TEST_varint_read_overlong_encoding(void)
{
struct mosquitto__packet packet;
uint8_t payload[20];
int rc;
/* Overlong encoding of 0 (1 byte value encoded as 2 bytes) */
memset(payload, 0, sizeof(payload));
packet.payload = payload;
payload[0] = 0x80;
payload[1] = 0x00;
varint_read_helper(payload, 2, MOSQ_ERR_PROTOCOL, -1, -1);
/* Overlong encoding of 127 (1 byte value encoded as 2 bytes) */
memset(payload, 0, sizeof(payload));
packet.payload = payload;
payload[0] = 0xFF;
payload[1] = 0x00;
varint_read_helper(payload, 2, MOSQ_ERR_PROTOCOL, -1, -1);
/* Overlong encoding of 128 (2 byte value encoded as 3 bytes) */
memset(payload, 0, sizeof(payload));
packet.payload = payload;
payload[0] = 0x80;
payload[1] = 0x81;
payload[2] = 0x00;
varint_read_helper(payload, 3, MOSQ_ERR_PROTOCOL, -1, -1);
/* Overlong encoding of 16,383 (2 byte value encoded as 3 bytes) */
memset(payload, 0, sizeof(payload));
packet.payload = payload;
payload[0] = 0xFF;
payload[1] = 0xFF;
payload[2] = 0x00;
varint_read_helper(payload, 3, MOSQ_ERR_PROTOCOL, -1, -1);
/* Overlong encoding of 16,384 (3 byte value encoded as 4 bytes) */
memset(payload, 0, sizeof(payload));
packet.payload = payload;
payload[0] = 0x80;
payload[1] = 0x80;
payload[2] = 0x81;
payload[3] = 0x00;
varint_read_helper(payload, 4, MOSQ_ERR_PROTOCOL, -1, -1);
/* Overlong encoding of 2,097,151 (3 byte value encoded as 4 bytes) */
memset(payload, 0, sizeof(payload));
packet.payload = payload;
payload[0] = 0xFF;
payload[1] = 0xFF;
payload[2] = 0xFF;
payload[3] = 0x00;
varint_read_helper(payload, 4, MOSQ_ERR_PROTOCOL, -1, -1);
}
int init_datatype_tests(void)
{
CU_pSuite test_suite = NULL;
test_suite = CU_add_suite("datatypes", NULL, NULL);
if(!test_suite){
printf("Error adding CUnit test suite.\n");
return 1;
}
if(0
|| !CU_add_test(test_suite, "Variable Byte Integer read (empty packet)", TEST_varint_read_empty)
|| !CU_add_test(test_suite, "Variable Byte Integer read (truncated packets)", TEST_varint_read_truncated)
|| !CU_add_test(test_suite, "Variable Byte Integer read (encoding boundaries)", TEST_varint_read_boundaries)
|| !CU_add_test(test_suite, "Variable Byte Integer read (five byte encoding)", TEST_varint_read_5_bytes)
|| !CU_add_test(test_suite, "Variable Byte Integer read (overlong encodings)", TEST_varint_read_overlong_encoding)
){
printf("Error adding datatypes CUnit tests.\n");
return 1;
}
return 0;
}

27
test/unit/test.c Normal file
View File

@ -0,0 +1,27 @@
#include <stdio.h>
#include <CUnit/CUnit.h>
#include <CUnit/Basic.h>
int init_datatype_tests(void);
int main(int argc, char *argv[])
{
if(CU_initialize_registry() != CUE_SUCCESS){
printf("Error initializing CUnit registry.\n");
return 1;
}
if(init_datatype_tests()){
CU_cleanup_registry();
return 1;
}
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
CU_cleanup_registry();
return 0;
}