libadc-cxx 1.0.0
Structured logging for scientific computing
Loading...
Searching...
No Matches
testBuilder.cpp
Go to the documentation of this file.
1#include "adc/factory.hpp"
2#if ADC_BOOST_JSON_PUBLIC
3#include "boost/json/src.hpp"
4#endif
5#include <cerrno>
6#include <cstring>
7#include <limits>
8
9std::map<std::string, std::string> adc_plugin_file_config =
10 {{ "ADC_FILE_PLUGIN_DIRECTORY", "./test.outputs"},
11 { "ADC_FILE_PLUGIN_FILE", "out.file.log" },
12 { "ADC_FILE_PLUGIN_APPEND", "true" }
13 };
14
15std::map<std::string, std::string> file_config =
16 {{ "DIRECTORY", "./test.outputs"},
17 { "FILE", "out.file.log" },
18 { "APPEND", "true" }
19 };
20
21// config w/file_config and call initialize.
22int test_publisher(std::shared_ptr<adc::publisher_api> pi, std::shared_ptr<adc::builder_api> b ) {
23 int err = 0;
24 int e = 0;
25 err = pi->config(file_config);
26 if (err) {
27 std::cout << "config failed " <<
28 std::strerror(err) << std::endl;
29 e += 1;
30 err = 0;
31 }
32 err = pi->initialize();
33 if (err) {
34 std::cout << "initialize failed " <<
35 std::strerror(err) << std::endl;
36 e += 1;
37 err = 0;
38 }
39 err = pi->publish(b); // there should be 1 b in the output
40 if (err) {
41 std::cout << "publish 1 failed " <<
42 std::strerror(err) << std::endl;
43 e += 1;
44 err = 0;
45 }
46 return e;
47}
48
49// check in builder named b for a field named NAME with value VAL and types as CPTYPE and CTYPE
50#define ROUNDTRIP(NAME, VAL, CPTYPE, CTYPE) \
51 ck = b->get_value(NAME); \
52 std::cerr << NAME << " roundtrip " << std::flush ; \
53 if (ck.kt != adc::k_value || ck.count != 1 || ck.st != adc::CPTYPE || \
54 *((CTYPE *)ck.vp) != VAL || !( std::get<CTYPE>(ck.data) == VAL) ) { \
55 std::cerr << "BAD" << std::endl; \
56 std::cerr << "\tkt: " << ck.kt <<std::endl; \
57 std::cerr << "\tst: " << to_string(ck.st) <<std::endl; \
58 std::cerr << "\tcount: " << ck.count <<std::endl; \
59 std::cerr << "\tvp: " << (CTYPE *)ck.vp <<std::endl; \
60 std::cerr << "\tdata: " << std::visit(adc::var_string(), ck.data) <<std::endl; \
61 } else \
62 std::cerr << "ok " << std::visit(adc::var_string(), ck.data) << std::endl
63
64template<typename STYPE>
65static int cmp_argv(std::string *argv, STYPE *val, size_t count)
66{
67 for (size_t i = 0; i < count; i++) {
68 if (argv[i] != std::string(val[i])) {
69 return 1;
70 }
71 }
72 return 0;
73}
74
75#define ROUNDTRIP_ARRAY_STRING(NAME, VAL, COUNT, CTYPE_VAL) roundtrip_array_string<CTYPE_VAL>(NAME, VAL, COUNT, b)
76template <typename STYPE>
77static void roundtrip_array_string(const char *name, STYPE* val, size_t count, std::shared_ptr< adc::builder_api > b)
78{
79 auto ck = b->get_value(name);
80 std::cerr << name << " roundtrip " << std::flush;
81
82 if (ck.kt != adc::k_value) {
83 std::cerr << "\n WRONG kt" << std::endl;
84 } else if ( ck.st != adc::cp_cstr ) {
85 std::cerr << "\n WRONG st" << std::endl;
86 } else if (ck.count != count) {
87 std::cerr << "\n WRONG: NOT len " << count <<
88 " (" << ck.count << " instead)" << std::endl;
89 } else if ( cmp_argv<STYPE>((std::string *)ck.vp, val, count) ) {
90 std::cerr << "\n WRONG data" << std::endl;
91 for (size_t i = 0; i < count; i++) {
92 std::cerr << "[" << i << "]:" <<
93 ((std::string *)ck.vp)[i] << " vs " << val[i] << std::endl;
94 }
95 } else {
96 std::cerr << " ok " << ck.container << std::endl;
97 return;
98 }
99 std::cerr << "BAD" << std::endl;
100 std::cerr << "\tkt: " << ck.kt <<std::endl;
101 std::cerr << "\tst: " << to_string(ck.st) <<std::endl;
102 std::cerr << "\tcount: " << ck.count <<std::endl;
103 std::cerr << "\tvp: " << std::endl;
104 std::string *argv = (std::string *)ck.vp;
105 for (size_t i = 0; i < count; i++) {
106 std::cerr << "\t\t" << argv[i] << std::endl;
107 }
108 std::cerr << "\tdata: " << std::visit(adc::var_string(ck.count), ck.data) <<std::endl; \
109 std::cerr << "\tcontainer: " << ck.container << std::endl; \
110}
111
112
113#define ROUNDTRIP_ARRAY(NAME, VAL, COUNT, CTYPE, CPTYPE) roundtrip_array<CTYPE>(NAME, VAL, adc:: CPTYPE, COUNT, b)
114template<typename CTYPE >
115void roundtrip_array(const char *name, CTYPE* val, adc::scalar_type cptype, size_t count, std::shared_ptr< adc::builder_api > b)
116{
117 auto ck = b->get_value(name);
118 std::cerr << name << " roundtrip " << std::flush;
119
120 if (ck.kt != adc::k_value) {
121 std::cerr << "\n WRONG kt" << std::endl;
122 } else if ( ck.st != cptype ) {
123 std::cerr << "\n WRONG st" << std::endl;
124 } else if (ck.count != count) {
125 std::cerr << "\n WRONG: NOT len " << count <<
126 " (" << ck.count << " instead)" << std::endl;
127 } else if ( memcmp(ck.vp, val, sizeof(CTYPE)*count) ) {
128 std::cerr << "\n WRONG data" << std::endl;
129 for (size_t i = 0; i < count; i++) {
130 std::cerr << "[" << i << "]:" <<
131 ((CTYPE *)ck.vp)[i] << " vs " << val[i] << std::endl;
132 }
133 } else {
134 std::cerr << " ok" << std::endl;
135 return;
136 }
137 std::cerr << "BAD" << std::endl;
138 std::cerr << "\tkt: " << ck.kt <<std::endl;
139 std::cerr << "\tst: " << to_string(ck.st) <<std::endl;
140 std::cerr << "\tcount: " << ck.count <<std::endl;
141 std::cerr << "\tvp: " << (CTYPE *)ck.vp <<std::endl;
142 std::cerr << "\tdata: " << std::visit(adc::var_string(ck.count), ck.data) <<std::endl; \
143}
144
145void roundtrip_string(const char *name, const char *val, adc::scalar_type cptype, std::shared_ptr< adc::builder_api > b)
146{
147 auto ck = b->get_value(name);
148 std::cerr << name << " roundtrip " << std::flush;
149 if (ck.kt != adc::k_value) {
150 std::cerr << "\n WRONG kt" << std::endl;
151 } else if ( ck.count != strlen(val) ) {
152 std::cerr << "\n WRONG count" << std::endl;
153 } else if ( ck.st != cptype ) {
154 std::cerr << "\n WRONG st" << std::endl;
155 } else if ( strcmp(((const char *)ck.vp), val) != 0 ) {
156 std::cerr << "\n WRONG vp" << std::endl;
157 } else {
158 std::cerr << " ok" << std::endl;
159 return;
160 }
161 std::cerr << val << " vs vp " << (const char *)ck.vp << std::endl;
162 std::cerr << "\tkt: " << ck.kt <<std::endl;
163 std::cerr << "\tst: " << adc::to_string(ck.st) << std::endl;
164 std::cerr << "\tcount: " << ck.count << std::endl;
165 std::cerr << "\tdata: " << std::visit(adc::var_string(), ck.data) << std::endl;
166}
167
168#if 0
169// check in builder named b for a string named NAME with char * value VAL and type as CPTYPE.
170// Unclear why this macro generates useafterdelete for some cases while the function version
171// does not. Some string apparently goes out of scope unexpectedly.
172#define ROUNDTRIP_STRING(NAME, VAL, CPTYPE) \
173 ck = b->get_value(NAME); \
174 std::cerr << NAME << " roundtrip " << std::flush; \
175 if (ck.kt != adc::k_value || ck.count != strlen(VAL) || \
176 ck.st != adc::CPTYPE || strcmp(((const char *)ck.vp), VAL) != 0 ) { \
177 std::cerr << " BAD " << VAL << " vs " << (const char *)ck.vp << std::endl; \
178 std::cerr << "\tkt: " << ck.kt <<std::endl; \
179 std::cerr << "\tst: " << to_string(ck.st) <<std::endl; \
180 std::cerr << "\tcount: " << ck.count << std::endl; \
181 std::cerr << "\tdata: " << std::visit(adc::var_string(), ck.data) <<std::endl; \
182 } else \
183 std::cerr << " ok" << std::endl
184#else
185#define ROUNDTRIP_STRING(NAME, VAL, CPTYPE) roundtrip_string(NAME, VAL, adc:: CPTYPE, b)
186#endif
187
188
189void populate_builder(std::shared_ptr< adc::builder_api > b, adc::factory & f) {
190#if ADC_BOOST_JSON_PUBLIC
191 boost::json::object jo = {{"a","b"},{"C","d"},{"n",1}};
192#endif
193 adc::field ck;
194 b->add("bool0", false);
195#if 1
196 ROUNDTRIP("bool0", false, cp_bool, bool);
197#else
198 ck = b->get_value("bool0"); \
199 if (ck.kt != adc::k_value || ck.count != 1 || ck.st != adc::cp_bool ||
200 *((bool *)ck.vp) != false || std::get<bool>(ck.data) != false)
201 std::cerr << "bool0" << " not returned correctly" << std::endl;
202#endif
203
204 b->add("bool1", true);
205 ROUNDTRIP("bool1", true, cp_bool, bool);
206
207 b->add("char1", 'A');
208 ROUNDTRIP("char1", 'A', cp_char, char);
209 char16_t c16 = u'¢';
210 b->add("c16", c16);
211 ROUNDTRIP("c16", c16, cp_char16, char16_t);
212 char32_t c32 = U'猫';
213 b->add("c32", c32);
214 ROUNDTRIP("c32", c32, cp_char32, char32_t);
215
216 uint8_t u8 = std::numeric_limits<uint8_t>::max() / 2;
217 uint16_t u16 = std::numeric_limits<uint16_t>::max() / 2;
218 uint32_t u32 = std::numeric_limits<uint32_t>::max() / 2;
219 uint64_t u64 = std::numeric_limits<uint64_t>::max() / 2;
220 b->add("u8", u8);
221 ROUNDTRIP("u8", u8, cp_uint8, uint8_t);
222 b->add("u16", u16);
223 ROUNDTRIP("u16", u16, cp_uint16, uint16_t);
224 b->add("u32", u32);
225 ROUNDTRIP("u32", u32, cp_uint32, uint32_t);
226 b->add("u64", u64);
227 ROUNDTRIP("u64", u64, cp_uint64, uint64_t);
228 int8_t i8 = std::numeric_limits<int8_t>::max() / 2;
229 int16_t i16 = std::numeric_limits<int16_t>::max() / 2;
230 int32_t i32 = std::numeric_limits<int32_t>::max() / 2;
231 int64_t i64 = std::numeric_limits<int64_t>::max() / 2;
232 float flt = std::numeric_limits<float>::max() / 2;
233 double dbl = std::numeric_limits<double>::max() / 2 ;
234 b->add("i8", i8);
235 ROUNDTRIP("i8", i8, cp_int8, int8_t);
236 b->add("i16", i16);
237 ROUNDTRIP("i16", i16, cp_int16, int16_t);
238 b->add("i32", i32);
239 ROUNDTRIP("i32", i32, cp_int32, int32_t);
240 b->add("i64", i64);
241 ROUNDTRIP("i64", i64, cp_int64, int64_t);
242 b->add("flt", flt);
243 ROUNDTRIP("flt", flt, cp_f32, float);
244 b->add("dbl", dbl);
245 ROUNDTRIP("dbl", dbl, cp_f64, double);
246
247 std::complex<float> fcplx(flt, flt);
248 std::complex<double> dcplx(dbl,dbl);
249
250 b->add("fcplx", fcplx);
251 ROUNDTRIP("fcplx", fcplx, cp_c_f32, std::complex<float>);
252
253 b->add("dcplx", dcplx);
254 ROUNDTRIP("dcplx", dcplx, cp_c_f64, std::complex<double>);
255
256 const std::string ccppstr("ccppstr");
257 b->add("ccppstr", ccppstr);
258 ROUNDTRIP_STRING("ccppstr", ccppstr.c_str(), cp_cstr);
259
260 std::string cppstr("cppstr");
261 b->add("cppstr", cppstr);
262 ROUNDTRIP_STRING("cppstr", cppstr.c_str(), cp_cstr);
263
264 const char *cstr = "cstr_nul";
265 b->add("cstr1", cstr);
266 ROUNDTRIP_STRING("cstr1", cstr, cp_cstr);
267
268 const char *jstr = "{\"a\":\"b\", \"c\":[1,2, 3]}";
269 b->add_json_string("jstr1", std::string(jstr));
270 ROUNDTRIP_STRING("jstr1", jstr, cp_json_str);
271
272 const char *ystr = "---\na: b\nc: [1,2, 3]\nd:\n e: 1\n f: 2";
273 b->add_yaml_string("ystr1", ystr);
274 ROUNDTRIP_STRING("ystr1", ystr, cp_yaml_str);
275
276 const char *xstr = "<note> <to>Tove</to> <from>Jani</from> </note>";
277 b->add_xml_string("xstr1", std::string (xstr));
278 ROUNDTRIP_STRING("xstr1", xstr, cp_xml_str);
279
280 const char *nstr = "1234567890123456789012345678901234567890.123";
281 b->add_number_string("number1", std::string (nstr));
282 ROUNDTRIP_STRING("number1", nstr, cp_number_str);
283#if ADC_BOOST_JSON_PUBLIC
284 b->add("jsonobj", jo);
285#endif
286 // fixme roundtrip complex
287 const char *cstrings[] = {"a", "B", "c2"};
288 char *vcstrings[4];
289 int32_t ia[4];
290 float fa[4];
291 double da[4];
292 uint64_t ua[4];
293 for (int i = 0; i < 4; i++) {
294 vcstrings[i] = new char[2];
295 snprintf(vcstrings[i], 2, "%d", i);
296 ua[i] = i;
297 ia[i] = -i;
298 da[i] = 3.14*i;
299 fa[i] = 3.14*i *2;
300 }
301 b->add_array("ia", ia, 4);
302 b->add_array("ua", ua, 4);
303 b->add_array("fa", fa, 4);
304 b->add_array("da", da, 4);
305 ROUNDTRIP_ARRAY("ia", ia, 4, int32_t, cp_int32);
306 ROUNDTRIP_ARRAY("ua", ua, 4, uint64_t, cp_uint64);
307 ROUNDTRIP_ARRAY("fa", fa, 4, float, cp_f32);
308 ROUNDTRIP_ARRAY("da", da, 4, double, cp_f64);
309
310 b->add_array("nulembed", "a\0b", 3);
311 ROUNDTRIP_ARRAY("nulembed", "a\0b", 3, const char, cp_char);
312
313 std::string cppstrings[] = {"ap", "Bp", "c2p"};
314 b->add_array("cstrs", cstrings, 3);
315 ROUNDTRIP_ARRAY_STRING("cstrs", cstrings, 3, const char *);
316 b->add_array("cppstrs", cppstrings, 3);
317 ROUNDTRIP_ARRAY_STRING("cppstrs", cppstrings, 3, std::string);
318 b->add_array("vcstrs", vcstrings, 4);
319 ROUNDTRIP_ARRAY_STRING("vcstrs", vcstrings, 4, char *);
320 for (int i = 0; i < 4; i++) {
321 delete [] vcstrings[i];
322 }
323 const char *e1="a1", *e2="a2", *e3="a3",* eb="b",* ec="c_";
324 std::vector<std::string> tcsv = { e1, eb, ec };
325 std::list<std::string> tcsl = { e2, eb, ec };
326 std::set<std::string> tcss = { e3, eb, ec };
327 const char * tcsv_a[] = { e1, eb, ec };
328 const char * tcsl_a[] = { e2, eb, ec };
329 const char * tcss_a[] = { e3, eb, ec };
330
331 b->add_array("sv", tcsv);
332 b->add_array("sl", tcsl);
333 b->add_array("ss", tcss);
334 ROUNDTRIP_ARRAY_STRING("sv", tcsv_a, 3, const char *);
335 ROUNDTRIP_ARRAY_STRING("sl", tcsl_a, 3, const char *);
336 // the ss test depends on strcmp order of tcss to match sortedness of tcss_a
337 ROUNDTRIP_ARRAY_STRING("ss", tcss_a, 3, const char *);
338
339 std::vector<std::string> children = { "uuid1", "uuid2", "uuid3"};
340 b->add_workflow_section();
341 b->add_workflow_children(children);
342
343
344 // section test with host-like data treated as app data
345 std::shared_ptr<adc::builder_api> host = f.get_builder();
346 std::shared_ptr<adc::builder_api> arch = f.get_builder();
347 std::shared_ptr<adc::builder_api> cpu = f.get_builder();
348 std::shared_ptr<adc::builder_api> mem = f.get_builder();
349
350 host->add("name","myhost");
351 host->add("cluster","mycluster");
352 cpu->add("processor","pentium II");
353 mem->add("size", "256G");
354
355 arch->add_section("cpu", cpu);
356 arch->add_section("memory", mem);
357 host->add_section("architecture",arch);
358 b->add_section("host", host);
359
360#if ADC_BOOST_JSON_PUBLIC
361 // section test with host-like data treated as standard schema data (json fields of default types), not app fields)
362 boost::json::object host2;
363 boost::json::object arch2;
364 boost::json::object cpu2;
365 boost::json::object mem2;
366 // fix [ below
367 host2["name"] = "myhost";
368 host2["cluster"]="mycluster";
369 cpu2["processor"]="pentium II";
370 mem2["size"]="256G";
371 arch2["cpu"]= cpu2;
372 arch2["memory"]= mem2;
373 host2["architecture"]=arch2;
374
375 b->add("host2", host2);
376#endif
377
378 //std::vector<short> vs = { 1, 2, 3};
379 //adc::builder_add_vector1(b, "v1", vs);
380 //adc::builder_add_vector2(b, "v2", vs);
381
382
383 std::string ss = b->serialize();
384 std::cout << "-------------------------------" << std::endl;
385 std::cout << ss << std::endl;
386 std::cout << "-------------------------------" << std::endl;
387}
388
389int main(int /* argc */ , char ** /* argv */)
390{
391 std::cout << "adc pub version: " << adc::publisher_api_version.name << std::endl;
392 std::cout << "adc builder version: " << adc::builder_api_version.name << std::endl;
393 std::cout << "adc enum version: " << adc::enum_version.name << std::endl;
394
395 adc::factory f;
396
397 std::shared_ptr< adc::builder_api > b = f.get_builder();
398
399 populate_builder(b, f);
400
401#if 1 // switch to 0 when developing new fields and testing them
402 std::shared_ptr< adc::publisher_api > p0 = f.get_publisher("none");
403 std::cout << test_publisher(p0, b) << std::endl;
404
405 std::shared_ptr< adc::publisher_api > p1 = f.get_publisher("file");
406 std::cout << test_publisher(p1, b) << std::endl;
407
408 std::shared_ptr< adc::publisher_api > p2 = f.get_publisher("stdout");
409 std::cout << test_publisher(p2, b) << std::endl;
410
411 std::shared_ptr< adc::publisher_api > p3 = f.get_publisher("syslog");
412 std::cout << test_publisher(p3, b) << std::endl;
413
414 std::shared_ptr<adc::multi_publisher_api> mp = f.get_multi_publisher();
415 mp->add(p0);
416 mp->add(p1);
417 mp->add(p2);
418 mp->add(p3);
419 mp->publish(b);
420 mp->pause();
421 mp->publish(b);
422 mp->resume();
423 mp->publish(b);
424 mp->terminate();
425#endif
426 int n;
427 if ((n = adc::test_enum_strings()))
428 std::cout << "scalar_type and to_string(st) are inconsistent: " << n << std::endl;
429 return 0;
430}
provides publishers and builders of application metadata.
Definition factory.hpp:37
std::shared_ptr< publisher_api > get_publisher(const std::string &name)
Definition factory.ipp:142
std::shared_ptr< multi_publisher_api > get_multi_publisher()
Definition factory.ipp:103
std::shared_ptr< builder_api > get_builder()
Definition factory.ipp:264
return string for printing from variant v.
Definition types.hpp:195
int test_enum_strings()
return non-zero if to_string and enum scalar_type are inconsisent.
Definition enums.ipp:358
version enum_version("1.0.0", {"none"})
the version number of enum scalar_type and object_type
const std::string to_string(float f)
get string of float using to_chars.
Definition enums.ipp:128
version publisher_api_version("1.0.0", {"none"})
version builder_api_version("1.0.0", {"none"})
scalar_type
field types for scientific data encode/decode with json.
Definition types.hpp:58
@ k_value
Definition types.hpp:109
@ cp_bool
bool (true/false,1/0)
Definition types.hpp:60
@ cp_cstr
c null-terminated string
Definition types.hpp:65
scalar_type st
scalar type of the data as published,
Definition types.hpp:159
size_t count
number of elements in vp.
Definition types.hpp:161
variant data
Definition types.hpp:163
key_type kt
kind of data associated with the name queried
Definition types.hpp:158
const void * vp
address of data to be cast according to st for use with c/fortran
Definition types.hpp:160
const std::string name
Definition types.hpp:25
void roundtrip_string(const char *name, const char *val, adc::scalar_type cptype, std::shared_ptr< adc::builder_api > b)
int main(int, char **)
void roundtrip_array(const char *name, CTYPE *val, adc::scalar_type cptype, size_t count, std::shared_ptr< adc::builder_api > b)
#define ROUNDTRIP_ARRAY_STRING(NAME, VAL, COUNT, CTYPE_VAL)
#define ROUNDTRIP_ARRAY(NAME, VAL, COUNT, CTYPE, CPTYPE)
void populate_builder(std::shared_ptr< adc::builder_api > b, adc::factory &f)
#define ROUNDTRIP(NAME, VAL, CPTYPE, CTYPE)
int test_publisher(std::shared_ptr< adc::publisher_api > pi, std::shared_ptr< adc::builder_api > b)
std::map< std::string, std::string > file_config
#define ROUNDTRIP_STRING(NAME, VAL, CPTYPE)
std::map< std::string, std::string > adc_plugin_file_config