kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

build_public_link_test.c (9892B)


      1 #include <kit/build_coord.h>
      2 
      3 #include "lib/kit_unit.h"
      4 
      5 #include <string.h>
      6 
      7 static KitUnit g_u;
      8 
      9 #define EXPECT(c, ...) CU_EXPECT(&g_u, c, __VA_ARGS__)
     10 
     11 typedef struct TestConn {
     12   int unused;
     13 } TestConn;
     14 
     15 typedef struct TestTransport {
     16   TestConn conn;
     17   const uint8_t* replies[16];
     18   size_t reply_lens[16];
     19   size_t nreplies;
     20   size_t next_reply;
     21   uint8_t writes[16][256];
     22   size_t write_lens[16];
     23   size_t nwrites;
     24   int dialed;
     25   int closed;
     26 } TestTransport;
     27 
     28 const char* kit_debug_getenv(const char* name) {
     29   if (kit_slice_eq_cstr(kit_slice_cstr(name), KIT_BUILD_ENV_SOCK))
     30     return "client-test";
     31   return NULL;
     32 }
     33 
     34 static void put_u8(uint8_t* buf, size_t* n, uint8_t v) { buf[(*n)++] = v; }
     35 
     36 static void put_u16(uint8_t* buf, size_t* n, uint16_t v) {
     37   put_u8(buf, n, (uint8_t)(v & 0xffu));
     38   put_u8(buf, n, (uint8_t)((v >> 8) & 0xffu));
     39 }
     40 
     41 static void put_u64(uint8_t* buf, size_t* n, uint64_t v) {
     42   size_t i;
     43   for (i = 0; i < 8u; ++i) put_u8(buf, n, (uint8_t)(v >> (8u * i)));
     44 }
     45 
     46 static void put_bytes(uint8_t* buf, size_t* n, const void* data, size_t len) {
     47   if (len) memcpy(buf + *n, data, len);
     48   *n += len;
     49 }
     50 
     51 static void put_slice(uint8_t* buf, size_t* n, KitSlice s) {
     52   put_u16(buf, n, (uint16_t)s.len);
     53   put_bytes(buf, n, s.data, s.len);
     54 }
     55 
     56 static void fill_id(uint8_t id[KIT_BUILD_HASH_LEN], uint8_t seed) {
     57   size_t i;
     58   for (i = 0; i < KIT_BUILD_HASH_LEN; ++i) id[i] = (uint8_t)(seed + i);
     59 }
     60 
     61 static size_t resp_config(uint8_t* buf, KitSlice value) {
     62   size_t n = 0;
     63   put_u8(buf, &n, 0);
     64   put_slice(buf, &n, value);
     65   return n;
     66 }
     67 
     68 static size_t resp_source(uint8_t* buf, uint8_t seed, KitSlice path) {
     69   uint8_t id[KIT_BUILD_HASH_LEN];
     70   size_t n = 0;
     71   fill_id(id, seed);
     72   put_u8(buf, &n, 0);
     73   put_bytes(buf, &n, id, sizeof id);
     74   put_slice(buf, &n, path);
     75   return n;
     76 }
     77 
     78 static size_t resp_glob_path(uint8_t* buf, KitSlice path) {
     79   size_t n = 0;
     80   put_u8(buf, &n, 0);
     81   put_u16(buf, &n, 1);
     82   put_slice(buf, &n, path);
     83   return n;
     84 }
     85 
     86 static size_t resp_status(uint8_t* buf, uint8_t status) {
     87   size_t n = 0;
     88   put_u8(buf, &n, status);
     89   return n;
     90 }
     91 
     92 static size_t resp_need(uint8_t* buf, uint8_t seed, KitSlice path) {
     93   uint8_t id[KIT_BUILD_HASH_LEN];
     94   size_t n = 0;
     95   fill_id(id, seed);
     96   put_u8(buf, &n, 0);
     97   put_bytes(buf, &n, id, sizeof id);
     98   put_slice(buf, &n, path);
     99   return n;
    100 }
    101 
    102 static size_t resp_submit(uint8_t* buf, uint64_t token) {
    103   size_t n = 0;
    104   put_u8(buf, &n, 0);
    105   put_u64(buf, &n, token);
    106   return n;
    107 }
    108 
    109 static int t_dial(void* user, KitSlice endpoint, KitBuildConn** out) {
    110   TestTransport* t = (TestTransport*)user;
    111   if (!kit_slice_eq(endpoint, KIT_SLICE_LIT("client-test")) || !out) return 1;
    112   t->dialed++;
    113   *out = (KitBuildConn*)&t->conn;
    114   return 0;
    115 }
    116 
    117 static int t_read(void* user, KitBuildConn* conn, uint8_t* buf, size_t cap,
    118                   size_t* n) {
    119   TestTransport* t = (TestTransport*)user;
    120   (void)conn;
    121   if (!buf || !n || t->next_reply >= t->nreplies ||
    122       t->reply_lens[t->next_reply] > cap)
    123     return 1;
    124   memcpy(buf, t->replies[t->next_reply], t->reply_lens[t->next_reply]);
    125   *n = t->reply_lens[t->next_reply];
    126   t->next_reply++;
    127   return 0;
    128 }
    129 
    130 static int t_write(void* user, KitBuildConn* conn, const uint8_t* buf,
    131                    size_t n) {
    132   TestTransport* t = (TestTransport*)user;
    133   (void)conn;
    134   if (!buf || t->nwrites >= 16 || n > sizeof t->writes[0]) return 1;
    135   memcpy(t->writes[t->nwrites], buf, n);
    136   t->write_lens[t->nwrites] = n;
    137   t->nwrites++;
    138   return 0;
    139 }
    140 
    141 static void t_close(void* user, KitBuildConn* conn) {
    142   TestTransport* t = (TestTransport*)user;
    143   (void)conn;
    144   t->closed++;
    145 }
    146 
    147 static int glob_count(void* user, KitSlice path) {
    148   int* n = (int*)user;
    149   if (kit_slice_eq(path, KIT_SLICE_LIT("src/a.c"))) ++*n;
    150   return 0;
    151 }
    152 
    153 static void test_client_transport(void) {
    154   TestTransport tt;
    155   KitBuildTransport tr;
    156   KitBuildClient* client = NULL;
    157   uint8_t r0[64], r1[128], r2[64], r3[4], r4[128], r5[32], r6[128];
    158   KitSlice value;
    159   int present = 0;
    160   uint8_t blob[KIT_BUILD_HASH_LEN];
    161   KitBuildKV kv;
    162   KitSlice argv;
    163   KitBuildRequest req;
    164   KitBuildResult result;
    165   KitBuildNeedToken token;
    166   int nglob = 0;
    167 
    168   memset(&tt, 0, sizeof tt);
    169   memset(&tr, 0, sizeof tr);
    170   tr.dial = t_dial;
    171   tr.read_frame = t_read;
    172   tr.write_frame = t_write;
    173   tr.close = t_close;
    174   tr.user = &tt;
    175   tt.replies[tt.nreplies] = r0;
    176   tt.reply_lens[tt.nreplies++] = resp_config(r0, KIT_SLICE_LIT("debug"));
    177   tt.replies[tt.nreplies] = r1;
    178   tt.reply_lens[tt.nreplies++] =
    179       resp_source(r1, 0x10, KIT_SLICE_LIT("/work/src/main.c"));
    180   tt.replies[tt.nreplies] = r2;
    181   tt.reply_lens[tt.nreplies++] = resp_glob_path(r2, KIT_SLICE_LIT("src/a.c"));
    182   tt.replies[tt.nreplies] = r3;
    183   tt.reply_lens[tt.nreplies++] = resp_status(r3, 3);
    184   tt.replies[tt.nreplies] = r4;
    185   tt.reply_lens[tt.nreplies++] =
    186       resp_need(r4, 0x20, KIT_SLICE_LIT("/out/lib"));
    187   tt.replies[tt.nreplies] = r5;
    188   tt.reply_lens[tt.nreplies++] = resp_submit(r5, 42);
    189   tt.replies[tt.nreplies] = r6;
    190   tt.reply_lens[tt.nreplies++] =
    191       resp_need(r6, 0x30, KIT_SLICE_LIT("/out/tool"));
    192 
    193   EXPECT(kit_build_client_open(&g_u.ctx, &tr, &client) == KIT_OK && client &&
    194              tt.dialed == 1,
    195          "client open dials env endpoint");
    196   EXPECT(kit_build_client_config_get(client, KIT_SLICE_LIT("mode"),
    197                                      KIT_SLICE_NULL, 0, &value, &present) ==
    198              KIT_OK &&
    199              present && kit_slice_eq(value, KIT_SLICE_LIT("debug")),
    200          "client config get");
    201   EXPECT(kit_build_client_source(client, KIT_SLICE_LIT("src/main.c"), blob,
    202                                  &value) == KIT_OK &&
    203              blob[0] == 0x10 &&
    204              kit_slice_eq(value, KIT_SLICE_LIT("/work/src/main.c")),
    205          "client source");
    206   EXPECT(kit_build_client_glob(client, KIT_SLICE_LIT("src/*.c"), glob_count,
    207                                &nglob) == KIT_OK &&
    208              nglob == 1,
    209          "client glob stream");
    210 
    211   kv.key = KIT_SLICE_LIT("opt");
    212   kv.value = KIT_SLICE_LIT("2");
    213   argv = KIT_SLICE_LIT("--fast");
    214   memset(&req, 0, sizeof req);
    215   req.target = KIT_SLICE_LIT("//lib:core");
    216   req.config = &kv;
    217   req.nconfig = 1;
    218   req.argv = &argv;
    219   req.argc = 1;
    220   EXPECT(kit_build_client_need(client, &req, &result) == KIT_OK &&
    221              result.output_tree[0] == 0x20 &&
    222              strcmp(result.path, "/out/lib") == 0,
    223          "client need");
    224   EXPECT(kit_build_client_need_submit(client, &req, &token) == KIT_OK &&
    225              token.id == 42,
    226          "client need submit");
    227   EXPECT(kit_build_client_need_await(client, token, &result) == KIT_OK &&
    228              result.output_tree[0] == 0x30 &&
    229              strcmp(result.path, "/out/tool") == 0,
    230          "client need await");
    231   EXPECT(tt.nwrites == 6 && tt.writes[0][0] == 1 && tt.writes[1][0] == 2 &&
    232              tt.writes[2][0] == 3 && tt.writes[3][0] == 4 &&
    233              tt.writes[4][0] == 5 && tt.writes[5][0] == 6,
    234          "client request command order");
    235   kit_build_client_close(client);
    236   EXPECT(tt.closed == 1, "client close");
    237 }
    238 
    239 static void test_public_symbols(void) {
    240   KitBuildStats stats;
    241   KitBuildClient* client = (KitBuildClient*)1;
    242   KitBuildNeedToken token;
    243   KitBuildResult result;
    244   KitBuildTestResult test_result;
    245   KitSlice value;
    246   int present = 1;
    247 
    248   memset(&stats, 0xff, sizeof stats);
    249   kit_build_stats(NULL, &stats);
    250   EXPECT(stats.deep_hits == 0 && stats.shallow_hits == 0 &&
    251              stats.recipes_run == 0 && stats.materialize_misses == 0 &&
    252              stats.object_fetches == 0 && stats.trace_pulls == 0 &&
    253              stats.test_runs == 0 && stats.test_cache_hits == 0 &&
    254              stats.test_failures == 0,
    255          "stats null handle clears output");
    256   EXPECT(kit_build(NULL, NULL, NULL) == KIT_INVALID, "kit_build rejects nulls");
    257   EXPECT(kit_build_test(NULL, NULL, NULL) == KIT_INVALID,
    258          "kit_build_test rejects nulls");
    259   memset(&test_result, 0, sizeof test_result);
    260   test_result.status = KIT_TEST_FAIL;
    261   EXPECT(test_result.status == KIT_TEST_FAIL &&
    262              sizeof test_result.stdout_blob == KIT_BUILD_HASH_LEN &&
    263              sizeof test_result.stderr_blob == KIT_BUILD_HASH_LEN,
    264          "test result public fields link");
    265   EXPECT(kit_build_coordinator_open(NULL, NULL, KIT_SLICE_NULL, NULL, NULL) ==
    266              KIT_INVALID,
    267          "coordinator open rejects nulls");
    268   EXPECT(kit_build_traces_export(NULL, NULL) == KIT_ERR,
    269          "trace export fails explicitly");
    270   EXPECT(kit_build_traces_import(NULL, NULL, NULL) == KIT_ERR,
    271          "trace import fails explicitly");
    272 
    273   EXPECT(kit_build_client_open(NULL, NULL, &client) == KIT_INVALID &&
    274              client == NULL,
    275          "client open rejects invalid args");
    276   EXPECT(kit_build_client_config_get(NULL, KIT_SLICE_LIT("x"), KIT_SLICE_NULL,
    277                                      0, &value, &present) == KIT_INVALID &&
    278              value.s == NULL && value.len == 0 && present == 0,
    279          "client config rejects invalid args");
    280   EXPECT(kit_build_client_source(NULL, KIT_SLICE_LIT("x"), result.output_tree,
    281                                  &value) == KIT_INVALID,
    282          "client source rejects invalid args");
    283   EXPECT(kit_build_client_glob(NULL, KIT_SLICE_LIT("*"), NULL, NULL) ==
    284              KIT_INVALID,
    285          "client glob rejects invalid args");
    286   EXPECT(kit_build_client_need(NULL, NULL, &result) == KIT_INVALID,
    287          "client need rejects invalid args");
    288   EXPECT(kit_build_client_need_submit(NULL, NULL, &token) == KIT_INVALID &&
    289              token.id == 0,
    290          "client need-submit rejects invalid args");
    291   token.id = 7;
    292   EXPECT(kit_build_client_need_await(NULL, token, &result) == KIT_INVALID,
    293          "client need-await rejects invalid args");
    294   kit_build_client_close(NULL);
    295 }
    296 
    297 int main(void) {
    298   kit_unit_init(&g_u);
    299   test_public_symbols();
    300   test_client_transport();
    301   kit_unit_summary(&g_u, "build_public_link_test");
    302   return kit_unit_status(&g_u);
    303 }