Values API: split into private and public APIs
[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_value_status value_ret;
172 enum bt_graph_status graph_ret;
173 struct bt_query_executor *query_exec = bt_query_executor_create();
174 int ret;
175
176 BT_ASSERT(query_exec);
177 BT_ASSERT(sfs_path);
178 diag("sfs plugin test below");
179
180 plugin_set = bt_plugin_create_all_from_file(sfs_path);
181 BT_ASSERT(plugin_set && bt_plugin_set_get_plugin_count(plugin_set) == 1);
182 plugin = bt_plugin_set_get_plugin(plugin_set, 0);
183 ok(bt_plugin_get_version(plugin, &major, &minor, &patch, &extra) ==
184 BT_PLUGIN_STATUS_OK,
185 "bt_plugin_get_version() succeeds when there's a version");
186 ok(major == 1,
187 "bt_plugin_get_version() returns the expected major version");
188 ok(minor == 2,
189 "bt_plugin_get_version() returns the expected minor version");
190 ok(patch == 3,
191 "bt_plugin_get_version() returns the expected patch version");
192 ok(strcmp(extra, "yes") == 0,
193 "bt_plugin_get_version() returns the expected extra version");
194 ok(bt_plugin_get_component_class_count(plugin) == 3,
195 "bt_plugin_get_component_class_count() returns the expected value");
196
197 source_comp_class = bt_plugin_get_component_class_by_name_and_type(
198 plugin, "source", BT_COMPONENT_CLASS_TYPE_SOURCE);
199 ok(source_comp_class,
200 "bt_plugin_get_component_class_by_name_and_type() finds a source component class");
201
202 sink_comp_class = bt_plugin_get_component_class_by_name_and_type(
203 plugin, "sink", BT_COMPONENT_CLASS_TYPE_SINK);
204 ok(sink_comp_class,
205 "bt_plugin_get_component_class_by_name_and_type() finds a sink component class");
206 ok(strcmp(bt_component_class_get_help(sink_comp_class),
207 "Bacon ipsum dolor amet strip steak cupim pastrami venison shoulder.\n"
208 "Prosciutto beef ribs flank meatloaf pancetta brisket kielbasa drumstick\n"
209 "venison tenderloin cow tail. Beef short loin shoulder meatball, sirloin\n"
210 "ground round brisket salami cupim pork bresaola turkey bacon boudin.\n") == 0,
211 "bt_component_class_get_help() returns the expected help text");
212
213 filter_comp_class = bt_plugin_get_component_class_by_name_and_type(
214 plugin, "filter", BT_COMPONENT_CLASS_TYPE_FILTER);
215 ok(filter_comp_class,
216 "bt_plugin_get_component_class_by_name_and_type() finds a filter component class");
217 ok(!bt_plugin_get_component_class_by_name_and_type(plugin, "filter",
218 BT_COMPONENT_CLASS_TYPE_SOURCE),
219 "bt_plugin_get_component_class_by_name_and_type() does not find a component class given the wrong type");
220 params = bt_private_value_integer_create_init(23);
221 BT_ASSERT(params);
222 ret = bt_query_executor_query(NULL, filter_comp_class, "object",
223 bt_value_borrow_from_private(params), &results);
224 ok (ret, "bt_query_executor_query() handles NULL (query executor)");
225 ret = bt_query_executor_query(query_exec, NULL, "object",
226 bt_value_borrow_from_private(params), &results);
227 ok (ret, "bt_query_executor_query() handles NULL (component class)");
228 ret = bt_query_executor_query(query_exec, filter_comp_class, NULL,
229 bt_value_borrow_from_private(params), &results);
230 ok (ret, "bt_query_executor_query() handles NULL (object)");
231 ret = bt_query_executor_query(query_exec, filter_comp_class,
232 "get-something", bt_value_borrow_from_private(params),
233 &results);
234 ok(ret == 0 && results, "bt_query_executor_query() succeeds");
235 BT_ASSERT(bt_value_is_array(results) && bt_value_array_get_size(results) == 2);
236 object = bt_value_array_borrow_element_by_index(results, 0);
237 BT_ASSERT(object && bt_value_is_string(object));
238 value_ret = bt_value_string_get(object, &object_str);
239 BT_ASSERT(value_ret == BT_VALUE_STATUS_OK);
240 ok(strcmp(object_str, "get-something") == 0,
241 "bt_component_class_query() receives the expected object name");
242 res_params = bt_value_array_borrow_element_by_index(results, 1);
243 ok(res_params == bt_value_borrow_from_private(params),
244 "bt_component_class_query() receives the expected parameters");
245
246 diag("> putting the plugin object here");
247 BT_OBJECT_PUT_REF_AND_RESET(plugin);
248 graph = bt_graph_create();
249 BT_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 plugin object is destroyed");
254 BT_OBJECT_PUT_REF_AND_RESET(sink_component);
255 BT_OBJECT_PUT_REF_AND_RESET(source_comp_class);
256 bt_object_put_ref(graph);
257 graph = bt_graph_create();
258 BT_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 source component class object is destroyed");
263 BT_OBJECT_PUT_REF_AND_RESET(sink_component);
264 BT_OBJECT_PUT_REF_AND_RESET(filter_comp_class);
265 bt_object_put_ref(graph);
266 graph = bt_graph_create();
267 BT_ASSERT(graph);
268 graph_ret = bt_graph_add_component(graph, sink_comp_class, "the-sink",
269 NULL, &sink_component);
270 ok(graph_ret == BT_GRAPH_STATUS_OK && sink_component,
271 "bt_graph_add_component() still works after the filter component class object is destroyed");
272 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
273 BT_OBJECT_PUT_REF_AND_RESET(sink_component);
274
275 free(sfs_path);
276 bt_object_put_ref(graph);
277 bt_object_put_ref(plugin_set);
278 bt_object_put_ref(results);
279 bt_object_put_ref(params);
280 bt_object_put_ref(query_exec);
281 }
282
283 static void test_create_all_from_dir(const char *plugin_dir)
284 {
285 struct bt_plugin_set *plugin_set;
286
287 diag("create from all test below");
288
289 plugin_set = bt_plugin_create_all_from_dir(NON_EXISTING_PATH, BT_FALSE);
290 ok(!plugin_set,
291 "bt_plugin_create_all_from_dir() fails with an invalid path");
292
293 plugin_set = bt_plugin_create_all_from_dir(plugin_dir, BT_FALSE);
294 ok(plugin_set, "bt_plugin_create_all_from_dir() succeeds with a valid path");
295
296 /* 2 or 4, if `.la` files are considered or not */
297 ok(bt_plugin_set_get_plugin_count(plugin_set) == 2 ||
298 bt_plugin_set_get_plugin_count(plugin_set) == 4,
299 "bt_plugin_create_all_from_dir() returns the expected number of plugin objects");
300
301 bt_object_put_ref(plugin_set);
302 }
303
304 static void test_find(const char *plugin_dir)
305 {
306 int ret;
307 struct bt_plugin *plugin;
308 struct bt_component_class *comp_cls_sink;
309 struct bt_component_class *comp_cls_source;
310 char *plugin_path;
311
312 ok(!bt_plugin_find(NULL),
313 "bt_plugin_find() handles NULL");
314 ok(!bt_plugin_find(NON_EXISTING_PATH),
315 "bt_plugin_find() returns NULL with an unknown plugin name");
316 ret = asprintf(&plugin_path, "%s" G_SEARCHPATH_SEPARATOR_S
317 G_DIR_SEPARATOR_S "ec1d09e5-696c-442e-b1c3-f9c6cf7f5958"
318 G_SEARCHPATH_SEPARATOR_S G_SEARCHPATH_SEPARATOR_S
319 G_SEARCHPATH_SEPARATOR_S "%s" G_SEARCHPATH_SEPARATOR_S
320 "8db46494-a398-466a-9649-c765ae077629"
321 G_SEARCHPATH_SEPARATOR_S,
322 NON_EXISTING_PATH, plugin_dir);
323 BT_ASSERT(ret > 0 && plugin_path);
324 g_setenv("BABELTRACE_PLUGIN_PATH", plugin_path, 1);
325 plugin = bt_plugin_find("test_minimal");
326 ok(plugin,
327 "bt_plugin_find() succeeds with a plugin name it can find");
328 ok(strcmp(bt_plugin_get_author(plugin), "Janine Sutto") == 0,
329 "bt_plugin_find() finds the correct plugin for a given name");
330 BT_OBJECT_PUT_REF_AND_RESET(plugin);
331 comp_cls_sink = bt_plugin_find_component_class(NULL, "sink",
332 BT_COMPONENT_CLASS_TYPE_SINK);
333 ok(!comp_cls_sink, "bt_plugin_find_component_class() handles NULL (plugin name)");
334 comp_cls_sink = bt_plugin_find_component_class("test_sfs", NULL,
335 BT_COMPONENT_CLASS_TYPE_SINK);
336 ok(!comp_cls_sink, "bt_plugin_find_component_class() handles NULL (component class name)");
337 comp_cls_sink = bt_plugin_find_component_class("test_sfs", "sink2",
338 BT_COMPONENT_CLASS_TYPE_SINK);
339 ok(!comp_cls_sink, "bt_plugin_find_component_class() fails with an unknown component class name");
340 comp_cls_sink = bt_plugin_find_component_class("test_sfs", "sink",
341 BT_COMPONENT_CLASS_TYPE_SINK);
342 ok(comp_cls_sink, "bt_plugin_find_component_class() succeeds with valid parameters");
343 ok(strcmp(bt_component_class_get_name(comp_cls_sink), "sink") == 0,
344 "bt_plugin_find_component_class() returns the appropriate component class (sink)");
345 comp_cls_source = bt_plugin_find_component_class("test_sfs", "source",
346 BT_COMPONENT_CLASS_TYPE_SOURCE);
347 ok(comp_cls_sink, "bt_plugin_find_component_class() succeeds with another component class name (same plugin)");
348 ok(strcmp(bt_component_class_get_name(comp_cls_source), "source") == 0,
349 "bt_plugin_find_component_class() returns the appropriate component class (source)");
350 BT_OBJECT_PUT_REF_AND_RESET(comp_cls_sink);
351 BT_OBJECT_PUT_REF_AND_RESET(comp_cls_source);
352 free(plugin_path);
353 }
354
355 int main(int argc, char **argv)
356 {
357 int ret;
358 const char *plugin_dir;
359
360 if (argc != 2) {
361 puts("Usage: test_plugin plugin_directory");
362 ret = 1;
363 goto end;
364 }
365
366 plugin_dir = argv[1];
367 plan_tests(NR_TESTS);
368 test_invalid(plugin_dir);
369 test_minimal(plugin_dir);
370 test_sfs(plugin_dir);
371 test_create_all_from_dir(plugin_dir);
372 test_find(plugin_dir);
373 ret = exit_status();
374 end:
375 return ret;
376 }
This page took 0.04191 seconds and 4 git commands to generate.