/* Cesar project {{{ * * Copyright (C) 2010 Spidcom * * <<>> * * }}} */ /** * \file bsu/test/utest/src/tests.c * \brief Test environment. * \ingroup bsu */ #include "common/std.h" #include "lib/bitstream.h" #include "lib/test.h" #include "bsu/bsu.h" #include "bsu/test/utest/tests.h" #include #include "bsu/inc/context.h" static struct bsu_aclf_test_phy_t phy_test_global; static int bsu_trace_buffer_dbg_dump_callback (void *user, const char *text, uint text_size) { return 0; } static void bsu_test_upper_layer_beacon_received (void *ctx, bsu_beacon_t *beacon) { bsu_test_t *test = (bsu_test_t*) ctx; dbg_assert (ctx); beacon->next = NULL; if (test->ul.beacon == INVALID_PTR) test->ul.beacon = beacon; else test->ul.beacon->next = beacon; } static void bsu_test_upper_layer_wd_refresh (void *ctx) { dbg_assert (ctx); } void bsu_test_upper_layer_beacon_received_init (bsu_test_t *ctx) { dbg_assert (ctx); ctx->ul.beacon = INVALID_PTR; } void bsu_test_reset_phy (bsu_aclf_test_phy_t *ctx) { ctx->frequency_hz = 50.0; ctx->phy_date = 0; ctx->zero_crossing_date = 0; ctx->use_phy_clock = true; } void bsu_test_init (bsu_test_t *ctx) { dbg_assert (ctx); trace_init (); lib_stats_init (); bsu_test_reset_phy (&phy_test_global); ctx->phy = &phy_test_global; mac_config_init (&ctx->mac_config); ctx->mac_config.tei = 0x0; ctx->mac_config.sta_mac_address = 0x123456789abcull; ctx->mac_store = mac_store_init (); ctx->timer = hal_timer_init (); bsu_aclf_t *aclf = bsu_aclf_init ((phy_t*) &ctx->phy, &ctx->mac_config); ctx->bsu = bsu_init (aclf, &ctx->mac_config, (phy_t*) &ctx->phy, ctx->mac_store, (ca_t*) &ctx->ca, (sar_t*) ctx, ctx->timer, INVALID_PTR); bsu_init_beacon_cb (ctx->bsu, bsu_test_upper_layer_beacon_received, ctx); bsu_init_refresh_cb (ctx->bsu, bsu_test_upper_layer_wd_refresh, ctx); /* Warn just for the test. */ ctx->bsu->sta_avln = &ctx->bsu->poweron; ctx->bsu->sta_avln->sync.ntb_offset_tck = 256; ctx->bsu->sta_avln->sync.fe = 2.0e-6; bsu_test_upper_layer_beacon_received_init (ctx); bsu_beacon_t beacon; bsu_test_create_beacon (ctx, &beacon); bsu_update (ctx->bsu, &beacon, BSU_UPDATE_STA_TYPE_CCO); bsu_power_on (ctx->bsu, 0); bsu_aclf_acl_frequency_detection (aclf); aclf->pwl_sync.trig_present = false; ctx->phy->phy_date = 0; } void bsu_test_uninit (bsu_test_t *ctx) { dbg_assert (ctx); trace_bundle_dump_all ("dbg", bsu_trace_buffer_dbg_dump_callback, NULL); bsu_uninit (ctx->bsu); bsu_aclf_uninit (ctx->bsu->aclf); mac_store_uninit (ctx->mac_store); lib_stats_uninit (); trace_uninit (); } static inline void bsu_test_schedules_persistent (bsu_test_t *ctx, bsu_beacon_bmi_persistent_schedule_t *ps) { /* Persistent schedules. */ ps->nb = 2; ps->ps[0].pscd = 0; ps->ps[0].cscd = 1; ps->ps[0].ns = 1; ps->ps[0].sais[0].stpf = true; ps->ps[0].sais[0].glid = 0; ps->ps[0].sais[0].start_time_atu = 700; ps->ps[0].sais[0].end_time_atu = 1000; ps->ps[1].pscd = 2; ps->ps[1].cscd = 2; ps->ps[1].ns = 2; ps->ps[1].sais[0].stpf = true; ps->ps[1].sais[0].glid = 0; ps->ps[1].sais[0].start_time_atu = 50; ps->ps[1].sais[0].end_time_atu = 500; ps->ps[1].sais[1].stpf = true; ps->ps[1].sais[1].glid = 0; ps->ps[1].sais[1].start_time_atu = 700; ps->ps[1].sais[1].end_time_atu = 1600; } static inline void bsu_test_schedules_non_persistent ( bsu_test_t *ctx, bsu_beacon_bmi_non_persistent_schedule_t *nps) { /* Non persistent schedules. */ nps->ns = 3; nps->sais[0].stpf = true; nps->sais[0].glid = 0; nps->sais[0].start_time_atu = 500; nps->sais[0].end_time_atu = 700; nps->sais[1].stpf = true; nps->sais[1].glid = 0; nps->sais[1].start_time_atu = 1600; nps->sais[1].end_time_atu = 2500; nps->sais[2].stpf = false; nps->sais[2].glid = 0; nps->sais[2].start_time_atu = 0; nps->sais[2].end_time_atu = 3907; } void bsu_test_create_beacon (bsu_test_t *ctx, bsu_beacon_t *beacon) { dbg_assert (ctx); dbg_assert (beacon); memset (beacon, 0, sizeof (bsu_beacon_t)); beacon->vf.nid = 0x123456789ull; beacon->vf.hm = MAC_COEXISTENCE_FULL_HYBRID_MODE; beacon->vf.ncnr = false; beacon->vf.npsm = false; beacon->vf.numslots = 0; beacon->vf.slotusage = 0; beacon->vf.slotid = 0; beacon->vf.aclsss = true; beacon->vf.hoip = false; beacon->vf.rtsbf = false; beacon->vf.nm = MAC_NM_CSMA_ONLY; beacon->vf.ccocap = 0; /* Regions. */ beacon->bmis.region.nb = 2; beacon->bmis.region.region[0].rt = BSU_BEACON_REGION_BEACON; beacon->bmis.region.region[0].end_time_atu = 50; beacon->bmis.region.region[1].rt = BSU_BEACON_REGION_SHARED_CSMA; beacon->bmis.region.region[1].end_time_atu = 3907; bsu_test_schedules_persistent (ctx, &beacon->bmis.ps); bsu_test_schedules_non_persistent (ctx, &beacon->bmis.nps); /* BSPTO. */ beacon->bmis.bpsto.present = true; beacon->bmis.bpsto.bpsto = 0xfed0; /* Discover. */ beacon->bmis.discover.present = true; beacon->bmis.discover.tei = 0xc; /* Discover info. */ beacon->bmis.discover_info.present = true; beacon->bmis.discover_info.info_data = 0xcafecafe; /* Handover. */ beacon->bmis.handover.present = true; beacon->bmis.handover.hcd = true; beacon->bmis.handover.tei = 0xd; /* Beacon relocation. */ beacon->bmis.relocation.present = true; beacon->bmis.relocation.rcd = 3; beacon->bmis.relocation.rlt = true; beacon->bmis.relocation.lgf = true; beacon->bmis.relocation.rlo = 3; beacon->bmis.relocation.rlslotid = 4; /* Relocation ACLS. */ beacon->bmis.aclsc.present = true; beacon->bmis.aclsc.countdown = 5; beacon->bmis.aclsc.reason_code = 0; /* CNS. */ beacon->bmis.cns.present = true; beacon->bmis.cns.nsccd = 5; beacon->bmis.cns.newnumslot = 4; /* Hybrid mode. */ beacon->bmis.change_hm.present = true; beacon->bmis.change_hm.hmccd = 4; beacon->bmis.change_hm.newhm = 0; /* Change snid. */ beacon->bmis.change_snid.present = true; beacon->bmis.change_snid.snidccd = 4; beacon->bmis.change_snid.new_snid = 0xf; /* Mac address. */ beacon->bmis.mac_address.present = true; beacon->bmis.mac_address.mac_address = 0x123456789abcull; /* Number of beacon entries. */ beacon->bmis.nbe = 14; } void bsu_test_beacon_check_generation (test_t t, bsu_test_t *ctx, bsu_beacon_t *beacon, pb_beacon_t *phy_beacon, bsu_beacon_type_t type) { bitstream_t stream; u64 nid; uint i, nbe, nb_ps = 0, length; bsu_beacon_entry_header_t header; uint nb_sai = 0; uint nb_nsai = 0; dbg_assert (ctx); dbg_assert (beacon); dbg_assert (phy_beacon); test_begin (t, "Beacon verification") { nid = phy_beacon->first_data_word; bitstream_read_init (&stream, phy_beacon->data, BLK_SIZE); nid |= (u64) bitstream_read (&stream, 22) << 32; test_fail_unless (nid == beacon->vf.nid); test_fail_unless (beacon->vf.hm == bitstream_read (&stream, 2)); test_fail_unless (ctx->mac_config.tei == bitstream_read (&stream, 8)); test_fail_unless (type == bitstream_read (&stream, 3)); test_fail_unless (beacon->vf.ncnr == bitstream_read (&stream, 1)); test_fail_unless (beacon->vf.npsm == bitstream_read (&stream, 1)); test_fail_unless (beacon->vf.numslots == bitstream_read (&stream, 3)); test_fail_unless (beacon->vf.slotusage == bitstream_read (&stream, 8)); test_fail_unless (beacon->vf.slotid == bitstream_read (&stream, 3)); test_fail_unless (beacon->vf.aclsss == bitstream_read (&stream, 3)); test_fail_unless (beacon->vf.hoip == bitstream_read (&stream, 1)); test_fail_unless (beacon->vf.rtsbf == bitstream_read (&stream, 1)); test_fail_unless (beacon->vf.nm == bitstream_read (&stream, 2)); test_fail_unless (beacon->vf.ccocap == bitstream_read (&stream, 2)); /* Reserved bits. */ bitstream_skip (&stream, 4); /* Number of Beacon Entries. */ nbe = bitstream_read (&stream, 8); test_fail_unless (beacon->bmis.nbe == nbe); test_fail_unless (nbe != 0); // Processing beacon entries. for (; nbe; nbe --) { header = bitstream_read (&stream, 8); length = bitstream_read (&stream, 8); switch (header) { case BSU_BEACON_ENTRY_HEADER_REGIONS: /* Region beacon entry (Mandatory). */ test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_REGION (beacon->bmis.region.nb)); test_fail_unless (bitstream_read (&stream, 6) == beacon->bmis.region.nb); bitstream_skip (&stream, 2); for (i = 0; i < beacon->bmis.region.nb; i++) { test_fail_unless (bitstream_read (&stream, 4) == beacon->bmis.region.region[i].rt); test_fail_unless (bitstream_read (&stream, 12) == beacon->bmis.region.region[i].end_time_atu); } break; case BSU_BEACON_ENTRY_HEADER_NON_PERSISTENT_SCHEDULE: nb_sai = 0; nb_nsai = 0; test_fail_unless (beacon->bmis.nps.ns == bitstream_read (&stream, 6)); bitstream_skip (&stream, 2); for (i = 0; i < beacon->bmis.nps.ns; i++) { test_fail_unless (bitstream_read (&stream, 1) == beacon->bmis.nps.sais[i].stpf); test_fail_unless (bitstream_read (&stream, 7) == beacon->bmis.nps.sais[i].glid); if (beacon->bmis.nps.sais[i].stpf) { test_fail_unless (bitstream_read (&stream, 12) == beacon->bmis.nps.sais[i].start_time_atu); nb_sai++; } else nb_nsai++; test_fail_unless (bitstream_read (&stream, 12) == beacon->bmis.nps.sais[i].end_time_atu); } test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_NON_PERSISTENT_SCHED (nb_sai, nb_nsai)); break; case BSU_BEACON_ENTRY_HEADER_PERSISTENT_SCHEDULE: nb_sai = 0; nb_nsai = 0; test_fail_unless (beacon->bmis.ps.ps[nb_ps].pscd == bitstream_read (&stream, 3)); test_fail_unless (beacon->bmis.ps.ps[nb_ps].cscd == bitstream_read (&stream, 3)); bitstream_skip (&stream, 2); test_fail_unless (beacon->bmis.ps.ps[nb_ps].ns == bitstream_read (&stream, 6)); bitstream_skip (&stream, 2); for (i = 0; i < beacon->bmis.ps.ps[nb_ps].ns; i++) { test_fail_unless (bitstream_read (&stream, 1) == beacon->bmis.ps.ps[nb_ps].sais[i].stpf); test_fail_unless (bitstream_read (&stream, 7) == beacon->bmis.ps.ps[nb_ps].sais[i].glid); if (beacon->bmis.ps.ps[nb_ps].sais[i].stpf) { test_fail_unless (bitstream_read (&stream, 12) == beacon->bmis.ps.ps[nb_ps].sais[i].start_time_atu); nb_sai++; } else nb_nsai++; test_fail_unless (bitstream_read (&stream, 12) == beacon->bmis.ps.ps[nb_ps].sais[i].end_time_atu); } test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_PERSISTENT_SCHED (nb_sai, nb_nsai)); nb_ps++; break; case BSU_BEACON_ENTRY_HEADER_MAC_ADDRESS: test_fail_unless (beacon->bmis.mac_address.present == true); test_fail_unless (ctx->mac_config.sta_mac_address == bitstream_read_large (&stream, 48)); test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_MAC_ADDRESS); break; case BSU_BEACON_ENTRY_HEADER_DISCOVER: test_fail_unless (beacon->bmis.discover.present == true); test_fail_unless (beacon->bmis.discover.tei == bitstream_read (&stream, 8)); test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_DISCOVER); break; case BSU_BEACON_ENTRY_HEADER_DISCOVERED_INFO: test_fail_unless (beacon->bmis.discover_info.present == true); test_fail_unless (beacon->bmis.discover_info.info_data == bitstream_read (&stream, 32)); test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_DISCOVER_INFO); break; case BSU_BEACON_ENTRY_HEADER_BEACON_PERIOD_START_TIME_OFFSET: test_fail_unless (beacon->bmis.bpsto.present == true); test_fail_unless (bitstream_read (&stream, 24) == 0); test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_BPSTO); break; case BSU_BEACON_ENTRY_HEADER_CCO_HANDOVER: test_fail_unless (beacon->bmis.handover.present == true); test_fail_unless (bitstream_read (&stream, 6) == beacon->bmis.handover.hcd); bitstream_skip (&stream, 2); test_fail_unless (bitstream_read (&stream, 8) == beacon->bmis.handover.tei); test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_HOIP); break; case BSU_BEACON_ENTRY_HEADER_CHANGE_HM: test_fail_unless (beacon->bmis.change_hm.present == true); test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_CHANGE_HM); test_fail_unless (bitstream_read (&stream, 6) == beacon->bmis.change_hm.hmccd); test_fail_unless (bitstream_read (&stream, 2) == beacon->bmis.change_hm.newhm); break; case BSU_BEACON_ENTRY_HEADER_CHANGE_SNID: test_fail_unless (beacon->bmis.change_snid.present == true); test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_CHANGE_SNID); test_fail_unless (bitstream_read (&stream, 4) == beacon->bmis.change_snid.snidccd); test_fail_unless (bitstream_read (&stream, 4) == beacon->bmis.change_snid.new_snid); break; case BSU_BEACON_ENTRY_HEADER_ENCRYPTION_KEY_CHANGE: test_fail_unless (beacon->bmis.eks.present == true); test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_EKC); test_fail_unless (bitstream_read (&stream, 6) == beacon->bmis.eks.kccd); test_fail_unless (bitstream_read (&stream, 1) == beacon->bmis.eks.kbc); bitstream_skip (&stream, 1); test_fail_unless (bitstream_read (&stream, 4) == beacon->bmis.eks.new_eks); bitstream_skip (&stream, 4); break; case BSU_BEACON_ENTRY_HEADER_BEACON_RELOCATION: test_fail_unless (beacon->bmis.relocation.present == true); test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_RLO); test_fail_unless (bitstream_read (&stream, 6) == beacon->bmis.relocation.rcd); test_fail_unless (bitstream_read (&stream, 1) == beacon->bmis.relocation.rlt); test_fail_unless (bitstream_read (&stream, 1) == beacon->bmis.relocation.lgf); test_fail_unless (bitstream_read (&stream, 17) == beacon->bmis.relocation.rlo); test_fail_unless (bitstream_read (&stream, 3) == beacon->bmis.relocation.rlslotid); bitstream_skip (&stream, 4); break; case BSU_BEACON_ENTRY_HEADER_AC_LINE_SYNC_COUNTDOWN: test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_ACL); test_fail_unless (beacon->bmis.aclsc.present == true); test_fail_unless (bitstream_read (&stream, 6) == beacon->bmis.aclsc.countdown); bitstream_skip (&stream, 2); test_fail_unless (bitstream_read (&stream, 2) == beacon->bmis.aclsc.reason_code); bitstream_skip (&stream, 6); break; case BSU_BEACON_ENTRY_HEADER_CHANGE_NUMSLOTS: test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_CHANGE_NUMSLOTS); test_fail_unless (beacon->bmis.cns.present == true); test_fail_unless (bitstream_read (&stream, 6) == beacon->bmis.cns.nsccd); bitstream_skip (&stream, 2); test_fail_unless (bitstream_read (&stream, 3) == beacon->bmis.cns.newnumslot); bitstream_skip (&stream, 5); break; default: test_fail_unless (false); } } } test_end; } void bsu_test_beacon_check_read (test_t t, bsu_test_t *ctx, bsu_beacon_t *beacon, bsu_avln_t *sched) { uint i,j; test_begin (t, "Beacon check read") { /* Only verify the schedules. */ test_fail_unless (beacon->bmis.ps.nb == sched->beacon.bmis.ps.nb); for (i = 0; i < beacon->bmis.ps.nb; i++) { test_fail_unless (beacon->bmis.ps.ps[i].pscd == sched->beacon.bmis.ps.ps[i].pscd); test_fail_unless (beacon->bmis.ps.ps[i].cscd == sched->beacon.bmis.ps.ps[i].cscd); test_fail_unless (beacon->bmis.ps.ps[i].ns == sched->beacon.bmis.ps.ps[i].ns); for (j = 0; j < sched->beacon.bmis.ps.ps[i].ns; j ++) { test_fail_unless (beacon->bmis.ps.ps[i].sais[j].stpf == sched->beacon.bmis.ps.ps[i].sais[j].stpf); test_fail_unless (beacon->bmis.ps.ps[i].sais[j].glid == sched->beacon.bmis.ps.ps[i].sais[j].glid); if (sched->beacon.bmis.ps.ps[i].sais[j].stpf) test_fail_unless ( beacon->bmis.ps.ps[i].sais[j].start_time_atu == sched->beacon.bmis.ps.ps[i].sais[j].start_time_atu); test_fail_unless ( beacon->bmis.ps.ps[i].sais[j].end_time_atu == sched->beacon.bmis.ps.ps[i].sais[j].end_time_atu); } } test_fail_unless (beacon->bmis.nps.ns == sched->beacon.bmis.nps.ns); for (i = 0; i < beacon->bmis.nps.ns; i++) { test_fail_unless (beacon->bmis.nps.sais[i].stpf == sched->beacon.bmis.nps.sais[i].stpf); test_fail_unless (beacon->bmis.nps.sais[i].glid == sched->beacon.bmis.nps.sais[i].glid); if (sched->beacon.bmis.nps.sais[i].stpf) test_fail_unless ( beacon->bmis.nps.sais[i].start_time_atu == sched->beacon.bmis.nps.sais[i].start_time_atu); test_fail_unless (beacon->bmis.nps.sais[i].end_time_atu == sched->beacon.bmis.nps.sais[i].end_time_atu); } } test_end; } void bsu_test_avln_create (bsu_test_t *ctx, bsu_avln_t *avln) { avln->beacon.bmis.bpsto.present = true; avln->beacon.bmis.bpsto.bpsto = 0x45; avln->beacon.vf.hm = MAC_COEXISTENCE_FULL_HYBRID_MODE; ctx->bsu->nek_switch = 0; avln->snid = 0; bsu_test_schedules_persistent (ctx, &avln->beacon.bmis.ps); bsu_test_schedules_non_persistent (ctx, &avln->beacon.bmis.nps); } static u32 phy_zero_cross_interval (bsu_aclf_test_phy_t *ctx) { return 25.0e6 / ctx->frequency_hz; } void phy_clock (bsu_aclf_test_phy_t *ctx, u32 ticks) { ctx->phy_date += ticks; uint zc_interval_tck = phy_zero_cross_interval (ctx); uint zc_nb_interval_since_last_date = (ctx->phy_date - ctx->zero_crossing_date) / zc_interval_tck; u32 zc_next_date = ctx->zero_crossing_date + zc_nb_interval_since_last_date * zc_interval_tck; ctx->zero_crossing_date = zc_next_date; } u32 phy_date (void) { if (phy_test_global.use_phy_clock) phy_clock (&phy_test_global, 1000); return phy_test_global.phy_date; } u32 phy_clock_get_zero_cross_captured_date (phy_t *ctx) { return phy_test_global.zero_crossing_date; } u32 phy_sysdate (void) { return phy_test_global.phy_date; } void phy_clock_set_numerator (phy_t *ctx, u32 numerator) { }