==> 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}