2a6e7fd87dd49b4844ad30a4326a11e6ee8d23f5
[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 char *ret;
60 char *plugin_file_name;
61
62 if (asprintf(&plugin_file_name, "plugin-%s." G_MODULE_SUFFIX,
63 plugin_name) == -1) {
64 abort();
65 }
66
67 ret = g_build_filename(plugin_dir, plugin_file_name, NULL);
68 free(plugin_file_name);
69
70 return ret;
71 }
72
73 static void test_invalid(const char *plugin_dir)
74 {
75 struct bt_plugin_set *plugin_set;
76
77 diag("invalid plugin test below");
78
79 plugin_set = bt_plugin_create_all_from_file(NON_EXISTING_PATH);
80 ok(!plugin_set, "bt_plugin_create_all_from_file() fails with a non-existing file");
81
82 plugin_set = bt_plugin_create_all_from_file(plugin_dir);
83 ok(!plugin_set, "bt_plugin_create_all_from_file() fails with a directory");
84
85 ok(!bt_plugin_create_all_from_file(NULL),
86 "bt_plugin_create_all_from_file() handles NULL correctly");
87 ok(!bt_plugin_create_all_from_dir(NULL, BT_FALSE),
88 "bt_plugin_create_all_from_dir() handles NULL correctly");
89 ok(!bt_plugin_get_name(NULL),
90 "bt_plugin_get_name() handles NULL correctly");
91 ok(!bt_plugin_get_description(NULL),
92 "bt_plugin_get_description() handles NULL correctly");
93 ok(bt_plugin_get_version(NULL, NULL, NULL, NULL, NULL) !=
94 BT_PLUGIN_STATUS_OK,
95 "bt_plugin_get_version() handles NULL correctly");
96 ok(!bt_plugin_get_author(NULL),
97 "bt_plugin_get_author() handles NULL correctly");
98 ok(!bt_plugin_get_license(NULL),
99 "bt_plugin_get_license() handles NULL correctly");
100 ok(!bt_plugin_get_path(NULL),
101 "bt_plugin_get_path() handles NULL correctly");
102 ok(bt_plugin_get_component_class_count(NULL) < 0,
103 "bt_plugin_get_component_class_count() handles NULL correctly");
104 ok(!bt_plugin_get_component_class_by_index(NULL, 0),
105 "bt_plugin_get_component_class_by_index() handles NULL correctly");
106 ok(!bt_plugin_get_component_class_by_name_and_type(NULL, NULL, 0),
107 "bt_plugin_get_component_class_by_name_and_type() handles NULL correctly");
108 }
109
110 static void test_minimal(const char *plugin_dir)
111 {
112 struct bt_plugin_set *plugin_set;
113 struct bt_plugin *plugin;
114 char *minimal_path = get_test_plugin_path(plugin_dir, "minimal");
115
116 assert(minimal_path);
117 diag("minimal plugin test below");
118
119 reset_test_plugin_env_vars();
120 plugin_set = bt_plugin_create_all_from_file(minimal_path);
121 ok(plugin_set && bt_plugin_set_get_plugin_count(plugin_set) == 1,
122 "bt_plugin_create_all_from_file() succeeds with a valid file");
123 ok(check_env_var("BT_TEST_PLUGIN_INIT_CALLED") == 1,
124 "plugin's initialization function is called during bt_plugin_create_all_from_file()");
125 ok(bt_plugin_set_get_plugin_count(plugin_set) == 1,
126 "bt_plugin_create_all_from_file() returns the expected number of plugins");
127 plugin = bt_plugin_set_get_plugin(plugin_set, 0);
128 ok(strcmp(bt_plugin_get_name(plugin), "test_minimal") == 0,
129 "bt_plugin_get_name() returns the expected name");
130 ok(strcmp(bt_plugin_get_description(plugin),
131 "Minimal Babeltrace plugin with no component classes") == 0,
132 "bt_plugin_get_description() returns the expected description");
133 ok(bt_plugin_get_version(plugin, NULL, NULL, NULL, NULL) !=
134 BT_PLUGIN_STATUS_OK,
135 "bt_plugin_get_version() fails when there's no version");
136 ok(strcmp(bt_plugin_get_author(plugin), "Janine Sutto") == 0,
137 "bt_plugin_get_author() returns the expected author");
138 ok(strcmp(bt_plugin_get_license(plugin), "Beerware") == 0,
139 "bt_plugin_get_license() returns the expected license");
140 ok(strcmp(bt_plugin_get_path(plugin), minimal_path) == 0,
141 "bt_plugin_get_path() returns the expected path");
142 ok(bt_plugin_get_component_class_count(plugin) == 0,
143 "bt_plugin_get_component_class_count() returns the expected value");
144 bt_put(plugin);
145 bt_put(plugin_set);
146 ok(check_env_var("BT_TEST_PLUGIN_EXIT_CALLED") == 1,
147 "plugin's exit function is called when the plugin is destroyed");
148
149 free(minimal_path);
150 }
151
152 static void test_sfs(const char *plugin_dir)
153 {
154 struct bt_plugin_set *plugin_set;
155 struct bt_plugin *plugin;
156 struct bt_component_class *sink_comp_class;
157 struct bt_component_class *source_comp_class;
158 struct bt_component_class *filter_comp_class;
159 struct bt_component *sink_component;
160 char *sfs_path = get_test_plugin_path(plugin_dir, "sfs");
161 unsigned int major, minor, patch;
162 const char *extra;
163 struct bt_value *params;
164 struct bt_value *results;
165 struct bt_value *object;
166 struct bt_value *res_params;
167 struct bt_graph *graph;
168 const char *object_str;
169 enum bt_value_status value_ret;
170 enum bt_graph_status graph_ret;
171
172 assert(sfs_path);
173 diag("sfs plugin test below");
174
175 plugin_set = bt_plugin_create_all_from_file(sfs_path);
176 assert(plugin_set && bt_plugin_set_get_plugin_count(plugin_set) == 1);
177 plugin = bt_plugin_set_get_plugin(plugin_set, 0);
178 ok(bt_plugin_get_version(plugin, &major, &minor, &patch, &extra) ==
179 BT_PLUGIN_STATUS_OK,
180 "bt_plugin_get_version() succeeds when there's a version");
181 ok(major == 1,
182 "bt_plugin_get_version() returns the expected major version");
183 ok(minor == 2,
184 "bt_plugin_get_version() returns the expected minor version");
185 ok(patch == 3,
186 "bt_plugin_get_version() returns the expected patch version");
187 ok(strcmp(extra, "yes") == 0,
188 "bt_plugin_get_version() returns the expected extra version");
189 ok(bt_plugin_get_component_class_count(plugin) == 3,
190 "bt_plugin_get_component_class_count() returns the expected value");
191
192 source_comp_class = bt_plugin_get_component_class_by_name_and_type(
193 plugin, "source", BT_COMPONENT_CLASS_TYPE_SOURCE);
194 ok(source_comp_class,
195 "bt_plugin_get_component_class_by_name_and_type() finds a source component class");
196
197 sink_comp_class = bt_plugin_get_component_class_by_name_and_type(
198 plugin, "sink", BT_COMPONENT_CLASS_TYPE_SINK);
199 ok(sink_comp_class,
200 "bt_plugin_get_component_class_by_name_and_type() finds a sink component class");
201 ok(strcmp(bt_component_class_get_help(sink_comp_class),
202 "Bacon ipsum dolor amet strip steak cupim pastrami venison shoulder.\n"
203 "Prosciutto beef ribs flank meatloaf pancetta brisket kielbasa drumstick\n"
204 "venison tenderloin cow tail. Beef short loin shoulder meatball, sirloin\n"
205 "ground round brisket salami cupim pork bresaola turkey bacon boudin.\n") == 0,
206 "bt_component_class_get_help() returns the expected help text");
207
208 filter_comp_class = bt_plugin_get_component_class_by_name_and_type(
209 plugin, "filter", BT_COMPONENT_CLASS_TYPE_FILTER);
210 ok(filter_comp_class,
211 "bt_plugin_get_component_class_by_name_and_type() finds a filter component class");
212 ok(!bt_plugin_get_component_class_by_name_and_type(plugin, "filter",
213 BT_COMPONENT_CLASS_TYPE_SOURCE),
214 "bt_plugin_get_component_class_by_name_and_type() does not find a component class given the wrong type");
215 params = bt_value_integer_create_init(23);
216 assert(params);
217 ok (!bt_component_class_query(NULL, "get-something", params),
218 "bt_component_class_query() handles NULL (component class)");
219 ok (!bt_component_class_query(filter_comp_class, NULL, params),
220 "bt_component_class_query() handles NULL (object)");
221 ok (!bt_component_class_query(filter_comp_class, "get-something", NULL),
222 "bt_component_class_query() handles NULL (parameters)");
223 results = bt_component_class_query(filter_comp_class,
224 "get-something", params);
225 ok(results, "bt_component_class_query() succeeds");
226 assert(bt_value_is_array(results) && bt_value_array_size(results) == 2);
227 object = bt_value_array_get(results, 0);
228 assert(object && bt_value_is_string(object));
229 value_ret = bt_value_string_get(object, &object_str);
230 assert(value_ret == BT_VALUE_STATUS_OK);
231 ok(strcmp(object_str, "get-something") == 0,
232 "bt_component_class_query() receives the expected object name");
233 res_params = bt_value_array_get(results, 1);
234 ok(res_params == params,
235 "bt_component_class_query() receives the expected parameters");
236
237 diag("> putting the plugin object here");
238 BT_PUT(plugin);
239 graph = bt_graph_create();
240 assert(graph);
241 graph_ret = bt_graph_add_component(graph, sink_comp_class, "the-sink",
242 NULL, &sink_component);
243 ok(graph_ret == BT_GRAPH_STATUS_OK && sink_component,
244 "bt_graph_add_component() still works after the plugin object is destroyed");
245 BT_PUT(sink_component);
246 BT_PUT(source_comp_class);
247 bt_put(graph);
248 graph = bt_graph_create();
249 assert(graph);
250 graph_ret = bt_graph_add_component(graph, sink_comp_class, "the-sink",
251 NULL, &sink_component);
252 ok(graph_ret == BT_GRAPH_STATUS_OK && sink_component,
253 "bt_graph_add_component() still works after the source component class object is destroyed");
254 BT_PUT(sink_component);
255 BT_PUT(filter_comp_class);
256 bt_put(graph);
257 graph = bt_graph_create();
258 assert(graph);
259 graph_ret = bt_graph_add_component(graph, sink_comp_class, "the-sink",
260 NULL, &sink_component);
261 ok(graph_ret == BT_GRAPH_STATUS_OK && sink_component,
262 "bt_graph_add_component() still works after the filter component class object is destroyed");
263 BT_PUT(sink_comp_class);
264 BT_PUT(sink_component);
265
266 free(sfs_path);
267 bt_put(graph);
268 bt_put(plugin_set);
269 bt_put(object);
270 bt_put(res_params);
271 bt_put(results);
272 bt_put(params);
273 }
274
275 static void test_create_all_from_dir(const char *plugin_dir)
276 {
277 struct bt_plugin_set *plugin_set;
278
279 diag("create from all test below");
280
281 plugin_set = bt_plugin_create_all_from_dir(NON_EXISTING_PATH, BT_FALSE);
282 ok(!plugin_set,
283 "bt_plugin_create_all_from_dir() fails with an invalid path");
284
285 plugin_set = bt_plugin_create_all_from_dir(plugin_dir, BT_FALSE);
286 ok(plugin_set, "bt_plugin_create_all_from_dir() succeeds with a valid path");
287
288 /* 2 or 4, if `.la` files are considered or not */
289 ok(bt_plugin_set_get_plugin_count(plugin_set) == 2 ||
290 bt_plugin_set_get_plugin_count(plugin_set) == 4,
291 "bt_plugin_create_all_from_dir() returns the expected number of plugin objects");
292
293 bt_put(plugin_set);
294 }
295
296 static void test_find(const char *plugin_dir)
297 {
298 int ret;
299 struct bt_plugin *plugin;
300 struct bt_component_class *comp_cls_sink;
301 struct bt_component_class *comp_cls_source;
302 char *plugin_path;
303
304 ok(!bt_plugin_find(NULL),
305 "bt_plugin_find() handles NULL");
306 ok(!bt_plugin_find(NON_EXISTING_PATH),
307 "bt_plugin_find() returns NULL with an unknown plugin name");
308 ret = asprintf(&plugin_path, "%s" G_SEARCHPATH_SEPARATOR_S
309 G_DIR_SEPARATOR_S "ec1d09e5-696c-442e-b1c3-f9c6cf7f5958"
310 G_SEARCHPATH_SEPARATOR_S G_SEARCHPATH_SEPARATOR_S
311 G_SEARCHPATH_SEPARATOR_S "%s" G_SEARCHPATH_SEPARATOR_S
312 "8db46494-a398-466a-9649-c765ae077629"
313 G_SEARCHPATH_SEPARATOR_S,
314 NON_EXISTING_PATH, plugin_dir);
315 assert(ret > 0 && plugin_path);
316 g_setenv("BABELTRACE_PLUGIN_PATH", plugin_path, 1);
317 plugin = bt_plugin_find("test_minimal");
318 ok(plugin,
319 "bt_plugin_find() succeeds with a plugin name it can find");
320 ok(strcmp(bt_plugin_get_author(plugin), "Janine Sutto") == 0,
321 "bt_plugin_find() finds the correct plugin for a given name");
322 BT_PUT(plugin);
323 comp_cls_sink = bt_plugin_find_component_class(NULL, "sink",
324 BT_COMPONENT_CLASS_TYPE_SINK);
325 ok(!comp_cls_sink, "bt_plugin_find_component_class() handles NULL (plugin name)");
326 comp_cls_sink = bt_plugin_find_component_class("test_sfs", NULL,
327 BT_COMPONENT_CLASS_TYPE_SINK);
328 ok(!comp_cls_sink, "bt_plugin_find_component_class() handles NULL (component class name)");
329 comp_cls_sink = bt_plugin_find_component_class("test_sfs", "sink2",
330 BT_COMPONENT_CLASS_TYPE_SINK);
331 ok(!comp_cls_sink, "bt_plugin_find_component_class() fails with an unknown component class name");
332 comp_cls_sink = bt_plugin_find_component_class("test_sfs", "sink",
333 BT_COMPONENT_CLASS_TYPE_SINK);
334 ok(comp_cls_sink, "bt_plugin_find_component_class() succeeds with valid parameters");
335 ok(strcmp(bt_component_class_get_name(comp_cls_sink), "sink") == 0,
336 "bt_plugin_find_component_class() returns the appropriate component class (sink)");
337 comp_cls_source = bt_plugin_find_component_class("test_sfs", "source",
338 BT_COMPONENT_CLASS_TYPE_SOURCE);
339 ok(comp_cls_sink, "bt_plugin_find_component_class() succeeds with another component class name (same plugin)");
340 ok(strcmp(bt_component_class_get_name(comp_cls_source), "source") == 0,
341 "bt_plugin_find_component_class() returns the appropriate component class (source)");
342 BT_PUT(comp_cls_sink);
343 BT_PUT(comp_cls_source);
344 free(plugin_path);
345 }
346
347 int main(int argc, char **argv)
348 {
349 int ret;
350 const char *plugin_dir;
351
352 if (argc != 2) {
353 puts("Usage: test_plugin plugin_directory");
354 ret = 1;
355 goto end;
356 }
357
358 plugin_dir = argv[1];
359 plan_tests(NR_TESTS);
360 test_invalid(plugin_dir);
361 test_minimal(plugin_dir);
362 test_sfs(plugin_dir);
363 test_create_all_from_dir(plugin_dir);
364 test_find(plugin_dir);
365 ret = exit_status();
366 end:
367 return ret;
368 }
This page took 0.037986 seconds and 3 git commands to generate.