You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pe...@apache.org on 2026/08/10 04:39:05 UTC
(celix) 35/35: Add jansson_ext conan test_package support and update CMake configuration
This is an automated email from the ASF dual-hosted git repository.
PengZheng pushed a commit to branch feature/json-schema
in repository https://gitbox.apache.org/repos/asf/celix.git
commit 6a9a357804ee8b7edc5fb2629a110c4099329036
Author: PengZheng <ho...@gmail.com>
AuthorDate: Mon Aug 10 11:01:30 2026 +0800
Add jansson_ext conan test_package support and update CMake configuration
---
conanfile.py | 9 ++-
libs/jansson_ext/CMakeLists.txt | 6 +-
test_package/CMakeLists.txt | 6 ++
test_package/conanfile.py | 8 +++
test_package/test_jansson_ext.c | 139 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 164 insertions(+), 4 deletions(-)
diff --git a/conanfile.py b/conanfile.py
index ba28528a7..bf9b910cb 100644
--- a/conanfile.py
+++ b/conanfile.py
@@ -50,6 +50,10 @@ class CelixConan(ConanFile):
"enable_fuzzing": False,
"enable_benchmarking": False,
"install_find_modules": False,
+ # Celix is always built as shared libraries by its CMake build system.
+ # Declared so that Conan treats the package as shared (e.g. adds the lib
+ # dir to the consumer run environment) and to allow for static builds later.
+ "shared": True,
"build_all": False,
"build_http_admin": False,
"build_log_service": False,
@@ -129,6 +133,9 @@ class CelixConan(ConanFile):
if self.settings.os != "Linux" and self.settings.os != "Macos":
raise ConanInvalidConfiguration("Celix is only supported for Linux/Macos")
+ if not self.options.shared:
+ raise ConanInvalidConfiguration("Celix is only packaged with shared libraries")
+
if self.options.build_rsa_remote_service_admin_shm_v2 and self.settings.os != "Linux":
raise ConanInvalidConfiguration("Celix build_rsa_remote_service_admin_shm_v2 is only supported for Linux")
@@ -415,7 +422,7 @@ class CelixConan(ConanFile):
def generate(self):
tc = CMakeToolchain(self)
- conan_internal_options = ["build_all"] #options are not used in CMake
+ conan_internal_options = ["build_all", "shared"] #options are not used in CMake
for opt in self._celix_defaults.keys():
if opt not in conan_internal_options:
tc.cache_variables[opt.upper()] = self.options.get_safe(opt)
diff --git a/libs/jansson_ext/CMakeLists.txt b/libs/jansson_ext/CMakeLists.txt
index 3270b363c..2a009fe35 100644
--- a/libs/jansson_ext/CMakeLists.txt
+++ b/libs/jansson_ext/CMakeLists.txt
@@ -42,10 +42,10 @@ if (JANSSON_EXT)
PRIVATE src
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
- $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/celix/gen/includes/jansson_ext>)
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/celix/gen/includes/jansson_ext>)
generate_export_header(jansson_ext
BASE_NAME CELIX_JANSSON_EXT
- EXPORT_FILE_NAME "${CMAKE_BINARY_DIR}/celix/gen/includes/jansson_ext/celix_jansson_ext_export.h")
+ EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/celix/gen/includes/jansson_ext/celix_jansson_ext_export.h")
add_library(Celix::jansson_ext ALIAS jansson_ext)
# Install (always, no option gate)
@@ -70,7 +70,7 @@ if (JANSSON_EXT)
PUBLIC
${CMAKE_CURRENT_LIST_DIR}/include
${CMAKE_CURRENT_LIST_DIR}/src
- ${CMAKE_BINARY_DIR}/celix/gen/includes/jansson_ext)
+ ${CMAKE_CURRENT_BINARY_DIR}/celix/gen/includes/jansson_ext)
target_compile_definitions(jansson_ext_cut PUBLIC CELIX_JANSSON_EXT_STATIC_DEFINE)
add_subdirectory(gtest)
endif ()
diff --git a/test_package/CMakeLists.txt b/test_package/CMakeLists.txt
index 5ba1b25e2..34d660c06 100644
--- a/test_package/CMakeLists.txt
+++ b/test_package/CMakeLists.txt
@@ -298,6 +298,12 @@ if (TEST_CELIX_DFI)
target_link_libraries(use_celix_dfi PRIVATE Celix::dfi)
endif ()
+option(TEST_JANSSON_EXT "Test jansson_ext" OFF)
+if (TEST_JANSSON_EXT)
+ add_executable(use_jansson_ext test_jansson_ext.c)
+ target_link_libraries(use_jansson_ext PRIVATE Celix::jansson_ext)
+endif ()
+
option(TEST_UTILS "Test utils" OFF)
if (TEST_UTILS)
add_executable(use_utils test_utils.c)
diff --git a/test_package/conanfile.py b/test_package/conanfile.py
index 57a2ddc97..a7b8e613e 100644
--- a/test_package/conanfile.py
+++ b/test_package/conanfile.py
@@ -32,6 +32,11 @@ class TestPackageConan(ConanFile):
def requirements(self):
self.requires(self.tested_reference_str)
+ # The public API of Celix::jansson_ext is built on jansson types (json_t), so the
+ # tests call jansson functions directly. Celix is a shared package, and Conan does
+ # not propagate the link dependencies of shared packages to consumers, so jansson
+ # must be required directly to be linkable here.
+ self.requires("jansson/[>=2.12 <3.0.0]")
def generate(self):
tc = CMakeToolchain(self)
@@ -63,6 +68,7 @@ class TestPackageConan(ConanFile):
tc.cache_variables["TEST_CXX_REMOTE_SERVICE_ADMIN"] = celix_options.build_cxx_remote_service_admin
tc.cache_variables["TEST_SHELL_API"] = celix_options.build_shell_api
tc.cache_variables["TEST_CELIX_DFI"] = celix_options.build_celix_dfi
+ tc.cache_variables["TEST_JANSSON_EXT"] = celix_options.build_jansson_ext
tc.cache_variables["TEST_UTILS"] = celix_options.build_utils
tc.cache_variables["TEST_EVENT_ADMIN"] = celix_options.build_event_admin
tc.cache_variables["TEST_EVENT_ADMIN_REMOTE_PROVIDER_MQTT"] = celix_options.build_event_admin_remote_provider_mqtt
@@ -138,6 +144,8 @@ class TestPackageConan(ConanFile):
self.run("./use_shell_api", env="conanrun")
if celix_options.build_celix_dfi:
self.run("./use_celix_dfi", env="conanrun")
+ if celix_options.build_jansson_ext:
+ self.run("./use_jansson_ext", env="conanrun")
if celix_options.build_utils:
self.run("./use_utils", env="conanrun")
if celix_options.build_event_admin:
diff --git a/test_package/test_jansson_ext.c b/test_package/test_jansson_ext.c
new file mode 100644
index 000000000..6699f7592
--- /dev/null
+++ b/test_package/test_jansson_ext.c
@@ -0,0 +1,139 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+#include <celix_jansson_pointer.h>
+#include <celix_jansson_schema.h>
+#include <celix_json_patch.h>
+#include <jansson.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main() {
+ /* ── JSON Schema draft-7 validation ─────────────────────────────────── */
+ json_error_t jerr;
+ json_t* schema = json_loads(
+ "{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\"}},\"required\":[\"name\"]}",
+ 0, &jerr);
+ if (!schema) {
+ fprintf(stderr, "Error parsing schema: %s\n", jerr.text);
+ return 1;
+ }
+
+ celix_jansson_schema_validator_t* validator = celix_jansson_schema_validator_create(
+ NULL, NULL, celix_jansson_schema_default_format_check, NULL, NULL, NULL);
+ if (!validator) {
+ fprintf(stderr, "Failed to create validator\n");
+ json_decref(schema);
+ return 1;
+ }
+
+ char* errmsg = NULL;
+ int rc = celix_jansson_schema_set_root_schema(validator, schema, &errmsg);
+ if (rc != CELIX_JANSSON_SCHEMA_OK) {
+ fprintf(stderr, "Schema compilation error: %s\n", errmsg ? errmsg : celix_jansson_schema_strerror(rc));
+ free(errmsg);
+ json_decref(schema);
+ celix_jansson_schema_validator_destroy(validator);
+ return 1;
+ }
+ free(errmsg);
+ json_decref(schema);
+
+ json_t* instance = json_loads("{\"name\":\"celix\"}", 0, &jerr);
+ if (!instance) {
+ fprintf(stderr, "Error parsing instance: %s\n", jerr.text);
+ celix_jansson_schema_validator_destroy(validator);
+ return 1;
+ }
+ int errors = celix_jansson_schema_validate(validator, instance, NULL, NULL, NULL);
+ printf("valid instance errors = %d\n", errors);
+ json_decref(instance);
+ if (errors != 0) {
+ celix_jansson_schema_validator_destroy(validator);
+ return 1;
+ }
+
+ instance = json_loads("{}", 0, &jerr);
+ if (!instance) {
+ fprintf(stderr, "Error parsing instance: %s\n", jerr.text);
+ celix_jansson_schema_validator_destroy(validator);
+ return 1;
+ }
+ errors = celix_jansson_schema_validate(validator, instance, NULL, NULL, NULL);
+ printf("invalid instance errors = %d\n", errors);
+ json_decref(instance);
+ celix_jansson_schema_validator_destroy(validator);
+ if (errors == 0) {
+ fprintf(stderr, "Expected invalid instance to be rejected\n");
+ return 1;
+ }
+
+ /* ── JSON Pointer (RFC 6901) ───────────────────────────────────────── */
+ json_t* doc = json_loads("{\"foo\":{\"bar\":1}}", 0, &jerr);
+ if (!doc) {
+ fprintf(stderr, "Error parsing document: %s\n", jerr.text);
+ return 1;
+ }
+ celix_json_pointer_t* ptr = celix_json_pointer_create("/foo/bar");
+ json_t* value = ptr ? celix_json_pointer_get(doc, ptr) : NULL;
+ char* ptr_str = ptr ? celix_json_pointer_to_string(ptr) : NULL;
+ if (!ptr || !value || !ptr_str || strcmp(ptr_str, "/foo/bar") != 0) {
+ fprintf(stderr, "JSON pointer resolution failed\n");
+ free(ptr_str);
+ celix_json_pointer_destroy(ptr);
+ json_decref(doc);
+ return 1;
+ }
+ printf("pointer = %s, value = %lld\n", ptr_str, json_integer_value(value));
+ free(ptr_str);
+
+ if (celix_json_pointer_set_new(doc, ptr, json_integer(42)) != 0) {
+ fprintf(stderr, "JSON pointer set failed\n");
+ celix_json_pointer_destroy(ptr);
+ json_decref(doc);
+ return 1;
+ }
+ printf("value after set = %lld\n", json_integer_value(celix_json_pointer_get(doc, ptr)));
+ celix_json_pointer_destroy(ptr);
+
+ /* ── JSON Patch (RFC 6902) ─────────────────────────────────────────── */
+ json_t* patch = json_array();
+ if (!patch || celix_json_patch_add(patch, "/foo/bar", json_integer(7)) != 0) {
+ fprintf(stderr, "JSON patch add failed\n");
+ json_decref(patch);
+ json_decref(doc);
+ return 1;
+ }
+ json_t* patched = celix_json_patch_apply(doc, patch);
+ if (!patched || json_integer_value(json_object_get(json_object_get(patched, "foo"), "bar")) != 7) {
+ fprintf(stderr, "JSON patch apply failed\n");
+ json_decref(patched);
+ json_decref(patch);
+ json_decref(doc);
+ return 1;
+ }
+ char* patched_str = json_dumps(patched, 0);
+ printf("patched = %s\n", patched_str ? patched_str : "?");
+ free(patched_str);
+ json_decref(patched);
+ json_decref(patch);
+ json_decref(doc);
+
+ return 0;
+}