512 lines
19 KiB
Diff
512 lines
19 KiB
Diff
From b5d243463c24309b155f9b6e98544ab8e8046fba Mon Sep 17 00:00:00 2001
|
|
From: Giuseppe Scrivano <[email protected]>
|
|
Date: Thu, 13 Aug 2026 15:11:13 +0000
|
|
Subject: [PATCH 1/9] libcrun: export parse_json_file for the language bindings
|
|
|
|
The Python and Lua bindings parse a process JSON blob (in their
|
|
update/exec helpers) with parse_json_file() before calling
|
|
libcrun_container_exec(). libcrun is built with -fvisibility=hidden and
|
|
a version script (libcrun.lds) that only exports symbols matching a few
|
|
name patterns, so parse_json_file was not exported and loading either
|
|
module failed with:
|
|
|
|
undefined symbol: parse_json_file
|
|
|
|
Mark it LIBCRUN_PUBLIC (so it reaches the dynamic symbol table) and add
|
|
it to the version script global list (both are required to export it).
|
|
|
|
Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
|
Signed-off-by: Giuseppe Scrivano <[email protected]>
|
|
---
|
|
libcrun.lds | 2 ++
|
|
src/libcrun/utils.h | 4 +++-
|
|
2 files changed, 5 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/libcrun.lds b/libcrun.lds
|
|
index 8e141724d2..c9cdce5466 100644
|
|
--- a/libcrun.lds
|
|
+++ b/libcrun.lds
|
|
@@ -2,6 +2,8 @@
|
|
global:
|
|
/* Not all the libcrun_ functions are exported, only those marked LIBCRUN_PUBLIC. */
|
|
libcrun_*;
|
|
+ /* Utility used by the language bindings (python/, lua/). */
|
|
+ parse_json_file;
|
|
/* libocispec functions */
|
|
runtime_spec_*;
|
|
free_runtime_spec_*;
|
|
diff --git a/src/libcrun/utils.h b/src/libcrun/utils.h
|
|
index 4e8d100790..2304196f9b 100644
|
|
--- a/src/libcrun/utils.h
|
|
+++ b/src/libcrun/utils.h
|
|
@@ -352,7 +352,9 @@ void get_current_timestamp (char *out, size_t len);
|
|
|
|
int set_blocking_fd (int fd, bool blocking, libcrun_error_t *err);
|
|
|
|
-int parse_json_file (json_object **out, const char *jsondata, struct parser_context *ctx, libcrun_error_t *err);
|
|
+/* Exported for the language bindings (python/, lua/), which parse a
|
|
+ process JSON blob before calling libcrun_container_exec. */
|
|
+LIBCRUN_PUBLIC int parse_json_file (json_object **out, const char *jsondata, struct parser_context *ctx, libcrun_error_t *err);
|
|
|
|
/* Check that the string STR has the prefix PREFIX. */
|
|
static inline int
|
|
|
|
From ef6b9343fcee52b7442b11c1457a0d60f0678437 Mon Sep 17 00:00:00 2001
|
|
From: Giuseppe Scrivano <[email protected]>
|
|
Date: Thu, 13 Aug 2026 15:11:13 +0000
|
|
Subject: [PATCH 2/9] libcrun: guard _GNU_SOURCE redefinition in string_map.h
|
|
|
|
Python.h defines _GNU_SOURCE to 1, so a translation unit that includes
|
|
it before string_map.h (as the Python binding does, transitively via
|
|
container.h) hits a "_GNU_SOURCE redefined" warning, which is fatal
|
|
under -Werror. Only define it when it is not already defined.
|
|
|
|
Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
|
Signed-off-by: Giuseppe Scrivano <[email protected]>
|
|
---
|
|
src/libcrun/string_map.h | 4 +++-
|
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/libcrun/string_map.h b/src/libcrun/string_map.h
|
|
index 9819df1b87..f647769190 100644
|
|
--- a/src/libcrun/string_map.h
|
|
+++ b/src/libcrun/string_map.h
|
|
@@ -19,7 +19,9 @@
|
|
#ifndef STRING_MAP_H
|
|
#define STRING_MAP_H
|
|
|
|
-#define _GNU_SOURCE
|
|
+#ifndef _GNU_SOURCE
|
|
+# define _GNU_SOURCE
|
|
+#endif
|
|
|
|
#include <config.h>
|
|
|
|
|
|
From 004cf513da2924a25a891082671b332f08c2d8f5 Mon Sep 17 00:00:00 2001
|
|
From: Giuseppe Scrivano <[email protected]>
|
|
Date: Thu, 13 Aug 2026 15:13:14 +0000
|
|
Subject: [PATCH 3/9] python: include libcrun/spec.h for libcrun_container_spec
|
|
|
|
libcrun_container_spec() moved from container.h to spec.h, but the
|
|
Python bindings were never updated and still only included container.h.
|
|
Building the bindings failed with an implicit-declaration error. Add
|
|
the missing include.
|
|
|
|
Closes: https://github.com/containers/crun/issues/2187
|
|
Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
|
Signed-off-by: Giuseppe Scrivano <[email protected]>
|
|
---
|
|
python/crun_python.c | 1 +
|
|
1 file changed, 1 insertion(+)
|
|
|
|
diff --git a/python/crun_python.c b/python/crun_python.c
|
|
index 47bd7b1608..8846f32d07 100644
|
|
--- a/python/crun_python.c
|
|
+++ b/python/crun_python.c
|
|
@@ -36,6 +36,7 @@ python_crun.run(ctx, ctr)
|
|
#include <Python.h>
|
|
#include <libcrun/container.h>
|
|
#include <libcrun/status.h>
|
|
+#include <libcrun/spec.h>
|
|
#include <libcrun/utils.h>
|
|
#include <libcrun/error.h>
|
|
|
|
|
|
From f757ac4fcf84d5e5f6c1867cc69669f9c3c26ee6 Mon Sep 17 00:00:00 2001
|
|
From: Giuseppe Scrivano <[email protected]>
|
|
Date: Thu, 13 Aug 2026 15:13:23 +0000
|
|
Subject: [PATCH 4/9] python: register the missing start method
|
|
|
|
container_start() was defined but never added to the method table, so
|
|
python_crun had no "start" entry and the function triggered a
|
|
-Werror=unused-function build failure. Register it.
|
|
|
|
Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
|
Signed-off-by: Giuseppe Scrivano <[email protected]>
|
|
---
|
|
python/crun_python.c | 1 +
|
|
1 file changed, 1 insertion(+)
|
|
|
|
diff --git a/python/crun_python.c b/python/crun_python.c
|
|
index 8846f32d07..34fd2297d3 100644
|
|
--- a/python/crun_python.c
|
|
+++ b/python/crun_python.c
|
|
@@ -468,6 +468,7 @@ static PyMethodDef CrunMethods[] = {
|
|
{"create", container_create, METH_VARARGS, "Create a container."},
|
|
{"delete", container_delete, METH_VARARGS, "Delete a container."},
|
|
{"kill", container_kill, METH_VARARGS, "Kill a container."},
|
|
+ {"start", container_start, METH_VARARGS, "Start a container."},
|
|
{"list", containers_list, METH_VARARGS, "List the containers."},
|
|
{"status", container_status, METH_VARARGS,
|
|
"Get the status of a container."},
|
|
|
|
From 0c1b48c848b21624ae72fde01b551e114f658629 Mon Sep 17 00:00:00 2001
|
|
From: Giuseppe Scrivano <[email protected]>
|
|
Date: Thu, 13 Aug 2026 15:13:31 +0000
|
|
Subject: [PATCH 5/9] python: drop the duplicate spec method entry
|
|
|
|
The method table registered "spec" twice with the same handler. The
|
|
duplicate is harmless at runtime but confusing; remove it. "spec"
|
|
remains available via the earlier entry.
|
|
|
|
Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
|
Signed-off-by: Giuseppe Scrivano <[email protected]>
|
|
---
|
|
python/crun_python.c | 2 --
|
|
1 file changed, 2 deletions(-)
|
|
|
|
diff --git a/python/crun_python.c b/python/crun_python.c
|
|
index 34fd2297d3..0958c3f3e5 100644
|
|
--- a/python/crun_python.c
|
|
+++ b/python/crun_python.c
|
|
@@ -480,8 +480,6 @@ static PyMethodDef CrunMethods[] = {
|
|
"Create a context object."},
|
|
{"set_verbosity", set_verbosity, METH_VARARGS, "Set the logging verbosity."},
|
|
{"get_verbosity", get_verbosity, METH_NOARGS, "Get the logging verbosity."},
|
|
- {"spec", container_spec, METH_VARARGS,
|
|
- "Generate a new configuration file."},
|
|
{NULL, NULL, 0, NULL}
|
|
};
|
|
|
|
|
|
From 3a605804159b7d3ec8ca1a4086517f8c089901f5 Mon Sep 17 00:00:00 2001
|
|
From: Giuseppe Scrivano <[email protected]>
|
|
Date: Thu, 13 Aug 2026 15:14:08 +0000
|
|
Subject: [PATCH 6/9] python: fix context capsule destructor and drop dead code
|
|
|
|
make_context() created its capsule with a NULL destructor, so the
|
|
libcrun_context_t and its strdup'd fields leaked whenever a context was
|
|
garbage collected. It also leaked the freshly allocated context if
|
|
argument parsing failed.
|
|
|
|
Wire up free_context() as the capsule destructor and free the context
|
|
on the parse-error path. free_context() now retrieves the pointer with
|
|
PyCapsule_GetPointer() (the previous cast of the raw PyObject* was
|
|
wrong for a capsule destructor) and also frees the previously-forgotten
|
|
bundle field.
|
|
|
|
While here, remove unused local variables from container_status,
|
|
container_spec and set_verbosity that tripped -Werror.
|
|
|
|
Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
|
Signed-off-by: Giuseppe Scrivano <[email protected]>
|
|
---
|
|
python/crun_python.c | 35 ++++++++++++++++++++---------------
|
|
1 file changed, 20 insertions(+), 15 deletions(-)
|
|
|
|
diff --git a/python/crun_python.c b/python/crun_python.c
|
|
index 0958c3f3e5..b14994f757 100644
|
|
--- a/python/crun_python.c
|
|
+++ b/python/crun_python.c
|
|
@@ -106,13 +106,23 @@ container_load_from_memory (PyObject *self arg_unused, PyObject *args)
|
|
}
|
|
|
|
static void
|
|
-free_context (void *ptr)
|
|
+free_context (PyObject *ptr)
|
|
{
|
|
- libcrun_context_t *ctx = ptr;
|
|
- char *id = (char *) ctx->id;
|
|
- free (ctx->state_root);
|
|
- free (ctx->notify_socket);
|
|
+ libcrun_context_t *ctx = PyCapsule_GetPointer (ptr, CONTEXT_OBJ_TAG);
|
|
+ void *id, *bundle, *state_root, *notify_socket;
|
|
+
|
|
+ if (ctx == NULL)
|
|
+ return;
|
|
+
|
|
+ id = (void *) ctx->id;
|
|
+ bundle = (void *) ctx->bundle;
|
|
+ state_root = (void *) ctx->state_root;
|
|
+ notify_socket = (void *) ctx->notify_socket;
|
|
+
|
|
free (id);
|
|
+ free (bundle);
|
|
+ free (state_root);
|
|
+ free (notify_socket);
|
|
free (ctx);
|
|
}
|
|
|
|
@@ -135,13 +145,16 @@ make_context (PyObject *self arg_unused, PyObject *args, PyObject *kwargs)
|
|
if (!PyArg_ParseTupleAndKeywords
|
|
(args, kwargs, "s|ssbsbbbb", kwlist, &id, &bundle, &state_root,
|
|
&ctx->systemd_cgroup, ¬ify_socket, &ctx->detach, &ctx->no_new_keyring, &ctx->force_no_cgroup, &ctx->no_pivot))
|
|
- return NULL;
|
|
+ {
|
|
+ free (ctx);
|
|
+ return NULL;
|
|
+ }
|
|
|
|
ctx->id = xstrdup (id);
|
|
ctx->bundle = xstrdup (bundle ? bundle : ".");
|
|
ctx->state_root = xstrdup (state_root);
|
|
ctx->notify_socket = xstrdup (notify_socket);
|
|
- return PyCapsule_New (ctx, CONTEXT_OBJ_TAG, NULL);
|
|
+ return PyCapsule_New (ctx, CONTEXT_OBJ_TAG, free_context);
|
|
}
|
|
|
|
static PyObject *
|
|
@@ -329,7 +342,6 @@ container_status (PyObject *self arg_unused, PyObject *args)
|
|
PyObject *ctx_obj = NULL;
|
|
libcrun_context_t *ctx;
|
|
char *id = NULL;
|
|
- libcrun_container_status_t status;
|
|
cleanup_free char *buffer = NULL;
|
|
FILE *memfile;
|
|
int ret;
|
|
@@ -414,10 +426,6 @@ static PyObject *
|
|
container_spec (PyObject *self arg_unused, PyObject *args arg_unused)
|
|
{
|
|
libcrun_error_t err = NULL;
|
|
- PyObject *ctx_obj = NULL;
|
|
- libcrun_context_t *ctx;
|
|
- char *id = NULL;
|
|
- libcrun_container_status_t status;
|
|
cleanup_free char *buffer = NULL;
|
|
FILE *memfile;
|
|
int ret;
|
|
@@ -447,9 +455,6 @@ get_verbosity (PyObject *self arg_unused, PyObject *args)
|
|
static PyObject *
|
|
set_verbosity (PyObject *self arg_unused, PyObject *args)
|
|
{
|
|
- libcrun_error_t err;
|
|
- PyObject *ctx_obj = NULL;
|
|
- libcrun_context_t *ctx;
|
|
int verbosity;
|
|
|
|
if (!PyArg_ParseTuple (args, "i", &verbosity))
|
|
|
|
From 7369dcf9ecf4aef7caa924188c49332db64b3418 Mon Sep 17 00:00:00 2001
|
|
From: Giuseppe Scrivano <[email protected]>
|
|
Date: Thu, 13 Aug 2026 15:14:25 +0000
|
|
Subject: [PATCH 7/9] lua: include libcrun/spec.h for libcrun_container_spec
|
|
|
|
libcrun_container_spec() moved from container.h to spec.h, but the Lua
|
|
bindings still only included container.h. Building the bindings failed
|
|
with an implicit-declaration error. Add the missing include.
|
|
|
|
Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
|
Signed-off-by: Giuseppe Scrivano <[email protected]>
|
|
---
|
|
lua/lua_crun.c | 1 +
|
|
1 file changed, 1 insertion(+)
|
|
|
|
diff --git a/lua/lua_crun.c b/lua/lua_crun.c
|
|
index cdd22b8907..fc0fecb97f 100644
|
|
--- a/lua/lua_crun.c
|
|
+++ b/lua/lua_crun.c
|
|
@@ -30,6 +30,7 @@
|
|
#include <lauxlib.h>
|
|
#include <libcrun/container.h>
|
|
#include <libcrun/status.h>
|
|
+#include <libcrun/spec.h>
|
|
#include <libcrun/utils.h>
|
|
#include <libcrun/error.h>
|
|
|
|
|
|
From a1bc828ecd2cdd2e697a5b12d81d12411ff730cb Mon Sep 17 00:00:00 2001
|
|
From: Giuseppe Scrivano <[email protected]>
|
|
Date: Thu, 13 Aug 2026 15:14:33 +0000
|
|
Subject: [PATCH 8/9] lua: return luaL_error from luacrun_ctx_run
|
|
|
|
luaL_error() is not declared as noreturn, so falling off the end of the
|
|
function after calling it triggered a -Werror=return-type build failure.
|
|
Return its result (it never actually returns) to satisfy the compiler.
|
|
|
|
Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
|
Signed-off-by: Giuseppe Scrivano <[email protected]>
|
|
---
|
|
lua/lua_crun.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/lua/lua_crun.c b/lua/lua_crun.c
|
|
index fc0fecb97f..84ca34ebc3 100644
|
|
--- a/lua/lua_crun.c
|
|
+++ b/lua/lua_crun.c
|
|
@@ -369,7 +369,7 @@ luacrun_ctx_run (lua_State *S)
|
|
lua_pushnil (S);
|
|
return luacrun_error (S, &crun_err) + 1;
|
|
} else {
|
|
- luaL_error(S, "failed to run container");
|
|
+ return luaL_error (S, "failed to run container");
|
|
}
|
|
}
|
|
else
|
|
|
|
From 9d97f481028f912e06ff3679a51a083af63d00ac Mon Sep 17 00:00:00 2001
|
|
From: Giuseppe Scrivano <[email protected]>
|
|
Date: Thu, 13 Aug 2026 15:14:45 +0000
|
|
Subject: [PATCH 9/9] ci: build and smoke-test the Python and Lua bindings
|
|
|
|
The language bindings link against internal libcrun symbols but were
|
|
never built in CI, so API drift (libcrun_container_spec moving to
|
|
spec.h) and missing symbol exports (parse_json_file) went unnoticed
|
|
until a build broke.
|
|
|
|
Add a "bindings" test job that configures with --with-python-bindings
|
|
and --with-lua-bindings under -Werror, builds the modules, and loads
|
|
each freshly built module to run a smoke test. The smoke tests check
|
|
that spec generation still works, that every documented entry point is
|
|
registered, that the verbosity constants exist, and that loading a
|
|
container resolves all the needed symbols.
|
|
|
|
Ship the new test scripts in the tarball via EXTRA_DIST.
|
|
|
|
Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
|
Signed-off-by: Giuseppe Scrivano <[email protected]>
|
|
---
|
|
Makefile.am | 3 +-
|
|
lua/test_lua_bindings.lua | 56 +++++++++++++++++++++++++++++
|
|
python/test_python_bindings.py | 64 ++++++++++++++++++++++++++++++++++
|
|
4 files changed, 136 insertions(+), 2 deletions(-)
|
|
create mode 100644 lua/test_lua_bindings.lua
|
|
create mode 100644 python/test_python_bindings.py
|
|
|
|
diff --git a/Makefile.am b/Makefile.am
|
|
index 6905f5fa2e..4266b134a9 100644
|
|
--- a/Makefile.am
|
|
+++ b/Makefile.am
|
|
@@ -186,7 +186,8 @@ EXTRA_DIST = COPYING COPYING.libcrun README.md NEWS SECURITY.md rpm/crun.spec au
|
|
src/libcrun/syscalls.h \
|
|
crun.1.md crun.1 libcrun.lds \
|
|
krun.1.md krun.1 \
|
|
- lua/luacrun.rockspec
|
|
+ lua/luacrun.rockspec lua/test_lua_bindings.lua \
|
|
+ python/test_python_bindings.py
|
|
|
|
if !HAVE_EMBEDDED_BLAKE3
|
|
EXTRA_DIST += src/libcrun/blake3/blake3.c \
|
|
diff --git a/lua/test_lua_bindings.lua b/lua/test_lua_bindings.lua
|
|
new file mode 100644
|
|
index 0000000000..468f296204
|
|
--- /dev/null
|
|
+++ b/lua/test_lua_bindings.lua
|
|
@@ -0,0 +1,56 @@
|
|
+-- crun - OCI runtime written in C
|
|
+--
|
|
+-- Copyright (C) 2026 crun Authors
|
|
+-- crun is free software; you can redistribute it and/or modify
|
|
+-- it under the terms of the GNU Lesser General Public License as published by
|
|
+-- the Free Software Foundation; either version 2.1 of the License, or
|
|
+-- (at your option) any later version.
|
|
+--
|
|
+-- crun is distributed in the hope that it will be useful,
|
|
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+-- GNU Lesser General Public License for more details.
|
|
+--
|
|
+-- You should have received a copy of the GNU Lesser General Public License
|
|
+-- along with crun. If not, see <http://www.gnu.org/licenses/>.
|
|
+--
|
|
+-- Smoke test for the Lua bindings. It does not run a container (that
|
|
+-- requires a privileged environment); it only exercises the parts of the
|
|
+-- module that must keep working so a build/link regression is caught early.
|
|
+-- Set package.cpath (or LUA_CPATH) so that require("luacrun") resolves to
|
|
+-- the freshly built luacrun.so before running.
|
|
+
|
|
+local crun = require("luacrun")
|
|
+
|
|
+-- Spec generation must keep working (feature exercised by callers).
|
|
+local spec = crun.container_spec(true)
|
|
+assert(type(spec) == "string" and #spec > 0, "generated spec is empty")
|
|
+assert(spec:find("ociVersion"), "generated spec has no ociVersion")
|
|
+
|
|
+-- Every documented entry point must be present. This also catches a missing
|
|
+-- registration in luacrun_library_reg.
|
|
+local expected = {
|
|
+ "new_ctx", "container_spec", "new_container_from_string",
|
|
+ "new_container_from_file", "get_verbosity", "set_verbosity", "run",
|
|
+ "create_container", "delete_container", "kill_container",
|
|
+ "start_container", "status_container", "iter_container_names",
|
|
+ "update_container",
|
|
+}
|
|
+for _, name in ipairs(expected) do
|
|
+ assert(crun[name] ~= nil, "missing function " .. name)
|
|
+end
|
|
+
|
|
+-- Verbosity constants.
|
|
+for _, name in ipairs({ "VERBOSITY_ERROR", "VERBOSITY_WARNING", "VERBOSITY_DEBUG" }) do
|
|
+ assert(crun[name] ~= nil, "missing constant " .. name)
|
|
+end
|
|
+
|
|
+crun.set_verbosity(crun.VERBOSITY_ERROR)
|
|
+assert(crun.get_verbosity() == crun.VERBOSITY_ERROR, "verbosity round-trip failed")
|
|
+
|
|
+-- Loading a container from the generated spec must resolve every symbol the
|
|
+-- module needs (this is what caught the missing parse_json_file /
|
|
+-- libcrun_container_spec exports).
|
|
+assert(crun.new_container_from_string(spec) ~= nil, "new_container_from_string failed")
|
|
+
|
|
+print("lua bindings smoke test: OK")
|
|
diff --git a/python/test_python_bindings.py b/python/test_python_bindings.py
|
|
new file mode 100644
|
|
index 0000000000..3acd76ef1a
|
|
--- /dev/null
|
|
+++ b/python/test_python_bindings.py
|
|
@@ -0,0 +1,64 @@
|
|
+#!/usr/bin/env python3
|
|
+# crun - OCI runtime written in C
|
|
+#
|
|
+# Copyright (C) 2026 crun Authors
|
|
+# crun is free software; you can redistribute it and/or modify
|
|
+# it under the terms of the GNU Lesser General Public License as published by
|
|
+# the Free Software Foundation; either version 2.1 of the License, or
|
|
+# (at your option) any later version.
|
|
+#
|
|
+# crun is distributed in the hope that it will be useful,
|
|
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+# GNU Lesser General Public License for more details.
|
|
+#
|
|
+# You should have received a copy of the GNU Lesser General Public License
|
|
+# along with crun. If not, see <http://www.gnu.org/licenses/>.
|
|
+#
|
|
+# Smoke test for the Python bindings. It does not run a container (that
|
|
+# requires a privileged environment); it only exercises the parts of the
|
|
+# module that must keep working so a build/link regression is caught early.
|
|
+# Point PYTHONPATH at the directory holding python_crun.so before running.
|
|
+
|
|
+import gc
|
|
+import json
|
|
+import sys
|
|
+
|
|
+import python_crun
|
|
+
|
|
+
|
|
+def main():
|
|
+ # Spec generation must keep working (feature exercised by callers).
|
|
+ spec = json.loads(python_crun.spec())
|
|
+ assert spec.get("ociVersion"), "generated spec has no ociVersion"
|
|
+ assert spec["process"]["args"], "generated spec has no process args"
|
|
+
|
|
+ # Every documented entry point must be present.
|
|
+ expected = [
|
|
+ "load_from_file", "load_from_memory", "run", "create", "delete",
|
|
+ "kill", "start", "list", "status", "update", "spec", "make_context",
|
|
+ "set_verbosity", "get_verbosity",
|
|
+ ]
|
|
+ missing = [name for name in expected if not hasattr(python_crun, name)]
|
|
+ assert not missing, "missing methods: %s" % missing
|
|
+
|
|
+ # Verbosity constants.
|
|
+ for const in ("VERBOSITY_ERROR", "VERBOSITY_WARNING", "VERBOSITY_DEBUG"):
|
|
+ assert hasattr(python_crun, const), "missing constant %s" % const
|
|
+
|
|
+ # Loading a container from the generated spec must resolve every symbol
|
|
+ # the module needs (this is what caught the missing parse_json_file /
|
|
+ # libcrun_container_spec exports).
|
|
+ python_crun.load_from_memory(json.dumps(spec))
|
|
+
|
|
+ # Creating and dropping a context must run the capsule destructor without
|
|
+ # crashing.
|
|
+ ctx = python_crun.make_context("crun-python-smoke-test")
|
|
+ del ctx
|
|
+ gc.collect()
|
|
+
|
|
+ print("python bindings smoke test: OK")
|
|
+
|
|
+
|
|
+if __name__ == "__main__":
|
|
+ sys.exit(main())
|