summaryrefslogtreecommitdiff
path: root/cesar/mac/pbproc/test/mfs/src/test_mfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/mac/pbproc/test/mfs/src/test_mfs.c')
-rw-r--r--cesar/mac/pbproc/test/mfs/src/test_mfs.c292
1 files changed, 292 insertions, 0 deletions
diff --git a/cesar/mac/pbproc/test/mfs/src/test_mfs.c b/cesar/mac/pbproc/test/mfs/src/test_mfs.c
new file mode 100644
index 0000000000..986e7a1b91
--- /dev/null
+++ b/cesar/mac/pbproc/test/mfs/src/test_mfs.c
@@ -0,0 +1,292 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/test_mfs.c
+ * \brief Test MFS related functions.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/test.h"
+#include "lib/rnd.h"
+#include "lib/blk.h"
+
+#include "mac/common/mfs.h"
+#include "mac/pbproc/pbproc.h"
+
+#define NB_ITER 1000
+
+struct test_pbproc_t
+{
+ uint next_it;
+ int to_take;
+ pb_t *tx_head, *tx_tail;
+ pb_t *free_head, *free_tail;
+ uint tx_seg_nb;
+ lib_rnd_t rnd[1];
+};
+typedef struct test_pbproc_t test_pbproc_t;
+
+struct test_param_t
+{
+ uint next_it;
+ uint to_take_max;
+ u32 free_r;
+ uint sar_add_min;
+ uint sar_add_max;
+};
+typedef struct test_param_t test_param_t;
+
+void
+test_pbproc_init (test_pbproc_t *ctx)
+{
+ ctx->next_it = 1;
+ ctx->to_take = 0;
+ ctx->tx_head = ctx->tx_tail = NULL;
+ ctx->free_head = ctx->free_tail = NULL;
+ ctx->tx_seg_nb = 0;
+ lib_rnd_init (ctx->rnd, 4321);
+}
+
+void
+test_pbproc_check (test_t t, test_pbproc_t *ctx, mfs_tx_t *mfs)
+{
+ test_within (t);
+ uint ssn = 0;
+ pb_t *p;
+ p = ctx->free_head;
+ test_fail_unless (p);
+ while (1)
+ {
+ if (!mfs->beacon)
+ test_fail_unless (p->header.ssn == ssn++);
+ else
+ {
+ pbproc_tx_beacon_params_t *params =
+ (void *) (p->data + MAC_PB136_BYTES);
+ test_fail_unless (params->bto[0] >= ssn
+ && params->bto[1] == params->bto[0] + 1
+ && params->bto[2] == params->bto[0] + 2
+ && params->bto[3] == params->bto[0] + 3
+ && params->bpsto == NULL);
+ ssn = params->bto[0];
+ }
+ if (p == ctx->free_tail)
+ break;
+ p = p->next;
+ }
+ test_fail_unless (mfs->pending_seg_nb == 0);
+ if (!mfs->beacon)
+ test_fail_unless (ssn + ctx->tx_seg_nb + ctx->to_take + mfs->seg_nb
+ == mfs->next_ssn);
+ test_verbose_print ("freed: %d, total: %d", ssn, mfs->next_ssn);
+}
+
+void
+test_pbproc_uninit (test_pbproc_t *ctx)
+{
+ blk_release_desc_range (&ctx->tx_head->blk, &ctx->tx_tail->blk);
+ blk_release_desc_range (&ctx->free_head->blk, &ctx->free_tail->blk);
+}
+
+void
+test_pbproc_free (test_pbproc_t *ctx)
+{
+ if (!ctx->free_head)
+ ctx->free_head = ctx->tx_head;
+ else
+ ctx->free_tail->next = ctx->tx_head;
+ ctx->free_tail = ctx->tx_tail;
+ ctx->tx_head = ctx->tx_tail = NULL;
+ ctx->tx_seg_nb = 0;
+}
+
+void
+test_pbproc_put_back (test_pbproc_t *ctx, mfs_tx_t *mfs)
+{
+ ctx->tx_tail->next = mfs->head;
+ if (!mfs->head)
+ mfs->tail = ctx->tx_tail;
+ mfs->head = ctx->tx_head;
+ ctx->tx_head = ctx->tx_tail = NULL;
+ mfs->seg_nb += ctx->tx_seg_nb;
+ ctx->tx_seg_nb = 0;
+}
+
+void
+test_pbproc_take (test_pbproc_t *ctx, mfs_tx_t *mfs, uint tt)
+{
+ uint i;
+ for (i = 0; i < tt; i++)
+ {
+ if (!ctx->tx_head)
+ ctx->tx_head = mfs->head;
+ else
+ ctx->tx_tail->next = mfs->head;
+ ctx->tx_tail = mfs->head;
+ if (mfs->head == mfs->tail)
+ {
+ mfs->head = NULL;
+ dbg_invalid_ptr (mfs->tail);
+ }
+ else
+ mfs->head = mfs->head->next;
+ dbg_invalid_ptr (ctx->tx_tail->next); /* simulate next clobber. */
+ ctx->to_take--;
+ ctx->tx_seg_nb++;
+ }
+}
+
+void
+test_pbproc_it (test_t t, test_pbproc_t *ctx, mfs_tx_t *mfs,
+ test_param_t *param)
+{
+ test_within (t);
+ if (!ctx->next_it--)
+ {
+ if (!ctx->to_take && ctx->tx_seg_nb)
+ {
+ if (lib_rnd_flip_coin (ctx->rnd, param->free_r))
+ test_pbproc_free (ctx);
+ else
+ test_pbproc_put_back (ctx, mfs);
+ }
+ else
+ {
+ if (!ctx->to_take)
+ {
+ /* New transmission. */
+ ctx->to_take = lib_rnd_uniform (ctx->rnd, param->to_take_max)
+ + 1;
+ if (mfs->seg_nb == -1)
+ ctx->to_take = 0;
+ else if (ctx->to_take > mfs->seg_nb)
+ ctx->to_take = mfs->seg_nb;
+ test_verbose_print ("to take: %d", ctx->to_take);
+ mfs->seg_nb -= ctx->to_take;
+ }
+ if (ctx->to_take)
+ test_pbproc_take (ctx, mfs, lib_rnd_uniform (
+ ctx->rnd, ctx->to_take) + 1);
+ }
+ ctx->next_it = lib_rnd_uniform (ctx->rnd, param->next_it);
+ }
+}
+
+void
+mfs_basic_test_case (test_t t)
+{
+ uint i;
+ lib_rnd_t rnd[1];
+ test_case_begin (t, "basic");
+ lib_rnd_init (rnd, 1234);
+ /* Test. */
+#define IT() test_pbproc_it (t, &test_pbproc, mfs, &param)
+ test_begin (t, "synchronous")
+ {
+ test_param_t param;
+ param.next_it = 5;
+ param.to_take_max = 200;
+ param.free_r = LIB_RND_RATIO (0.7);
+ param.sar_add_min = 1;
+ param.sar_add_max = 30;
+ test_pbproc_t test_pbproc;
+ test_pbproc_init (&test_pbproc);
+ mfs_tx_t *mfs = blk_alloc ();
+ mfs_tx_init (mfs, false, false, 0, 1);
+ mfs->dynamic_cap = true;
+ for (i = 0; i < NB_ITER; i++)
+ {
+ uint add = lib_rnd_uniform (rnd, param.sar_add_max -
+ param.sar_add_min + 1)
+ + param.sar_add_min;
+ test_verbose_print ("add: %d", add);
+ pb_t *tail = pbproc_mfs_extract_tail (mfs);
+ IT ();
+ uint insert = tail ? add - 1 : add;
+ test_verbose_print ("insert: %d", insert);
+ if (insert)
+ {
+ pb_t *sar_head, *sar_tail, *p;
+ sar_head = (pb_t *) blk_alloc_desc_range (insert, (blk_t **)
+ &sar_tail);
+ p = sar_head;
+ do
+ {
+ pb_header_t h;
+ h.ssn = mfs->next_ssn++;
+ h.mfbo = 0;
+ h.vpbf = true;
+ h.mmqf = false;
+ h.mfbf = false;
+ h.opsf = false;
+ h.rsvd = 0;
+ p->header = h;
+ if (p == sar_tail)
+ break;
+ p = p->next;
+ } while (1);
+ pbproc_mfs_insert (mfs, sar_head, sar_tail, insert, 0);
+ IT ();
+ }
+ pbproc_mfs_provide (mfs, add);
+ IT ();
+ }
+ test_pbproc_check (t, &test_pbproc, mfs);
+ if (mfs->head)
+ blk_release_desc_range (&mfs->head->blk, &mfs->tail->blk);
+ blk_release (mfs);
+ test_pbproc_uninit (&test_pbproc);
+ } test_end;
+ test_begin (t, "beacon")
+ {
+ test_param_t param;
+ param.next_it = 2;
+ param.to_take_max = 1;
+ param.free_r = 0xffffffff;
+ test_pbproc_t test_pbproc;
+ test_pbproc_init (&test_pbproc);
+ mfs_tx_t *mfs = blk_alloc ();
+ mfs_tx_init (mfs, false, false, 0, 1);
+ mfs->beacon = true;
+ for (i = 0; i < NB_ITER; i++)
+ {
+ test_verbose_print ("prepare");
+ pb_beacon_t *beacon = (pb_beacon_t *) blk_alloc_desc ();
+ pbproc_tx_beacon_params_t params =
+ { { mfs->next_ssn, mfs->next_ssn + 1,
+ mfs->next_ssn + 2, mfs->next_ssn + 3 }, NULL };
+ beacon->first_data_word = 42;
+ mfs->next_ssn++;
+ pbproc_mfs_beacon_prepare (INVALID_PTR, mfs, beacon, &params);
+ IT ();
+ }
+ test_pbproc_check (t, &test_pbproc, mfs);
+ if (mfs->head)
+ blk_release_desc_range (&mfs->head->blk, &mfs->tail->blk);
+ blk_release (mfs);
+ test_pbproc_uninit (&test_pbproc);
+ } test_end;
+}
+
+void
+mfs_test_suite (test_t t)
+{
+ test_suite_begin (t, "mfs");
+ mfs_basic_test_case (t);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ test_init (t, argc, argv);
+ mfs_test_suite (t);
+ test_result (t);
+ return test_nb_failed (t) == 0 ? 0 : 1;
+}