17#define BOOST_BIND_GLOBAL_PLACEHOLDERS
18#define BOOST_TEST_MODULE CCDB
19#define BOOST_TEST_MAIN
20#define BOOST_TEST_DYN_LINK
26#include <boost/test/unit_test.hpp>
33#include <TStreamerInfo.h>
39#include <boost/property_tree/json_parser.hpp>
40#include <boost/property_tree/ptree.hpp>
41#include <boost/foreach.hpp>
42#include <boost/optional/optional.hpp>
46namespace utf = boost::unit_test;
49static std::string
ccdbUrl =
"http://ccdb-test.cern.ch:8080";
50static std::string basePath;
62 if (
const char* host = std::getenv(
"ALICEO2_CCDB_HOST")) {
66 cout <<
"ccdb url: " <<
ccdbUrl << endl;
69 char hostname[_POSIX_HOST_NAME_MAX];
70 gethostname(hostname, _POSIX_HOST_NAME_MAX);
71 basePath = std::string(
"Test/TestCcdbApi/") + hostname +
"/pid" + getpid() +
"/";
73 std::replace(basePath.begin(), basePath.end(),
'-',
'_');
74 cout <<
"Path we will use in this test suite : " + basePath << endl;
80 std::map<std::string, std::string> metadata;
83 cout <<
"Test data truncated (" << basePath <<
")" << endl;
107 std::cout <<
"*** " << boost::unit_test::framework::current_test_case().p_name <<
" ***" << std::endl;
119 TH1F h1(
"th1name",
"th1name", 100, 0, 99);
120 h1.FillRandom(
"gaus", 10000);
122 cout << basePath +
"th1" << endl;
123 f.api.storeAsTFile(&h1, basePath +
"th1",
f.metadata);
126 graph.SetPoint(0, 2, 3);
127 f.api.storeAsTFile(&graph, basePath +
"graph",
f.metadata);
129 TTree
tree(
"mytree",
"mytree");
131 tree.Branch(
"det", &
a,
"a/I");
133 f.api.storeAsTFile(&
tree, basePath +
"tree",
f.metadata);
143 path.setPath(
"HelloWorld");
145 f.api.storeAsTFileAny(&
path, basePath +
"CCDBPath",
f.metadata);
151 path2 =
f.api.retrieveFromTFileAny<
o2::ccdb::IdPath>(basePath +
"CCDBPath",
f.metadata);
152 BOOST_CHECK_NE(path2,
nullptr);
161 std::map<std::string, std::string> md;
162 path2 =
f.api.retrieveFromTFileAny<
o2::ccdb::IdPath>(basePath +
"CCDBPath",
f.metadata, -1, &md);
169 auto tree =
new TTree(
"tree123",
"tree123");
171 tree->Branch(
"det", &
a,
"a/I");
173 f.api.storeAsTFileAny(
tree, basePath +
"tree2",
f.metadata);
177 tree =
f.api.retrieveFromTFileAny<TTree>(basePath +
"tree2",
f.metadata);
188 std::filesystem::create_directories(ph);
189 std::cout <<
"Creating snapshot at " << ph <<
"\n";
191 std::cout <<
"Creating snapshot at " << ph <<
"\n";
201 auto tree = snapshot.retrieveFromTFileAny<TTree>(basePath +
"tree2",
f.metadata);
208 if (std::filesystem::exists(ph)) {
209 std::filesystem::remove_all(ph);
220 path.setPath(
"HelloWorld");
222 int result =
f.api.storeAsTFileAny(&
path, basePath +
"CCDBPath",
f.metadata);
224 result =
f.api.storeAsTFileAny(&
path, basePath +
"CCDBPath",
f.metadata, -1, -1, 1 );
236 path.setPath(
"HelloWorld");
238 const long timestamp = 1000;
239 const long endvalidity = timestamp + 10;
240 f.api.storeAsTFileAny(&
path, basePath +
"CCDBPathUnitTest",
f.metadata, timestamp, endvalidity);
246 path2 =
f.api.retrieveFromTFileAny<
o2::ccdb::IdPath>(basePath +
"CCDBPathUnitTest",
f.metadata, timestamp);
247 BOOST_CHECK_NE(path2,
nullptr);
250 for (
int t = timestamp; t < endvalidity; ++t) {
251 auto p =
f.api.retrieveFromTFileAny<
o2::ccdb::IdPath>(basePath +
"CCDBPathUnitTest",
f.metadata, t);
252 BOOST_CHECK_NE(p,
nullptr);
256 auto plower =
f.api.retrieveFromTFileAny<
o2::ccdb::IdPath>(basePath +
"CCDBPathUnitTest",
f.metadata, timestamp - 1);
259 auto pupper =
f.api.retrieveFromTFileAny<
o2::ccdb::IdPath>(basePath +
"CCDBPathUnitTest",
f.metadata, endvalidity);
269 path.setPath(
"HelloWorld");
272 f.api.storeAsTFileAny(&
path, basePath +
"CCDBPathUnitTest",
f.metadata, from, to);
275 std::map<std::string, std::string> headers;
276 std::map<std::string, std::string> meta;
277 cout <<
"basePath + \"CCDBPathUnitTest\" : " << basePath +
"CCDBPathUnitTest" << endl;
278 cout <<
"from+1 : " << from + 1 << endl;
279 auto*
object =
f.api.retrieveFromTFileAny<
o2::ccdb::IdPath>(basePath +
"CCDBPathUnitTest", meta, from + 1, &headers);
288 TObject* obj =
f.api.retrieveFromTFileAny<
TObject>(basePath +
"th1",
f.metadata);
289 BOOST_CHECK_NE(obj,
nullptr);
291 auto h1 =
dynamic_cast<TH1F*
>(obj);
292 BOOST_CHECK_NE(h1,
nullptr);
296 obj =
f.api.retrieveFromTFileAny<
TObject>(basePath +
"graph",
f.metadata);
297 BOOST_CHECK_NE(obj,
nullptr);
299 auto graph =
dynamic_cast<TGraph*
>(obj);
300 BOOST_CHECK_NE(graph,
nullptr);
302 int ret = graph->GetPoint(0,
x,
y);
308 std::map<std::string, std::string> headers;
309 obj =
f.api.retrieveFromTFileAny<
TObject>(basePath +
"tree",
f.metadata, -1, &headers);
310 BOOST_CHECK_NE(obj,
nullptr);
312 auto tree =
dynamic_cast<TTree*
>(obj);
313 BOOST_CHECK_NE(
tree,
nullptr);
321 obj =
f.api.retrieveFromTFileAny<
TObject>(
"Wrong/wrong",
f.metadata);
329 TH1F
h(
"object1",
"object1", 100, 0, 99);
330 f.api.storeAsTFile(&
h, basePath +
"Detector",
f.metadata);
331 auto h1 =
f.api.retrieveFromTFileAny<TH1F>(basePath +
"Detector",
f.metadata);
333 f.api.truncate(basePath +
"Detector");
334 h1 =
f.api.retrieveFromTFileAny<TH1F>(basePath +
"Detector",
f.metadata);
342 TH1F h1(
"object1",
"object1", 100, 0, 99);
345 f.api.storeAsTFile(&h1, basePath +
"Detector",
f.metadata, from, to);
346 auto h2 =
f.api.retrieveFromTFileAny<TH1F>(basePath +
"Detector",
f.metadata);
348 f.api.deleteObject(basePath +
"Detector");
349 h2 =
f.api.retrieveFromTFileAny<TH1F>(basePath +
"Detector",
f.metadata);
353void countItems(
const std::string& s,
int& countObjects,
int& countSubfolders)
357 std::stringstream ss(s);
359 boost::property_tree::ptree pt;
360 boost::property_tree::read_json(ss, pt);
362 if (pt.count(
"objects") > 0) {
363 countObjects = pt.get_child(
"objects").size();
366 if (pt.count(
"subfolders") > 0) {
367 countSubfolders = pt.get_child(
"subfolders").size();
376 std::string s =
f.api.list(
"",
"application/json");
377 long nbLines = std::count(s.begin(), s.end(),
'\n') + 1;
381 f.api.truncate(basePath +
"Detector*");
382 s =
f.api.list(basePath +
"Detector",
false,
"application/json");
383 int countObjects = 0;
384 int countSubfolders = 0;
389 TH1F h1(
"object1",
"object1", 100, 0, 99);
390 cout <<
"storing object 2 in Test/Detector" << endl;
391 f.api.storeAsTFile(&h1, basePath +
"Detector",
f.metadata);
392 cout <<
"storing object 3 in Test/Detector" << endl;
393 f.api.storeAsTFile(&h1, basePath +
"Detector",
f.metadata);
394 cout <<
"storing object 4 in Test/Detector" << endl;
395 f.api.storeAsTFile(&h1, basePath +
"Detector",
f.metadata);
396 cout <<
"storing object 5 in Test/Detector/Sub/abc" << endl;
397 f.api.storeAsTFile(&h1, basePath +
"Detector/Sub/abc",
f.metadata);
399 s =
f.api.list(basePath +
"Detector",
false,
"application/json");
404 s =
f.api.list(basePath +
"Detector*",
false,
"application/json");
409 s =
f.api.list(basePath +
"Detector",
true,
"application/json");
416 std::vector<std::string> headers = {
418 "Content-Location: /download/6dcb77c0-ca56-11e9-a807-200114580202",
419 "Date: Thu, 26 Sep 2019 08:09:20 GMT",
420 "Valid-Until: 1567771311999",
421 "Valid-From: 1567080816927",
422 "InitialValidityLimit: 1598616816927",
423 "Created: 1567080816956",
424 "ETag: \"6dcb77c0-ca56-11e9-a807-200114580202\"",
425 "Last-Modified: Thu, 29 Aug 2019 12:13:36 GMT",
426 "UpdatedFrom: 2001:1458:202:28:0:0:100:35",
428 "Content-Disposition: inline;filename=\"o2::dataformats::CalibLHCphaseTOF_1567080816916.root\"",
429 "Accept-Ranges: bytes",
430 "Content-MD5: 9481c9d036660f80e21dae5943c2096f",
431 "Content-Type: application/octet-stream",
432 "Content-Length: 2097152"};
433 std::vector<std::string> results;
437 BOOST_REQUIRE_EQUAL(results.size(), 1);
444 std::string objectPath = basePath +
"objectETag";
446 TH1F h1(
"objectETag",
"objectETag", 100, 0, 99);
447 f.api.storeAsTFile(&h1, objectPath,
f.metadata);
451 std::vector<std::string> headers;
452 std::vector<std::string> pfns;
456 BOOST_REQUIRE(headers.size() != 0);
458 BOOST_REQUIRE(
etag !=
"");
459 BOOST_REQUIRE(pfns.size());
468 TH1F h1(
"object1",
"object1", 100, 0, 99);
469 cout <<
"storing object 1 in " << basePath <<
"Test" << endl;
470 std::map<std::string, std::string> metadata;
471 metadata[
"custom"] =
"whatever";
472 f.api.storeAsTFile(&h1, basePath +
"Test", metadata);
474 std::map<std::string, std::string> headers =
f.api.retrieveHeaders(basePath +
"Test", metadata);
475 BOOST_CHECK_NE(headers.size(), 0);
476 std::string
h = headers[
"custom"];
480 for (
auto h : headers) {
481 cout <<
i++ <<
" : " <<
h.first <<
" -> " <<
h.second << endl;
484 headers =
f.api.retrieveHeaders(basePath +
"Test", metadata);
485 BOOST_CHECK_NE(headers.size(), 0);
486 h = headers[
"custom"];
489 metadata[
"custom"] =
"something";
490 headers =
f.api.retrieveHeaders(basePath +
"Test", metadata);
493 for (
auto h : headers) {
494 cout <<
i++ <<
" : " <<
h.first <<
" -> " <<
h.second << endl;
504 TH1F h1(
"object1",
"object1", 100, 0, 99);
505 cout <<
"storing object 1 in " << basePath <<
"Test" << endl;
506 std::map<std::string, std::string> metadata;
507 metadata[
"custom"] =
"whatever";
508 metadata[
"id"] =
"first";
509 f.api.storeAsTFile(&h1, basePath +
"Test", metadata);
512 std::map<std::string, std::string> headers =
f.api.retrieveHeaders(basePath +
"Test", metadata);
515 std::string firstID = headers.at(
"ETag");
516 firstID.erase(std::remove(firstID.begin(), firstID.end(),
'"'), firstID.end());
518 std::map<std::string, std::string> newMetadata;
519 newMetadata[
"custom"] =
"somethingelse";
523 headers =
f.api.retrieveHeaders(basePath +
"Test", newMetadata);
525 BOOST_CHECK(headers.at(
"custom") ==
"somethingelse");
528 cout <<
"storing object 2 in " << basePath <<
"Test" << endl;
530 metadata[
"custom"] =
"whatever";
531 metadata[
"id"] =
"second";
532 f.api.storeAsTFile(&h1, basePath +
"Test", metadata);
535 cout <<
"get id" << endl;
536 headers =
f.api.retrieveHeaders(basePath +
"Test", metadata);
537 std::string secondID = headers.at(
"ETag");
538 secondID.erase(std::remove(secondID.begin(), secondID.end(),
'"'), secondID.end());
541 cout <<
"update the metadata by id" << endl;
543 newMetadata[
"custom"] =
"first";
546 newMetadata[
"custom"] =
"second";
551 metadata[
"id"] =
"first";
552 headers =
f.api.retrieveHeaders(basePath +
"Test", metadata);
556 metadata[
"id"] =
"second";
557 headers =
f.api.retrieveHeaders(basePath +
"Test", metadata);
566 std::map<std::string, std::string> metadata;
567 std::map<std::string, std::string> headers;
569 std::string
url =
"Analysis/ALICE3/Centrality";
579 int TEST_SAMPLE_SIZE = 5;
580 std::vector<o2::pmr::vector<char>> dests(TEST_SAMPLE_SIZE);
581 std::vector<std::map<std::string, std::string>> metadatas(TEST_SAMPLE_SIZE);
582 std::vector<std::map<std::string, std::string>> headers(TEST_SAMPLE_SIZE);
584 std::vector<CcdbApi::RequestContext> contexts;
585 for (
int i = 0;
i < TEST_SAMPLE_SIZE;
i++) {
587 contexts.at(
i).path =
"Analysis/ALICE3/Centrality";
588 contexts.at(
i).timestamp = 1645780010602;
589 contexts.at(
i).considerSnapshot =
true;
594 for (
auto context : contexts) {
603 BOOST_CHECK_EXCEPTION(api.
init(
url), invalid_argument, [](std::invalid_argument
const&) ->
bool { return true; });
Class for time synchronization of RawReader instances.
void init(std::string const &hosts)
bool isHostReachable() const
void loadFileToMemory(std::vector< char > &dest, std::string const &path, std::map< std::string, std::string > const &metadata, long timestamp, std::map< std::string, std::string > *headers, std::string const &etag, const std::string &createdNotAfter, const std::string &createdNotBefore, bool considerSnapshot=true) const
void vectoredLoadFileToMemory(std::vector< RequestContext > &requestContext) const
static bool getCCDBEntryHeaders(std::string const &url, std::string const &etag, std::vector< std::string > &headers, const std::string &agentID="")
void truncate(std::string const &path) const
static void parseCCDBHeaders(std::vector< std::string > const &headers, std::vector< std::string > &pfns, std::string &etag)
const TString & getPathString() const
GLsizei const GLchar *const * path
GLboolean GLboolean GLboolean GLboolean a
information complementary to a CCDB object (path, metadata, startTimeValidity, endTimeValidity etc)
long getCurrentTimestamp()
returns the timestamp in long corresponding to "now"
long getFutureTimestamp(int secondsInFuture)
returns the timestamp in long corresponding to "now + secondsInFuture"
std::vector< T, fair::mq::pmr::polymorphic_allocator< T > > vector
std::string to_string(gsl::span< T, Size > span)
tt::assertion_result operator()(utf::test_unit_id)
static std::string concat_string(Ts const &... ts)
static std::string create_unique_path(const std::string_view prefix="", int length=16)
std::map< std::string, std::string > metadata
void countItems(const std::string &s, int &countObjects, int &countSubfolders)
BOOST_AUTO_TEST_CASE(storeTMemFile_test, *utf::precondition(if_reachable()))
BOOST_GLOBAL_FIXTURE(Fixture)
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))
BOOST_CHECK_EQUAL(triggersD.size(), triggers.size())