Variable Byte Integer reading tests.
This commit is contained in:
parent
99a1c0e43a
commit
b6b8da1fa6
18
.gitignore
vendored
18
.gitignore
vendored
@ -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__
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
27
test/unit/Makefile
Normal 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
259
test/unit/datatypes.c
Normal 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
27
test/unit/test.c
Normal 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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user