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