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