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