Unit testing and memory fixes

yamux
John Jones 2017-07-26 09:48:04 -05:00
parent 692d3406c8
commit 10aa932e08
15 changed files with 256 additions and 75 deletions

View File

@ -134,7 +134,8 @@ int ipfs_blocks_block_add_data(const unsigned char* data, size_t data_size, stru
return 0;
}
if (ipfs_cid_new(0, hash, 32, CID_PROTOBUF, &(block->cid)) == 0) {
block->cid = ipfs_cid_new(0, hash, 32, CID_PROTOBUF);
if (block->cid == NULL) {
return 0;
}

View File

@ -127,7 +127,7 @@ int ipfs_blockstore_get(const struct BlockstoreContext* context, struct Cid* cid
int retVal = ipfs_blocks_block_protobuf_decode(buffer, bytes_read, block);
(*block)->cid = cid;
(*block)->cid = ipfs_cid_copy(cid);
free(key);
free(filename);

View File

@ -84,7 +84,8 @@ int ipfs_cid_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct
}
retVal = ipfs_cid_new(version, hash, hash_length, codec, output);
*output = ipfs_cid_new(version, hash, hash_length, codec);
retVal = *output != NULL;
free(hash);
return retVal;
}
@ -95,32 +96,27 @@ int ipfs_cid_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct
* @param hash the multihash
* @param hash_length the length of the multihash in bytes
* @param codec the codec to be used (NOTE: For version 0, this should be CID_PROTOBUF)
* @param cid where to put the results
* @returns true(1) on success
* @returns the new Cid or NULL if there was a problem
*/
int ipfs_cid_new(int version, const unsigned char* hash, size_t hash_length, const char codec, struct Cid** ptrToCid) {
// allocate memory
*ptrToCid = (struct Cid*)malloc(sizeof(struct Cid));
struct Cid* cid = *ptrToCid;
if (cid == NULL)
return 0;
if (hash == NULL) {
cid->hash = NULL;
} else {
cid->hash = malloc(sizeof(unsigned char) * hash_length);
if (cid->hash == NULL) {
free(cid);
return 0;
struct Cid* ipfs_cid_new(int version, const unsigned char* hash, size_t hash_length, const char codec) {
struct Cid* cid = (struct Cid*) malloc(sizeof(struct Cid));
if (cid != NULL) {
cid->hash_length = hash_length;
if (hash_length == 0 || hash == NULL) {
cid->hash = NULL;
} else {
cid->hash = (unsigned char*) malloc(sizeof(unsigned char) * hash_length);
if (cid->hash == NULL) {
free(cid);
return NULL;
}
memcpy(cid->hash, hash, hash_length);
}
memcpy(cid->hash, hash, hash_length);
// assign other values
cid->version = version;
cid->codec = codec;
}
// assign values
cid->version = version;
cid->codec = codec;
cid->hash_length = hash_length;
return 1;
return cid;
}
/***
@ -176,7 +172,8 @@ int ipfs_cid_decode_hash_from_base58(const unsigned char* incoming, size_t incom
if (retVal == 0)
return 0;
// now we have the hash, build the object
return ipfs_cid_new(0, &hash[2], hash_length - 2, CID_PROTOBUF, cid);
*cid = ipfs_cid_new(0, &hash[2], hash_length - 2, CID_PROTOBUF);
return *cid != NULL;
}
// TODO: finish this

View File

@ -63,6 +63,9 @@ int ipfs_node_free(struct IpfsNode* node) {
if (node->mode == MODE_ONLINE) {
ipfs_routing_online_free(node->routing);
}
if (node->blockstore != NULL) {
ipfs_blockstore_free(node->blockstore);
}
free(node);
}
return 1;

View File

@ -14,16 +14,15 @@
* @param sessionContext the context
* @returns an allocated Exchange structure
*/
struct Exchange* ipfs_bitswap_exchange_start(struct SessionContext* sessionContext, struct IpfsNode* ipfs_node) {
struct Exchange* ipfs_bitswap_exchange_start(struct IpfsNode* ipfs_node) {
struct Exchange* exchange = (struct Exchange*) malloc(sizeof(struct Exchange));
if (exchange != NULL) {
struct BitswapContext* bitswapContext = (struct BitswapContext*) malloc(sizeof(struct BitswapContext));
if (exchange->exchangeContext == NULL) {
if (bitswapContext == NULL) {
free(exchange);
return NULL;
}
exchange->exchangeContext = (void*) bitswapContext;
bitswapContext->sessionContext = sessionContext;
bitswapContext->ipfsNode = ipfs_node;
exchange->IsOnline = ipfs_bitswap_is_online;
exchange->Close = ipfs_bitswap_close;
@ -43,7 +42,6 @@ struct Exchange* ipfs_bitswap_exchange_start(struct SessionContext* sessionConte
int ipfs_bitswap_free(struct Exchange* exchange) {
if (exchange != NULL) {
if (exchange->exchangeContext != NULL) {
ipfs_bitswap_close(exchange->exchangeContext);
free(exchange->exchangeContext);
}
free(exchange);
@ -54,22 +52,15 @@ int ipfs_bitswap_free(struct Exchange* exchange) {
/**
* Implements the Exchange->IsOnline method
*/
int ipfs_bitswap_is_online(void* exchangeContext) {
if (exchangeContext != NULL) {
struct BitswapContext* bitswapContext = (struct BitswapContext*)exchangeContext;
//TODO: Is this an accurate way to determine if we're running?
if (bitswapContext->sessionContext != NULL)
return 1;
}
return 0;
int ipfs_bitswap_is_online(struct Exchange* exchange) {
return 1;
}
/***
* Implements the Exchange->Close method
*/
int ipfs_bitswap_close(void* exchangeContext) {
//TODO: Implement this method
// Should it close the exchange?
int ipfs_bitswap_close(struct Exchange* exchange) {
ipfs_bitswap_free(exchange);
return 0;
}
@ -80,7 +71,7 @@ int ipfs_bitswap_close(void* exchangeContext) {
* But this does not make sense right now, as the GO code looks like it
* adds the block to the blockstore. This still has to be sorted.
*/
int ipfs_bitswap_has_block(void* exchangeContext, struct Block* block) {
int ipfs_bitswap_has_block(struct Exchange* exchange, struct Block* block) {
//TODO: Implement this method
// NOTE: The GO version adds the block to the blockstore. I have yet to
// understand the flow and if this is correct for us.
@ -96,8 +87,8 @@ int ipfs_bitswap_has_block(void* exchangeContext, struct Block* block) {
* @param block a pointer to where to put the result
* @returns true(1) if found, false(0) if not
*/
int ipfs_bitswap_get_block(void* exchangeContext, struct Cid* cid, struct Block** block) {
struct BitswapContext* bitswapContext = (struct BitswapContext*)exchangeContext;
int ipfs_bitswap_get_block(struct Exchange* exchange, struct Cid* cid, struct Block** block) {
struct BitswapContext* bitswapContext = (struct BitswapContext*)exchange->exchangeContext;
if (bitswapContext != NULL) {
// check locally first
if (bitswapContext->ipfsNode->blockstore->Get(bitswapContext->ipfsNode->blockstore->blockstoreContext, cid, block))
@ -140,7 +131,7 @@ int ipfs_bitswap_get_block(void* exchangeContext, struct Cid* cid, struct Block*
/**
* Implements the Exchange->GetBlocks method
*/
int ipfs_bitswap_get_blocks(void* exchangeContext, struct Libp2pVector* Cids, struct Libp2pVector** blocks) {
int ipfs_bitswap_get_blocks(struct Exchange* exchange, struct Libp2pVector* Cids, struct Libp2pVector** blocks) {
// TODO: Implement this method
return 0;
}

View File

@ -69,10 +69,9 @@ size_t ipfs_cid_protobuf_encode_size(struct Cid* incoming);
* @param hash the multihash
* @param hash_length the length of the multihash in bytes
* @param codec the codec to be used (NOTE: For version 0, this should be CID_PROTOBUF)
* @param cid where to put the results
* @returns true(1) on success
* @returns the Cid, or NULL if there was a problem
*/
int ipfs_cid_new(int version, const unsigned char* hash, size_t hash_length, const char codec, struct Cid** cid);
struct Cid* ipfs_cid_new(int version, const unsigned char* hash, size_t hash_length, const char codec);
/***
* Free the resources from a Cid

View File

@ -9,17 +9,16 @@
#include "ipfs/exchange/exchange.h"
struct BitswapContext {
struct SessionContext* sessionContext;
struct IpfsNode* ipfsNode;
struct WantListQueue* localWantlist;
};
/**
* Start up the bitswap exchange
* @param sessionContext the context
* @param ipfsNode the context
* @returns an Exchange struct that refers to the exchange
*/
struct Exchange* ipfs_bitswap_exchange_start(struct SessionContext* sessionContext, struct IpfsNode* ipfsNode);
struct Exchange* ipfs_bitswap_exchange_start(struct IpfsNode* ipfsNode);
/***
* These are the implementation methods for the exchange "Interface"
@ -30,14 +29,14 @@ struct Exchange* ipfs_bitswap_exchange_start(struct SessionContext* sessionConte
* @param exhcnageContext a pointer to a BitswapContext
* @reutrns true(1) if online, false(0) otherwise.
*/
int ipfs_bitswap_is_online(void* exchangeContext);
int ipfs_bitswap_is_online(struct Exchange* exchange);
/***
* Closes down the Bitswap network
* @param exchangeContext a pointer to a BitswapContext
* @returns true(1)
*/
int ipfs_bitswap_close(void* exchangeContext);
int ipfs_bitswap_close(struct Exchange* exchange);
/****
* Notify the BitswapNetwork that we have this block
@ -45,7 +44,7 @@ int ipfs_bitswap_close(void* exchangeContext);
* @block the block that we have
* @reutrns true(1) if successful, false(0) if not.
*/
int ipfs_bitswap_has_block(void* exchangeContext, struct Block* block);
int ipfs_bitswap_has_block(struct Exchange* exchange, struct Block* block);
/**
* Retrieve a block from the BitswapNetwork
@ -57,7 +56,7 @@ int ipfs_bitswap_has_block(void* exchangeContext, struct Block* block);
* @param block a pointer to the block when we find it.
* @returns true(1) on success, false(0) otherwise.
*/
int ipfs_bitswap_get_block(void* exchangeContext, struct Cid* cid, struct Block** block);
int ipfs_bitswap_get_block(struct Exchange* exchange, struct Cid* cid, struct Block** block);
/***
* Retrieve a collection of blocks from the BitswapNetwork
@ -68,4 +67,4 @@ int ipfs_bitswap_get_block(void* exchangeContext, struct Cid* cid, struct Block*
* @param blocks a collection that contains the results.
* @param true(1) on success, false(0) otherwise
*/
int ipfs_bitswap_get_blocks(void* exchangeContext, struct Libp2pVector* cids, struct Libp2pVector** blocks);
int ipfs_bitswap_get_blocks(struct Exchange* exchange, struct Libp2pVector* cids, struct Libp2pVector** blocks);

View File

@ -27,7 +27,7 @@ struct Exchange {
* @param block a pointer to the block (allocated by this method if return is true)
* @returns true(1) on success, false(0) otherwise
*/
int (*GetBlock)(void* exchangeContext, struct Cid* cid, struct Block** block);
int (*GetBlock)(struct Exchange* exchange, struct Cid* cid, struct Block** block);
/**
* Retrieve several blocks
@ -36,7 +36,7 @@ struct Exchange {
* @param blocks a pointer to a vector of retrieved blocks (will be NULL on error)
* @returns true(1) on success, otherwise false(0)
*/
int (*GetBlocks)(void* exchangeContext, struct Libp2pVector* Cids, struct Libp2pVector** blocks);
int (*GetBlocks)(struct Exchange* exchange, struct Libp2pVector* Cids, struct Libp2pVector** blocks);
/**
* Announces the existance of a block to this bitswap service. The service will
@ -45,19 +45,19 @@ struct Exchange {
* @param block the block being announced
* @returns true(1) on success, false(0) if not
*/
int (*HasBlock)(void* exchangeContext, struct Block* block);
int (*HasBlock)(struct Exchange* exchange, struct Block* block);
/**
* Determine if we're online
* @returns true(1) if we're online
*/
int (*IsOnline)(void* exchangeContext);
int (*IsOnline)(struct Exchange*);
/**
* Close up the exchange, and go offline
* @returns true(1);
*/
int (*Close)(void* exchangeContext);
int (*Close)(struct Exchange*);
/**
* Used by each implementation to maintain state

View File

@ -261,13 +261,10 @@ int ipfs_namesys_routing_resolve_once (char **path, char *name, int depth, char
} else {
// Its an old style multihash record
//log.Warning("Detected old style multihash record")
struct Cid *cid = NULL;;
err = ipfs_cid_new(0, multihash, multihash_size, CID_PROTOBUF, &cid);
if (err) {
struct Cid *cid = ipfs_cid_new(0, multihash, multihash_size, CID_PROTOBUF);
if (cid == NULL) {
free(multihash);
if (cid != NULL)
ipfs_cid_free(cid);
return err;
return 0;
}
err = ipfs_path_parse_from_cid (*path, (char*)cid->hash);

View File

@ -803,8 +803,8 @@ int ipfs_repo_fsrepo_block_read(const unsigned char* hash, size_t hash_length, s
if (retVal == 0) // maybe it doesn't exist?
return 0;
// now get the block from the blockstore
struct Cid* cid = NULL;
if (!ipfs_cid_new(0, hash, hash_length, CID_PROTOBUF, &cid))
struct Cid* cid = ipfs_cid_new(0, hash, hash_length, CID_PROTOBUF);
if (cid == NULL)
return 0;
struct Blockstore* blockstore = ipfs_blockstore_new(fs_repo);
if (blockstore == NULL) {

View File

@ -10,10 +10,11 @@
int test_cid_new_free() {
struct Cid* cid;
unsigned char* hash = (unsigned char*)"ABC123";
int retVal = ipfs_cid_new(0, hash, strlen((char*)hash), CID_PROTOBUF, &cid);
if (retVal == 0)
struct Cid* cid = ipfs_cid_new(0, hash, strlen((char*)hash), CID_PROTOBUF);
if (cid == NULL)
return 0;
if (cid->version != 0)

View File

@ -1,5 +1,11 @@
#include "ipfs/exchange/bitswap/message.h"
#include <pthread.h>
#include "../test_helper.h"
#include "../routing/test_routing.h" // for test_routing_daemon_start
#include "libp2p/utils/vector.h"
#include "libp2p/utils/logger.h"
#include "ipfs/exchange/bitswap/bitswap.h"
#include "ipfs/exchange/bitswap/message.h"
#include "ipfs/importer/importer.h"
uint8_t* generate_bytes(size_t size) {
uint8_t* buffer = (uint8_t*) malloc(size);
@ -105,3 +111,185 @@ int test_bitswap_protobuf() {
retVal = 1;
return retVal;
}
/***
* Put a file in ipfs and attempt to retrieve it using bitswap's Exchange interface
*/
int test_bitswap_retrieve_file()
{
int retVal = 0;
struct Exchange* exchange = NULL;
struct IpfsNode* localNode = NULL;
const char* ipfs_path = "/tmp/ipfstest1";
struct HashtableNode* node = NULL; // the node created by adding the file
size_t bytes_written = 0;
struct Block* block = NULL;
struct Cid* cid = NULL;
// build and open the new IPFS repository with no bootstrap peers
os_utils_setenv("IPFS_PATH", ipfs_path, 1);
drop_and_build_repository(ipfs_path, 4001, NULL, NULL);
ipfs_node_online_new(ipfs_path, &localNode);
// add a file
localNode->routing->Bootstrap(localNode->routing);
ipfs_import_file(NULL, "/home/parallels/ipfstest/hello_world.txt", &node, localNode, &bytes_written, 0);
// build the Cid from the node information
cid = ipfs_cid_new(0, node->hash, node->hash_size, CID_PROTOBUF);
if (cid == NULL)
goto exit;
// fire up the exchange
exchange = ipfs_bitswap_exchange_start(localNode);
// attempt to retrieve the file
if (!exchange->GetBlock(exchange, cid, &block)) {
goto exit;
}
retVal = 1;
exit:
// cleanup
if (block != NULL)
ipfs_block_free(block);
if (cid != NULL)
ipfs_cid_free(cid);
if (node != NULL)
ipfs_hashtable_node_free(node);
if (exchange != NULL) {
exchange->Close(exchange);
}
ipfs_node_free(localNode);
return retVal;
}
/***
* Attempt to retrieve a file from a previously unknown node
*/
int test_bitswap_retrieve_file_third_party() {
int retVal = 0;
/*
libp2p_logger_add_class("online");
libp2p_logger_add_class("multistream");
libp2p_logger_add_class("null");
libp2p_logger_add_class("dht_protocol");
libp2p_logger_add_class("providerstore");
libp2p_logger_add_class("peerstore");
libp2p_logger_add_class("exporter");
libp2p_logger_add_class("peer");
libp2p_logger_add_class("test_bitswap");
*/
// clean out repository
char* ipfs_path = "/tmp/test1";
char* peer_id_1 = NULL, *peer_id_2 = NULL, *peer_id_3 = NULL;
struct IpfsNode* ipfs_node2 = NULL, *ipfs_node3 = NULL;
pthread_t thread1, thread2;
int thread1_started = 0, thread2_started = 0;
struct MultiAddress* ma_peer1 = NULL;
struct Libp2pVector* ma_vector2 = NULL, *ma_vector3 = NULL;
struct HashtableNode* node = NULL, *result_node = NULL;
// create peer 1
drop_and_build_repository(ipfs_path, 4001, NULL, &peer_id_1);
char multiaddress_string[255];
sprintf(multiaddress_string, "/ip4/127.0.0.1/tcp/4001/ipfs/%s", peer_id_1);
ma_peer1 = multiaddress_new_from_string(multiaddress_string);
// start the daemon in a separate thread
libp2p_logger_debug("test_bitswap", "Firing up daemon 1.\n");
if (pthread_create(&thread1, NULL, test_routing_daemon_start, (void*)ipfs_path) < 0) {
fprintf(stderr, "Unable to start thread 1\n");
goto exit;
}
thread1_started = 1;
// wait for everything to start up
// JMJ debugging =
sleep(3);
// create peer 2
ipfs_path = "/tmp/test2";
// create a vector to hold peer1's multiaddress so we can connect as a peer
ma_vector2 = libp2p_utils_vector_new(1);
libp2p_utils_vector_add(ma_vector2, ma_peer1);
// note: this destroys some things, as it frees the fs_repo_3:
drop_and_build_repository(ipfs_path, 4002, ma_vector2, &peer_id_2);
multiaddress_free(ma_peer1);
// add a file, to prime the connection to peer 1
//TODO: Find a better way to do this...
size_t bytes_written = 0;
if (!ipfs_node_online_new(ipfs_path, &ipfs_node2))
goto exit;
ipfs_node2->routing->Bootstrap(ipfs_node2->routing);
ipfs_import_file(NULL, "/home/parallels/ipfstest/hello_world.txt", &node, ipfs_node2, &bytes_written, 0);
ipfs_node_free(ipfs_node2);
// start the daemon in a separate thread
libp2p_logger_debug("test_routing", "Firing up daemon 2.\n");
if (pthread_create(&thread2, NULL, test_routing_daemon_start, (void*)ipfs_path) < 0) {
fprintf(stderr, "Unable to start thread 2\n");
goto exit;
}
thread2_started = 1;
// wait for everything to start up
// JMJ debugging =
sleep(3);
libp2p_logger_debug("test_routing", "Firing up the 3rd client\n");
// create my peer, peer 3
ipfs_path = "/tmp/test3";
ma_peer1 = multiaddress_new_from_string(multiaddress_string);
ma_vector3 = libp2p_utils_vector_new(1);
libp2p_utils_vector_add(ma_vector3, ma_peer1);
drop_and_build_repository(ipfs_path, 4003, ma_vector3, &peer_id_3);
multiaddress_free(ma_peer1);
ipfs_node_online_new(ipfs_path, &ipfs_node3);
ipfs_node3->routing->Bootstrap(ipfs_node3->routing);
if (!ipfs_exporter_get_node(ipfs_node3, node->hash, node->hash_size, &result_node)) {
fprintf(stderr, "Get_Node returned false\n");
goto exit;
}
if (node->hash_size != result_node->hash_size) {
fprintf(stderr, "Node hash sizes do not match. Should be %lu but is %lu\n", node->hash_size, result_node->hash_size);
goto exit;
}
if (node->data_size != result_node->data_size) {
fprintf(stderr, "Result sizes do not match. Should be %lu but is %lu\n", node->data_size, result_node->data_size);
goto exit;
}
retVal = 1;
exit:
ipfs_daemon_stop();
if (thread1_started)
pthread_join(thread1, NULL);
if (thread2_started)
pthread_join(thread2, NULL);
if (ipfs_node3 != NULL)
ipfs_node_free(ipfs_node3);
if (peer_id_1 != NULL)
free(peer_id_1);
if (peer_id_2 != NULL)
free(peer_id_2);
if (peer_id_3 != NULL)
free(peer_id_3);
if (ma_vector2 != NULL) {
libp2p_utils_vector_free(ma_vector2);
}
if (ma_vector3 != NULL) {
libp2p_utils_vector_free(ma_vector3);
}
if (node != NULL)
ipfs_hashtable_node_free(node);
if (result_node != NULL)
ipfs_hashtable_node_free(result_node);
return retVal;
}

View File

@ -1,5 +1,7 @@
#pragma once
#include <pthread.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "libp2p/os/utils.h"
#include "libp2p/utils/logger.h"
@ -9,6 +11,7 @@
#include "ipfs/core/daemon.h"
#include "ipfs/core/ipfs_node.h"
#include "ipfs/routing/routing.h"
#include "ipfs/importer/importer.h"
#include "ipfs/importer/exporter.h"
#include "../test_helper.h"

View File

@ -146,7 +146,7 @@ int drop_and_build_repository(const char* path, int swarm_port, struct Libp2pVec
}
mkdir(path, S_IRWXU);
return -make_ipfs_repository(path, swarm_port, bootstrap_peers, peer_id);
return make_ipfs_repository(path, swarm_port, bootstrap_peers, peer_id);
}

View File

@ -36,6 +36,7 @@ int testit(const char* name, int (*func)(void)) {
const char* names[] = {
"test_bitswap_new_free",
"test_bitswap_peer_request_queue_new",
"test_bitswap_retrieve_file",
"test_cid_new_free",
"test_cid_cast_multihash",
"test_cid_cast_non_multihash",
@ -88,6 +89,7 @@ const char* names[] = {
int (*funcs[])(void) = {
test_bitswap_new_free,
test_bitswap_peer_request_queue_new,
test_bitswap_retrieve_file,
test_cid_new_free,
test_cid_cast_multihash,
test_cid_cast_non_multihash,