mirror of
https://github.com/NohamR/Reclass.git
synced 2026-05-10 19:59:21 +00:00
feat: add C# and Python ctypes code generators
- C# backend: [StructLayout(LayoutKind.Explicit)] with [FieldOffset], IntPtr pointers, fixed arrays, enums - Python backend: ctypes.Structure with _fields_, POINTER() for typed pointers, c_void_p, padding - Both support enums, vectors, bitfields, arrays, unions, static fields - Export menu: C# Structs... and Python ctypes... entries - Format combo auto-populates new options - 14 new tests for both backends (all passing)
This commit is contained in:
@@ -873,6 +873,559 @@ private slots:
|
||||
QVERIFY2(result.contains("sizeof(Small) == 0x4"),
|
||||
qPrintable("Expected sizeof(Small) == 0x4:\n" + result));
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// ── Rust backend tests ──
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
void testRustSimpleStruct() {
|
||||
auto tree = makeSimpleStruct();
|
||||
uint64_t rootId = tree.nodes[0].id;
|
||||
QString result = rcx::renderRust(tree, rootId, nullptr, true);
|
||||
|
||||
QVERIFY(result.contains("// Generated by Reclass 2027"));
|
||||
QVERIFY(result.contains("#[repr(C)]"));
|
||||
QVERIFY(result.contains("pub struct Player {"));
|
||||
QVERIFY(result.contains("pub health: i32,"));
|
||||
QVERIFY(result.contains("pub speed: f32,"));
|
||||
QVERIFY(result.contains("pub id: u64,"));
|
||||
QVERIFY(result.contains("// 0x0"));
|
||||
QVERIFY(result.contains("// 0x4"));
|
||||
QVERIFY(result.contains("// 0x8"));
|
||||
QVERIFY(result.contains("core::mem::size_of::<Player>() == 0x10"));
|
||||
|
||||
// Without asserts
|
||||
QString noAsserts = rcx::renderRust(tree, rootId);
|
||||
QVERIFY(!noAsserts.contains("size_of"));
|
||||
}
|
||||
|
||||
void testRustPadding() {
|
||||
rcx::NodeTree tree;
|
||||
rcx::Node root;
|
||||
root.kind = rcx::NodeKind::Struct;
|
||||
root.name = "Padded";
|
||||
root.structTypeName = "Padded";
|
||||
root.parentId = 0;
|
||||
int ri = tree.addNode(root);
|
||||
uint64_t rootId = tree.nodes[ri].id;
|
||||
|
||||
rcx::Node f1;
|
||||
f1.kind = rcx::NodeKind::UInt32;
|
||||
f1.name = "a";
|
||||
f1.parentId = rootId;
|
||||
f1.offset = 0;
|
||||
tree.addNode(f1);
|
||||
|
||||
rcx::Node f2;
|
||||
f2.kind = rcx::NodeKind::UInt32;
|
||||
f2.name = "b";
|
||||
f2.parentId = rootId;
|
||||
f2.offset = 8;
|
||||
tree.addNode(f2);
|
||||
|
||||
QString result = rcx::renderRust(tree, rootId);
|
||||
QVERIFY(result.contains("pub _pad"));
|
||||
QVERIFY(result.contains("[u8; 0x4]"));
|
||||
}
|
||||
|
||||
void testRustPointers() {
|
||||
rcx::NodeTree tree;
|
||||
|
||||
rcx::Node target;
|
||||
target.kind = rcx::NodeKind::Struct;
|
||||
target.name = "Target";
|
||||
target.structTypeName = "Target";
|
||||
target.parentId = 0;
|
||||
target.offset = 0x100;
|
||||
int ti = tree.addNode(target);
|
||||
uint64_t targetId = tree.nodes[ti].id;
|
||||
|
||||
rcx::Node tf;
|
||||
tf.kind = rcx::NodeKind::UInt32;
|
||||
tf.name = "val";
|
||||
tf.parentId = targetId;
|
||||
tf.offset = 0;
|
||||
tree.addNode(tf);
|
||||
|
||||
rcx::Node main;
|
||||
main.kind = rcx::NodeKind::Struct;
|
||||
main.name = "PtrTest";
|
||||
main.structTypeName = "PtrTest";
|
||||
main.parentId = 0;
|
||||
int mi = tree.addNode(main);
|
||||
uint64_t mainId = tree.nodes[mi].id;
|
||||
|
||||
rcx::Node p1;
|
||||
p1.kind = rcx::NodeKind::Pointer64;
|
||||
p1.name = "typed";
|
||||
p1.parentId = mainId;
|
||||
p1.offset = 0;
|
||||
p1.refId = targetId;
|
||||
tree.addNode(p1);
|
||||
|
||||
rcx::Node p2;
|
||||
p2.kind = rcx::NodeKind::Pointer64;
|
||||
p2.name = "untyped";
|
||||
p2.parentId = mainId;
|
||||
p2.offset = 8;
|
||||
tree.addNode(p2);
|
||||
|
||||
QString result = rcx::renderRust(tree, mainId);
|
||||
QVERIFY(result.contains("pub typed: *mut Target,"));
|
||||
QVERIFY(result.contains("pub untyped: *mut core::ffi::c_void,"));
|
||||
}
|
||||
|
||||
void testRustVectors() {
|
||||
rcx::NodeTree tree;
|
||||
rcx::Node root;
|
||||
root.kind = rcx::NodeKind::Struct;
|
||||
root.name = "Vecs";
|
||||
root.structTypeName = "Vecs";
|
||||
root.parentId = 0;
|
||||
int ri = tree.addNode(root);
|
||||
uint64_t rootId = tree.nodes[ri].id;
|
||||
|
||||
rcx::Node v2;
|
||||
v2.kind = rcx::NodeKind::Vec2;
|
||||
v2.name = "pos";
|
||||
v2.parentId = rootId;
|
||||
v2.offset = 0;
|
||||
tree.addNode(v2);
|
||||
|
||||
rcx::Node v4;
|
||||
v4.kind = rcx::NodeKind::Vec4;
|
||||
v4.name = "color";
|
||||
v4.parentId = rootId;
|
||||
v4.offset = 8;
|
||||
tree.addNode(v4);
|
||||
|
||||
QString result = rcx::renderRust(tree, rootId);
|
||||
QVERIFY(result.contains("pub pos: [f32; 2],"));
|
||||
QVERIFY(result.contains("pub color: [f32; 4],"));
|
||||
}
|
||||
|
||||
void testRustFuncPtr() {
|
||||
rcx::NodeTree tree;
|
||||
rcx::Node root;
|
||||
root.kind = rcx::NodeKind::Struct;
|
||||
root.name = "FP";
|
||||
root.structTypeName = "FP";
|
||||
root.parentId = 0;
|
||||
int ri = tree.addNode(root);
|
||||
uint64_t rootId = tree.nodes[ri].id;
|
||||
|
||||
rcx::Node fp;
|
||||
fp.kind = rcx::NodeKind::FuncPtr64;
|
||||
fp.name = "callback";
|
||||
fp.parentId = rootId;
|
||||
fp.offset = 0;
|
||||
tree.addNode(fp);
|
||||
|
||||
QString result = rcx::renderRust(tree, rootId);
|
||||
QVERIFY(result.contains("pub callback: Option<unsafe extern \"C\" fn()>,"));
|
||||
}
|
||||
|
||||
void testRustAll() {
|
||||
auto tree = makeSimpleStruct();
|
||||
QString result = rcx::renderRustAll(tree, nullptr, true);
|
||||
QVERIFY(result.contains("#[repr(C)]"));
|
||||
QVERIFY(result.contains("pub struct Player {"));
|
||||
QVERIFY(result.contains("core::mem::size_of::<Player>()"));
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// ── #define offsets backend tests ──
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
void testDefineSimpleStruct() {
|
||||
auto tree = makeSimpleStruct();
|
||||
uint64_t rootId = tree.nodes[0].id;
|
||||
QString result = rcx::renderDefines(tree, rootId);
|
||||
|
||||
QVERIFY(result.contains("#pragma once"));
|
||||
QVERIFY(result.contains("// Player"));
|
||||
QVERIFY(result.contains("#define Player_health 0x0"));
|
||||
QVERIFY(result.contains("#define Player_speed 0x4"));
|
||||
QVERIFY(result.contains("#define Player_id 0x8"));
|
||||
}
|
||||
|
||||
void testDefineSkipsHex() {
|
||||
rcx::NodeTree tree;
|
||||
rcx::Node root;
|
||||
root.kind = rcx::NodeKind::Struct;
|
||||
root.name = "HexTest";
|
||||
root.structTypeName = "HexTest";
|
||||
root.parentId = 0;
|
||||
int ri = tree.addNode(root);
|
||||
uint64_t rootId = tree.nodes[ri].id;
|
||||
|
||||
rcx::Node h;
|
||||
h.kind = rcx::NodeKind::Hex32;
|
||||
h.name = "padding";
|
||||
h.parentId = rootId;
|
||||
h.offset = 0;
|
||||
tree.addNode(h);
|
||||
|
||||
rcx::Node f;
|
||||
f.kind = rcx::NodeKind::UInt32;
|
||||
f.name = "real_field";
|
||||
f.parentId = rootId;
|
||||
f.offset = 4;
|
||||
tree.addNode(f);
|
||||
|
||||
QString result = rcx::renderDefines(tree, rootId);
|
||||
QVERIFY(!result.contains("padding"));
|
||||
QVERIFY(result.contains("#define HexTest_real_field 0x4"));
|
||||
}
|
||||
|
||||
void testDefineAll() {
|
||||
auto tree = makeSimpleStruct();
|
||||
QString result = rcx::renderDefinesAll(tree);
|
||||
QVERIFY(result.contains("#pragma once"));
|
||||
QVERIFY(result.contains("#define Player_health 0x0"));
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// ── Format dispatch tests ──
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
void testCodeFormatDispatch() {
|
||||
auto tree = makeSimpleStruct();
|
||||
uint64_t rootId = tree.nodes[0].id;
|
||||
|
||||
QString cpp = rcx::renderCode(rcx::CodeFormat::CppHeader, tree, rootId);
|
||||
QVERIFY(cpp.contains("struct Player"));
|
||||
|
||||
QString rust = rcx::renderCode(rcx::CodeFormat::RustStruct, tree, rootId);
|
||||
QVERIFY(rust.contains("pub struct Player"));
|
||||
|
||||
QString defs = rcx::renderCode(rcx::CodeFormat::DefineOffsets, tree, rootId);
|
||||
QVERIFY(defs.contains("#define Player_health"));
|
||||
}
|
||||
|
||||
void testCodeFormatAllDispatch() {
|
||||
auto tree = makeSimpleStruct();
|
||||
|
||||
QString cpp = rcx::renderCodeAll(rcx::CodeFormat::CppHeader, tree);
|
||||
QVERIFY(cpp.contains("struct Player"));
|
||||
|
||||
QString rust = rcx::renderCodeAll(rcx::CodeFormat::RustStruct, tree);
|
||||
QVERIFY(rust.contains("pub struct Player"));
|
||||
|
||||
QString defs = rcx::renderCodeAll(rcx::CodeFormat::DefineOffsets, tree);
|
||||
QVERIFY(defs.contains("#define Player_health"));
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// ── Scope tests (Current + Deps) ──
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
void testTreeScopeIncludesReferencedTypes() {
|
||||
rcx::NodeTree tree;
|
||||
|
||||
// Target struct (referenced by pointer)
|
||||
rcx::Node target;
|
||||
target.kind = rcx::NodeKind::Struct;
|
||||
target.name = "Target";
|
||||
target.structTypeName = "Target";
|
||||
target.parentId = 0;
|
||||
target.offset = 0x100;
|
||||
int ti = tree.addNode(target);
|
||||
uint64_t targetId = tree.nodes[ti].id;
|
||||
|
||||
rcx::Node tf;
|
||||
tf.kind = rcx::NodeKind::UInt32;
|
||||
tf.name = "val";
|
||||
tf.parentId = targetId;
|
||||
tf.offset = 0;
|
||||
tree.addNode(tf);
|
||||
|
||||
// Main struct with a pointer to Target
|
||||
rcx::Node main;
|
||||
main.kind = rcx::NodeKind::Struct;
|
||||
main.name = "Main";
|
||||
main.structTypeName = "Main";
|
||||
main.parentId = 0;
|
||||
int mi = tree.addNode(main);
|
||||
uint64_t mainId = tree.nodes[mi].id;
|
||||
|
||||
rcx::Node ptr;
|
||||
ptr.kind = rcx::NodeKind::Pointer64;
|
||||
ptr.name = "pTarget";
|
||||
ptr.parentId = mainId;
|
||||
ptr.offset = 0;
|
||||
ptr.refId = targetId;
|
||||
tree.addNode(ptr);
|
||||
|
||||
// "Current" scope: only Main, no Target definition
|
||||
QString current = rcx::renderCpp(tree, mainId);
|
||||
QVERIFY(current.contains("struct Main\n{"));
|
||||
QVERIFY(!current.contains("struct Target\n{"));
|
||||
|
||||
// "Current + Deps" scope: Main AND Target definitions
|
||||
QString withDeps = rcx::renderCppTree(tree, mainId);
|
||||
QVERIFY(withDeps.contains("struct Main\n{"));
|
||||
QVERIFY(withDeps.contains("struct Target\n{"));
|
||||
|
||||
// Same for Rust
|
||||
QString rustDeps = rcx::renderRustTree(tree, mainId);
|
||||
QVERIFY(rustDeps.contains("pub struct Main {"));
|
||||
QVERIFY(rustDeps.contains("pub struct Target {"));
|
||||
|
||||
// Same for #define
|
||||
QString defDeps = rcx::renderDefinesTree(tree, mainId);
|
||||
QVERIFY(defDeps.contains("#define Main_pTarget"));
|
||||
QVERIFY(defDeps.contains("#define Target_val"));
|
||||
}
|
||||
|
||||
void testTreeScopeDispatch() {
|
||||
rcx::NodeTree tree;
|
||||
|
||||
rcx::Node a;
|
||||
a.kind = rcx::NodeKind::Struct;
|
||||
a.name = "A";
|
||||
a.structTypeName = "A";
|
||||
a.parentId = 0;
|
||||
int ai = tree.addNode(a);
|
||||
uint64_t aId = tree.nodes[ai].id;
|
||||
|
||||
rcx::Node af;
|
||||
af.kind = rcx::NodeKind::UInt32;
|
||||
af.name = "x";
|
||||
af.parentId = aId;
|
||||
af.offset = 0;
|
||||
tree.addNode(af);
|
||||
|
||||
// renderCodeTree should work for all formats
|
||||
QString cpp = rcx::renderCodeTree(rcx::CodeFormat::CppHeader, tree, aId);
|
||||
QVERIFY(cpp.contains("struct A"));
|
||||
|
||||
QString rust = rcx::renderCodeTree(rcx::CodeFormat::RustStruct, tree, aId);
|
||||
QVERIFY(rust.contains("pub struct A"));
|
||||
|
||||
QString defs = rcx::renderCodeTree(rcx::CodeFormat::DefineOffsets, tree, aId);
|
||||
QVERIFY(defs.contains("#define A_x"));
|
||||
|
||||
QString cs = rcx::renderCodeTree(rcx::CodeFormat::CSharpStruct, tree, aId);
|
||||
QVERIFY(cs.contains("public unsafe struct A"));
|
||||
|
||||
QString py = rcx::renderCodeTree(rcx::CodeFormat::PythonCtypes, tree, aId);
|
||||
QVERIFY(py.contains("class A(ctypes.Structure)"));
|
||||
}
|
||||
|
||||
// ── C# backend ──
|
||||
|
||||
void testCSharpSimpleStruct() {
|
||||
auto tree = makeSimpleStruct();
|
||||
uint64_t rootId = tree.nodes[0].id;
|
||||
QString result = rcx::renderCSharp(tree, rootId);
|
||||
|
||||
QVERIFY(result.contains("using System.Runtime.InteropServices;"));
|
||||
QVERIFY(result.contains("[StructLayout(LayoutKind.Explicit, Size = 0x10)]"));
|
||||
QVERIFY(result.contains("public unsafe struct Player"));
|
||||
QVERIFY(result.contains("[FieldOffset(0x0)] public int health;"));
|
||||
QVERIFY(result.contains("[FieldOffset(0x4)] public float speed;"));
|
||||
QVERIFY(result.contains("[FieldOffset(0x8)] public ulong id;"));
|
||||
}
|
||||
|
||||
void testCSharpPointers() {
|
||||
rcx::NodeTree tree;
|
||||
rcx::Node root;
|
||||
root.kind = rcx::NodeKind::Struct;
|
||||
root.name = "Foo";
|
||||
root.structTypeName = "Foo";
|
||||
root.parentId = 0;
|
||||
root.offset = 0;
|
||||
int ri = tree.addNode(root);
|
||||
uint64_t rootId = tree.nodes[ri].id;
|
||||
|
||||
rcx::Node p;
|
||||
p.kind = rcx::NodeKind::Pointer64;
|
||||
p.name = "ptr";
|
||||
p.parentId = rootId;
|
||||
p.offset = 0;
|
||||
tree.addNode(p);
|
||||
|
||||
QString result = rcx::renderCSharp(tree, rootId);
|
||||
QVERIFY(result.contains("IntPtr ptr"));
|
||||
}
|
||||
|
||||
void testCSharpAll() {
|
||||
auto tree = makeSimpleStruct();
|
||||
QString result = rcx::renderCSharpAll(tree);
|
||||
QVERIFY(result.contains("public unsafe struct Player"));
|
||||
QVERIFY(result.contains("[StructLayout("));
|
||||
}
|
||||
|
||||
void testCSharpEnum() {
|
||||
rcx::NodeTree tree;
|
||||
rcx::Node e;
|
||||
e.kind = rcx::NodeKind::Struct;
|
||||
e.name = "Color";
|
||||
e.structTypeName = "Color";
|
||||
e.classKeyword = "enum";
|
||||
e.parentId = 0;
|
||||
e.offset = 0;
|
||||
e.enumMembers = {{"Red", 0}, {"Green", 1}, {"Blue", 2}};
|
||||
tree.addNode(e);
|
||||
|
||||
QString result = rcx::renderCSharpAll(tree);
|
||||
QVERIFY(result.contains("public enum Color : long"));
|
||||
QVERIFY(result.contains("Red = 0"));
|
||||
QVERIFY(result.contains("Green = 1"));
|
||||
QVERIFY(result.contains("Blue = 2"));
|
||||
}
|
||||
|
||||
void testCSharpVectors() {
|
||||
rcx::NodeTree tree;
|
||||
rcx::Node root;
|
||||
root.kind = rcx::NodeKind::Struct;
|
||||
root.name = "Xform";
|
||||
root.structTypeName = "Xform";
|
||||
root.parentId = 0;
|
||||
root.offset = 0;
|
||||
int ri = tree.addNode(root);
|
||||
uint64_t rootId = tree.nodes[ri].id;
|
||||
|
||||
rcx::Node v;
|
||||
v.kind = rcx::NodeKind::Vec3;
|
||||
v.name = "position";
|
||||
v.parentId = rootId;
|
||||
v.offset = 0;
|
||||
tree.addNode(v);
|
||||
|
||||
QString result = rcx::renderCSharp(tree, rootId);
|
||||
QVERIFY(result.contains("public fixed float position[3]"));
|
||||
}
|
||||
|
||||
// ── Python ctypes backend ──
|
||||
|
||||
void testPythonSimpleStruct() {
|
||||
auto tree = makeSimpleStruct();
|
||||
uint64_t rootId = tree.nodes[0].id;
|
||||
QString result = rcx::renderPython(tree, rootId);
|
||||
|
||||
QVERIFY(result.contains("import ctypes"));
|
||||
QVERIFY(result.contains("class Player(ctypes.Structure)"));
|
||||
QVERIFY(result.contains("_fields_ = ["));
|
||||
QVERIFY(result.contains("(\"health\", ctypes.c_int32)"));
|
||||
QVERIFY(result.contains("(\"speed\", ctypes.c_float)"));
|
||||
QVERIFY(result.contains("(\"id\", ctypes.c_uint64)"));
|
||||
}
|
||||
|
||||
void testPythonPointers() {
|
||||
rcx::NodeTree tree;
|
||||
rcx::Node root;
|
||||
root.kind = rcx::NodeKind::Struct;
|
||||
root.name = "Bar";
|
||||
root.structTypeName = "Bar";
|
||||
root.parentId = 0;
|
||||
root.offset = 0;
|
||||
int ri = tree.addNode(root);
|
||||
uint64_t rootId = tree.nodes[ri].id;
|
||||
|
||||
rcx::Node p;
|
||||
p.kind = rcx::NodeKind::Pointer64;
|
||||
p.name = "ptr";
|
||||
p.parentId = rootId;
|
||||
p.offset = 0;
|
||||
tree.addNode(p);
|
||||
|
||||
QString result = rcx::renderPython(tree, rootId);
|
||||
QVERIFY(result.contains("(\"ptr\", ctypes.c_void_p)"));
|
||||
}
|
||||
|
||||
void testPythonTypedPointers() {
|
||||
rcx::NodeTree tree;
|
||||
rcx::Node target;
|
||||
target.kind = rcx::NodeKind::Struct;
|
||||
target.name = "Target";
|
||||
target.structTypeName = "Target";
|
||||
target.parentId = 0;
|
||||
target.offset = 0;
|
||||
int ti = tree.addNode(target);
|
||||
uint64_t targetId = tree.nodes[ti].id;
|
||||
|
||||
rcx::Node root;
|
||||
root.kind = rcx::NodeKind::Struct;
|
||||
root.name = "Holder";
|
||||
root.structTypeName = "Holder";
|
||||
root.parentId = 0;
|
||||
root.offset = 0;
|
||||
int ri = tree.addNode(root);
|
||||
uint64_t rootId = tree.nodes[ri].id;
|
||||
|
||||
rcx::Node p;
|
||||
p.kind = rcx::NodeKind::Pointer64;
|
||||
p.name = "ref";
|
||||
p.parentId = rootId;
|
||||
p.offset = 0;
|
||||
p.refId = targetId;
|
||||
tree.addNode(p);
|
||||
|
||||
QString result = rcx::renderPython(tree, rootId);
|
||||
QVERIFY(result.contains("ctypes.POINTER(Target)"));
|
||||
}
|
||||
|
||||
void testPythonAll() {
|
||||
auto tree = makeSimpleStruct();
|
||||
QString result = rcx::renderPythonAll(tree);
|
||||
QVERIFY(result.contains("class Player(ctypes.Structure)"));
|
||||
}
|
||||
|
||||
void testPythonEnum() {
|
||||
rcx::NodeTree tree;
|
||||
rcx::Node e;
|
||||
e.kind = rcx::NodeKind::Struct;
|
||||
e.name = "Status";
|
||||
e.structTypeName = "Status";
|
||||
e.classKeyword = "enum";
|
||||
e.parentId = 0;
|
||||
e.offset = 0;
|
||||
e.enumMembers = {{"Active", 1}, {"Inactive", 0}};
|
||||
tree.addNode(e);
|
||||
|
||||
QString result = rcx::renderPythonAll(tree);
|
||||
QVERIFY(result.contains("class Status:"));
|
||||
QVERIFY(result.contains("Active = 1"));
|
||||
QVERIFY(result.contains("Inactive = 0"));
|
||||
}
|
||||
|
||||
void testPythonVectors() {
|
||||
rcx::NodeTree tree;
|
||||
rcx::Node root;
|
||||
root.kind = rcx::NodeKind::Struct;
|
||||
root.name = "Pos";
|
||||
root.structTypeName = "Pos";
|
||||
root.parentId = 0;
|
||||
root.offset = 0;
|
||||
int ri = tree.addNode(root);
|
||||
uint64_t rootId = tree.nodes[ri].id;
|
||||
|
||||
rcx::Node v;
|
||||
v.kind = rcx::NodeKind::Vec4;
|
||||
v.name = "color";
|
||||
v.parentId = rootId;
|
||||
v.offset = 0;
|
||||
tree.addNode(v);
|
||||
|
||||
QString result = rcx::renderPython(tree, rootId);
|
||||
QVERIFY(result.contains("(\"color\", ctypes.c_float * 4)"));
|
||||
}
|
||||
|
||||
void testCSharpDispatch() {
|
||||
auto tree = makeSimpleStruct();
|
||||
uint64_t rootId = tree.nodes[0].id;
|
||||
QString result = rcx::renderCode(rcx::CodeFormat::CSharpStruct, tree, rootId);
|
||||
QVERIFY(result.contains("[StructLayout("));
|
||||
}
|
||||
|
||||
void testPythonDispatch() {
|
||||
auto tree = makeSimpleStruct();
|
||||
uint64_t rootId = tree.nodes[0].id;
|
||||
QString result = rcx::renderCode(rcx::CodeFormat::PythonCtypes, tree, rootId);
|
||||
QVERIFY(result.contains("ctypes.Structure"));
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_MAIN(TestGenerator)
|
||||
|
||||
Reference in New Issue
Block a user