Port: replace setenv() by g_setenv()
[babeltrace.git] / tests / lib / test_plugin.c
1 /*
2 * test_plugin.c
3 *
4 * CTF IR Reference Count test
5 *
6 * Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; under version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22 #include <babeltrace/plugin/plugin.h>
23 #include <babeltrace/ref.h>
24 #include <babeltrace/values.h>
25 #include <babeltrace/graph/component.h>
26 #include <babeltrace/graph/graph.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdio.h>
30 #include <assert.h>
31 #include <glib.h>
32 #include "tap/tap.h"
33 #include "common.h"
34
35 #define NR_TESTS 58
36 #define NON_EXISTING_PATH "/this/hopefully/does/not/exist/5bc75f8d-0dba-4043-a509-d7984b97e42b.so"
37
38 /* Those symbols are written to by some test plugins */
39 static int check_env_var(const char *name)
40 {
41 const char *val = getenv(name);
42
43 if (!val) {
44 return -1;
45 }
46
47 return atoi(val);
48 }
49
50 static void reset_test_plugin_env_vars(void)
51 {
52 g_setenv("BT_TEST_PLUGIN_INIT_CALLED", "0", 1);
53 g_setenv("BT_TEST_PLUGIN_EXIT_CALLED", "0", 1);
54 }
55
56 static char *get_test_plugin_path(const char *plugin_dir,
57 const char *plugin_name)
58 {
59 GString *path = g_string_new(plugin_dir);
60 char *ret;
61
62 assert(path);
63 g_string_append_printf(path, "/plugin-%s.so", plugin_name);
64 ret = path->str;
65 g_string_free(path, FALSE);
66 return ret;
67 }
68
69 static void test_invalid(const char *plugin_dir)
70 {
71 struct bt_plugin_set *plugin_set;
72
73 plugin_set = bt_plugin_create_all_from_file(NON_EXISTING_PATH);
74 ok(!plugin_set, "bt_plugin_create_all_from_file() fails with a non-existing file");
75
76 plugin_set = bt_plugin_create_all_from_file(plugin_dir);
77 ok(!plugin_set, "bt_plugin_create_all_from_file() fails with a directory");
78
79 ok(!bt_plugin_create_all_from_file(NULL),
80 "bt_plugin_create_all_from_file() handles NULL correctly");
81 ok(!bt_plugin_create_all_from_dir(NULL, BT_FALSE),
82 "bt_plugin_create_all_from_dir() handles NULL correctly");
83 ok(!bt_plugin_get_name(NULL),
84 "bt_plugin_get_name() handles NULL correctly");
85 ok(!bt_plugin_get_description(NULL),
86 "bt_plugin_get_description() handles NULL correctly");
87 ok(bt_plugin_get_version(NULL, NULL, NULL, NULL, NULL) !=
88 BT_PLUGIN_STATUS_OK,
89 "bt_plugin_get_version() handles NULL correctly");
90 ok(!bt_plugin_get_author(NULL),
91 "bt_plugin_get_author() handles NULL correctly");
92 ok(!bt_plugin_get_license(NULL),
93 "bt_plugin_get_license() handles NULL correctly");
94 ok(!bt_plugin_get_path(NULL),
95 "bt_plugin_get_path() handles NULL correctly");
96 ok(bt_plugin_get_component_class_count(NULL) < 0,
97 "bt_plugin_get_component_class_count() handles NULL correctly");
98 ok(!bt_plugin_get_component_class_by_index(NULL, 0),
99 "bt_plugin_get_component_class_by_index() handles NULL correctly");
100 ok(!bt_plugin_get_component_class_by_name_and_type(NULL, NULL, 0),
101 "bt_plugin_get_component_class_by_name_and_type() handles NULL correctly");
102 }
103
104 static void test_minimal(const char *plugin_dir)
105 {
106 struct bt_plugin_set *plugin_set;
107 struct bt_plugin *plugin;
108 char *minimal_path = get_test_plugin_path(plugin_dir, "minimal");
109
110 assert(minimal_path);
111 diag("minimal plugin test below");
112
113 reset_test_plugin_env_vars();
114 plugin_set = bt_plugin_create_all_from_file(minimal_path);
115 ok(plugin_set && bt_plugin_set_get_plugin_count(plugin_set) == 1,
116 "bt_plugin_create_all_from_file() succeeds with a valid file");
117 ok(check_env_var("BT_TEST_PLUGIN_INIT_CALLED") == 1,
118 "plugin's initialization function is called during bt_plugin_create_all_from_file()");
119 ok(bt_plugin_set_get_plugin_count(plugin_set) == 1,
120 "bt_plugin_create_all_from_file() returns the expected number of plugins");
121 plugin = bt_plugin_set_get_plugin(plugin_set, 0);
122 ok(strcmp(bt_plugin_get_name(plugin), "test_minimal") == 0,
123 "bt_plugin_get_name() returns the expected name");
124 ok(strcmp(bt_plugin_get_description(plugin),
125 "Minimal Babeltrace plugin with no component classes") == 0,
126 "bt_plugin_get_description() returns the expected description");
127 ok(bt_plugin_get_version(plugin, NULL, NULL, NULL, NULL) !=
128 BT_PLUGIN_STATUS_OK,
129 "bt_plugin_get_version() fails when there's no version");
130 ok(strcmp(bt_plugin_get_author(plugin), "Janine Sutto") == 0,
131 "bt_plugin_get_author() returns the expected author");
132 ok(strcmp(bt_plugin_get_license(plugin), "Beerware") == 0,
133 "bt_plugin_get_license() returns the expected license");
134 ok(strcmp(bt_plugin_get_path(plugin), minimal_path) == 0,
135 "bt_plugin_get_path() returns the expected path");
136 ok(bt_plugin_get_component_class_count(plugin) == 0,
137 "bt_plugin_get_component_class_count() returns the expected value");
138 bt_put(plugin);
139 bt_put(plugin_set);
140 ok(check_env_var("BT_TEST_PLUGIN_EXIT_CALLED") == 1,
141 "plugin's exit function is called when the plugin is destroyed");
142
143 free(minimal_path);
144 }
145
146 static void test_sfs(const char *plugin_dir)
147 {
148 struct bt_plugin_set *plugin_set;
149 struct bt_plugin *plugin;
150 struct bt_component_class *sink_comp_class;
151 struct bt_component_class *source_comp_class;
152 struct bt_component_class *filter_comp_class;
153 struct bt_component *sink_component;
154 char *sfs_path = get_test_plugin_path(plugin_dir, "sfs");
155 unsigned int major, minor, patch;
156 const char *extra;
157 struct bt_value *params;
158 struct bt_value *results;
159 struct bt_value *object;
160 struct bt_value *res_params;
161 struct bt_graph *graph;
162 const char *object_str;
163 int ret;
164
165 assert(sfs_path);
166 diag("sfs plugin test below");
167
168 plugin_set = bt_plugin_create_all_from_file(sfs_path);
169 assert(plugin_set && bt_plugin_set_get_plugin_count(plugin_set) == 1);
170 plugin = bt_plugin_set_get_plugin(plugin_set, 0);
171 ok(bt_plugin_get_version(plugin, &major, &minor, &patch, &extra) ==
172 BT_PLUGIN_STATUS_OK,
173 "bt_plugin_get_version() succeeds when there's a version");
174 ok(major == 1,
175 "bt_plugin_get_version() returns the expected major version");
176 ok(minor == 2,
177 "bt_plugin_get_version() returns the expected minor version");
178 ok(patch == 3,
179 "bt_plugin_get_version() returns the expected patch version");
180 ok(strcmp(extra, "yes") == 0,
181 "bt_plugin_get_version() returns the expected extra version");
182 ok(bt_plugin_get_component_class_count(plugin) == 3,
183 "bt_plugin_get_component_class_count() returns the expected value");
184
185 source_comp_class = bt_plugin_get_component_class_by_name_and_type(
186 plugin, "source", BT_COMPONENT_CLASS_TYPE_SOURCE);
187 ok(source_comp_class,
188 "bt_plugin_get_component_class_by_name_and_type() finds a source component class");
189
190 sink_comp_class = bt_plugin_get_component_class_by_name_and_type(
191 plugin, "sink", BT_COMPONENT_CLASS_TYPE_SINK);
192 ok(sink_comp_class,
193 "bt_plugin_get_component_class_by_name_and_type() finds a sink component class");
194 ok(strcmp(bt_component_class_get_help(sink_comp_class),
195 "Bacon ipsum dolor amet strip steak cupim pastrami venison shoulder.\n"
196 "Prosciutto beef ribs flank meatloaf pancetta brisket kielbasa drumstick\n"
197 "venison tenderloin cow tail. Beef short loin shoulder meatball, sirloin\n"
198 "ground round brisket salami cupim pork bresaola turkey bacon boudin.\n") == 0,
199 "bt_component_class_get_help() returns the expected help text");
200
201 filter_comp_class = bt_plugin_get_component_class_by_name_and_type(
202 plugin, "filter", BT_COMPONENT_CLASS_TYPE_FILTER);
203 ok(filter_comp_class,
204 "bt_plugin_get_component_class_by_name_and_type() finds a filter component class");
205 ok(!bt_plugin_get_component_class_by_name_and_type(plugin, "filter",
206 BT_COMPONENT_CLASS_TYPE_SOURCE),
207 "bt_plugin_get_component_class_by_name_and_type() does not find a component class given the wrong type");
208 params = bt_value_integer_create_init(23);
209 assert(params);
210 ok (!bt_component_class_query(NULL, "get-something", params),
211 "bt_component_class_query() handles NULL (component class)");
212 ok (!bt_component_class_query(filter_comp_class, NULL, params),
213 "bt_component_class_query() handles NULL (object)");
214 ok (!bt_component_class_query(filter_comp_class, "get-something", NULL),
215 "bt_component_class_query() handles NULL (parameters)");
216 results = bt_component_class_query(filter_comp_class,
217 "get-something", params);
218 ok(results, "bt_component_class_query() succeeds");
219 assert(bt_value_is_array(results) && bt_value_array_size(results) == 2);
220 object = bt_value_array_get(results, 0);
221 assert(object && bt_value_is_string(object));
222 ret = bt_value_string_get(object, &object_str);
223 assert(ret == 0);
224 ok(strcmp(object_str, "get-something") == 0,
225 "bt_component_class_query() receives the expected object name");
226 res_params = bt_value_array_get(results, 1);
227 ok(res_params == params,
228 "bt_component_class_query() receives the expected parameters");
229
230 diag("> putting the plugin object here");
231 BT_PUT(plugin);
232 graph = bt_graph_create();
233 assert(graph);
234 ret = bt_graph_add_component(graph, sink_comp_class, "the-sink", NULL,
235 &sink_component);
236 ok(ret == 0 && sink_component,
237 "bt_graph_add_component() still works after the plugin object is destroyed");
238 BT_PUT(sink_component);
239 BT_PUT(source_comp_class);
240 bt_put(graph);
241 graph = bt_graph_create();
242 assert(graph);
243 ret = bt_graph_add_component(graph, sink_comp_class, "the-sink", NULL,
244 &sink_component);
245 ok(ret == 0 && sink_component,
246 "bt_graph_add_component() still works after the source component class object is destroyed");
247 BT_PUT(sink_component);
248 BT_PUT(filter_comp_class);
249 bt_put(graph);
250 graph = bt_graph_create();
251 assert(graph);
252 ret = bt_graph_add_component(graph, sink_comp_class, "the-sink", NULL,
253 &sink_component);
254 ok(ret == 0 && sink_component,
255 "bt_graph_add_component() still works after the filter component class object is destroyed");
256 BT_PUT(sink_comp_class);
257 BT_PUT(sink_component);
258
259 free(sfs_path);
260 bt_put(graph);
261 bt_put(plugin_set);
262 bt_put(object);
263 bt_put(res_params);
264 bt_put(results);
265 bt_put(params);
266 }
267
268 static void test_create_all_from_dir(const char *plugin_dir)
269 {
270 struct bt_plugin_set *plugin_set;
271
272 diag("create from all test below");
273
274 plugin_set = bt_plugin_create_all_from_dir(NON_EXISTING_PATH, BT_FALSE);
275 ok(!plugin_set,
276 "bt_plugin_create_all_from_dir() fails with an invalid path");
277
278 plugin_set = bt_plugin_create_all_from_dir(plugin_dir, BT_FALSE);
279 ok(plugin_set, "bt_plugin_create_all_from_dir() succeeds with a valid path");
280
281 /* 2 or 4, if `.la` files are considered or not */
282 ok(bt_plugin_set_get_plugin_count(plugin_set) == 2 ||
283 bt_plugin_set_get_plugin_count(plugin_set) == 4,
284 "bt_plugin_create_all_from_dir() returns the expected number of plugin objects");
285
286 bt_put(plugin_set);
287 }
288
289 static void test_find(const char *plugin_dir)
290 {
291 int ret;
292 struct bt_plugin *plugin;
293 struct bt_component_class *comp_cls_sink;
294 struct bt_component_class *comp_cls_source;
295 char *plugin_path;
296
297 ok(!bt_plugin_find(NULL),
298 "bt_plugin_find() handles NULL");
299 ok(!bt_plugin_find(NON_EXISTING_PATH),
300 "bt_plugin_find() returns NULL with an unknown plugin name");
301 ret = asprintf(&plugin_path, "%s:/ec1d09e5-696c-442e-b1c3-f9c6cf7f5958:::%s:8db46494-a398-466a-9649-c765ae077629:",
302 NON_EXISTING_PATH, plugin_dir);
303 assert(ret > 0 && plugin_path);
304 g_setenv("BABELTRACE_PLUGIN_PATH", plugin_path, 1);
305 plugin = bt_plugin_find("test_minimal");
306 ok(plugin,
307 "bt_plugin_find() succeeds with a plugin name it can find");
308 ok(strcmp(bt_plugin_get_author(plugin), "Janine Sutto") == 0,
309 "bt_plugin_find() finds the correct plugin for a given name");
310 BT_PUT(plugin);
311 comp_cls_sink = bt_plugin_find_component_class(NULL, "sink",
312 BT_COMPONENT_CLASS_TYPE_SINK);
313 ok(!comp_cls_sink, "bt_plugin_find_component_class() handles NULL (plugin name)");
314 comp_cls_sink = bt_plugin_find_component_class("test_sfs", NULL,
315 BT_COMPONENT_CLASS_TYPE_SINK);
316 ok(!comp_cls_sink, "bt_plugin_find_component_class() handles NULL (component class name)");
317 comp_cls_sink = bt_plugin_find_component_class("test_sfs", "sink2",
318 BT_COMPONENT_CLASS_TYPE_SINK);
319 ok(!comp_cls_sink, "bt_plugin_find_component_class() fails with an unknown component class name");
320 comp_cls_sink = bt_plugin_find_component_class("test_sfs", "sink",
321 BT_COMPONENT_CLASS_TYPE_SINK);
322 ok(comp_cls_sink, "bt_plugin_find_component_class() succeeds with valid parameters");
323 ok(strcmp(bt_component_class_get_name(comp_cls_sink), "sink") == 0,
324 "bt_plugin_find_component_class() returns the appropriate component class (sink)");
325 comp_cls_source = bt_plugin_find_component_class("test_sfs", "source",
326 BT_COMPONENT_CLASS_TYPE_SOURCE);
327 ok(comp_cls_sink, "bt_plugin_find_component_class() succeeds with another component class name (same plugin)");
328 ok(strcmp(bt_component_class_get_name(comp_cls_source), "source") == 0,
329 "bt_plugin_find_component_class() returns the appropriate component class (source)");
330 BT_PUT(comp_cls_sink);
331 BT_PUT(comp_cls_source);
332 free(plugin_path);
333 }
334
335 int main(int argc, char **argv)
336 {
337 int ret;
338 const char *plugin_dir;
339
340 if (argc != 2) {
341 puts("Usage: test_plugin plugin_directory");
342 ret = 1;
343 goto end;
344 }
345
346 plugin_dir = argv[1];
347 plan_tests(NR_TESTS);
348 test_invalid(plugin_dir);
349 test_minimal(plugin_dir);
350 test_sfs(plugin_dir);
351 test_create_all_from_dir(plugin_dir);
352 test_find(plugin_dir);
353 ret = exit_status();
354 end:
355 return ret;
356 }
This page took 0.035582 seconds and 4 git commands to generate.