1 | /* module-test.c - test program for GMODULE |
2 | * Copyright (C) 1998 Tim Janik |
3 | * |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public |
6 | * License as published by the Free Software Foundation; either |
7 | * version 2.1 of the License, or (at your option) any later version. |
8 | * |
9 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Lesser General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
16 | */ |
17 | |
18 | /* |
19 | * Modified by the GLib Team and others 1997-2000. See the AUTHORS |
20 | * file for a list of people on the GLib Team. See the ChangeLog |
21 | * files for a list of changes. These files are distributed with |
22 | * GLib at ftp://ftp.gtk.org/pub/gtk/. |
23 | */ |
24 | |
25 | #undef G_DISABLE_ASSERT |
26 | #undef G_LOG_DOMAIN |
27 | |
28 | #include <gmodule.h> |
29 | #include <string.h> |
30 | |
31 | #ifdef _MSC_VER |
32 | # define MODULE_FILENAME_PREFIX "" |
33 | #else |
34 | # define MODULE_FILENAME_PREFIX "lib" |
35 | #endif |
36 | |
37 | gchar* global_state; |
38 | |
39 | G_MODULE_EXPORT void g_clash_func (void); |
40 | |
41 | G_MODULE_EXPORT void |
42 | g_clash_func (void) |
43 | { |
44 | global_state = "global clash" ; |
45 | } |
46 | |
47 | typedef void (*SimpleFunc) (void); |
48 | typedef void (*GModuleFunc) (GModule *); |
49 | |
50 | static gchar **gplugin_a_state; |
51 | static gchar **gplugin_b_state; |
52 | |
53 | static void |
54 | compare (const gchar *desc, const gchar *expected, const gchar *found) |
55 | { |
56 | if (!expected && !found) |
57 | return; |
58 | |
59 | if (expected && found && strcmp (s1: expected, s2: found) == 0) |
60 | return; |
61 | |
62 | g_error ("error: %s state should have been \"%s\", but is \"%s\"" , |
63 | desc, expected ? expected : "NULL" , found ? found : "NULL" ); |
64 | } |
65 | |
66 | static void |
67 | test_states (const gchar *global, const gchar *gplugin_a, |
68 | const gchar *gplugin_b) |
69 | { |
70 | compare (desc: "global" , expected: global, found: global_state); |
71 | compare (desc: "Plugin A" , expected: gplugin_a, found: *gplugin_a_state); |
72 | compare (desc: "Plugin B" , expected: gplugin_b, found: *gplugin_b_state); |
73 | |
74 | global_state = *gplugin_a_state = *gplugin_b_state = NULL; |
75 | } |
76 | |
77 | static SimpleFunc plugin_clash_func = NULL; |
78 | |
79 | int |
80 | main (int argc, |
81 | char **argv) |
82 | { |
83 | GModule *module_self, *module_a, *module_b; |
84 | gchar *plugin_a, *plugin_b; |
85 | SimpleFunc f_a, f_b, f_self; |
86 | GModuleFunc gmod_f; |
87 | |
88 | g_test_init (argc: &argc, argv: &argv, NULL); |
89 | |
90 | if (!g_module_supported ()) |
91 | g_error ("dynamic modules not supported" ); |
92 | |
93 | plugin_a = g_test_build_filename (file_type: G_TEST_BUILT, MODULE_FILENAME_PREFIX "moduletestplugin_a_" MODULE_TYPE, NULL); |
94 | plugin_b = g_test_build_filename (file_type: G_TEST_BUILT, MODULE_FILENAME_PREFIX "moduletestplugin_b_" MODULE_TYPE, NULL); |
95 | |
96 | /* module handles */ |
97 | |
98 | module_self = g_module_open (NULL, flags: G_MODULE_BIND_LAZY); |
99 | if (!module_self) |
100 | g_error ("error: %s" , g_module_error ()); |
101 | |
102 | if (!g_module_symbol (module: module_self, symbol_name: "g_module_close" , symbol: (gpointer *) &f_self)) |
103 | g_error ("error: %s" , g_module_error ()); |
104 | |
105 | module_a = g_module_open (file_name: plugin_a, flags: G_MODULE_BIND_LAZY); |
106 | if (!module_a) |
107 | g_error ("error: %s" , g_module_error ()); |
108 | |
109 | module_b = g_module_open (file_name: plugin_b, flags: G_MODULE_BIND_LAZY); |
110 | if (!module_b) |
111 | g_error ("error: %s" , g_module_error ()); |
112 | |
113 | /* get plugin state vars */ |
114 | |
115 | if (!g_module_symbol (module: module_a, symbol_name: "gplugin_a_state" , |
116 | symbol: (gpointer *) &gplugin_a_state)) |
117 | g_error ("error: %s" , g_module_error ()); |
118 | |
119 | if (!g_module_symbol (module: module_b, symbol_name: "gplugin_b_state" , |
120 | symbol: (gpointer *) &gplugin_b_state)) |
121 | g_error ("error: %s" , g_module_error ()); |
122 | test_states (NULL, NULL, gplugin_b: "check-init" ); |
123 | |
124 | /* get plugin specific symbols and call them |
125 | */ |
126 | if (!g_module_symbol (module: module_a, symbol_name: "gplugin_a_func" , symbol: (gpointer *) &f_a)) |
127 | g_error ("error: %s" , g_module_error ()); |
128 | test_states (NULL, NULL, NULL); |
129 | |
130 | if (!g_module_symbol (module: module_b, symbol_name: "gplugin_b_func" , symbol: (gpointer *) &f_b)) |
131 | g_error ("error: %s" , g_module_error ()); |
132 | test_states (NULL, NULL, NULL); |
133 | |
134 | f_a (); |
135 | test_states (NULL, gplugin_a: "Hello world" , NULL); |
136 | |
137 | f_b (); |
138 | test_states (NULL, NULL, gplugin_b: "Hello world" ); |
139 | |
140 | /* get and call globally clashing functions |
141 | */ |
142 | |
143 | if (!g_module_symbol (module: module_self, symbol_name: "g_clash_func" , symbol: (gpointer *) &f_self)) |
144 | g_error ("error: %s" , g_module_error ()); |
145 | test_states (NULL, NULL, NULL); |
146 | |
147 | if (!g_module_symbol (module: module_a, symbol_name: "g_clash_func" , symbol: (gpointer *) &f_a)) |
148 | g_error ("error: %s" , g_module_error ()); |
149 | test_states (NULL, NULL, NULL); |
150 | |
151 | if (!g_module_symbol (module: module_b, symbol_name: "g_clash_func" , symbol: (gpointer *) &f_b)) |
152 | g_error ("error: %s" , g_module_error ()); |
153 | test_states (NULL, NULL, NULL); |
154 | |
155 | f_self (); |
156 | test_states (global: "global clash" , NULL, NULL); |
157 | |
158 | f_a (); |
159 | test_states (NULL, gplugin_a: "global clash" , NULL); |
160 | |
161 | f_b (); |
162 | test_states (NULL, NULL, gplugin_b: "global clash" ); |
163 | |
164 | /* get and call clashing plugin functions */ |
165 | |
166 | if (!g_module_symbol (module: module_a, symbol_name: "gplugin_clash_func" , symbol: (gpointer *) &f_a)) |
167 | g_error ("error: %s" , g_module_error ()); |
168 | test_states (NULL, NULL, NULL); |
169 | |
170 | if (!g_module_symbol (module: module_b, symbol_name: "gplugin_clash_func" , symbol: (gpointer *) &f_b)) |
171 | g_error ("error: %s" , g_module_error ()); |
172 | test_states (NULL, NULL, NULL); |
173 | |
174 | plugin_clash_func = f_a; |
175 | plugin_clash_func (); |
176 | test_states (NULL, gplugin_a: "plugin clash" , NULL); |
177 | |
178 | plugin_clash_func = f_b; |
179 | plugin_clash_func (); |
180 | test_states (NULL, NULL, gplugin_b: "plugin clash" ); |
181 | |
182 | /* call gmodule function from A */ |
183 | |
184 | if (!g_module_symbol (module: module_a, symbol_name: "gplugin_a_module_func" , symbol: (gpointer *) &gmod_f)) |
185 | g_error ("error: %s" , g_module_error ()); |
186 | test_states (NULL, NULL, NULL); |
187 | |
188 | gmod_f (module_b); |
189 | test_states (NULL, NULL, gplugin_b: "BOOH" ); |
190 | |
191 | gmod_f (module_a); |
192 | test_states (NULL, gplugin_a: "BOOH" , NULL); |
193 | |
194 | /* unload plugins */ |
195 | |
196 | if (!g_module_close (module: module_a)) |
197 | g_error ("error: %s" , g_module_error ()); |
198 | |
199 | if (!g_module_close (module: module_b)) |
200 | g_error ("error: %s" , g_module_error ()); |
201 | |
202 | g_free (mem: plugin_a); |
203 | g_free (mem: plugin_b); |
204 | g_module_close (module: module_self); |
205 | return 0; |
206 | } |
207 | |