skip to content
==> tests/groups.c <==
1/* fleet.rs group_epochs. */
2#include "mesh/check.h"
3#include "mesh/fleet_groups.h"
4#include "mesh/mt.h"
5
6#include <stdlib.h>
7
8
9int main(void) {
10    mfd_group g = {.name = mt_strdup("train"), .program = mt_strdup("train"), .epoch = 1, .cycle = 3, .op = {MFD_OP_UPGRADE, 0, 0},
11                   .members = ml_of((uint32_t[]){0, 1, 2}, 3), .state = MFD_RUNNING, .on_loss = MFD_LOSS_PAUSE};
12    mfd_group p, r, q, s, t, x;
13    CHECK(!mfg_policy(&g, 7, -1, &x));
14    CHECK(mfg_policy(&g, 3, -1, &p));
15    CHECK(p.state == MFD_PAUSED && p.epoch == 1 && p.members.n == 3);
16    CHECK(!mfg_policy(&p, 3, 60000, &x));
17    CHECK(mfg_policy(&p, 15, -1, &r));
18    CHECK(r.state == MFD_RUNNING && r.epoch == 2 && r.cycle == 0 && r.members.n == 3 && r.op.kind == MFD_OP_NONE);
19    q = mfd_group_clone(&p);
20    q.on_loss = MFD_LOSS_REFORM;
21    q.auto_ms = 2000;
22    CHECK(!mfg_policy(&q, 5, 1999, &x));
23    CHECK(mfg_policy(&q, 5, 2000, &s));
24    CHECK(s.epoch == 2 && s.members.n == 2 && s.members.v[0] == 0 && s.members.v[1] == 2 && s.state == MFD_RUNNING);
25    /* A member that comes back later does not disturb the running epoch... */
26    CHECK(!mfg_policy(&s, 7, -1, &x));
27    /* ... until the next reform, which takes every eligible up member. */
28    ml_list all = ml_of((uint32_t[]){0, 1, 2}, 3), empty = {0};
29    char *err = NULL;
30    CHECK(mfg_reform(&s, &all, &t, &err) && t.epoch == 3 && t.members.n == 3);
31    CHECK(!mfg_reform(&s, &empty, &x, &err));
32    CHECK_S(err, "group train: no member that can run train is up");
33    free(err);
34    /* Survivors gone too: no reform. */
35    CHECK(!mfg_policy(&q, 8, 5000, &x));
36    ml_free(&all);
37    mfd_group_free(&g), mfd_group_free(&p), mfd_group_free(&r), mfd_group_free(&q), mfd_group_free(&s), mfd_group_free(&t);
38    return mesh_check_done();
39}