skip to content
==> tests/doc.c <==
1/* fleet.rs document_round_trips (the document part), group rank/order, can_run, decode errors. */
2#include "mesh/check.h"
3#include "mesh/fleet_doc.h"
4
5#include <stdlib.h>
6
7static mfd_doc doc(void) {
8    mfd_doc d = {.version = 7, .term = 3};
9    mesh_needs n = msn_default();
10    mfd_prog h = mfd_prog_new("hello", 0xabc, true, &n);
11    h.reset = 2;
12    mt_push(&h.backends, "cuda");
13    mt_push(&h.backends, "wasm");
14    mfd_prog_put(&d, "hello", h);
15    mfd_prog t = mfd_prog_new("train-b", 0x123, true, &n);
16    t.lockstep = true;
17    mt_push(&t.backends, "cuda");
18    t.has_prev = true;
19    t.prev_dir = mt_strdup("train");
20    t.prev_hash = 0x99;
21    mfd_prog_put(&d, "train", t);
22    mesh_needs_free(&n);
23    mfd_group g = {.name = mt_strdup("train"), .program = mt_strdup("train"), .epoch = 4, .cycle = 2, .op = {MFD_OP_TASK, 3, 1000593162},
24                   .members = ml_of((uint32_t[]){0, 2, 3}, 3), .state = MFD_RUNNING, .on_loss = MFD_LOSS_REFORM, .auto_ms = 5000};
25    mfd_group_push(&d, g);
26    mt_strs w = {0};
27    mt_push(&w, "split");
28    mt_push(&w, "auto");
29    mfd_place_put(&d, "doom", w);
30    return d;
31}
32
33static void round_trip(const mfd_doc *d) {
34    char *e = mfd_encode(d);
35    mfd_doc back;
36    char *err = NULL;
37    CHECK(mfd_decode(e, &back, &err));
38    CHECK(mfd_doc_eq(&back, d));
39    mfd_doc_free(&back);
40    free(e);
41}
42
43static void bad(const char *text, const char *want) {
44    mfd_doc d;
45    char *err = NULL;
46    CHECK(!mfd_decode(text, &d, &err));
47    if (want) CHECK_S(err, want);
48    free(err);
49}
50
51int main(void) {
52    mfd_doc d = doc();
53    round_trip(&d);
54    char *e = mfd_encode(&d);
55    CHECK_S(e, "doc version 7 term 3\n"
56               "program hello dir hello hash 0000000000000abc run 1 reset 2 lockstep 0 backends cuda,wasm prev - 0 at * from - pin * needs "
57               "b=cuda;ar=-;mm=0;pf=-;av=-;r=all;sp=spread;co=-;fd=-;g=-;gs=0;gm=-;pr=0;cpu=0;mem=0;mg=state;ls=0;vb=0;w=1;sh=0 why \n"
58               "program train dir train-b hash 0000000000000123 run 1 reset 0 lockstep 1 backends cuda prev train 0000000000000099 at * from - pin * needs "
59               "b=cuda;ar=-;mm=0;pf=-;av=-;r=all;sp=spread;co=-;fd=-;g=-;gs=0;gm=-;pr=0;cpu=0;mem=0;mg=state;ls=0;vb=0;w=1;sh=0 why \n"
60               "group train program train epoch 4 cycle 2 op task:3:1000593162 members 0,2,3 state running on_loss reform auto_ms 5000\n"
61               "place doom split,auto\n"
62               "sched paused 0 autoreform 0 cordon -\n");
63    free(e);
64    mfd_doc empty = {0};
65    round_trip(&empty);
66    /* The scheduler's fields: a placement, a migration, a pin, the needs, the why; the sched flags. */
67    mfd_doc x = mfd_doc_clone(&d);
68    mfd_prog *h = mfd_prog_get(&x, "hello");
69    ml_opt_free(&h->at);
70    h->at = ml_some((uint32_t[]){1, 3}, 2);
71    h->has_from = h->has_to = true;
72    h->from = 2;
73    h->to = 3;
74    h->since = 41;
75    h->pin = ml_some((uint32_t[]){3}, 1);
76    h->needs.replicas = (mesh_replicas){false, 2};
77    msn_terms_push(&h->needs.prefer, &h->needs.nprefer, msn_term_new(MESH_TERM_HOST, "dgx-00", 0));
78    mt_set(&h->why, "replicas 2: system 1 0.812, system 3 0.700; next system 0 0.6");
79    mfd_prog *t = mfd_prog_get(&x, "train");
80    t->at = ml_some(NULL, 0);
81    x.sched_paused = true;
82    x.autoreform = true;
83    x.cordon = 9;
84    round_trip(&x);
85    /* A migration's source alone (no target). */
86    h->has_to = false;
87    h->since = 0;
88    round_trip(&x);
89    mfd_doc_free(&x);
90    bad("program x", "fleet document line 1: \"program x\"");
91    bad("", "fleet document: no `doc version .. term ..` line");
92    bad("doc version 1 term 1\ngroup g program p epoch 1 cycle 0 op bogus members - state running on_loss pause auto_ms 0", "bad op \"bogus\"");
93    bad("doc version 1 term 1\ngroup g program p epoch 1 cycle 0 op none members 9 state running on_loss pause auto_ms 0", "member 9 >= 8");
94    bad("doc version 1 term 1\ngroup g program p epoch 1 cycle 0 op none members - state sleeping on_loss pause auto_ms 0", NULL);
95    bad("doc version x term 1", "fleet document line 1: \"doc version x term 1\"");
96    /* Group rank and order. */
97    uint32_t r;
98    CHECK(mfd_group_rank(&d.groups[0], 2, &r) && r == 1 && !mfd_group_rank(&d.groups[0], 1, &r));
99    uint8_t o[MESH_MAX_SYSTEMS];
100    mfd_group_order(&d.groups[0], o);
101    CHECK(o[0] == 0 && o[1] == 2 && o[2] == 3 && o[3] == 0xff && o[7] == 0xff);
102    CHECK_U(mfd_group_mask(&d.groups[0]), 0xd);
103    /* here: placed there, or the source of a migration. */
104    mfd_prog *hp = mfd_prog_get(&d, "hello");
105    CHECK(mfd_prog_here(hp, 5));
106    hp->at = ml_some((uint32_t[]){1}, 1);
107    CHECK(mfd_prog_here(hp, 1) && !mfd_prog_here(hp, 2));
108    hp->has_from = true;
109    hp->from = 2;
110    CHECK(mfd_prog_here(hp, 2));
111    /* can_run: the member's GPU, or wasm / native anywhere. */
112    mt_strs b = {0};
113    mt_push(&b, "metal");
114    CHECK(mfd_can_run(&b, 1) && !mfd_can_run(&b, 0) && !mfd_can_run(&b, 99));
115    mt_push(&b, "native");
116    CHECK(mfd_can_run(&b, 0));
117    mt_strs_free(&b);
118    /* Maps: replace, remove. */
119    CHECK(mfd_prog_remove(&d, "hello") && !mfd_prog_remove(&d, "hello") && d.nprogs == 1);
120    CHECK(mfd_place_remove(&d, "doom") && mfd_place_get(&d, "doom") == NULL);
121    CHECK(mfd_group_of(&d, "train") && mfd_group_named(&d, "train") && !mfd_group_of(&d, "x"));
122    mfd_group_remove_at(&d, 0);
123    CHECK_U(d.ngroups, 0);
124    CHECK(mfd_id_cmp(3, 9, 4, 1) < 0 && mfd_id_cmp(4, 2, 4, 1) > 0 && mfd_id_cmp(1, 1, 1, 1) == 0);
125    mfd_doc_free(&d);
126    return mesh_check_done();
127}