From 510f4514cb154f9b9414e8b836c18992e3ab9925 Mon Sep 17 00:00:00 2001 From: Martin Eide <43970264+mrtineide@users.noreply.github.com> Date: Thu, 2 Oct 2025 15:54:09 +0200 Subject: [PATCH 1/2] Change unit tests to only use one CCDB api init This (hopefully) fixes some tests that are fine on desktop but the subprocess aborts even when all tests are green in CI. malloc_consolidate(): invalid chunk size This might have happend because the deconstructor of CCDBApi calling curl global cleanup and with both a CCDB api and a BasicCCDBManager we have one global CURL cleanup called twice, one for the api and one for the manager. --- CCDB/test/testCcdbApiHeaders.cxx | 100 ++++++++++++++----------------- 1 file changed, 44 insertions(+), 56 deletions(-) diff --git a/CCDB/test/testCcdbApiHeaders.cxx b/CCDB/test/testCcdbApiHeaders.cxx index 4cad30b7099d5..84187a5da86b1 100644 --- a/CCDB/test/testCcdbApiHeaders.cxx +++ b/CCDB/test/testCcdbApiHeaders.cxx @@ -39,15 +39,16 @@ bool hostReachable = false; struct Fixture { Fixture() { - o2::ccdb::CcdbApi api; + auto& ccdbManager = o2::ccdb::BasicCCDBManager::instance(); if (std::getenv("ALICEO2_CCDB_HOST")) { ccdbUrl = std::string(std::getenv("ALICEO2_CCDB_HOST")); } - api.init(ccdbUrl); - hostReachable = api.isHostReachable(); + hostReachable = ccdbManager.getCCDBAccessor().isHostReachable(); char hostname[_POSIX_HOST_NAME_MAX]; gethostname(hostname, _POSIX_HOST_NAME_MAX); - basePath = std::string("Users/m/meide/BasicCCDBManager/"); + basePath = std::string("Users/m/meide/Tests/") + hostname+"/pid-" +getpid()+ "/BasicCCDBManager/"; + + ccdbManager.setURL(ccdbUrl); LOG(info) << "Path we will use in this test suite : " + basePath << std::endl; LOG(info) << "ccdb url: " << ccdbUrl << std::endl; @@ -56,9 +57,7 @@ struct Fixture { ~Fixture() { if (hostReachable) { - o2::ccdb::CcdbApi api; - api.init(ccdbUrl); - api.truncate(basePath + "*"); // This deletes the data after test is run, disable if you want to inspect the data + o2::ccdb::BasicCCDBManager::instance().getCCDBAccessor().truncate(basePath + "*"); // This deletes the data after test is run, disable if you want to inspect the data LOG(info) << "Test data truncated/deleted (" << basePath << ")" << std::endl; } } @@ -74,22 +73,6 @@ struct if_reachable { return hostReachable; } }; -/** - * Fixture for the tests, i.e. code is ran in every test that uses it, i.e. it is like a setup and teardown for tests. - * Copied from testCcdbApi.cxx - */ -struct test_fixture { - test_fixture() - { - api.init(ccdbUrl); - metadata["Hello"] = "World"; - LOG(info) << "*** " << boost::unit_test::framework::current_test_case().p_name << " ***" << std::endl; - } - ~test_fixture() = default; - - o2::ccdb::CcdbApi api; - std::map metadata; -}; // Only compare known and stable keys (avoid volatile ones like Date) static const std::set sStableKeys = { @@ -112,23 +95,24 @@ BOOST_AUTO_TEST_CASE(testCachedHeaders, *boost::unit_test::precondition(if_reach { /// ━━━━━━━ ARRANGE ━━━━━━━━━ // First store objects to test with - test_fixture f; - + auto& ccdbManager = o2::ccdb::BasicCCDBManager::instance(); std::string pathA = basePath + "CachingA"; std::string pathB = basePath + "CachingB"; std::string pathC = basePath + "CachingC"; std::string ccdbObjO = "testObjectO"; std::string ccdbObjN = "testObjectN"; std::string ccdbObjX = "testObjectX"; - std::map md = f.metadata; + std::map md = { + {"Hello", "World"}, + {"Key1", "Value1"}, + {"Key2", "Value2"}, + }; long start = 1000, stop = 3000; - f.api.storeAsTFileAny(&ccdbObjO, pathA, md, start, stop); - f.api.storeAsTFileAny(&ccdbObjN, pathB, md, start, stop); - f.api.storeAsTFileAny(&ccdbObjX, pathC, md, start, stop); + ccdbManager.getCCDBAccessor().storeAsTFileAny(&ccdbObjO, pathA, md, start, stop); + ccdbManager.getCCDBAccessor().storeAsTFileAny(&ccdbObjN, pathB, md, start, stop); + ccdbManager.getCCDBAccessor().storeAsTFileAny(&ccdbObjX, pathC, md, start, stop); // initilize the BasicCCDBManager - o2::ccdb::BasicCCDBManager& ccdbManager = o2::ccdb::BasicCCDBManager::instance(); ccdbManager.clearCache(); - ccdbManager.setURL(ccdbUrl); ccdbManager.setCaching(true); // This is what we want to test. /// ━━━━━━━━━━━ ACT ━━━━━━━━━━━━ @@ -193,20 +177,21 @@ BOOST_AUTO_TEST_CASE(testNonCachedHeaders, *boost::unit_test::precondition(if_re { /// ━━━━━━━ ARRANGE ━━━━━━━━━ // First store objects to test with - test_fixture f; - + auto& ccdbManager = o2::ccdb::BasicCCDBManager::instance(); std::string pathA = basePath + "NonCachingA"; std::string pathB = basePath + "NonCachingB"; std::string ccdbObjO = "testObjectO"; std::string ccdbObjN = "testObjectN"; - std::map md = f.metadata; + std::map md = { + {"Hello", "World"}, + {"Key1", "Value1"}, + {"Key2", "Value2"}, + }; long start = 1000, stop = 2000; - f.api.storeAsTFileAny(&ccdbObjO, pathA, md, start, stop); - f.api.storeAsTFileAny(&ccdbObjN, pathB, md, start, stop); + ccdbManager.getCCDBAccessor().storeAsTFileAny(&ccdbObjO, pathA, md, start, stop); + ccdbManager.getCCDBAccessor().storeAsTFileAny(&ccdbObjN, pathB, md, start, stop); // initilize the BasicCCDBManager - o2::ccdb::BasicCCDBManager& ccdbManager = o2::ccdb::BasicCCDBManager::instance(); ccdbManager.clearCache(); - ccdbManager.setURL(ccdbUrl); ccdbManager.setCaching(false); // This is what we want to test, no caching /// ━━━━━━━━━━━ ACT ━━━━━━━━━━━━ @@ -217,6 +202,7 @@ BOOST_AUTO_TEST_CASE(testNonCachedHeaders, *boost::unit_test::precondition(if_re auto* obj2 = ccdbManager.getForTimeStamp(pathB, (start + stop) / 2, &headers2); auto* obj3 = ccdbManager.getForTimeStamp(pathA, (start + stop) / 2, &headers3); // Should not be cached since explicitly disabled + ccdbManager.setCaching(true); // Restore default state /// ━━━━━━━━━━━ ASSERT ━━━━━━━━━━━ /// Check that we got something BOOST_REQUIRE(obj1 != nullptr); @@ -249,12 +235,17 @@ BOOST_AUTO_TEST_CASE(testNonCachedHeaders, *boost::unit_test::precondition(if_re BOOST_TEST(headers3.size() != 0); BOOST_TEST(headers2.size() != 0); BOOST_TEST(headers1 != headers2, "The headers for different objects should be different"); + + //cleanup + delete obj1; + delete obj2; + delete obj3; } -BOOST_AUTO_TEST_CASE(CacheFirstRetrievalAndHeadersPersistence) +BOOST_AUTO_TEST_CASE(CacheFirstRetrievalAndHeadersPersistence,*boost::unit_test::precondition(if_reachable())) { - test_fixture f; /// ━━━━━━━ ARRANGE ━━━━━━━━━ + auto& mgr = o2::ccdb::BasicCCDBManager::instance(); // Prepare two validity slots for same path to test ETag change later std::string path = basePath + "ObjA"; std::string objV1 = "ObjectVersion1"; @@ -268,11 +259,9 @@ BOOST_AUTO_TEST_CASE(CacheFirstRetrievalAndHeadersPersistence) long v2stop = v2start + (v1stop - v1start); long mid1 = (v1start + v1stop) / 2; // Store 2 versions - f.api.storeAsTFileAny(&objV1, path, meta1, v1start, v1stop); - f.api.storeAsTFileAny(&objV2, path, meta1, v2start, v2stop); + mgr.getCCDBAccessor().storeAsTFileAny(&objV1, path, meta1, v1start, v1stop); + mgr.getCCDBAccessor().storeAsTFileAny(&objV2, path, meta1, v2start, v2stop); - auto& mgr = o2::ccdb::BasicCCDBManager::instance(); - mgr.setURL(ccdbUrl); mgr.clearCache(); mgr.setCaching(true); mgr.setFatalWhenNull(true); @@ -294,6 +283,8 @@ BOOST_AUTO_TEST_CASE(CacheFirstRetrievalAndHeadersPersistence) // 5) Fifth retrieval with headers again to check persistence auto* p5 = mgr.getForTimeStamp(path, mid1, &headers5); + mgr.setFatalWhenNull(false); // restore default + /// ━━━━━━━ASSERT━━━━━━━━━ BOOST_TEST(p1 != nullptr); @@ -336,17 +327,16 @@ BOOST_AUTO_TEST_CASE(CacheFirstRetrievalAndHeadersPersistence) BOOST_TEST(headers5["UserKey1"] == "UValue1"); // internal unchanged } -BOOST_AUTO_TEST_CASE(FailedFetchDoesNotGiveMetadata) +BOOST_AUTO_TEST_CASE(FailedFetchDoesNotGiveMetadata,*boost::unit_test::precondition(if_reachable())) { - test_fixture f; /// ━━━━━━━ ARRANGE ━━━━━━━━━ + auto& mgr = o2::ccdb::BasicCCDBManager::instance(); std::string path = basePath + "FailThenRecover"; std::string content = "ContentX"; std::map meta{{"Alpha", "Beta"}}; long s = 300'000, e = 310'000; - f.api.storeAsTFileAny(&content, path, meta, s, e); - auto& mgr = o2::ccdb::BasicCCDBManager::instance(); + mgr.getCCDBAccessor().storeAsTFileAny(&content, path, meta, s, e); mgr.clearCache(); mgr.setCaching(true); mgr.setFatalWhenNull(false); @@ -368,17 +358,16 @@ BOOST_AUTO_TEST_CASE(FailedFetchDoesNotGiveMetadata) mgr.setFatalWhenNull(true); } -BOOST_AUTO_TEST_CASE(FirstCallWithoutHeadersThenWithHeaders) +BOOST_AUTO_TEST_CASE(FirstCallWithoutHeadersThenWithHeaders, *boost::unit_test::precondition(if_reachable())) { - test_fixture f; + auto& mgr = o2::ccdb::BasicCCDBManager::instance(); std::string path = basePath + "LateHeaders"; std::string body = "Late"; std::map meta{{"LateKey", "LateVal"}}; long s = 400'000, e = 410'000; - f.api.storeAsTFileAny(&body, path, meta, s, e); + mgr.getCCDBAccessor().storeAsTFileAny(&body, path, meta, s, e); - auto& mgr = o2::ccdb::BasicCCDBManager::instance(); mgr.clearCache(); mgr.setCaching(true); long ts = (s + e) / 2; @@ -398,17 +387,16 @@ BOOST_AUTO_TEST_CASE(FirstCallWithoutHeadersThenWithHeaders) BOOST_TEST(h2.count("Valid-Until") == 1); } -BOOST_AUTO_TEST_CASE(HeadersAreStableAcrossMultipleHits) +BOOST_AUTO_TEST_CASE(HeadersAreStableAcrossMultipleHits, *boost::unit_test::precondition(if_reachable())) { - test_fixture f; + auto& mgr = o2::ccdb::BasicCCDBManager::instance(); std::string path = basePath + "StableHeaders"; std::string body = "Stable"; std::map meta{{"HK", "HV"}}; long s = 500'000, e = 510'000; - f.api.storeAsTFileAny(&body, path, meta, s, e); + mgr.getCCDBAccessor().storeAsTFileAny(&body, path, meta, s, e); - auto& mgr = o2::ccdb::BasicCCDBManager::instance(); mgr.clearCache(); mgr.setCaching(true); long ts = (s + e) / 2; From 64c40fd2aea49eff576849d04ec2d39755b8568e Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Tue, 7 Oct 2025 15:17:47 +0000 Subject: [PATCH 2/2] Please consider the following formatting changes --- CCDB/test/testCcdbApiHeaders.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CCDB/test/testCcdbApiHeaders.cxx b/CCDB/test/testCcdbApiHeaders.cxx index 84187a5da86b1..1a6d50de58fe1 100644 --- a/CCDB/test/testCcdbApiHeaders.cxx +++ b/CCDB/test/testCcdbApiHeaders.cxx @@ -46,7 +46,7 @@ struct Fixture { hostReachable = ccdbManager.getCCDBAccessor().isHostReachable(); char hostname[_POSIX_HOST_NAME_MAX]; gethostname(hostname, _POSIX_HOST_NAME_MAX); - basePath = std::string("Users/m/meide/Tests/") + hostname+"/pid-" +getpid()+ "/BasicCCDBManager/"; + basePath = std::string("Users/m/meide/Tests/") + hostname + "/pid-" + getpid() + "/BasicCCDBManager/"; ccdbManager.setURL(ccdbUrl); @@ -236,13 +236,13 @@ BOOST_AUTO_TEST_CASE(testNonCachedHeaders, *boost::unit_test::precondition(if_re BOOST_TEST(headers2.size() != 0); BOOST_TEST(headers1 != headers2, "The headers for different objects should be different"); - //cleanup + // cleanup delete obj1; delete obj2; delete obj3; } -BOOST_AUTO_TEST_CASE(CacheFirstRetrievalAndHeadersPersistence,*boost::unit_test::precondition(if_reachable())) +BOOST_AUTO_TEST_CASE(CacheFirstRetrievalAndHeadersPersistence, *boost::unit_test::precondition(if_reachable())) { /// ━━━━━━━ ARRANGE ━━━━━━━━━ auto& mgr = o2::ccdb::BasicCCDBManager::instance(); @@ -327,7 +327,7 @@ BOOST_AUTO_TEST_CASE(CacheFirstRetrievalAndHeadersPersistence,*boost::unit_test: BOOST_TEST(headers5["UserKey1"] == "UValue1"); // internal unchanged } -BOOST_AUTO_TEST_CASE(FailedFetchDoesNotGiveMetadata,*boost::unit_test::precondition(if_reachable())) +BOOST_AUTO_TEST_CASE(FailedFetchDoesNotGiveMetadata, *boost::unit_test::precondition(if_reachable())) { /// ━━━━━━━ ARRANGE ━━━━━━━━━