Apostolos Fanakis
6 years ago
3 changed files with 361 additions and 0 deletions
@ -0,0 +1,126 @@ |
|||||
|
#include <stdlib.h> |
||||
|
#include <assert.h> |
||||
|
#include <stdio.h> |
||||
|
#include <string.h> |
||||
|
|
||||
|
#include "node.h" |
||||
|
|
||||
|
//enum node_status { NODE_INITIALIAZED, NODE_PRESENT, NODE_GONE };
|
||||
|
|
||||
|
// Defines the node structure
|
||||
|
struct node_t { |
||||
|
struct sockaddr_in addr; |
||||
|
uint64_t** events; |
||||
|
uint64_t appearance_duration; |
||||
|
uint8_t events_size; |
||||
|
node_status _node_status; |
||||
|
}; |
||||
|
|
||||
|
node_handle_t node_init(struct sockaddr_in addr) { |
||||
|
//assert(addr);
|
||||
|
|
||||
|
node_handle_t node = malloc(sizeof(node_t)); |
||||
|
assert(node); |
||||
|
|
||||
|
node->addr = addr; |
||||
|
node->events_size = 0; |
||||
|
node->events = (uint64_t **) malloc(2 * sizeof(uint64_t)); |
||||
|
node->events[0] = (uint64_t *) malloc(sizeof(uint64_t)); |
||||
|
node->events[1] = (uint64_t *) malloc(sizeof(uint64_t)); |
||||
|
node->events[0][0] = 0; |
||||
|
node->events[1][0] = 0; |
||||
|
node->appearance_duration = 0; |
||||
|
node->_node_status = NODE_INITIALIAZED; |
||||
|
|
||||
|
return node; |
||||
|
} |
||||
|
|
||||
|
void node_free(node_handle_t node) { |
||||
|
assert(node); |
||||
|
|
||||
|
free(node->events[0]); |
||||
|
free(node->events[1]); |
||||
|
free(node->events); |
||||
|
free(node); |
||||
|
} |
||||
|
|
||||
|
void node_add_timestamp(node_handle_t node, time_t timestamp, bool visible) { |
||||
|
assert(node && timestamp); |
||||
|
|
||||
|
if ((visible && !node->events[1][node->events_size - 1]) || |
||||
|
(!visible && node->events[1][node->events_size - 1])) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (visible) { |
||||
|
int* realloc_r = realloc(node->events[0], node->events_size + 1); |
||||
|
if (!realloc_r) { |
||||
|
node_free(node); |
||||
|
perror("Error trying to reallocate memory for event timestamps!"); |
||||
|
exit(EXIT_FAILURE); |
||||
|
} |
||||
|
realloc_r = realloc(node->events[1], node->events_size + 1); |
||||
|
if (!realloc_r) { |
||||
|
node_free(node); |
||||
|
perror("Error trying to reallocate memory for event timestamps!"); |
||||
|
exit(EXIT_FAILURE); |
||||
|
} |
||||
|
|
||||
|
node->events[0][node->events_size] = timestamp; |
||||
|
node->events[1][node->events_size] = 0; |
||||
|
node->_node_status = NODE_PRESENT; |
||||
|
++node->events_size; |
||||
|
} else { |
||||
|
node->events[1][node->events_size - 1] = timestamp; |
||||
|
node->_node_status = NODE_GONE; |
||||
|
node->appearance_duration += node->events[1][node->events_size - 1] - |
||||
|
node->events[0][node->events_size - 1]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
struct sockaddr_in node_get_addr(node_handle_t node) { |
||||
|
assert(node); |
||||
|
|
||||
|
return node->addr; |
||||
|
} |
||||
|
|
||||
|
enum node_status node_get_status(node_handle_t node) { |
||||
|
assert(node); |
||||
|
|
||||
|
return node->_node_status; |
||||
|
} |
||||
|
|
||||
|
uint8_t node_get_latest_appearance_duration(node_handle_t node) { |
||||
|
assert(node); |
||||
|
|
||||
|
if (node->_node_status == NODE_INITIALIAZED) { |
||||
|
return 0; |
||||
|
} else if (node->events[1][node->events_size - 1] == 0) { |
||||
|
return (uint64_t)time(NULL) - node->events[0][node->events_size - 1]; |
||||
|
} else { |
||||
|
return node->events[1][node->events_size - 1] - node->events[0][node->events_size - 1]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
uint8_t node_get_total_appearance_duration(node_handle_t node) { |
||||
|
assert(node); |
||||
|
|
||||
|
return node->appearance_duration; |
||||
|
} |
||||
|
|
||||
|
uint8_t node_get_event_table(node_handle_t node, time_t*** event_table) { |
||||
|
assert(node && event_table); |
||||
|
|
||||
|
if (node->events_size < 1) { |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
(*event_table) = (time_t **) malloc(2 * sizeof(time_t *)); |
||||
|
(*event_table)[0] = (time_t *) malloc(node->events_size * sizeof(time_t)); |
||||
|
(*event_table)[1] = (time_t *) malloc(node->events_size * sizeof(time_t)); |
||||
|
|
||||
|
memcpy((*event_table)[0], node->events[0], node->events_size * sizeof(time_t)); |
||||
|
memcpy((*event_table)[1], node->events[1], node->events_size * sizeof(time_t)); |
||||
|
|
||||
|
return node->events_size; |
||||
|
} |
@ -0,0 +1,59 @@ |
|||||
|
#ifndef NODE_H_ |
||||
|
#define NODE_H_ |
||||
|
|
||||
|
#include <stdbool.h> |
||||
|
#include <time.h> |
||||
|
#include <arpa/inet.h> |
||||
|
|
||||
|
// Node structure
|
||||
|
typedef struct node_t node_t; |
||||
|
// and handle type
|
||||
|
typedef node_t* node_handle_t; |
||||
|
|
||||
|
typedef enum node_status { NODE_INITIALIAZED, NODE_PRESENT, NODE_GONE } node_status; |
||||
|
|
||||
|
#ifdef TEST //This is a test build
|
||||
|
// Makes private functions reachable by the tester
|
||||
|
#define unit_static |
||||
|
#else |
||||
|
#define unit_static static |
||||
|
#endif |
||||
|
|
||||
|
// Initializes a node structure and returns the node handle.
|
||||
|
node_handle_t node_init(struct sockaddr_in addr); |
||||
|
|
||||
|
// Frees a node structure.
|
||||
|
void node_free(node_handle_t node); |
||||
|
|
||||
|
// Adds an event timestamp to the node. Either the (re)appearance or the disappearance of the node.
|
||||
|
void node_add_timestamp(node_handle_t node, time_t timestamp, bool visible); |
||||
|
|
||||
|
// Returns the address of the node
|
||||
|
struct sockaddr_in node_get_addr(node_handle_t node); |
||||
|
|
||||
|
node_status node_get_status(node_handle_t node); |
||||
|
|
||||
|
//uint8_t node_get_appear_count(node_handle_t node);
|
||||
|
|
||||
|
//uint8_t node_get_disappear_count(node_handle_t node);
|
||||
|
|
||||
|
//void node_get_latest_appear(node_handle_t node, );
|
||||
|
|
||||
|
//void node_get_latest_disappear(node_handle_t node, );
|
||||
|
|
||||
|
// Returns the duration (in seconds) of the latest stretch of time that this node has been visible.
|
||||
|
uint8_t node_get_latest_appearance_duration(node_handle_t node); |
||||
|
|
||||
|
// Returns the total duration (in seconds) of time that this node was visible.
|
||||
|
uint8_t node_get_total_appearance_duration(node_handle_t node); |
||||
|
|
||||
|
// Returns the event timestamps table for this node.
|
||||
|
uint8_t node_get_event_table(node_handle_t node, time_t*** event_table); |
||||
|
|
||||
|
// Serializes the whole node to a single string
|
||||
|
//int circ_buf_serialize(node_handle_t node, char** serialized);
|
||||
|
|
||||
|
// De-serializes a string to a node
|
||||
|
//int circ_buf_deserialize(node_handle_t node, const char* serialized);
|
||||
|
|
||||
|
#endif //NODE_H_
|
@ -0,0 +1,176 @@ |
|||||
|
#include <stdlib.h> |
||||
|
#include "unity.h" |
||||
|
|
||||
|
#include "node.h" |
||||
|
|
||||
|
struct node_t { |
||||
|
struct sockaddr_in addr; |
||||
|
uint64_t** events; |
||||
|
uint64_t appearance_duration; |
||||
|
uint8_t events_size; |
||||
|
node_status _node_status; |
||||
|
}; |
||||
|
|
||||
|
void test_node_init(void) { |
||||
|
struct sockaddr_in myaddr; |
||||
|
|
||||
|
myaddr.sin_family = AF_INET; |
||||
|
myaddr.sin_port = htons(2288); |
||||
|
myaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
||||
|
|
||||
|
node_handle_t node = node_init(myaddr); |
||||
|
TEST_ASSERT_NOT_NULL(node); |
||||
|
|
||||
|
node_free(node); |
||||
|
} |
||||
|
|
||||
|
void test_node_add_timestamp(void) { |
||||
|
struct sockaddr_in myaddr; |
||||
|
|
||||
|
myaddr.sin_family = AF_INET; |
||||
|
myaddr.sin_port = htons(2288); |
||||
|
myaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
||||
|
|
||||
|
node_handle_t node = node_init(myaddr); |
||||
|
|
||||
|
time_t base_time = time(NULL); |
||||
|
|
||||
|
node_add_timestamp(node, base_time - 15, true); |
||||
|
TEST_ASSERT_EQUAL_MEMORY(base_time - 15, node->events[0][0], sizeof(time_t)); |
||||
|
TEST_ASSERT_EQUAL_MEMORY(0, node->events[1][0], sizeof(time_t)); |
||||
|
|
||||
|
node_add_timestamp(node, base_time - 10, false); |
||||
|
TEST_ASSERT_EQUAL_MEMORY(base_time - 10, node->events[1][0], sizeof(time_t)); |
||||
|
|
||||
|
node_add_timestamp(node, base_time - 5, true); |
||||
|
TEST_ASSERT_EQUAL_MEMORY(base_time - 5, node->events[0][1], sizeof(time_t)); |
||||
|
TEST_ASSERT_EQUAL_MEMORY(0, node->events[1][1], sizeof(time_t)); |
||||
|
|
||||
|
node_add_timestamp(node, base_time, false); |
||||
|
TEST_ASSERT_EQUAL_MEMORY(base_time, node->events[1][1], sizeof(time_t)); |
||||
|
|
||||
|
node_add_timestamp(node, base_time + 5, false); |
||||
|
TEST_ASSERT_EQUAL_MEMORY(base_time, node->events[1][1], sizeof(time_t)); |
||||
|
|
||||
|
node_add_timestamp(node, base_time + 10, true); |
||||
|
TEST_ASSERT_EQUAL_MEMORY(base_time + 10, node->events[0][2], sizeof(time_t)); |
||||
|
TEST_ASSERT_EQUAL_MEMORY(0, node->events[1][2], sizeof(time_t)); |
||||
|
|
||||
|
node_free(node); |
||||
|
} |
||||
|
|
||||
|
void test_node_get_addr(void){ |
||||
|
struct sockaddr_in myaddr; |
||||
|
|
||||
|
myaddr.sin_family = AF_INET; |
||||
|
myaddr.sin_port = htons(2288); |
||||
|
myaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
||||
|
|
||||
|
node_handle_t node = node_init(myaddr); |
||||
|
|
||||
|
struct sockaddr_in actual = node_get_addr(node); |
||||
|
TEST_ASSERT_EQUAL_MEMORY(&myaddr, &actual, sizeof(myaddr)); |
||||
|
|
||||
|
node_free(node); |
||||
|
} |
||||
|
|
||||
|
void test_node_get_status(void){ |
||||
|
struct sockaddr_in myaddr; |
||||
|
|
||||
|
myaddr.sin_family = AF_INET; |
||||
|
myaddr.sin_port = htons(2288); |
||||
|
myaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
||||
|
|
||||
|
node_handle_t node = node_init(myaddr); |
||||
|
|
||||
|
TEST_ASSERT_EQUAL_INT(NODE_INITIALIAZED, node_get_status(node)); |
||||
|
|
||||
|
node_add_timestamp(node, time(NULL), true); |
||||
|
TEST_ASSERT_EQUAL_INT(NODE_PRESENT, node_get_status(node)); |
||||
|
|
||||
|
node_add_timestamp(node, time(NULL), false); |
||||
|
TEST_ASSERT_EQUAL_INT(NODE_GONE, node_get_status(node)); |
||||
|
|
||||
|
node_free(node); |
||||
|
} |
||||
|
|
||||
|
void test_node_get_latest_appearance_duration(void){ |
||||
|
struct sockaddr_in myaddr; |
||||
|
|
||||
|
myaddr.sin_family = AF_INET; |
||||
|
myaddr.sin_port = htons(2288); |
||||
|
myaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
||||
|
|
||||
|
node_handle_t node = node_init(myaddr); |
||||
|
|
||||
|
time_t base_time = time(NULL); |
||||
|
node_add_timestamp(node, base_time - 10, true); |
||||
|
TEST_ASSERT_UINT8_WITHIN(1, 10, node_get_latest_appearance_duration(node)); |
||||
|
|
||||
|
node_add_timestamp(node, base_time + 10, false); |
||||
|
TEST_ASSERT_EQUAL_UINT8(20, node_get_latest_appearance_duration(node)); |
||||
|
|
||||
|
node_free(node); |
||||
|
} |
||||
|
|
||||
|
void test_node_get_total_appearance_duration(void){ |
||||
|
struct sockaddr_in myaddr; |
||||
|
|
||||
|
myaddr.sin_family = AF_INET; |
||||
|
myaddr.sin_port = htons(2288); |
||||
|
myaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
||||
|
|
||||
|
node_handle_t node = node_init(myaddr); |
||||
|
|
||||
|
time_t base_time = time(NULL); |
||||
|
|
||||
|
node_add_timestamp(node, base_time - 30, true); |
||||
|
node_add_timestamp(node, base_time - 25, false); |
||||
|
TEST_ASSERT_EQUAL_UINT8(5, node_get_total_appearance_duration(node)); |
||||
|
|
||||
|
node_add_timestamp(node, base_time - 12, true); |
||||
|
node_add_timestamp(node, base_time - 5, false); |
||||
|
TEST_ASSERT_EQUAL_UINT8(12, node_get_total_appearance_duration(node)); |
||||
|
|
||||
|
node_free(node); |
||||
|
} |
||||
|
|
||||
|
void test_node_get_event_table(void){ |
||||
|
struct sockaddr_in myaddr; |
||||
|
|
||||
|
myaddr.sin_family = AF_INET; |
||||
|
myaddr.sin_port = htons(2288); |
||||
|
myaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
||||
|
|
||||
|
node_handle_t node = node_init(myaddr); |
||||
|
|
||||
|
time_t base_time = time(NULL); |
||||
|
|
||||
|
node_add_timestamp(node, base_time - 15, true); |
||||
|
node_add_timestamp(node, base_time - 10, false); |
||||
|
node_add_timestamp(node, base_time - 5, true); |
||||
|
node_add_timestamp(node, base_time, false); |
||||
|
node_add_timestamp(node, base_time + 5, false); |
||||
|
node_add_timestamp(node, base_time + 10, true); |
||||
|
|
||||
|
time_t** event_table; |
||||
|
uint8_t num_entries = node_get_event_table(node, &event_table); |
||||
|
TEST_ASSERT_EQUAL_UINT8(3, num_entries); |
||||
|
TEST_ASSERT_NOT_NULL(event_table); |
||||
|
|
||||
|
time_t** expected_table = (time_t**) malloc(2 * sizeof(time_t *)); |
||||
|
expected_table[0] = (time_t*) malloc(3 * sizeof(time_t)); |
||||
|
expected_table[1] = (time_t*) malloc(3 * sizeof(time_t)); |
||||
|
|
||||
|
expected_table[0][0] = base_time - 15; |
||||
|
expected_table[1][0] = base_time - 10; |
||||
|
expected_table[0][1] = base_time - 5; |
||||
|
expected_table[1][1] = base_time; |
||||
|
expected_table[0][2] = base_time + 10; |
||||
|
expected_table[1][2] = 0; |
||||
|
|
||||
|
TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected_table[0], event_table[0], sizeof(time_t), 3); |
||||
|
TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected_table[1], event_table[1], sizeof(time_t), 3); |
||||
|
|
||||
|
node_free(node); |
||||
|
} |
Loading…
Reference in new issue