build_pure_test.c (23047B)
1 #include "build/build.h" 2 #include "build/bundle.h" 3 #include "build/cfg.h" 4 #include "build/defn.h" 5 #include "build/protocol.h" 6 #include "build/trace.h" 7 #include "lib/kit_unit.h" 8 9 #include <string.h> 10 11 static KitUnit g_u; 12 13 #define EXPECT(c, ...) CU_EXPECT(&g_u, c, __VA_ARGS__) 14 15 static int emit_to_slice(int (*emit)(void*, KitWriter*), void* obj, 16 KitSlice* out, KitWriter** writer_out) { 17 KitWriter* w = NULL; 18 const uint8_t* bytes; 19 size_t len; 20 if (kit_writer_mem(&g_u.heap, &w) != KIT_OK || !w) return 0; 21 if (emit(obj, w) != BUILD_OK || kit_writer_status(w) != KIT_OK) { 22 kit_writer_close(w); 23 return 0; 24 } 25 bytes = kit_writer_mem_bytes(w, &len); 26 out->data = bytes; 27 out->len = len; 28 *writer_out = w; 29 return 1; 30 } 31 32 static int emit_config_adapter(void* obj, KitWriter* w) { 33 return build_config_emit((const BuildConfig*)obj, w); 34 } 35 36 static int emit_argv_adapter(void* obj, KitWriter* w) { 37 return build_argv_emit((const BuildArgv*)obj, w); 38 } 39 40 static void fill_id(uint8_t id[BUILD_HASH_LEN], uint8_t seed) { 41 size_t i; 42 for (i = 0; i < BUILD_HASH_LEN; ++i) id[i] = (uint8_t)(seed + i); 43 } 44 45 static int bytes_contains(const void* hay, size_t hay_len, const char* needle) { 46 const uint8_t* h = (const uint8_t*)hay; 47 size_t n = strlen(needle); 48 size_t i; 49 if (!needle || n == 0u) return 1; 50 if (!hay || hay_len < n) return 0; 51 for (i = 0; i + n <= hay_len; ++i) 52 if (memcmp(h + i, needle, n) == 0) return 1; 53 return 0; 54 } 55 56 static void test_config_and_argv(void) { 57 BuildConfigEntry cfg_storage[4], parsed_storage[4], over_storage[4]; 58 char argv_storage[3][BUILD_VAL_MAX], parsed_argv_storage[3][BUILD_VAL_MAX]; 59 BuildConfig cfg, parsed, over; 60 BuildArgv argv, parsed_argv; 61 KitBuildKV ov[2]; 62 KitSlice bytes; 63 KitWriter* w = NULL; 64 KitSlice val; 65 int present = 0; 66 uint8_t id1[BUILD_HASH_LEN], id2[BUILD_HASH_LEN]; 67 static const char bad[] = "kit-build-config 1\nz 1\na 2\n"; 68 69 build_config_init(&cfg, cfg_storage, 4); 70 build_config_init(&parsed, parsed_storage, 4); 71 build_config_init(&over, over_storage, 4); 72 EXPECT(build_config_set(&cfg, KIT_SLICE_LIT("opt"), KIT_SLICE_LIT("2")) == 73 BUILD_OK, 74 "set opt"); 75 EXPECT(build_config_set(&cfg, KIT_SLICE_LIT("arch"), KIT_SLICE_LIT("aa64")) == 76 BUILD_OK, 77 "set arch"); 78 EXPECT(emit_to_slice(emit_config_adapter, &cfg, &bytes, &w), 79 "emit config"); 80 EXPECT(bytes.len == strlen("kit-build-config 1\narch aa64\nopt 2\n") && 81 memcmp(bytes.data, "kit-build-config 1\narch aa64\nopt 2\n", 82 bytes.len) == 0, 83 "canonical config bytes"); 84 EXPECT(build_config_parse(bytes.data, bytes.len, &parsed, NULL, 0) == 85 BUILD_OK, 86 "parse emitted config"); 87 EXPECT(build_config_get(&parsed, KIT_SLICE_LIT("arch"), &val, &present) == 88 BUILD_OK && 89 present && kit_slice_eq(val, KIT_SLICE_LIT("aa64")), 90 "get parsed config"); 91 EXPECT(build_config_id(&g_u.heap, &cfg, id1) == BUILD_OK && 92 build_config_id(&g_u.heap, &parsed, id2) == BUILD_OK && 93 build_id_eq(id1, id2), 94 "config id roundtrip"); 95 kit_writer_close(w); 96 97 EXPECT(build_config_parse((const uint8_t*)bad, sizeof bad - 1u, &parsed, NULL, 98 0) == BUILD_ERR, 99 "reject non-canonical config"); 100 101 ov[0].key = KIT_SLICE_LIT("opt"); 102 ov[0].value = KIT_SLICE_LIT("3"); 103 ov[1].key = KIT_SLICE_LIT("mode"); 104 ov[1].value = KIT_SLICE_LIT("dbg"); 105 EXPECT(build_config_overlay(&cfg, ov, 2, &over) == BUILD_OK, 106 "overlay config"); 107 EXPECT(build_config_get(&over, KIT_SLICE_LIT("opt"), &val, &present) == 108 BUILD_OK && 109 present && kit_slice_eq(val, KIT_SLICE_LIT("3")), 110 "overlay replaces"); 111 112 build_argv_init(&argv, argv_storage, 3); 113 build_argv_init(&parsed_argv, parsed_argv_storage, 3); 114 { 115 KitSlice args[2]; 116 args[0] = KIT_SLICE_LIT("--emit"); 117 args[1] = KIT_SLICE_LIT("obj"); 118 EXPECT(build_argv_set(&argv, args, 2) == BUILD_OK, "set argv"); 119 } 120 EXPECT(emit_to_slice(emit_argv_adapter, &argv, &bytes, &w), "emit argv"); 121 EXPECT(bytes.len == strlen("kit-build-argv 1\n--emit\nobj\n") && 122 memcmp(bytes.data, "kit-build-argv 1\n--emit\nobj\n", 123 bytes.len) == 0, 124 "argv preserves order"); 125 EXPECT(build_argv_parse(bytes.data, bytes.len, &parsed_argv, NULL, 0) == 126 BUILD_OK && 127 parsed_argv.n == 2 && 128 strcmp(parsed_argv.args[0], "--emit") == 0 && 129 strcmp(parsed_argv.args[1], "obj") == 0, 130 "parse argv"); 131 kit_writer_close(w); 132 } 133 134 static void test_defn(void) { 135 static const char text[] = "kit-build 1\n" 136 "[target bin]\n" 137 "recipe //recipes/app.sh\n" 138 "[target core]\n" 139 "recipe recipes/lib.sh\n"; 140 static const char text2[] = "kit-build 2\n" 141 "\n" 142 "[default c.object]\n" 143 "recipe //recipes/c-object.sh\n" 144 "\n" 145 "[rule object]\n" 146 "match *.o\n" 147 "type c.object\n" 148 "\n" 149 "[redo-defaults]\n" 150 "enabled true\n" 151 "search . do\n" 152 "walk-parents true\n"; 153 static const char unsorted[] = "kit-build 1\n" 154 "[target z]\n" 155 "recipe recipes/z.sh\n" 156 "[target a]\n" 157 "recipe recipes/a.sh\n"; 158 BuildTargetDefn storage[4]; 159 BuildDefaultDefn defaults[2]; 160 BuildRuleDefn rules[2]; 161 BuildDefn defn; 162 const BuildTargetDefn* t; 163 const BuildRuleDefn* r; 164 const BuildDefaultDefn* d; 165 char label[BUILD_TARGET_MAX]; 166 char package[BUILD_PATH_MAX]; 167 char local[BUILD_TARGET_MAX]; 168 int ambiguous = 0; 169 170 memset(&defn, 0, sizeof defn); 171 defn.targets = storage; 172 defn.cap_targets = 4; 173 defn.defaults = defaults; 174 defn.cap_defaults = 2; 175 defn.rules = rules; 176 defn.cap_rules = 2; 177 EXPECT(build_defn_parse((const uint8_t*)text, sizeof text - 1u, &defn, NULL, 178 0) == BUILD_OK, 179 "parse defn"); 180 t = build_defn_find(&defn, KIT_SLICE_LIT("core")); 181 EXPECT(t && strcmp(t->recipe_path, "recipes/lib.sh") == 0, "find target"); 182 EXPECT(build_defn_find(&defn, KIT_SLICE_LIT("none")) == NULL, 183 "missing target"); 184 EXPECT(build_defn_parse((const uint8_t*)unsorted, sizeof unsorted - 1u, &defn, 185 NULL, 0) == BUILD_ERR, 186 "reject unsorted defn"); 187 EXPECT(build_defn_parse((const uint8_t*)text2, sizeof text2 - 1u, &defn, 188 NULL, 0) == BUILD_OK, 189 "parse defn v2"); 190 d = build_defn_default_find(&defn, KIT_SLICE_LIT("c.object")); 191 EXPECT(d && strcmp(d->recipe_path, "//recipes/c-object.sh") == 0, 192 "find default recipe"); 193 r = build_defn_rule_match(&defn, KIT_SLICE_LIT("foo.o"), &ambiguous); 194 EXPECT(r && !ambiguous && strcmp(r->type, "c.object") == 0, 195 "match rule"); 196 EXPECT(defn.redo.enabled && defn.redo.walk_parents && 197 defn.redo.n_search == 2 && 198 strcmp(defn.redo.search[0], ".") == 0 && 199 strcmp(defn.redo.search[1], "do") == 0, 200 "parse redo defaults"); 201 EXPECT(build_target_canonicalize(KIT_SLICE_LIT("//app"), KIT_SLICE_NULL, 202 KIT_SLICE_NULL, label, NULL, 0) == 203 BUILD_OK && 204 strcmp(label, "//app:app") == 0, 205 "canonical package shorthand"); 206 EXPECT(build_target_canonicalize(KIT_SLICE_LIT(":lib"), 207 KIT_SLICE_NULL, KIT_SLICE_LIT("pkg/sub"), 208 label, NULL, 0) == 209 BUILD_OK && 210 strcmp(label, "//pkg/sub:lib") == 0, 211 "canonical relative label"); 212 EXPECT(build_target_canonicalize(KIT_SLICE_LIT("//dep:lib"), 213 KIT_SLICE_LIT("ext"), 214 KIT_SLICE_LIT("pkg/sub"), label, NULL, 0) == 215 BUILD_OK && 216 strcmp(label, "@ext//dep:lib") == 0, 217 "canonical repo-rooted label inside external repo"); 218 EXPECT(build_target_split_repo(KIT_SLICE_LIT("@ext//dep:lib"), label, 219 package, local) == BUILD_OK && 220 strcmp(label, "ext") == 0 && strcmp(package, "dep") == 0 && 221 strcmp(local, "lib") == 0, 222 "split external canonical target"); 223 EXPECT(build_target_canonicalize(KIT_SLICE_LIT("@child//dep:lib"), 224 KIT_SLICE_LIT("ext"), 225 KIT_SLICE_LIT("pkg/sub"), label, NULL, 0) == 226 BUILD_OK && 227 strcmp(label, "@ext+child//dep:lib") == 0, 228 "canonical nested external repo label"); 229 EXPECT(build_target_split(KIT_SLICE_LIT("//pkg/sub:lib"), package, local) == 230 BUILD_OK && 231 strcmp(package, "pkg/sub") == 0 && strcmp(local, "lib") == 0, 232 "split canonical target"); 233 } 234 235 static void test_trace(void) { 236 BuildShallowTrace st; 237 BuildConfigLeaf keys[2]; 238 BuildConfigLeaf ds_configs[2]; 239 BuildSourceLeaf sources[2], parsed_sources[2]; 240 BuildGlobLeaf globs[1], parsed_globs[1]; 241 BuildDepEdge deps[1], parsed_deps[1]; 242 BuildConfigLeaf parsed_keys[2]; 243 BuildDeepSet parsed_ds; 244 BuildShallowTrace parsed; 245 BuildDeepTrace deep, parsed_deep; 246 BuildTargetRecord rec; 247 BuildRecordRow rows[20], row; 248 KitWriter* w = NULL; 249 KitSlice bytes; 250 uint8_t trace_id[BUILD_HASH_LEN]; 251 char err[128]; 252 static const char dup_source[] = 253 "kit-build-shallow 1\n" 254 "target //app:bin\n" 255 "recipe " 256 "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\n" 257 "output " 258 "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20\n" 259 "argv " 260 "030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122\n" 261 "[config]\n" 262 "[source]\n" 263 "a.c -\n" 264 "a.c -\n" 265 "[glob]\n" 266 "[dep]\n"; 267 static const char bad_config[] = 268 "kit-build-shallow 1\n" 269 "target //app:bin\n" 270 "recipe " 271 "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\n" 272 "output " 273 "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20\n" 274 "argv " 275 "030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122\n" 276 "[config]\n" 277 "z present " 278 "0a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526272829 -\n" 279 "a unset - -\n" 280 "[source]\n" 281 "[glob]\n" 282 "[dep]\n"; 283 static const char bad_deepset_config[] = 284 "kit-build-deepset 1\n" 285 "target //app:bin\n" 286 "recipe " 287 "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\n" 288 "[config]\n" 289 "z present " 290 "0a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526272829 -\n" 291 "a unset - -\n" 292 "[source]\n" 293 "[glob]\n" 294 "[blob]\n" 295 "[child]\n"; 296 297 memset(&st, 0, sizeof st); 298 strcpy(st.target, "//app:bin"); 299 fill_id(st.recipe, 0); 300 fill_id(st.output, 1); 301 fill_id(st.argv, 3); 302 st.configs = keys; 303 st.n_configs = 2; 304 st.cap_configs = 2; 305 strcpy(keys[0].key, "z"); 306 keys[0].present = 1; 307 keys[0].has_default = 0; 308 fill_id(keys[0].value_hash, 10); 309 memset(keys[0].default_hash, 0, sizeof keys[0].default_hash); 310 strcpy(keys[1].key, "a"); 311 keys[1].present = 0; 312 keys[1].has_default = 0; 313 memset(keys[1].value_hash, 0, sizeof keys[1].value_hash); 314 memset(keys[1].default_hash, 0, sizeof keys[1].default_hash); 315 st.sources = sources; 316 st.n_sources = 2; 317 st.cap_sources = 2; 318 strcpy(sources[0].path, "src/z.c"); 319 fill_id(sources[0].blob, 4); 320 sources[0].absent = 0; 321 strcpy(sources[1].path, "src/a.c"); 322 sources[1].absent = 1; 323 st.globs = globs; 324 st.n_globs = 1; 325 st.cap_globs = 1; 326 strcpy(globs[0].pattern, "src/*.c"); 327 fill_id(globs[0].result_hash, 5); 328 st.deps = deps; 329 st.n_deps = 1; 330 st.cap_deps = 1; 331 strcpy(deps[0].name, "//lib:core"); 332 fill_id(deps[0].overlay_id, 6); 333 fill_id(deps[0].argv_id, 8); 334 fill_id(deps[0].output_tree, 9); 335 336 EXPECT(kit_writer_mem(&g_u.heap, &w) == KIT_OK && w, "trace writer"); 337 EXPECT(build_shallow_emit(&st, w, err, sizeof err) == BUILD_OK, 338 "emit shallow"); 339 bytes.data = kit_writer_mem_bytes(w, &bytes.len); 340 build_trace_id(bytes.data, bytes.len, trace_id); 341 EXPECT(!bytes_contains(bytes.data, bytes.len, "\nconfig "), 342 "shallow omits redundant effective config id"); 343 EXPECT(bytes_contains( 344 bytes.data, bytes.len, 345 "\n[dep]\n//lib:core " 346 "060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425 " 347 "08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627 " 348 "090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728\n"), 349 "shallow canonical dep row"); 350 351 memset(&parsed, 0, sizeof parsed); 352 parsed.configs = parsed_keys; 353 parsed.cap_configs = 2; 354 parsed.sources = parsed_sources; 355 parsed.cap_sources = 2; 356 parsed.globs = parsed_globs; 357 parsed.cap_globs = 1; 358 parsed.deps = parsed_deps; 359 parsed.cap_deps = 1; 360 EXPECT(build_shallow_parse(bytes.data, bytes.len, &parsed, err, sizeof err) == 361 BUILD_OK, 362 "parse shallow"); 363 EXPECT(strcmp(parsed.configs[0].key, "a") == 0 && 364 strcmp(parsed.sources[0].path, "src/a.c") == 0 && 365 parsed.sources[0].absent && 366 memcmp(parsed.deps[0].overlay_id, deps[0].overlay_id, 367 BUILD_HASH_LEN) == 0 && 368 memcmp(parsed.deps[0].argv_id, deps[0].argv_id, 369 BUILD_HASH_LEN) == 0 && 370 memcmp(parsed.deps[0].output_tree, deps[0].output_tree, 371 BUILD_HASH_LEN) == 0, 372 "shallow canonical sections"); 373 EXPECT(build_shallow_parse((const uint8_t*)dup_source, sizeof dup_source - 1u, 374 &parsed, err, sizeof err) == BUILD_ERR, 375 "reject duplicate source"); 376 EXPECT(build_shallow_parse((const uint8_t*)bad_config, 377 sizeof bad_config - 1u, &parsed, err, 378 sizeof err) == BUILD_ERR, 379 "reject non-canonical shallow config"); 380 kit_writer_close(w); 381 382 w = NULL; 383 EXPECT(kit_writer_mem(&g_u.heap, &w) == KIT_OK && w, "test trace writer"); 384 EXPECT(build_test_shallow_emit(&st, w, err, sizeof err) == BUILD_OK, 385 "emit test shallow"); 386 bytes.data = kit_writer_mem_bytes(w, &bytes.len); 387 EXPECT(bytes.len > strlen(BUILD_TEST_SHALLOW_MAGIC) && 388 memcmp(bytes.data, BUILD_TEST_SHALLOW_MAGIC, 389 strlen(BUILD_TEST_SHALLOW_MAGIC)) == 0 && 390 bytes_contains(bytes.data, bytes.len, "\nresult ") && 391 !bytes_contains(bytes.data, bytes.len, "\noutput "), 392 "test shallow uses result field"); 393 memset(&parsed, 0, sizeof parsed); 394 parsed.configs = parsed_keys; 395 parsed.cap_configs = 2; 396 parsed.sources = parsed_sources; 397 parsed.cap_sources = 2; 398 parsed.globs = parsed_globs; 399 parsed.cap_globs = 1; 400 parsed.deps = parsed_deps; 401 parsed.cap_deps = 1; 402 EXPECT(build_test_shallow_parse(bytes.data, bytes.len, &parsed, err, 403 sizeof err) == BUILD_OK && 404 build_id_eq(parsed.output, st.output), 405 "parse test shallow"); 406 EXPECT(build_shallow_parse(bytes.data, bytes.len, &parsed, err, sizeof err) == 407 BUILD_ERR, 408 "build shallow rejects test magic"); 409 kit_writer_close(w); 410 411 memset(&deep, 0, sizeof deep); 412 strcpy(deep.target, "//app:bin"); 413 fill_id(deep.recipe, 0); 414 fill_id(deep.output, 1); 415 fill_id(deep.argv, 3); 416 fill_id(deep.deepset, 4); 417 w = NULL; 418 EXPECT(kit_writer_mem(&g_u.heap, &w) == KIT_OK && w, "test deep writer"); 419 EXPECT(build_test_deep_emit(&deep, w, err, sizeof err) == BUILD_OK, 420 "emit test deep"); 421 bytes.data = kit_writer_mem_bytes(w, &bytes.len); 422 EXPECT(bytes_contains(bytes.data, bytes.len, "\nresult ") && 423 !bytes_contains(bytes.data, bytes.len, "\noutput "), 424 "test deep uses result field"); 425 memset(&parsed_deep, 0, sizeof parsed_deep); 426 EXPECT(build_test_deep_parse(bytes.data, bytes.len, &parsed_deep, err, 427 sizeof err) == BUILD_OK && 428 build_id_eq(parsed_deep.output, deep.output), 429 "parse test deep"); 430 EXPECT(build_deep_parse(bytes.data, bytes.len, &parsed_deep, err, 431 sizeof err) == BUILD_ERR, 432 "build deep rejects test magic"); 433 kit_writer_close(w); 434 435 memset(&parsed_ds, 0, sizeof parsed_ds); 436 parsed_ds.configs = ds_configs; 437 parsed_ds.cap_configs = 2; 438 EXPECT(build_deepset_parse((const uint8_t*)bad_deepset_config, 439 sizeof bad_deepset_config - 1u, &parsed_ds, err, 440 sizeof err) == BUILD_ERR, 441 "reject non-canonical deepset config"); 442 443 memset(&rec, 0, sizeof rec); 444 strcpy(rec.target, "//app:bin"); 445 rec.rows = rows; 446 rec.cap_rows = sizeof rows / sizeof rows[0]; 447 row.kind = (uint8_t)BUILD_TRACE_DEEP; 448 memcpy(row.trace_id, trace_id, BUILD_HASH_LEN); 449 EXPECT(build_record_prepend(&rec, &row) == BUILD_OK && rec.n_rows == 1, 450 "record prepend"); 451 EXPECT(build_record_prepend(&rec, &row) == BUILD_OK && rec.n_rows == 1, 452 "record dedup"); 453 } 454 455 static int glob_seen(void* user, KitSlice path) { 456 int* n = (int*)user; 457 if (kit_slice_eq(path, KIT_SLICE_LIT("src/a.c"))) ++*n; 458 return 0; 459 } 460 461 static void test_protocol(void) { 462 uint8_t buf[BUILD_FRAME_MAX]; 463 size_t n = 0; 464 KitBuildKV overrides[1], dec_overrides[1]; 465 KitSlice argv[1], dec_argv[1]; 466 BuildReq req, dec_req; 467 BuildResp resp, dec_resp; 468 int seen = 0; 469 470 memset(&req, 0, sizeof req); 471 req.cmd = BUILD_CMD_NEED; 472 req.arg = KIT_SLICE_LIT("//lib:core"); 473 overrides[0].key = KIT_SLICE_LIT("opt"); 474 overrides[0].value = KIT_SLICE_LIT("2"); 475 req.overrides = overrides; 476 req.noverrides = 1; 477 argv[0] = KIT_SLICE_LIT("--fast"); 478 req.argv = argv; 479 req.argc = 1; 480 EXPECT(build_proto_encode_req(&req, buf, sizeof buf, &n) == BUILD_OK, 481 "encode need"); 482 EXPECT(build_proto_decode_req(buf, n, &dec_req, dec_overrides, 1, dec_argv, 483 1) == BUILD_OK, 484 "decode need"); 485 EXPECT(dec_req.cmd == BUILD_CMD_NEED && 486 kit_slice_eq(dec_req.arg, KIT_SLICE_LIT("//lib:core")) && 487 dec_req.noverrides == 1 && 488 kit_slice_eq(dec_req.overrides[0].value, KIT_SLICE_LIT("2")) && 489 dec_req.argc == 1 && 490 kit_slice_eq(dec_req.argv[0], KIT_SLICE_LIT("--fast")), 491 "need roundtrip"); 492 493 memset(&req, 0, sizeof req); 494 req.cmd = BUILD_CMD_CONFIG_GET; 495 req.arg = KIT_SLICE_LIT("mode"); 496 argv[0] = KIT_SLICE_LIT("fallback"); 497 req.argv = argv; 498 req.argc = 1; 499 EXPECT(build_proto_encode_req(&req, buf, sizeof buf, &n) == BUILD_OK && 500 build_proto_decode_req(buf, n, &dec_req, dec_overrides, 1, 501 dec_argv, 1) == BUILD_OK && 502 dec_req.cmd == BUILD_CMD_CONFIG_GET && 503 dec_req.argc == 1 && 504 kit_slice_eq(dec_req.argv[0], KIT_SLICE_LIT("fallback")), 505 "config default request roundtrip"); 506 memset(&resp, 0, sizeof resp); 507 resp.status = BUILD_RESP_DEFAULT; 508 resp.text = KIT_SLICE_LIT("fallback"); 509 EXPECT(build_proto_encode_resp(&req, &resp, buf, sizeof buf, &n) == 510 BUILD_OK && 511 build_proto_decode_resp(buf, n, BUILD_CMD_CONFIG_GET, &dec_resp, 512 NULL, NULL) == BUILD_OK && 513 dec_resp.status == BUILD_RESP_DEFAULT && 514 kit_slice_eq(dec_resp.text, KIT_SLICE_LIT("fallback")), 515 "config default response roundtrip"); 516 517 memset(&req, 0, sizeof req); 518 req.cmd = BUILD_CMD_GLOB; 519 memset(&resp, 0, sizeof resp); 520 resp.status = BUILD_RESP_OK; 521 resp.text = KIT_SLICE_LIT("src/a.c"); 522 EXPECT(build_proto_encode_resp(&req, &resp, buf, sizeof buf, &n) == BUILD_OK, 523 "encode glob batch"); 524 EXPECT(build_proto_decode_resp(buf, n, BUILD_CMD_GLOB, &dec_resp, glob_seen, 525 &seen) == BUILD_OK && 526 seen == 1, 527 "decode glob batch"); 528 } 529 530 static void test_bundle_manifest(void) { 531 BuildTraceClaim claims[2], parsed[2]; 532 KitWriter* w = NULL; 533 KitSlice bytes; 534 size_t n = 0; 535 char err[128]; 536 static const char bad[] = 537 "kit-build-traces 1\n" 538 "//z deep " 539 "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f " 540 "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20\n" 541 "//a deep " 542 "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f " 543 "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20\n"; 544 545 memset(claims, 0, sizeof claims); 546 strcpy(claims[0].target, "//z"); 547 claims[0].kind = (uint8_t)BUILD_TRACE_SHALLOW; 548 fill_id(claims[0].trace_id, 1); 549 fill_id(claims[0].output_tree, 2); 550 strcpy(claims[1].target, "//a"); 551 claims[1].kind = (uint8_t)BUILD_TRACE_DEEP; 552 fill_id(claims[1].trace_id, 3); 553 fill_id(claims[1].output_tree, 4); 554 555 EXPECT(kit_writer_mem(&g_u.heap, &w) == KIT_OK && w, "bundle writer"); 556 EXPECT(build_bundle_manifest_emit(claims, 2, w) == BUILD_OK, 557 "emit bundle manifest"); 558 bytes.data = kit_writer_mem_bytes(w, &bytes.len); 559 EXPECT(build_bundle_manifest_parse(bytes.data, bytes.len, parsed, 2, &n, err, 560 sizeof err) == BUILD_OK && 561 n == 2 && strcmp(parsed[0].target, "//a") == 0 && 562 parsed[0].kind == (uint8_t)BUILD_TRACE_DEEP, 563 "parse sorted bundle manifest"); 564 EXPECT(build_bundle_manifest_parse((const uint8_t*)bad, sizeof bad - 1u, 565 parsed, 2, &n, err, 566 sizeof err) == BUILD_ERR, 567 "reject unsorted bundle manifest"); 568 kit_writer_close(w); 569 } 570 571 int main(void) { 572 uint8_t key1[BUILD_HASH_LEN], key2[BUILD_HASH_LEN], test_key[BUILD_HASH_LEN]; 573 BuildPathBlob paths[1]; 574 uint8_t glob_id[BUILD_HASH_LEN]; 575 576 kit_unit_init(&g_u); 577 578 EXPECT(build_target_key(KIT_SLICE_LIT("//app:bin"), key1) == BUILD_OK, 579 "target key"); 580 EXPECT(build_target_key(KIT_SLICE_LIT("//app:bin"), key2) == BUILD_OK && 581 build_id_eq(key1, key2), 582 "target key stable"); 583 EXPECT(build_test_target_key(KIT_SLICE_LIT("//app:bin"), test_key) == 584 BUILD_OK && 585 !build_id_eq(key1, test_key), 586 "test target key differs from build target key"); 587 strcpy(paths[0].path, "src/a.c"); 588 fill_id(paths[0].blob, 9); 589 EXPECT(build_glob_result_hash(&g_u.heap, paths, 1, glob_id) == BUILD_OK, 590 "glob result hash"); 591 592 test_config_and_argv(); 593 test_defn(); 594 test_trace(); 595 test_protocol(); 596 test_bundle_manifest(); 597 598 kit_unit_summary(&g_u, "build_pure_test"); 599 return kit_unit_status(&g_u); 600 }