schemagen: add regression test for nullable cyclic $ref targets #50
@@ -353,6 +353,132 @@ class SchemagenCyclicArrayTest(unittest.TestCase):
|
||||
self.assertIn("std::optional<std::vector<Role>> roles;", stdout)
|
||||
|
||||
|
||||
class SchemagenCyclicNullableObjectTest(unittest.TestCase):
|
||||
"""Regression tests for issue #14: nullable cyclic $ref targets."""
|
||||
|
||||
def setUp(self):
|
||||
self.repo_root = os.path.dirname(
|
||||
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
)
|
||||
self.include_dir = os.path.join(self.repo_root, "include")
|
||||
self.lib_src = os.path.join(self.repo_root, "src", "lib.cpp")
|
||||
self.compiler = shutil.which("c++")
|
||||
|
||||
def _compile_harness(self, tmpdir, schema, harness):
|
||||
schema_path = os.path.join(tmpdir, "schema.json")
|
||||
with open(schema_path, "w") as fp:
|
||||
json.dump(schema, fp)
|
||||
header_path = os.path.join(tmpdir, "gen.h")
|
||||
result = subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
SCRIPT,
|
||||
schema_path,
|
||||
"-o",
|
||||
header_path,
|
||||
"--namespace",
|
||||
"test_schema",
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
self.assertEqual(result.returncode, 0, msg=result.stderr)
|
||||
|
||||
lib_obj = os.path.join(tmpdir, "lib.o")
|
||||
comp_lib = subprocess.run(
|
||||
[
|
||||
self.compiler,
|
||||
"-std=c++20",
|
||||
"-I",
|
||||
self.include_dir,
|
||||
"-I",
|
||||
os.path.join(self.repo_root, "third_party", "include"),
|
||||
"-I",
|
||||
os.path.join(self.repo_root, "third_party", "valgrind"),
|
||||
"-c",
|
||||
self.lib_src,
|
||||
"-o",
|
||||
lib_obj,
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
self.assertEqual(comp_lib.returncode, 0, msg=comp_lib.stderr)
|
||||
|
||||
cpp_path = os.path.join(tmpdir, "test.cpp")
|
||||
with open(cpp_path, "w") as fp:
|
||||
fp.write(harness)
|
||||
|
||||
exe_path = os.path.join(tmpdir, "test")
|
||||
comp = subprocess.run(
|
||||
[
|
||||
self.compiler,
|
||||
"-std=c++20",
|
||||
"-I",
|
||||
self.include_dir,
|
||||
"-I",
|
||||
tmpdir,
|
||||
lib_obj,
|
||||
cpp_path,
|
||||
"-o",
|
||||
exe_path,
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
self.assertEqual(comp.returncode, 0, msg=comp.stderr)
|
||||
run = subprocess.run([exe_path], capture_output=True, text=True, check=False)
|
||||
self.assertEqual(run.returncode, 0, msg=run.stdout + run.stderr)
|
||||
|
||||
def test_self_referential_nullable_object_accepts_nested_null(self):
|
||||
"""A nullable object $def must stay nullable on recursive $refs."""
|
||||
if not self.compiler:
|
||||
self.skipTest("C++ compiler not available")
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {"self": {"$ref": "#/$defs/Self"}},
|
||||
"$defs": {
|
||||
"Self": {
|
||||
"type": ["object", "null"],
|
||||
"properties": {"self": {"$ref": "#/$defs/Self"}},
|
||||
}
|
||||
},
|
||||
}
|
||||
harness = textwrap.dedent(
|
||||
"""
|
||||
#include "gen.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
struct Case { const char *s; WeaselJsonStatus expected; };
|
||||
int main() {
|
||||
Case cases[] = {
|
||||
{ R"({"self": null})", WeaselJson_OK },
|
||||
{ R"({"self": {"self": null}})", WeaselJson_OK },
|
||||
{ R"({"self": {"self": {}}})", WeaselJson_OK },
|
||||
};
|
||||
for (const auto &c : cases) {
|
||||
test_schema::RootBuilder b;
|
||||
char buf[256];
|
||||
std::strncpy(buf, c.s, sizeof(buf) - 1);
|
||||
buf[sizeof(buf) - 1] = '\\0';
|
||||
WeaselJsonStatus st = b.feed(buf, std::strlen(buf));
|
||||
st = b.finish();
|
||||
if (st != c.expected) {
|
||||
std::printf("case %s expected %d got %d\\n", c.s, c.expected, st);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
"""
|
||||
)
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
self._compile_harness(tmpdir, schema, harness)
|
||||
|
||||
|
||||
class SchemagenIntegerBoundaryTest(unittest.TestCase):
|
||||
"""Regression tests for issue #19: integer slot parsing near int64 boundaries."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user