/* This file is part of libbrandt. * Copyright (C) 2016 GNUnet e.V. * * libbrandt is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * libbrandt is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * libbrandt. If not, see . */ /** * @file test_brandt.c * @brief testing API functions. * @author Markus Teich */ #include "platform.h" #include #include "brandt.h" #include "crypto.h" #include "test.h" #include "util.h" struct msg { uint16_t sender; uint16_t receiver; void *buf; size_t buf_len; }; struct test { uint16_t ret; uint16_t m; uint16_t outcome_public; }; static uint16_t *id; static uint16_t *result_called; static struct BRANDT_Auction **ad; static uint16_t unexpected_result; /* TEST CONFIGURATION */ static const uint16_t bidders = 4; static const uint16_t prizes = 3; static const uint16_t bids[] = { 1, 2, 0, 2 }; static struct BRANDT_Result * expected_outcome (uint16_t m, uint16_t outcome_public, uint16_t i) { int32_t highest_bidder = -1; int32_t highest_bid = -1; struct BRANDT_Result *ret; for (uint16_t i = 0; i < bidders; i++) { if (bids[i] > highest_bid) { highest_bid = bids[i]; highest_bidder = i; } } if (!outcome_public && !(i == highest_bidder || i == bidders)) return NULL; ret = GNUNET_new (struct BRANDT_Result); ret->bidder = highest_bidder; ret->price = highest_bid; ret->status = BRANDT_bidder_won; return ret; } static void bidder_start (void *arg) { uint16_t i = *(uint16_t *)arg; weprintf ("starting bidder %d", i); BRANDT_bidder_start (ad[i], i, bidders); } static void transfer_message (void *arg) { struct msg *m = (struct msg *)arg; struct msg_head *h = (struct msg_head *)m->buf; weprintf ("xfer msg %d %x from %d to %d", ntohl ( h->msg_type), arg, m->sender, m->receiver); BRANDT_got_message (ad[m->receiver], m->sender, m->buf, m->buf_len); free (arg); } static uint16_t cb_start (void *auction_closure) { uint16_t *s = (uint16_t *)auction_closure; if (!s || bidders != *s) { weprintf ("start callback called from bidder"); _exit (1); } for (uint16_t i = 0; i < bidders; i++) GNUNET_SCHEDULER_add_now (&bidder_start, &id[i]); return bidders; } static int cb_broadcast (void *auction_closure, const void *msg, size_t msg_len) { uint16_t *s = (uint16_t *)auction_closure; struct msg *m; for (uint16_t i = 0; i <= bidders; i++) { if (i == *s) continue; m = GNUNET_new (struct msg); m->sender = *s; m->receiver = i; m->buf = GNUNET_new_array (msg_len, unsigned char); memcpy (m->buf, msg, msg_len); m->buf_len = msg_len; GNUNET_SCHEDULER_add_now (&transfer_message, m); } return 0; } static int cb_unicast (void *auction_closure, const void *msg, size_t msg_len) { uint16_t *s = (uint16_t *)auction_closure; struct msg *m; m = GNUNET_new (struct msg); m->sender = *s; m->receiver = bidders; /* == seller */ m->buf = GNUNET_new_array (msg_len, unsigned char); memcpy (m->buf, msg, msg_len); m->buf_len = msg_len; GNUNET_SCHEDULER_add_now (&transfer_message, m); return 0; } static void cb_result (void *auction_closure, struct BRANDT_Result results[], uint16_t results_len) { uint16_t *s = (uint16_t *)auction_closure; struct BRANDT_Result *must = expected_outcome (ad[*s]->m, ad[*s]->outcome_public, *s); if (0 == results_len) { weprintf ("result from agent %d: %p", *s, must); weprintf ("expected result is: (nil)"); if (NULL != must) unexpected_result = 1; } for (uint16_t i = 0; i < results_len; i++) { weprintf ("result from agent %d: bidder %d got status %d with price %d", *s, results[i].bidder, results[i].status, results[i].price); weprintf ("expected result is: bidder %d got status %d with price %d", must[i].bidder, must[i].status, must[i].price); if (NULL == must || must[i].bidder != results[i].bidder || must[i].status != results[i].status || must[i].price != results[i].price) unexpected_result = 1; } result_called[*s] = 1; } static void run_auction (void *arg) { struct test *asetup = arg; const char description[] = "test description for test_auctions"; void *desc; size_t desc_len; ad = GNUNET_new_array (bidders + 1, struct BRANDT_Auction *); ad[bidders] = BRANDT_new (&cb_result, &cb_broadcast, &cb_start, &id[bidders], &desc, &desc_len, description, sizeof (description), GNUNET_TIME_absolute_get (), GNUNET_TIME_UNIT_MINUTES, prizes, /* number of prizes */ asetup->m, /* m */ asetup->outcome_public); /* outcome public */ if (!ad[bidders]) { weprintf ("BRANDT_new() failed."); _exit (1); } for (uint16_t i = 0; i < bidders; i++) { ad[i] = BRANDT_join (&cb_result, &cb_broadcast, &cb_unicast, &id[i], desc, desc_len, description, sizeof (description), bids[i]); /* bid */ if (!ad[i]) { weprintf ("BRANDT_join() failed."); _exit (1); } if (ad[bidders]->k != ad[i]->k || ad[bidders]->m != ad[i]->m || ad[bidders]->outcome_public != ad[i]->outcome_public || ad[bidders]->time_start.abs_value_us != ad[i]->time_start.abs_value_us || ad[bidders]->time_round.rel_value_us != ad[i]->time_round.rel_value_us || !ad[bidders]->seller_mode || /* todo: split out */ ad[i]->seller_mode) { weprintf ("error/mismatch in basic auction data"); _exit (1); } } } static int test_auctions () { id = GNUNET_new_array (bidders + 1, uint16_t); for (uint16_t i = 0; i <= bidders; i++) id[i] = i; for (size_t atype = 0; atype < auction_last; atype++) { if (auction_firstPrice != atype) /* others not yet implemented */ continue; for (size_t oc = 0; oc < outcome_last; oc++) { struct test asetup; result_called = GNUNET_new_array (bidders + 1, uint16_t); unexpected_result = 0; asetup.ret = 0; asetup.m = atype; asetup.outcome_public = oc; GNUNET_SCHEDULER_run (&run_auction, &asetup); for (uint16_t i = 0; i <= bidders; i++) { BRANDT_destroy (ad[i]); if (!result_called[i]) { weprintf ("result callback not called for bidder %d", i); unexpected_result = 1; } } if (unexpected_result) return 0; } } return 1; } int main (int argc, char *argv[]) { struct GNUNET_CRYPTO_EccDlogContext *edc; edc = GNUNET_CRYPTO_ecc_dlog_prepare (1024, 16); BRANDT_init (edc); RUN (test_auctions); GNUNET_CRYPTO_ecc_dlog_release (edc); return ret; }