Code

t/integration: Add a simple time-series fetcher test.
[sysdb.git] / t / integration / mock_plugin.c
1 /*
2  * SysDB - t/integration/mock_plugin.c
3  * Copyright (C) 2014 Sebastian 'tokkee' Harl <sh@tokkee.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
28 #if HAVE_CONFIG_H
29 #       include "config.h"
30 #endif /* HAVE_CONFIG_H */
32 #include "sysdb.h"
33 #include "core/plugin.h"
34 #include "core/store.h"
35 #include "utils/error.h"
37 #include "liboconfig/utils.h"
39 #include <stdlib.h>
40 #include <string.h>
42 #define MAGIC_DATA (void *)0x4711
44 SDB_PLUGIN_MAGIC;
46 static const char *hostnames[] = {
47         "some.host.name",
48         "other.host.name",
49         "host1.example.com",
50         "host2.example.com",
51         "localhost",
52 };
54 static struct {
55         const char *hostname;
56         const char *metric;
57         sdb_metric_store_t store;
58 } metrics[] = {
59         { "some.host.name", "foo/bar/qux",
60                 { "mock", "/var/lib/collectd/rrd/foo/bar/qux.rrd" } },
61         { "some.host.name", "foo/bar/baz",
62                 { "mock", "/var/lib/collectd/rrd/foo/bar/baz.rrd" } },
63         { "some.host.name", "foo2/bar/qux",
64                 { "mock", "/var/lib/collectd/rrd/foo2/bar/qux.rrd" } },
65         { "some.host.name", "foo2/bar/baz",
66                 { "mock", "/var/lib/collectd/rrd/foo2/bar/baz.rrd" } },
67         { "other.host.name", "foo/bar/qux",
68                 { "mock", "/var/lib/collectd/rrd/foo/bar/qux.rrd" } },
69         { "other.host.name", "foo/bar/baz",
70                 { "mock", "/var/lib/collectd/rrd/foo/bar/baz.rrd" } },
71         { "other.host.name", "foo2/bar/qux",
72                 { "mock", "/var/lib/collectd/rrd/foo2/bar/qux.rrd" } },
73         { "other.host.name", "foo2/bar/baz",
74                 { "mock", "/var/lib/collectd/rrd/foo2/bar/baz.rrd" } },
75 };
77 static struct {
78         const char *hostname;
79         const char *service;
80 } services[] = {
81         { "some.host.name", "mock service" },
82         { "some.host.name", "other service" },
83         { "some.host.name", "database" },
84         { "host1.example.com", "mock service" },
85         { "host1.example.com", "example service one" },
86         { "host1.example.com", "example service two" },
87         { "host1.example.com", "example service three" },
88         { "host2.example.com", "mock service" },
89         { "host2.example.com", "example service one" },
90         { "host2.example.com", "example service two" },
91         { "host2.example.com", "example service three" },
92         { "localhost", "sysdbd" },
93 };
95 static struct {
96         const char *hostname;
97         const char *name;
98         const char *value;
99 } attributes[] = {
100         { "other.host.name", "attribute", "value" },
101         { "other.host.name", "architecture", "varch" },
102         { "other.host.name", "processor0", "Vendor TYPE4711 CPU MAGIC" },
103         { "other.host.name", "processor1", "Vendor TYPE4711 CPU MAGIC" },
104         { "other.host.name", "processor2", "Vendor TYPE4711 CPU MAGIC" },
105         { "other.host.name", "processor3", "Vendor TYPE4711 CPU MAGIC" },
106         { "host1.example.com", "other attribute", "special value" },
107         { "host1.example.com", "architecture", "x42" },
108         { "host1.example.com", "timezone", "UTC" },
109         { "host2.example.com", "other attribute", "special value" },
110         { "host2.example.com", "architecture", "x42" },
111         { "host2.example.com", "timezone", "UTC" },
112         { "localhost", "attr1", "value1" },
113         { "localhost", "attr2", "value2" },
114         { "localhost", "attr3", "value3" },
115 };
117 /*
118  * plugin API
119  */
121 static int
122 mock_init(sdb_object_t *user_data)
124         if (SDB_OBJ_WRAPPER(user_data)->data != MAGIC_DATA) {
125                 sdb_log(SDB_LOG_ERR, "mock::plugin: Invalid user data %p "
126                                 "passed to init", SDB_OBJ_WRAPPER(user_data)->data);
127                 exit(1);
128         }
129         return 0;
130 } /* mock_init */
132 static int
133 mock_shutdown(sdb_object_t *user_data)
135         if (SDB_OBJ_WRAPPER(user_data)->data != MAGIC_DATA) {
136                 sdb_log(SDB_LOG_ERR, "mock::plugin: Invalid user data %p "
137                                 "passed to shutdown", SDB_OBJ_WRAPPER(user_data)->data);
138                 exit(1);
139         }
140         return 0;
141 } /* mock_shutdown */
143 static int
144 mock_collect(sdb_object_t *user_data)
146         size_t i;
147         int check;
149         if (SDB_OBJ_WRAPPER(user_data)->data != MAGIC_DATA) {
150                 sdb_log(SDB_LOG_ERR, "mock::plugin: Invalid user data %p "
151                                 "passed to collect", SDB_OBJ_WRAPPER(user_data)->data);
152                 exit(1);
153         }
155         for (i = 0; i < SDB_STATIC_ARRAY_LEN(hostnames); ++i) {
156                 if ((check = sdb_store_host(hostnames[i], sdb_gettime()))) {
157                         sdb_log(SDB_LOG_ERR, "mock::plugin: Failed to store host: "
158                                         "status %d", check);
159                         exit(1);
160                 }
161         }
162         for (i = 0; i < SDB_STATIC_ARRAY_LEN(metrics); ++i) {
163                 if ((check = sdb_store_metric(metrics[i].hostname,
164                                                 metrics[i].metric, &metrics[i].store,
165                                                 sdb_gettime()))) {
166                         sdb_log(SDB_LOG_ERR, "mock::plugin: Failed to store metric: "
167                                         "status %d", check);
168                         exit(1);
169                 }
170         }
171         for (i = 0; i < SDB_STATIC_ARRAY_LEN(services); ++i) {
172                 if ((check = sdb_store_service(services[i].hostname,
173                                                 services[i].service, sdb_gettime()))) {
174                         sdb_log(SDB_LOG_ERR, "mock::plugin: Failed to store service: "
175                                         "status %d", check);
176                         exit(1);
177                 }
178         }
179         for (i = 0; i < SDB_STATIC_ARRAY_LEN(attributes); ++i) {
180                 sdb_data_t datum = { SDB_TYPE_STRING, { .string = NULL } };
181                 datum.data.string = strdup(attributes[i].value);
183                 if ((check = sdb_store_attribute(attributes[i].hostname,
184                                                 attributes[i].name, &datum, sdb_gettime()))) {
185                         sdb_log(SDB_LOG_ERR, "mock::plugin: Failed to store attribute: "
186                                         "status %d", check);
187                         exit(1);
188                 }
190                 free(datum.data.string);
191         }
192         return 0;
193 } /* mock_collect */
195 static sdb_timeseries_t *
196 mock_fetch_ts(const char *id, sdb_timeseries_opts_t *opts,
197                 sdb_object_t *user_data)
199         sdb_timeseries_t *ts;
200         const char *names[] = { "nameA", "nameB" };
201         size_t i, j;
203         if (*id != '/') {
204                 sdb_log(SDB_LOG_ERR, "mock::plugin: Invalid time-series %s", id);
205                 exit(1);
206         }
208         if (SDB_OBJ_WRAPPER(user_data)->data != MAGIC_DATA) {
209                 sdb_log(SDB_LOG_ERR, "mock::plugin: Invalid user data %p "
210                                 "passed to collect", SDB_OBJ_WRAPPER(user_data)->data);
211                 exit(1);
212         }
214         ts = sdb_timeseries_create(SDB_STATIC_ARRAY_LEN(names), names, 10);
215         if (! ts)
216                 return NULL;
218         ts->start = opts->start;
219         ts->end = opts->end;
221         for (i = 0; i < 10; ++i) {
222                 for (j = 0; j < SDB_STATIC_ARRAY_LEN(names); ++j) {
223                         ts->data[j][i].timestamp = ts->start
224                                 + i * (ts->end - ts->start) / 10;
225                         ts->data[j][i].value = (double)(i + j);
226                 }
227         }
228         return ts;
229 } /* mock_fetch_ts */
231 static int
232 mock_config(oconfig_item_t *ci)
234         sdb_object_t *user_data;
236         int i;
238         if (! ci) /* deconfiguration */
239                 return 0;
241         for (i = 0; i < ci->children_num; ++i) {
242                 oconfig_item_t *child = ci->children + i;
244                 sdb_log(SDB_LOG_WARNING, "mock::plugin: Ignoring unknown config "
245                                 "option '%s'", child->key);
246         }
248         user_data = sdb_object_create_wrapper("mock_data", MAGIC_DATA, NULL);
249         if (! user_data) {
250                 sdb_log(SDB_LOG_ERR, "mock::plugin: Failed to allocate user data");
251                 exit(1);
252         }
254         sdb_plugin_register_init("main", mock_init, user_data);
255         sdb_plugin_register_shutdown("main", mock_shutdown, user_data);
256         sdb_plugin_register_collector("main", mock_collect,
257                         /* interval = */ NULL, user_data);
259         sdb_plugin_register_ts_fetcher("mock", mock_fetch_ts, user_data);
261         sdb_object_deref(user_data);
262         return 0;
263 } /* mock_config */
265 int
266 sdb_module_init(sdb_plugin_info_t *info)
268         sdb_plugin_set_info(info, SDB_PLUGIN_INFO_DESC, "a mock plugin");
269         sdb_plugin_set_info(info, SDB_PLUGIN_INFO_COPYRIGHT,
270                         "Copyright (C) 2012 Sebastian 'tokkee' Harl <sh@tokkee.org>");
271         sdb_plugin_set_info(info, SDB_PLUGIN_INFO_LICENSE, "BSD");
272         sdb_plugin_set_info(info, SDB_PLUGIN_INFO_VERSION, SDB_VERSION);
273         sdb_plugin_set_info(info, SDB_PLUGIN_INFO_PLUGIN_VERSION, SDB_VERSION);
275         sdb_plugin_register_config(mock_config);
276         return 0;
277 } /* sdb_module_init */
279 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */