71 """Build the type table the `codegen_harness.cpp` test program references.
73 The aliases below give every emitted struct a stable, hand-written C++
74 name (e.g. `StdU`) so the harness can use plain identifiers rather than
75 spelling the auto-generated mangled names.
80 [(
"u8", _uint8), (
"u16", _uint16), (
"u32", _uint32), (
"u64", _uint64)],
86 [(
"s8", _sint8), (
"s16", _sint16), (
"s32", _sint32), (
"s64", _sint64)],
127 [(
"inner", mis_inner), (
"tag", _uint3)])
128 misaligned =
types.TypeAlias(
"@Misaligned",
"Misaligned", misaligned_inner)
172 sb_cell_arr =
types.TypeAlias(
"@SbCellArr",
"SbCellArr", sb_cell_arr_inner)
196 nested_cell =
types.TypeAlias(
"@NestedCell",
"NestedCell", nested_cell_inner)
205 (
"signed_small", _sint5),
206 (
"cell", sb_cell), (
"big", _uint12)])
211 list_id =
"!esi.list<ui32>"
215 [(
"tag", _uint16), (
"items", list_type)],
218 "@ListWindow::header",
219 [(
"tag", _uint16), (
"items_count", _uint16)],
226 "@ListWindow::lowered",
227 [(
"header", win_header_inner), (
"data", win_data_inner)],
229 window_id = (
'!esi.window<"ListWindow", @ListWindow::arg, '
230 '[<"header", [<"tag">, <"items" countWidth 16>]>, '
231 '<"data", [<"items", 1>]>]>')
252 list_window =
types.TypeAlias(
"@ListWindow",
"ListWindow", list_window_inner)
259 "@SmallListWindow::arg",
260 [(
"tag", _uint16), (
"items", list_type)],
263 "@SmallListWindow::header",
264 [(
"tag", _uint16), (
"items_count", _uint2)],
267 "@SmallListWindow::data",
271 "@SmallListWindow::lowered",
272 [(
"header", sw_header_inner), (
"data", sw_data_inner)],
274 sw_window_id = (
'!esi.window<"SmallListWindow", @SmallListWindow::arg, '
275 '[<"header", [<"tag">, <"items" countWidth 2>]>, '
276 '<"data", [<"items", 1>]>]>')
296 small_list_window =
types.TypeAlias(
"@SmallListWindow",
"SmallListWindow",
297 small_list_window_inner)
302 (
"items", narrow_data_list)])
304 "@NarrowDataWindow::data",
307 [(
"header", sw_header_inner),
308 (
"data", narrow_data_frame)])
310 '!esi.window<"NarrowDataWindow", @NarrowDataWindow::arg, '
311 '[<"header", [<"tag">, <"items" countWidth 2>]>, '
312 '<"data", [<"items", 1>]>]>',
316 small_list_window_inner.frames,
318 narrow_data_window =
types.TypeAlias(
"@NarrowDataWindow",
"NarrowDataWindow",
319 narrow_data_window_inner)
329 [(
"u96", _uint96), (
"u128", _uint128)],
334 [(
"s96", _sint96), (
"s128", _sint128)],
342 [(
"wide", _bits128)],
353 "@WideMisaligned::inner",
354 [(
"payload", _uint128), (
"tag", _uint3)],
367 [(
"items", arr3_u128_type)],
374 "@ArrViewsMis::inner",
375 [(
"items", arr3_u128_type), (
"tag", _uint3)],
381 std_u, std_s, odd_u, odd_s, sub_u, sub_s, bool_field, outer, misaligned,
382 arr4, u3_arr, bits1_arr, s5_arr, u24_arr, sb_cell, sb_cell_arr, nested3,
383 nested_cell, union_two, union_subbyte, list_window, small_list_window,
384 narrow_data_window, wide_u, wide_s, bits_field, wide_mis, arr_views,
396 """Compile `codegen_harness.cpp` against a freshly-generated `types.h`
397 and run it. The harness asserts every wire-format and accessor invariant
398 end-to-end; this Python test just drives the cmake build and reports
402 esi_dll_path = get_dll_dir()
403 if sys.platform ==
"win32":
404 runtime_lib = esi_dll_path /
"ESICppRuntime.lib"
405 runtime_dll = esi_dll_path /
"ESICppRuntime.dll"
407 runtime_lib = esi_dll_path /
"libESICppRuntime.so"
413 generated_dir = tmp_path /
"generated"
414 (generated_dir /
"codegen_harness").mkdir(parents=
True)
417 emitter.write_header(generated_dir /
"codegen_harness",
"esi_system")
419 build_dir = tmp_path /
"build"
426 "-DCMAKE_BUILD_TYPE=Debug",
427 f
"-DCODEGEN_HARNESS_GENERATED_DIR={generated_dir}",
428 f
"-DESI_RUNTIME_LIB={runtime_lib}",
430 if sys.platform ==
"win32":
431 configure_cmd.append(f
"-DESI_RUNTIME_DLL={runtime_dll}")
432 configure_proc = subprocess.run(configure_cmd, capture_output=
True, text=
True)
433 if configure_proc.returncode != 0:
435 "cmake configure failed for the codegen harness "
436 f
"(rc={configure_proc.returncode}):\n"
437 f
"--- cmd ---\n{' '.join(configure_cmd)}\n"
438 f
"--- stdout ---\n{configure_proc.stdout}\n"
439 f
"--- stderr ---\n{configure_proc.stderr}",
445 str(build_dir),
"--target",
"codegen_harness",
"--config",
"Debug"
447 build_proc = subprocess.run(build_cmd, capture_output=
True, text=
True)
448 if build_proc.returncode != 0:
453 "codegen_harness.cpp failed to compile against the generated "
454 f
"types.h (rc={build_proc.returncode}):\n"
455 f
"--- cmd ---\n{' '.join(build_cmd)}\n"
456 f
"--- stdout ---\n{build_proc.stdout}\n"
457 f
"--- stderr ---\n{build_proc.stderr}\n"
458 "--- generated types.h ---\n" +
459 (generated_dir /
"codegen_harness" /
"types.h").read_text(),
466 binary_name =
"codegen_harness" + sysconfig.get_config_var(
"EXE")
467 candidates = list(build_dir.rglob(binary_name))
470 f
"codegen_harness binary not found under {build_dir}; "
471 "the cmake build reported success but produced no executable.",
474 binary = candidates[0]
476 run_proc = subprocess.run([str(binary)], capture_output=
True, text=
True)
477 if run_proc.returncode != 0
or run_proc.stdout.strip() !=
"OK":
479 f
"codegen_harness reported failure (rc={run_proc.returncode}):\n"
480 f
"--- stdout ---\n{run_proc.stdout}\n"
481 f
"--- stderr ---\n{run_proc.stderr}",
513 """Golden check of the per-port-kind `connect()` snippets for ALL kinds.
515 The round-trip harness only exercises the types; the live port-kind paths
516 are covered by the (heavyweight) cosim integration suite. This test pins
517 the generated resolution code for every kind -- including the ones the
518 sample manifest doesn't contain (Callback / FromHost / MMIO / Metric /
519 Bundle) -- so a typo in the `CppPortKind` table can't slip through.
523 kinds = {cls.__name__: kind
for cls, kind
in CPP_PORT_KINDS}
524 kinds[
"BundlePort"] = CPP_BUNDLE_KIND
525 ae =
'esi::AppID("p")'
526 aei =
'esi::AppID("p", idx)'
528 def scalar(name: str) -> str:
530 return k.scalar_find_code(f
"p{k.param_suffix}", ae)
532 def indexed(name: str) -> str:
533 return kinds[name].indexed_find_code(
"p_backing", aei)
536 assert scalar(
"FunctionPort") == (
538 " esi::findPortAsOrThrow<esi::services::FuncService::Function>(\n"
539 ' rawModule, esi::AppID("p"));')
540 assert scalar(
"CallbackPort") == (
542 " esi::findPortAsOrThrow<esi::services::CallService::Callback>(\n"
543 ' rawModule, esi::AppID("p"));')
544 assert scalar(
"ToHostPort") == (
546 " esi::findPortAsOrThrow<esi::services::ChannelService::ToHost>(\n"
547 ' rawModule, esi::AppID("p"))->getRawRead("data");')
548 assert scalar(
"FromHostPort") == (
550 " esi::findPortAsOrThrow<esi::services::ChannelService::FromHost>(\n"
551 ' rawModule, esi::AppID("p"))->getRawWrite("data");')
552 assert scalar(
"MMIORegion") == (
554 " *esi::findPortAsOrThrow<esi::services::MMIO::MMIORegion>(\n"
555 ' rawModule, esi::AppID("p"));')
556 assert scalar(
"MetricPort") == (
558 " *esi::findPortAsOrThrow<esi::services::TelemetryService::Metric>(\n"
559 ' rawModule, esi::AppID("p"));')
560 assert scalar(
"BundlePort") == (
561 'auto &p_port = esi::findPortOrThrow(rawModule, esi::AppID("p"));')
564 assert indexed(
"FunctionPort") == (
565 " p_backing.try_emplace(\n"
566 " static_cast<int>(idx),\n"
567 " esi::findPortAsOrThrow<esi::services::FuncService::Function>(\n"
568 ' rawModule, esi::AppID("p", idx)));')
569 assert indexed(
"ToHostPort") == (
571 " esi::findPortAsOrThrow<esi::services::ChannelService::ToHost>(\n"
572 ' rawModule, esi::AppID("p", idx));\n'
573 " p_backing.try_emplace(\n"
574 " static_cast<int>(idx),\n"
575 ' svc->getRawRead("data"));')
576 assert indexed(
"FromHostPort") == (
578 " esi::findPortAsOrThrow<esi::services::ChannelService::FromHost>(\n"
579 ' rawModule, esi::AppID("p", idx));\n'
580 " p_backing.try_emplace(\n"
581 " static_cast<int>(idx),\n"
582 ' svc->getRawWrite("data"));')
583 assert indexed(
"MMIORegion") == (
584 " p_backing.try_emplace(\n"
585 " static_cast<int>(idx),\n"
586 " esi::findPortAsOrThrow<esi::services::MMIO::MMIORegion>(\n"
587 ' rawModule, esi::AppID("p", idx)));')
588 assert indexed(
"BundlePort") == (
589 " p_backing.try_emplace(\n"
590 " static_cast<int>(idx),\n"
591 " &esi::findPortOrThrow(rawModule, esi::AppID(\"p\", idx)));")
596 for k
in (kinds[
"FunctionPort"], kinds[
"CallbackPort"],
597 kinds[
"ToHostPort"], kinds[
"FromHostPort"], kinds[
"MMIORegion"],
598 kinds[
"MetricPort"], kinds[
"BundlePort"])
599 ] == [
True,
False,
True,
True,
False,
True,
False]
600 assert kinds[
"FunctionPort"].param_suffix ==
"_port"
601 assert kinds[
"ToHostPort"].param_suffix ==
"_chan"
602 assert kinds[
"MMIORegion"].param_suffix ==
"_svc"
603 assert (kinds[
"FunctionPort"].member_template ==
604 "esi::TypedFunction<{p}Args, {p}Result>")
605 assert kinds[
"MMIORegion"].member_template
is None
607 kinds[
"MMIORegion"].indexed_elem ==
"esi::services::MMIO::MMIORegion *")
608 assert kinds[
"FunctionPort"].alias_kind ==
"func"
609 assert kinds[
"ToHostPort"].alias_kind ==
"chan"
610 assert kinds[
"MMIORegion"].alias_kind
is None