void TestBT_Peer_shares_one_piece(
    CuTest * tc
)
{
    int ii;
    client_t* a, *b;
    hashmap_iterator_t iter;
    void* mt;
    char *addr;

    clients_setup();
    mt = mocktorrent_new(1, 5);
    a = mock_client_setup(5);
    b = mock_client_setup(5);

    for (
        hashmap_iterator(clients_get(), &iter);
        hashmap_iterator_has_next(clients_get(), &iter);
    )
    {
        char hash[21];

        client_t* cli = hashmap_iterator_next_value(clients_get(), &iter);
        void* bt = cli->bt;
        void *cfg = bt_dm_get_config(bt);
        /* default configuration for clients */
        config_set(cfg, "npieces", "1");
        config_set_va(cfg, "piece_length", "%d", 5);
        config_set(cfg, "infohash", "00000000000000000000");
        /* add files/pieces */
        //bt_piecedb_add_file(bt_dm_get_piecedb(bt),"test.txt",8,5);
        bt_piecedb_increase_piece_space(bt_dm_get_piecedb(bt), 5);
        bt_piecedb_add_with_hash_and_size(bt_dm_get_piecedb(bt),
                                          mocktorrent_get_piece_sha1(mt, hash,
                                                  0), 5);
    }

    /* write blocks to client A */
    {
        void* data;
        bt_block_t blk;

        data = mocktorrent_get_data(mt, 0);
        blk.piece_idx = 0;
        blk.offset = 0;
        blk.len = 5;
        bt_diskmem_write_block(
            bt_piecedb_get_diskstorage(bt_dm_get_piecedb(a->bt)),
            NULL, &blk, data);
    }

    bt_dm_check_pieces(a->bt);
    bt_dm_check_pieces(b->bt);
    /* let validation jobs run */
    bt_dm_periodic(a->bt, NULL);
    CuAssertTrue(tc, 1 ==
                 bt_piecedb_all_pieces_are_complete(bt_dm_get_piecedb(a->bt)));

    /* connect clients */
    asprintf(&addr, "%p", a);
    client_add_peer(b, NULL, 0, addr, strlen(addr), 0);

    for (ii = 0; ii < 10; ii++)
    {
#if 0   /* debugging */
        printf("\nStep %d:\n", ii + 1);
#endif

        bt_dm_periodic(a->bt, NULL);
        bt_dm_periodic(b->bt, NULL);

        network_poll(a->bt, (void*)&a, 0,
                     bt_dm_dispatch_from_buffer,
                     mock_on_connect);

        network_poll(b->bt, (void*)&b, 0,
                     bt_dm_dispatch_from_buffer,
                     mock_on_connect);

//        __print_client_contents();
    }

    /* let validation jobs run */
    bt_dm_periodic(a->bt, NULL);
    bt_dm_periodic(b->bt, NULL);

    CuAssertTrue(tc, 1 ==
                 bt_piecedb_all_pieces_are_complete(bt_dm_get_piecedb(b->bt)));
}
void TestBT_Peer_share_20_pieces(CuTest * tc)
{
    int num_pieces;
    int ii;
    client_t* a, *b;
    hashmap_iterator_t iter;
    void* mt;
    char *addr;

    num_pieces = 50;
    clients_setup();
    mt = mocktorrent_new(num_pieces, 5);
    a = mock_client_setup(5);
    b = mock_client_setup(5);

    for (
        hashmap_iterator(clients_get(), &iter);
        hashmap_iterator_has_next(clients_get(), &iter);
        )
    {
        void* bt, *cfg;
        client_t* cli;

        cli = hashmap_iterator_next_value(clients_get(), &iter);
        bt = cli->bt;

        /* default configuration for clients */
        cfg = bt_dm_get_config(bt);
        config_set_va(cfg, "npieces", "%d", num_pieces);
        config_set(cfg, "piece_length", "5");
        config_set(cfg, "infohash", "00000000000000000000");

        /* add files/pieces */
        bt_piecedb_increase_piece_space(bt_dm_get_piecedb(bt), num_pieces * 5);
        for (ii = 0; ii < num_pieces; ii++)
        {
            char hash[21];
            void* pd;

            pd = bt_dm_get_piecedb(bt);
            mocktorrent_get_piece_sha1(mt, hash, ii);
            bt_piecedb_add_with_hash_and_size(pd, hash, 5);
        }
    }

    /* B will initiate the connection */
    asprintf(&addr, "%p", b);
    client_add_peer(a, NULL, 0, addr, strlen(addr), 0);

    __add_random_piece_subset_of_mocktorrent(
        bt_dm_get_piecedb(a->bt),
        mt, num_pieces);

    __add_piece_intersection_of_mocktorrent(
        bt_dm_get_piecedb(b->bt),
        bt_dm_get_piecedb(a->bt),
        mt, num_pieces);

    bt_dm_check_pieces(a->bt);
    bt_dm_check_pieces(b->bt);

    for (ii = 0; ii < 2000; ii++)
    {
#if 0   /* debugging */
        printf("\nStep %d:\n", ii + 1);
#endif
        bt_dm_periodic(a->bt, NULL);
        bt_dm_periodic(b->bt, NULL);

        network_poll(a->bt, (void*)&a, 0,
                     bt_dm_dispatch_from_buffer,
                     mock_on_connect);

        network_poll(b->bt, (void*)&b, 0,
                     bt_dm_dispatch_from_buffer,
                     mock_on_connect);
    }

    bt_dm_periodic(a->bt, NULL);
    bt_dm_periodic(b->bt, NULL);

//    bt_piecedb_print_pieces_downloaded(bt_dm_get_piecedb(a->bt));
//    bt_piecedb_print_pieces_downloaded(bt_dm_get_piecedb(b->bt));

    CuAssertTrue(tc, 1 ==
                 bt_piecedb_all_pieces_are_complete(bt_dm_get_piecedb(a->bt)));
    CuAssertTrue(tc, 1 ==
                 bt_piecedb_all_pieces_are_complete(bt_dm_get_piecedb(b->bt)));
}
/** a have message has to be sent by client B, for client A and C to finish */
void TestBT_Peer_three_share_all_pieces_between_each_other(CuTest * tc)
{
    int ii;
    client_t* a, *b, *c;
    hashmap_iterator_t iter;
    void* mt;
    char *addr;

    clients_setup();
    mt = mocktorrent_new(3,5);
    a = mock_client_setup(5);
    b = mock_client_setup(5);
    c = mock_client_setup(5);

    for (
        hashmap_iterator(clients_get(), &iter);
        hashmap_iterator_has_next(clients_get(), &iter);
        )
    {
        char hash[21];
        void* bt, *cfg;
        client_t* cli;

        cli = hashmap_iterator_next_value(clients_get(), &iter);
        bt = cli->bt;
        cfg = bt_dm_get_config(bt);
        /* default configuration for clients */
        config_set(cfg, "npieces", "3");
        config_set(cfg, "piece_length", "5");
        config_set(cfg, "infohash", "00000000000000000000");
        /* add files/pieces */
        bt_piecedb_increase_piece_space(bt_dm_get_piecedb(bt),20);
        bt_piecedb_add_with_hash_and_size(bt_dm_get_piecedb(bt),
                mocktorrent_get_piece_sha1(mt,hash,0), 5);
        bt_piecedb_add_with_hash_and_size(bt_dm_get_piecedb(bt),
                mocktorrent_get_piece_sha1(mt,hash,1), 5);
        bt_piecedb_add_with_hash_and_size(bt_dm_get_piecedb(bt),
                mocktorrent_get_piece_sha1(mt,hash,2), 5);
    }

    /* write blocks to client A & B */
    {
        void* data;
        bt_block_t blk;

        blk.piece_idx = 0;
        blk.offset = 0;
        blk.len = 5;

        data = mocktorrent_get_data(mt,0);
        bt_diskmem_write_block(
                bt_piecedb_get_diskstorage(bt_dm_get_piecedb(a->bt)),
                NULL, &blk, data);

        blk.piece_idx = 1;
        data = mocktorrent_get_data(mt,1);
        bt_diskmem_write_block(
                bt_piecedb_get_diskstorage(bt_dm_get_piecedb(b->bt)),
                NULL, &blk, data);

        blk.piece_idx = 2;
        data = mocktorrent_get_data(mt,2);
        bt_diskmem_write_block(
                bt_piecedb_get_diskstorage(bt_dm_get_piecedb(c->bt)),
                NULL, &blk, data);
    }

    bt_dm_check_pieces(a->bt);
    bt_dm_check_pieces(b->bt);
    bt_dm_check_pieces(c->bt);

    /* A connects to B */
    asprintf(&addr,"%p", b);
    client_add_peer(a,NULL,0,addr,strlen(addr),0);
    /* B connects to C */
    asprintf(&addr,"%p", c);
    client_add_peer(b,NULL,0,addr,strlen(addr),0);

    for (ii=0; ii<10; ii++)
    {
#if 0 /* debugging */
        printf("\nStep %d:\n", ii+1);
#endif

        bt_dm_periodic(a->bt, NULL);
        bt_dm_periodic(b->bt, NULL);
        bt_dm_periodic(c->bt, NULL);

        network_poll(a->bt, (void*)&a, 0,
                bt_dm_dispatch_from_buffer,
                mock_on_connect);

        network_poll(b->bt, (void*)&b, 0,
                bt_dm_dispatch_from_buffer,
                mock_on_connect);

        network_poll(c->bt, (void*)&c, 0,
                bt_dm_dispatch_from_buffer,
                mock_on_connect);

//        __print_client_contents();
    }

//    bt_piecedb_print_pieces_downloaded(bt_dm_get_piecedb(a->bt));
//    bt_piecedb_print_pieces_downloaded(bt_dm_get_piecedb(b->bt));
//    bt_piecedb_print_pieces_downloaded(bt_dm_get_piecedb(c->bt));

    /* empty jobs */
    bt_dm_periodic(a->bt, NULL);
    bt_dm_periodic(b->bt, NULL);
    bt_dm_periodic(c->bt, NULL);

    CuAssertTrue(tc, 1 == bt_piecedb_all_pieces_are_complete(bt_dm_get_piecedb(a->bt)));
    CuAssertTrue(tc, 1 == bt_piecedb_all_pieces_are_complete(bt_dm_get_piecedb(b->bt)));
    CuAssertTrue(tc, 1 == bt_piecedb_all_pieces_are_complete(bt_dm_get_piecedb(c->bt)));
}