diff --git a/blocks/block.c b/blocks/block.c index ec8faef..aaa5c66 100644 --- a/blocks/block.c +++ b/blocks/block.c @@ -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; } diff --git a/blocks/blockstore.c b/blocks/blockstore.c index a06472a..8408afa 100644 --- a/blocks/blockstore.c +++ b/blocks/blockstore.c @@ -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); diff --git a/cid/cid.c b/cid/cid.c index 622cf3e..abc0103 100644 --- a/cid/cid.c +++ b/cid/cid.c @@ -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 diff --git a/core/ipfs_node.c b/core/ipfs_node.c index aae5376..50ae916 100644 --- a/core/ipfs_node.c +++ b/core/ipfs_node.c @@ -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; diff --git a/exchange/bitswap/bitswap.c b/exchange/bitswap/bitswap.c index f5d1064..9f9adfe 100644 --- a/exchange/bitswap/bitswap.c +++ b/exchange/bitswap/bitswap.c @@ -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; } diff --git a/include/ipfs/cid/cid.h b/include/ipfs/cid/cid.h index e17f86b..7969f1a 100644 --- a/include/ipfs/cid/cid.h +++ b/include/ipfs/cid/cid.h @@ -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 diff --git a/include/ipfs/exchange/bitswap/bitswap.h b/include/ipfs/exchange/bitswap/bitswap.h index 6400b9a..b797228 100644 --- a/include/ipfs/exchange/bitswap/bitswap.h +++ b/include/ipfs/exchange/bitswap/bitswap.h @@ -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); diff --git a/include/ipfs/exchange/exchange.h b/include/ipfs/exchange/exchange.h index 5a2cf70..920d761 100644 --- a/include/ipfs/exchange/exchange.h +++ b/include/ipfs/exchange/exchange.h @@ -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 diff --git a/namesys/routing.c b/namesys/routing.c index 82c787f..562a7a3 100644 --- a/namesys/routing.c +++ b/namesys/routing.c @@ -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); diff --git a/repo/fsrepo/fs_repo.c b/repo/fsrepo/fs_repo.c index 2d8d6c0..294cc5c 100644 --- a/repo/fsrepo/fs_repo.c +++ b/repo/fsrepo/fs_repo.c @@ -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) { diff --git a/test/cid/test_cid.h b/test/cid/test_cid.h index c2239c0..ab34847 100644 --- a/test/cid/test_cid.h +++ b/test/cid/test_cid.h @@ -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) diff --git a/test/exchange/test_bitswap.h b/test/exchange/test_bitswap.h index 69d9b30..1b1eeb3 100644 --- a/test/exchange/test_bitswap.h +++ b/test/exchange/test_bitswap.h @@ -1,5 +1,11 @@ -#include "ipfs/exchange/bitswap/message.h" +#include +#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; + +} + diff --git a/test/routing/test_routing.h b/test/routing/test_routing.h index 68a839b..1294cff 100644 --- a/test/routing/test_routing.h +++ b/test/routing/test_routing.h @@ -1,5 +1,7 @@ +#pragma once #include #include +#include #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" diff --git a/test/test_helper.c b/test/test_helper.c index 64e3d4c..203ac88 100644 --- a/test/test_helper.c +++ b/test/test_helper.c @@ -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); } diff --git a/test/testit.c b/test/testit.c index f472098..c260c11 100644 --- a/test/testit.c +++ b/test/testit.c @@ -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,