1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#include "test_exporting_engine.h"
4
+#include "libnetdata/required_dummies.h"
5
+
6
+RRDHOST *localhost;
7
+netdata_rwlock_t rrd_rwlock;
8
+
9
+// global variables needed by read_exporting_config()
10
+struct config netdata_config;
11
+char *netdata_configured_user_config_dir = ".";
12
+char *netdata_configured_stock_config_dir = ".";
13
+char *netdata_configured_hostname = "test_host";
14
+
15
+char log_line[MAX_LOG_LINE + 1];
16
+
17
+void init_connectors_in_tests(struct engine *engine)
18
+{
19
+ expect_function_call(__wrap_now_realtime_sec);
20
+ will_return(__wrap_now_realtime_sec, 2);
21
+
22
+ expect_function_call(__wrap_uv_thread_create);
23
+
24
+ expect_value(__wrap_uv_thread_create, thread, &engine->connector_root->instance_root->thread);
25
+ expect_value(__wrap_uv_thread_create, worker, simple_connector_worker);
26
+ expect_value(__wrap_uv_thread_create, arg, engine->connector_root->instance_root);
27
+
28
+ assert_int_equal(__real_init_connectors(engine), 0);
29
+
30
+ assert_int_equal(engine->now, 2);
31
+ assert_int_equal(engine->connector_root->instance_root->after, 2);
32
+}
33
+
34
+static void test_exporting_engine(void **state)
35
+{
36
+ struct engine *engine = *state;
37
+
38
+ expect_function_call(__wrap_read_exporting_config);
39
+ will_return(__wrap_read_exporting_config, engine);
40
+
41
+ expect_function_call(__wrap_init_connectors);
42
+ expect_memory(__wrap_init_connectors, engine, engine, sizeof(struct engine));
43
+ will_return(__wrap_init_connectors, 0);
44
+
45
+ expect_function_call(__wrap_now_realtime_sec);
46
+ will_return(__wrap_now_realtime_sec, 2);
47
+
48
+ expect_function_call(__wrap_mark_scheduled_instances);
49
+ expect_memory(__wrap_mark_scheduled_instances, engine, engine, sizeof(struct engine));
50
+ will_return(__wrap_mark_scheduled_instances, 1);
51
+
52
+ expect_function_call(__wrap_prepare_buffers);
53
+ expect_memory(__wrap_prepare_buffers, engine, engine, sizeof(struct engine));
54
+ will_return(__wrap_prepare_buffers, 0);
55
+
56
+ expect_function_call(__wrap_notify_workers);
57
+ expect_memory(__wrap_notify_workers, engine, engine, sizeof(struct engine));
58
+ will_return(__wrap_notify_workers, 0);
59
+
60
+ expect_function_call(__wrap_send_internal_metrics);
61
+ expect_memory(__wrap_send_internal_metrics, engine, engine, sizeof(struct engine));
62
+ will_return(__wrap_send_internal_metrics, 0);
63
+
64
+ void *ptr = malloc(sizeof(int));
65
+ assert_ptr_equal(exporting_main(ptr), NULL);
66
+ assert_int_equal(engine->now, 2);
67
+ free(ptr);
68
+}
69
+
70
+static void test_read_exporting_config(void **state)
71
+{
72
+ struct engine *engine = __mock_read_exporting_config(); // TODO: use real read_exporting_config() function
73
+ *state = engine;
74
+
75
+ assert_ptr_not_equal(engine, NULL);
76
+ assert_string_equal(engine->config.prefix, "netdata");
77
+ assert_string_equal(engine->config.hostname, "test-host");
78
+ assert_int_equal(engine->config.update_every, 3);
79
+ assert_int_equal(engine->instance_num, 0);
80
+
81
+ struct connector *connector = engine->connector_root;
82
+ assert_ptr_not_equal(connector, NULL);
83
+ assert_ptr_equal(connector->next, NULL);
84
+ assert_ptr_equal(connector->engine, engine);
85
+ assert_int_equal(connector->config.type, BACKEND_TYPE_GRAPHITE);
86
+
87
+ struct instance *instance = connector->instance_root;
88
+ assert_ptr_not_equal(instance, NULL);
89
+ assert_ptr_equal(instance->next, NULL);
90
+ assert_ptr_equal(instance->connector, connector);
91
+ assert_string_equal(instance->config.destination, "localhost");
92
+ assert_int_equal(instance->config.update_every, 1);
93
+ assert_int_equal(instance->config.buffer_on_failures, 10);
94
+ assert_int_equal(instance->config.timeoutms, 10000);
95
+ assert_true(simple_pattern_matches(instance->config.charts_pattern, "any_chart"));
96
+ assert_true(simple_pattern_matches(instance->config.hosts_pattern, "anyt_host"));
97
+ assert_int_equal(instance->config.options, EXPORTING_SOURCE_DATA_AS_COLLECTED | EXPORTING_OPTION_SEND_NAMES);
98
+
99
+ teardown_configured_engine(state);
100
+}
101
+
102
+static void test_init_connectors(void **state)
103
+{
104
+ struct engine *engine = *state;
105
+
106
+ init_connectors_in_tests(engine);
107
+
108
+ assert_int_equal(engine->instance_num, 1);
109
+
110
+ struct connector *connector = engine->connector_root;
111
+ assert_ptr_equal(connector->next, NULL);
112
+ assert_ptr_equal(connector->worker, simple_connector_worker);
113
+
114
+ struct simple_connector_config *connector_specific_config = connector->config.connector_specific_config;
115
+ assert_int_equal(connector_specific_config->default_port, 2003);
116
+
117
+ struct instance *instance = connector->instance_root;
118
+ assert_ptr_equal(instance->next, NULL);
119
+ assert_int_equal(instance->index, 0);
120
+ assert_ptr_equal(instance->start_batch_formatting, NULL);
121
+ assert_ptr_equal(instance->start_host_formatting, NULL);
122
+ assert_ptr_equal(instance->start_chart_formatting, NULL);
123
+ assert_ptr_equal(instance->metric_formatting, format_dimension_collected_graphite_plaintext);
124
+ assert_ptr_equal(instance->end_chart_formatting, NULL);
125
+ assert_ptr_equal(instance->end_host_formatting, NULL);
126
+ assert_ptr_equal(instance->end_batch_formatting, NULL);
127
+
128
+ BUFFER *buffer = instance->buffer;
129
+ assert_ptr_not_equal(buffer, NULL);
130
+ buffer_sprintf(buffer, "%s", "graphite test");
131
+ assert_string_equal(buffer_tostring(buffer), "graphite test");
132
+}
133
+
134
+static void test_init_graphite_instance(void **state)
135
+{
136
+ struct engine *engine = *state;
137
+ struct connector *connector = engine->connector_root;
138
+ struct instance *instance = connector->instance_root;
139
+
140
+ init_graphite_connector(connector);
141
+ assert_int_equal(
142
+ ((struct simple_connector_config *)(connector->config.connector_specific_config))->default_port, 2003);
143
+ freez(connector->config.connector_specific_config);
144
+
145
+ instance->config.options = EXPORTING_SOURCE_DATA_AS_COLLECTED | EXPORTING_OPTION_SEND_NAMES;
146
+ assert_int_equal(init_graphite_instance(instance), 0);
147
+ assert_ptr_equal(instance->metric_formatting, format_dimension_collected_graphite_plaintext);
148
+ assert_ptr_not_equal(instance->buffer, NULL);
149
+ buffer_free(instance->buffer);
150
+
151
+ instance->config.options = EXPORTING_SOURCE_DATA_AVERAGE | EXPORTING_OPTION_SEND_NAMES;
152
+ assert_int_equal(init_graphite_instance(instance), 0);
153
+ assert_ptr_equal(instance->metric_formatting, format_dimension_stored_graphite_plaintext);
154
+}
155
+
156
+static void test_init_json_instance(void **state)
157
+{
158
+ struct engine *engine = *state;
159
+ struct connector *connector = engine->connector_root;
160
+ struct instance *instance = connector->instance_root;
161
+
162
+ init_json_connector(connector);
163
+ assert_int_equal(
164
+ ((struct simple_connector_config *)(connector->config.connector_specific_config))->default_port, 5448);
165
+ freez(connector->config.connector_specific_config);
166
+
167
+ instance->config.options = EXPORTING_SOURCE_DATA_AS_COLLECTED | EXPORTING_OPTION_SEND_NAMES;
168
+ assert_int_equal(init_json_instance(instance), 0);
169
+ assert_ptr_equal(instance->metric_formatting, format_dimension_collected_json_plaintext);
170
+ assert_ptr_not_equal(instance->buffer, NULL);
171
+ buffer_free(instance->buffer);
172
+
173
+ instance->config.options = EXPORTING_SOURCE_DATA_AVERAGE | EXPORTING_OPTION_SEND_NAMES;
174
+ assert_int_equal(init_json_instance(instance), 0);
175
+ assert_ptr_equal(instance->metric_formatting, format_dimension_stored_json_plaintext);
176
+}
177
+
178
+static void test_init_opentsdb_connector(void **state)
179
+{
180
+ struct engine *engine = *state;
181
+ struct connector *connector = engine->connector_root;
182
+
183
+ init_opentsdb_connector(connector);
184
+ assert_int_equal(
185
+ ((struct simple_connector_config *)(connector->config.connector_specific_config))->default_port, 4242);
186
+ freez(connector->config.connector_specific_config);
187
+}
188
+
189
+static void test_init_opentsdb_telnet_instance(void **state)
190
+{
191
+ struct engine *engine = *state;
192
+ struct connector *connector = engine->connector_root;
193
+ struct instance *instance = connector->instance_root;
194
+
195
+ instance->config.options = EXPORTING_SOURCE_DATA_AS_COLLECTED | EXPORTING_OPTION_SEND_NAMES;
196
+ assert_int_equal(init_opentsdb_telnet_instance(instance), 0);
197
+ assert_ptr_equal(instance->metric_formatting, format_dimension_collected_opentsdb_telnet);
198
+ assert_ptr_not_equal(instance->buffer, NULL);
199
+ buffer_free(instance->buffer);
200
+
201
+ instance->config.options = EXPORTING_SOURCE_DATA_AVERAGE | EXPORTING_OPTION_SEND_NAMES;
202
+ assert_int_equal(init_opentsdb_telnet_instance(instance), 0);
203
+ assert_ptr_equal(instance->metric_formatting, format_dimension_stored_opentsdb_telnet);
204
+}
205
+
206
+static void test_init_opentsdb_http_instance(void **state)
207
+{
208
+ struct engine *engine = *state;
209
+ struct connector *connector = engine->connector_root;
210
+ struct instance *instance = connector->instance_root;
211
+
212
+ instance->config.options = EXPORTING_SOURCE_DATA_AS_COLLECTED | EXPORTING_OPTION_SEND_NAMES;
213
+ assert_int_equal(init_opentsdb_http_instance(instance), 0);
214
+ assert_ptr_equal(instance->metric_formatting, format_dimension_collected_opentsdb_http);
215
+ assert_ptr_not_equal(instance->buffer, NULL);
216
+ buffer_free(instance->buffer);
217
+
218
+ instance->config.options = EXPORTING_SOURCE_DATA_AVERAGE | EXPORTING_OPTION_SEND_NAMES;
219
+ assert_int_equal(init_opentsdb_http_instance(instance), 0);
220
+ assert_ptr_equal(instance->metric_formatting, format_dimension_stored_opentsdb_http);
221
+}
222
+
223
+static void test_mark_scheduled_instances(void **state)
224
+{
225
+ struct engine *engine = *state;
226
+
227
+ assert_int_equal(__real_mark_scheduled_instances(engine), 1);
228
+
229
+ struct instance *instance = engine->connector_root->instance_root;
230
+ assert_int_equal(instance->scheduled, 1);
231
+ assert_int_equal(instance->before, 2);
232
+}
233
+
234
+static void test_rrdhost_is_exportable(void **state)
235
+{
236
+ struct engine *engine = *state;
237
+ struct instance *instance = engine->connector_root->instance_root;
238
+
239
+ expect_function_call(__wrap_info_int);
240
+
241
+ assert_ptr_equal(localhost->exporting_flags, NULL);
242
+
243
+ assert_int_equal(__real_rrdhost_is_exportable(instance, localhost), 1);
244
+
245
+ assert_string_equal(log_line, "enabled exporting of host 'localhost' for instance 'instance_name'");
246
+
247
+ assert_ptr_not_equal(localhost->exporting_flags, NULL);
248
+ assert_int_equal(localhost->exporting_flags[0], RRDHOST_FLAG_BACKEND_SEND);
249
+}
250
+
251
+static void test_false_rrdhost_is_exportable(void **state)
252
+{
253
+ struct engine *engine = *state;
254
+ struct instance *instance = engine->connector_root->instance_root;
255
+
256
+ simple_pattern_free(instance->config.hosts_pattern);
257
+ instance->config.hosts_pattern = simple_pattern_create("!*", NULL, SIMPLE_PATTERN_EXACT);
258
+
259
+ expect_function_call(__wrap_info_int);
260
+
261
+ assert_ptr_equal(localhost->exporting_flags, NULL);
262
+
263
+ assert_int_equal(__real_rrdhost_is_exportable(instance, localhost), 0);
264
+
265
+ assert_string_equal(log_line, "disabled exporting of host 'localhost' for instance 'instance_name'");
266
+
267
+ assert_ptr_not_equal(localhost->exporting_flags, NULL);
268
+ assert_int_equal(localhost->exporting_flags[0], RRDHOST_FLAG_BACKEND_DONT_SEND);
269
+}
270
+
271
+static void test_rrdset_is_exportable(void **state)
272
+{
273
+ struct engine *engine = *state;
274
+ struct instance *instance = engine->connector_root->instance_root;
275
+ RRDSET *st = localhost->rrdset_root;
276
+
277
+ assert_ptr_equal(st->exporting_flags, NULL);
278
+
279
+ assert_int_equal(__real_rrdset_is_exportable(instance, st), 1);
280
+
281
+ assert_ptr_not_equal(st->exporting_flags, NULL);
282
+ assert_int_equal(st->exporting_flags[0], RRDSET_FLAG_BACKEND_SEND);
283
+}
284
+
285
+static void test_false_rrdset_is_exportable(void **state)
286
+{
287
+ struct engine *engine = *state;
288
+ struct instance *instance = engine->connector_root->instance_root;
289
+ RRDSET *st = localhost->rrdset_root;
290
+
291
+ simple_pattern_free(instance->config.charts_pattern);
292
+ instance->config.charts_pattern = simple_pattern_create("!*", NULL, SIMPLE_PATTERN_EXACT);
293
+
294
+ assert_ptr_equal(st->exporting_flags, NULL);
295
+
296
+ assert_int_equal(__real_rrdset_is_exportable(instance, st), 0);
297
+
298
+ assert_ptr_not_equal(st->exporting_flags, NULL);
299
+ assert_int_equal(st->exporting_flags[0], RRDSET_FLAG_BACKEND_IGNORE);
300
+}
301
+
302
+static void test_exporting_calculate_value_from_stored_data(void **state)
303
+{
304
+ struct engine *engine = *state;
305
+ struct instance *instance = engine->connector_root->instance_root;
306
+ RRDDIM *rd = localhost->rrdset_root->dimensions;
307
+ time_t timestamp;
308
+
309
+ instance->after = 3;
310
+ instance->before = 10;
311
+
312
+ expect_function_call(__mock_rrddim_query_oldest_time);
313
+ will_return(__mock_rrddim_query_oldest_time, 1);
314
+
315
+ expect_function_call(__mock_rrddim_query_latest_time);
316
+ will_return(__mock_rrddim_query_latest_time, 2);
317
+
318
+ expect_function_call(__mock_rrddim_query_init);
319
+ expect_value(__mock_rrddim_query_init, start_time, 1);
320
+ expect_value(__mock_rrddim_query_init, end_time, 2);
321
+
322
+ expect_function_call(__mock_rrddim_query_is_finished);
323
+ will_return(__mock_rrddim_query_is_finished, 0);
324
+ expect_function_call(__mock_rrddim_query_next_metric);
325
+ will_return(__mock_rrddim_query_next_metric, pack_storage_number(27, SN_EXISTS));
326
+
327
+ expect_function_call(__mock_rrddim_query_is_finished);
328
+ will_return(__mock_rrddim_query_is_finished, 0);
329
+ expect_function_call(__mock_rrddim_query_next_metric);
330
+ will_return(__mock_rrddim_query_next_metric, pack_storage_number(45, SN_EXISTS));
331
+
332
+ expect_function_call(__mock_rrddim_query_is_finished);
333
+ will_return(__mock_rrddim_query_is_finished, 1);
334
+
335
+ expect_function_call(__mock_rrddim_query_finalize);
336
+
337
+ assert_int_equal(__real_exporting_calculate_value_from_stored_data(instance, rd, ×tamp), 36);
338
+}
339
+
340
+static void test_prepare_buffers(void **state)
341
+{
342
+ struct engine *engine = *state;
343
+ struct instance *instance = engine->connector_root->instance_root;
344
+
345
+ instance->start_batch_formatting = __mock_start_batch_formatting;
346
+ instance->start_host_formatting = __mock_start_host_formatting;
347
+ instance->start_chart_formatting = __mock_start_chart_formatting;
348
+ instance->metric_formatting = __mock_metric_formatting;
349
+ instance->end_chart_formatting = __mock_end_chart_formatting;
350
+ instance->end_host_formatting = __mock_end_host_formatting;
351
+ instance->end_batch_formatting = __mock_end_batch_formatting;
352
+ __real_mark_scheduled_instances(engine);
353
+
354
+ expect_function_call(__mock_start_batch_formatting);
355
+ expect_value(__mock_start_batch_formatting, instance, instance);
356
+ will_return(__mock_start_batch_formatting, 0);
357
+
358
+ expect_function_call(__wrap_rrdhost_is_exportable);
359
+ expect_value(__wrap_rrdhost_is_exportable, instance, instance);
360
+ expect_value(__wrap_rrdhost_is_exportable, host, localhost);
361
+ will_return(__wrap_rrdhost_is_exportable, 1);
362
+
363
+ expect_function_call(__mock_start_host_formatting);
364
+ expect_value(__mock_start_host_formatting, instance, instance);
365
+ expect_value(__mock_start_host_formatting, host, localhost);
366
+ will_return(__mock_start_host_formatting, 0);
367
+
368
+ RRDSET *st = localhost->rrdset_root;
369
+ expect_function_call(__wrap_rrdset_is_exportable);
370
+ expect_value(__wrap_rrdset_is_exportable, instance, instance);
371
+ expect_value(__wrap_rrdset_is_exportable, st, st);
372
+ will_return(__wrap_rrdset_is_exportable, 1);
373
+
374
+ expect_function_call(__mock_start_chart_formatting);
375
+ expect_value(__mock_start_chart_formatting, instance, instance);
376
+ expect_value(__mock_start_chart_formatting, st, st);
377
+ will_return(__mock_start_chart_formatting, 0);
378
+
379
+ RRDDIM *rd = localhost->rrdset_root->dimensions;
380
+ expect_function_call(__mock_metric_formatting);
381
+ expect_value(__mock_metric_formatting, instance, instance);
382
+ expect_value(__mock_metric_formatting, rd, rd);
383
+ will_return(__mock_metric_formatting, 0);
384
+
385
+ expect_function_call(__mock_end_chart_formatting);
386
+ expect_value(__mock_end_chart_formatting, instance, instance);
387
+ expect_value(__mock_end_chart_formatting, st, st);
388
+ will_return(__mock_end_chart_formatting, 0);
389
+
390
+ expect_function_call(__mock_end_host_formatting);
391
+ expect_value(__mock_end_host_formatting, instance, instance);
392
+ expect_value(__mock_end_host_formatting, host, localhost);
393
+ will_return(__mock_end_host_formatting, 0);
394
+
395
+ expect_function_call(__mock_end_batch_formatting);
396
+ expect_value(__mock_end_batch_formatting, instance, instance);
397
+ will_return(__mock_end_batch_formatting, 0);
398
+
399
+ assert_int_equal(__real_prepare_buffers(engine), 0);
400
+
401
+ assert_int_equal(instance->stats.chart_buffered_metrics, 1);
402
+
403
+ // check with NULL functions
404
+ instance->start_batch_formatting = NULL;
405
+ instance->start_host_formatting = NULL;
406
+ instance->start_chart_formatting = NULL;
407
+ instance->metric_formatting = NULL;
408
+ instance->end_chart_formatting = NULL;
409
+ instance->end_host_formatting = NULL;
410
+ instance->end_batch_formatting = NULL;
411
+ assert_int_equal(__real_prepare_buffers(engine), 0);
412
+
413
+ assert_int_equal(instance->scheduled, 0);
414
+ assert_int_equal(instance->after, 2);
415
+}
416
+
417
+static void test_exporting_name_copy(void **state)
418
+{
419
+ (void)state;
420
+
421
+ char *source_name = "test.name-with/special#characters_";
422
+ char destination_name[RRD_ID_LENGTH_MAX + 1];
423
+
424
+ assert_int_equal(exporting_name_copy(destination_name, source_name, RRD_ID_LENGTH_MAX), 34);
425
+ assert_string_equal(destination_name, "test.name_with_special_characters_");
426
+}
427
+
428
+static void test_format_dimension_collected_graphite_plaintext(void **state)
429
+{
430
+ struct engine *engine = *state;
431
+
432
+ RRDDIM *rd = localhost->rrdset_root->dimensions;
433
+ assert_int_equal(format_dimension_collected_graphite_plaintext(engine->connector_root->instance_root, rd), 0);
434
+ assert_string_equal(
435
+ buffer_tostring(engine->connector_root->instance_root->buffer),
436
+ "netdata.test-host.chart_name.dimension_name;TAG1=VALUE1 TAG2=VALUE2 123000321 15051\n");
437
+}
438
+
439
+static void test_format_dimension_stored_graphite_plaintext(void **state)
440
+{
441
+ struct engine *engine = *state;
442
+
443
+ expect_function_call(__wrap_exporting_calculate_value_from_stored_data);
444
+ will_return(__wrap_exporting_calculate_value_from_stored_data, pack_storage_number(27, SN_EXISTS));
445
+
446
+ RRDDIM *rd = localhost->rrdset_root->dimensions;
447
+ assert_int_equal(format_dimension_stored_graphite_plaintext(engine->connector_root->instance_root, rd), 0);
448
+ assert_string_equal(
449
+ buffer_tostring(engine->connector_root->instance_root->buffer),
450
+ "netdata.test-host.chart_name.dimension_name;TAG1=VALUE1 TAG2=VALUE2 690565856.0000000 15052\n");
451
+}
452
+
453
+static void test_format_dimension_collected_json_plaintext(void **state)
454
+{
455
+ struct engine *engine = *state;
456
+
457
+ RRDDIM *rd = localhost->rrdset_root->dimensions;
458
+ assert_int_equal(format_dimension_collected_json_plaintext(engine->connector_root->instance_root, rd), 0);
459
+ assert_string_equal(
460
+ buffer_tostring(engine->connector_root->instance_root->buffer),
461
+ "{\"prefix\":\"netdata\",\"hostname\":\"test-host\",\"host_tags\":\"TAG1=VALUE1 TAG2=VALUE2\","
462
+ "\"chart_id\":\"chart_id\",\"chart_name\":\"chart_name\",\"chart_family\":\"(null)\","
463
+ "\"chart_context\": \"(null)\",\"chart_type\":\"(null)\",\"units\": \"(null)\",\"id\":\"dimension_id\","
464
+ "\"name\":\"dimension_name\",\"value\":123000321,\"timestamp\": 15051}\n");
465
+}
466
+
467
+static void test_format_dimension_stored_json_plaintext(void **state)
468
+{
469
+ struct engine *engine = *state;
470
+
471
+ expect_function_call(__wrap_exporting_calculate_value_from_stored_data);
472
+ will_return(__wrap_exporting_calculate_value_from_stored_data, pack_storage_number(27, SN_EXISTS));
473
+
474
+ RRDDIM *rd = localhost->rrdset_root->dimensions;
475
+ assert_int_equal(format_dimension_stored_json_plaintext(engine->connector_root->instance_root, rd), 0);
476
+ assert_string_equal(
477
+ buffer_tostring(engine->connector_root->instance_root->buffer),
478
+ "{\"prefix\":\"netdata\",\"hostname\":\"test-host\",\"host_tags\":\"TAG1=VALUE1 TAG2=VALUE2\","
479
+ "\"chart_id\":\"chart_id\",\"chart_name\":\"chart_name\",\"chart_family\":\"(null)\"," \
480
+ "\"chart_context\": \"(null)\",\"chart_type\":\"(null)\",\"units\": \"(null)\",\"id\":\"dimension_id\","
481
+ "\"name\":\"dimension_name\",\"value\":690565856.0000000,\"timestamp\": 15052}\n");
482
+}
483
+
484
+static void test_format_dimension_collected_opentsdb_telnet(void **state)
485
+{
486
+ struct engine *engine = *state;
487
+
488
+ RRDDIM *rd = localhost->rrdset_root->dimensions;
489
+ assert_int_equal(format_dimension_collected_opentsdb_telnet(engine->connector_root->instance_root, rd), 0);
490
+ assert_string_equal(
491
+ buffer_tostring(engine->connector_root->instance_root->buffer),
492
+ "put netdata.chart_name.dimension_name 15051 123000321 host=test-host TAG1=VALUE1 TAG2=VALUE2\n");
493
+}
494
+
495
+static void test_format_dimension_stored_opentsdb_telnet(void **state)
496
+{
497
+ struct engine *engine = *state;
498
+
499
+ expect_function_call(__wrap_exporting_calculate_value_from_stored_data);
500
+ will_return(__wrap_exporting_calculate_value_from_stored_data, pack_storage_number(27, SN_EXISTS));
501
+
502
+ RRDDIM *rd = localhost->rrdset_root->dimensions;
503
+ assert_int_equal(format_dimension_stored_opentsdb_telnet(engine->connector_root->instance_root, rd), 0);
504
+ assert_string_equal(
505
+ buffer_tostring(engine->connector_root->instance_root->buffer),
506
+ "put netdata.chart_name.dimension_name 15052 690565856.0000000 host=test-host TAG1=VALUE1 TAG2=VALUE2\n");
507
+}
508
+
509
+static void test_format_dimension_collected_opentsdb_http(void **state)
510
+{
511
+ struct engine *engine = *state;
512
+
513
+ RRDDIM *rd = localhost->rrdset_root->dimensions;
514
+ assert_int_equal(format_dimension_collected_opentsdb_http(engine->connector_root->instance_root, rd), 0);
515
+ assert_string_equal(
516
+ buffer_tostring(engine->connector_root->instance_root->buffer),
517
+ "POST /api/put HTTP/1.1\r\n"
518
+ "Host: test-host\r\n"
519
+ "Content-Type: application/json\r\n"
520
+ "Content-Length: 153\r\n\r\n"
521
+ "{ \"metric\": \"netdata.chart_name.dimension_name\", "
522
+ "\"timestamp\": 15051, "
523
+ "\"value\": 123000321, "
524
+ "\"tags\": { \"host\": \"test-host TAG1=VALUE1 TAG2=VALUE2\" }}");
525
+}
526
+
527
+static void test_format_dimension_stored_opentsdb_http(void **state)
528
+{
529
+ struct engine *engine = *state;
530
+
531
+ expect_function_call(__wrap_exporting_calculate_value_from_stored_data);
532
+ will_return(__wrap_exporting_calculate_value_from_stored_data, pack_storage_number(27, SN_EXISTS));
533
+
534
+ RRDDIM *rd = localhost->rrdset_root->dimensions;
535
+ assert_int_equal(format_dimension_stored_opentsdb_http(engine->connector_root->instance_root, rd), 0);
536
+ assert_string_equal(
537
+ buffer_tostring(engine->connector_root->instance_root->buffer),
538
+ "POST /api/put HTTP/1.1\r\n"
539
+ "Host: test-host\r\n"
540
+ "Content-Type: application/json\r\n"
541
+ "Content-Length: 161\r\n\r\n"
542
+ "{ \"metric\": \"netdata.chart_name.dimension_name\", "
543
+ "\"timestamp\": 15052, "
544
+ "\"value\": 690565856.0000000, "
545
+ "\"tags\": { \"host\": \"test-host TAG1=VALUE1 TAG2=VALUE2\" }}");
546
+}
547
+
548
+static void test_exporting_discard_response(void **state)
549
+{
550
+ struct engine *engine = *state;
551
+
552
+ BUFFER *response = buffer_create(0);
553
+ buffer_sprintf(response, "Test response");
554
+
555
+ expect_function_call(__wrap_info_int);
556
+
557
+ assert_int_equal(exporting_discard_response(response, engine->connector_root->instance_root), 0);
558
+
559
+ assert_string_equal(
560
+ log_line,
561
+ "EXPORTING: received 13 bytes from instance_name connector instance. Ignoring them. Sample: 'Test response'");
562
+
563
+ assert_int_equal(buffer_strlen(response), 0);
564
+
565
+ buffer_free(response);
566
+}
567
+
568
+static void test_simple_connector_receive_response(void **state)
569
+{
570
+ struct engine *engine = *state;
571
+ struct instance *instance = engine->connector_root->instance_root;
572
+ struct stats *stats = &instance->stats;
573
+
574
+ int sock = 1;
575
+
576
+ expect_function_call(__wrap_recv);
577
+ expect_value(__wrap_recv, sockfd, 1);
578
+ expect_not_value(__wrap_recv, buf, 0);
579
+ expect_value(__wrap_recv, len, 4096);
580
+ expect_value(__wrap_recv, flags, MSG_DONTWAIT);
581
+
582
+ expect_function_call(__wrap_info_int);
583
+
584
+ simple_connector_receive_response(&sock, instance);
585
+
586
+ assert_string_equal(
587
+ log_line,
588
+ "EXPORTING: received 9 bytes from instance_name connector instance. Ignoring them. Sample: 'Test recv'");
589
+
590
+ assert_int_equal(stats->chart_received_bytes, 9);
591
+ assert_int_equal(stats->chart_receptions, 1);
592
+ assert_int_equal(sock, 1);
593
+}
594
+
595
+static void test_simple_connector_send_buffer(void **state)
596
+{
597
+ struct engine *engine = *state;
598
+ struct instance *instance = engine->connector_root->instance_root;
599
+ struct stats *stats = &instance->stats;
600
+ BUFFER *buffer = instance->buffer;
601
+
602
+ int sock = 1;
603
+ int failures = 3;
604
+
605
+ __real_mark_scheduled_instances(engine);
606
+
607
+ expect_function_call(__wrap_rrdhost_is_exportable);
608
+ expect_value(__wrap_rrdhost_is_exportable, instance, instance);
609
+ expect_value(__wrap_rrdhost_is_exportable, host, localhost);
610
+ will_return(__wrap_rrdhost_is_exportable, 1);
611
+
612
+ RRDSET *st = localhost->rrdset_root;
613
+ expect_function_call(__wrap_rrdset_is_exportable);
614
+ expect_value(__wrap_rrdset_is_exportable, instance, instance);
615
+ expect_value(__wrap_rrdset_is_exportable, st, st);
616
+ will_return(__wrap_rrdset_is_exportable, 1);
617
+
618
+ __real_prepare_buffers(engine);
619
+
620
+ expect_function_call(__wrap_send);
621
+ expect_value(__wrap_send, sockfd, 1);
622
+ expect_value(__wrap_send, buf, buffer_tostring(buffer));
623
+ expect_string(
624
+ __wrap_send, buf, "netdata.test-host.chart_name.dimension_name;TAG1=VALUE1 TAG2=VALUE2 123000321 15051\n");
625
+ expect_value(__wrap_send, len, 84);
626
+ expect_value(__wrap_send, flags, MSG_NOSIGNAL);
627
+
628
+ simple_connector_send_buffer(&sock, &failures, instance);
629
+
630
+ assert_int_equal(failures, 0);
631
+ assert_int_equal(stats->chart_transmission_successes, 1);
632
+ assert_int_equal(stats->chart_sent_bytes, 84);
633
+ assert_int_equal(stats->chart_sent_metrics, 1);
634
+ assert_int_equal(stats->chart_transmission_failures, 0);
635
+
636
+ assert_int_equal(buffer_strlen(buffer), 0);
637
+
638
+ assert_int_equal(sock, 1);
639
+}
640
+
641
+static void test_simple_connector_worker(void **state)
642
+{
643
+ struct engine *engine = *state;
644
+ struct instance *instance = engine->connector_root->instance_root;
645
+ BUFFER *buffer = instance->buffer;
646
+
647
+ __real_mark_scheduled_instances(engine);
648
+
649
+ expect_function_call(__wrap_rrdhost_is_exportable);
650
+ expect_value(__wrap_rrdhost_is_exportable, instance, instance);
651
+ expect_value(__wrap_rrdhost_is_exportable, host, localhost);
652
+ will_return(__wrap_rrdhost_is_exportable, 1);
653
+
654
+ RRDSET *st = localhost->rrdset_root;
655
+ expect_function_call(__wrap_rrdset_is_exportable);
656
+ expect_value(__wrap_rrdset_is_exportable, instance, instance);
657
+ expect_value(__wrap_rrdset_is_exportable, st, st);
658
+ will_return(__wrap_rrdset_is_exportable, 1);
659
+
660
+ __real_prepare_buffers(engine);
661
+
662
+ expect_function_call(__wrap_connect_to_one_of);
663
+ expect_string(__wrap_connect_to_one_of, destination, "localhost");
664
+ expect_value(__wrap_connect_to_one_of, default_port, 2003);
665
+ expect_not_value(__wrap_connect_to_one_of, reconnects_counter, 0);
666
+ expect_value(__wrap_connect_to_one_of, connected_to, 0);
667
+ expect_value(__wrap_connect_to_one_of, connected_to_size, 0);
668
+ will_return(__wrap_connect_to_one_of, 2);
669
+
670
+ expect_function_call(__wrap_send);
671
+ expect_value(__wrap_send, sockfd, 2);
672
+ expect_value(__wrap_send, buf, buffer_tostring(buffer));
673
+ expect_string(
674
+ __wrap_send, buf, "netdata.test-host.chart_name.dimension_name;TAG1=VALUE1 TAG2=VALUE2 123000321 15051\n");
675
+ expect_value(__wrap_send, len, 84);
676
+ expect_value(__wrap_send, flags, MSG_NOSIGNAL);
677
+
678
+ simple_connector_worker(instance);
679
+}
680
+
681
+int main(void)
682
+{
683
+ const struct CMUnitTest tests[] = {
684
+ cmocka_unit_test_setup_teardown(test_exporting_engine, setup_initialized_engine, teardown_initialized_engine),
685
+ cmocka_unit_test(test_read_exporting_config),
686
+ cmocka_unit_test_setup_teardown(test_init_connectors, setup_configured_engine, teardown_configured_engine),
687
+ cmocka_unit_test_setup_teardown(
688
+ test_init_graphite_instance, setup_configured_engine, teardown_configured_engine),
689
+ cmocka_unit_test_setup_teardown(
690
+ test_init_json_instance, setup_configured_engine, teardown_configured_engine),
691
+ cmocka_unit_test_setup_teardown(
692
+ test_init_opentsdb_connector, setup_configured_engine, teardown_configured_engine),
693
+ cmocka_unit_test_setup_teardown(
694
+ test_init_opentsdb_telnet_instance, setup_configured_engine, teardown_configured_engine),
695
+ cmocka_unit_test_setup_teardown(
696
+ test_init_opentsdb_http_instance, setup_configured_engine, teardown_configured_engine),
697
+ cmocka_unit_test_setup_teardown(
698
+ test_mark_scheduled_instances, setup_initialized_engine, teardown_initialized_engine),
699
+ cmocka_unit_test_setup_teardown(
700
+ test_rrdhost_is_exportable, setup_initialized_engine, teardown_initialized_engine),
701
+ cmocka_unit_test_setup_teardown(
702
+ test_false_rrdhost_is_exportable, setup_initialized_engine, teardown_initialized_engine),
703
+ cmocka_unit_test_setup_teardown(
704
+ test_rrdset_is_exportable, setup_initialized_engine, teardown_initialized_engine),
705
+ cmocka_unit_test_setup_teardown(
706
+ test_false_rrdset_is_exportable, setup_initialized_engine, teardown_initialized_engine),
707
+ cmocka_unit_test_setup_teardown(
708
+ test_exporting_calculate_value_from_stored_data, setup_initialized_engine, teardown_initialized_engine),
709
+ cmocka_unit_test_setup_teardown(test_prepare_buffers, setup_initialized_engine, teardown_initialized_engine),
710
+ cmocka_unit_test(test_exporting_name_copy),
711
+ cmocka_unit_test_setup_teardown(
712
+ test_format_dimension_collected_graphite_plaintext, setup_initialized_engine, teardown_initialized_engine),
713
+ cmocka_unit_test_setup_teardown(
714
+ test_format_dimension_stored_graphite_plaintext, setup_initialized_engine, teardown_initialized_engine),
715
+ cmocka_unit_test_setup_teardown(
716
+ test_format_dimension_collected_json_plaintext, setup_initialized_engine, teardown_initialized_engine),
717
+ cmocka_unit_test_setup_teardown(
718
+ test_format_dimension_stored_json_plaintext, setup_initialized_engine, teardown_initialized_engine),
719
+ cmocka_unit_test_setup_teardown(
720
+ test_format_dimension_collected_opentsdb_telnet, setup_initialized_engine, teardown_initialized_engine),
721
+ cmocka_unit_test_setup_teardown(
722
+ test_format_dimension_stored_opentsdb_telnet, setup_initialized_engine, teardown_initialized_engine),
723
+ cmocka_unit_test_setup_teardown(
724
+ test_format_dimension_collected_opentsdb_http, setup_initialized_engine, teardown_initialized_engine),
725
+ cmocka_unit_test_setup_teardown(
726
+ test_format_dimension_stored_opentsdb_http, setup_initialized_engine, teardown_initialized_engine),
727
+ cmocka_unit_test_setup_teardown(
728
+ test_exporting_discard_response, setup_initialized_engine, teardown_initialized_engine),
729
+ cmocka_unit_test_setup_teardown(
730
+ test_simple_connector_receive_response, setup_initialized_engine, teardown_initialized_engine),
731
+ cmocka_unit_test_setup_teardown(
732
+ test_simple_connector_send_buffer, setup_initialized_engine, teardown_initialized_engine),
733
+ cmocka_unit_test_setup_teardown(
734
+ test_simple_connector_worker, setup_initialized_engine, teardown_initialized_engine),
735
+ };
736
+
737
+ return cmocka_run_group_tests_name("exporting_engine", tests, NULL, NULL);
738
+}