1 : /*
2 : * This file is part of MIN Test Framework. Copyright © 2008 Nokia Corporation
3 : * and/or its subsidiary(-ies).
4 : * Contact: Sampo Saaristo
5 : * Contact e-mail: DG.MIN-Support@nokia.com
6 : *
7 : * This program is free software: you can redistribute it and/or modify it
8 : * under the terms of the GNU General Public License as published by the Free
9 : * Software Foundation, version 2 of the License.
10 : *
11 : * This program is distributed in the hope that it will be useful, but WITHOUT
12 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 : * more details. You should have received a copy of the GNU General Public
15 : * License along with this program. If not, see
16 : * <http://www.gnu.org/licenses/>.
17 : */
18 :
19 :
20 : /**
21 : * @file tllib.c
22 : * @version 0.1
23 : * @brief This file contains implementation of min test library loader
24 : */
25 :
26 : /* ------------------------------------------------------------------------- */
27 : /* INCLUDE FILES */
28 : #include <stdio.h>
29 : #include <string.h>
30 :
31 : #include <tllib.h>
32 : #include <min_text.h>
33 : #include <min_common.h>
34 : #include <min_logger.h>
35 :
36 : /* ------------------------------------------------------------------------- */
37 : /* EXTERNAL DATA STRUCTURES */
38 : /* None */
39 :
40 : /* ------------------------------------------------------------------------- */
41 : /* EXTERNAL FUNCTION PROTOTYPES */
42 : /* None */
43 :
44 : /* ------------------------------------------------------------------------- */
45 : /* CONSTANTS */
46 : /* None */
47 :
48 : /* ------------------------------------------------------------------------- */
49 : /* MACROS */
50 : /* None */
51 :
52 : /* ------------------------------------------------------------------------- */
53 : /* LOCAL CONSTANTS AND MACROS */
54 : /* None */
55 :
56 : /* ------------------------------------------------------------------------- */
57 : /* MODULE DATA STRUCTURES */
58 : /* None */
59 :
60 : /* ------------------------------------------------------------------------- */
61 : /* LOCAL FUNCTION PROTOTYPES */
62 : /* ------------------------------------------------------------------------- */
63 : /** Loads .so library.
64 : * @param libname[in] the name of the library
65 : * @return pointer to dll handler, or INITPTR in case of failure.
66 : *
67 : * It loads the library. .so extension is added automatically, settings
68 : * system is used to fetch lobrary paths.
69 : */
70 : LOCAL void* tl_load_lib( const char *libname );
71 : /* ------------------------------------------------------------------------- */
72 : /* FORWARD DECLARATIONS */
73 : /* None */
74 :
75 : /* ==================== LOCAL FUNCTIONS ==================================== */
76 : /* ------------------------------------------------------------------------- */
77 : LOCAL void* tl_load_lib( const char *libname )
78 701 : {
79 701 : void *retval = INITPTR;
80 701 : void *shmaddr = INITPTR;
81 701 : void *tmp = INITPTR;
82 701 : char *path = INITPTR;
83 701 : int shmid = 0;
84 701 : int plen = 0;
85 701 : char *c = INITPTR;
86 701 : char *c2 = INITPTR;
87 701 : Text *fullpath = INITPTR;
88 701 : if( libname == INITPTR ) { return retval; }
89 :
90 : /* If path specified try to open. */
91 701 : if(strrchr(libname,'/')!=NULL) {
92 187 : retval = dlopen(libname,RTLD_LOCAL|RTLD_LAZY);
93 187 : if(retval==NULL) {
94 1 : MIN_NOTICE ("Library [%s] not opened because: %s"
95 : ,libname,dlerror());
96 1 : retval = INITPTR;
97 : }
98 187 : return retval;
99 : }
100 :
101 : /* Get paths from settings system. */
102 514 : shmid = sm_create ('a', sizeof (struct logger_settings_t));
103 514 : shmaddr = sm_attach (shmid);
104 514 : tmp = shmaddr + sizeof (struct logger_settings_t);
105 514 : plen = strlen (tmp);
106 514 : path = NEW2 (char, plen + 2);
107 514 : memset (path, 0x0, plen + 2);
108 514 : sm_read (tmp, path, plen);
109 514 : sm_detach (shmaddr);
110 : /* Try each path to load library. */
111 514 : path [plen] = '\0';
112 514 : c = &path[0];
113 514 : c2 = c;
114 514 : fullpath = tx_create ("");
115 : do {
116 514 : c = strchr (c2,':');
117 514 : if( c == NULL) {
118 0 : if (strlen (c2) != 0) { c = &path [plen]; }
119 0 : else { c = INITPTR; break; }
120 514 : } else { *c='\0'; }
121 :
122 514 : if( *(c-1) == '/' ) {
123 0 : tx_c_append(fullpath,c2);
124 0 : tx_c_append(fullpath,libname);
125 0 : if(!strchr(libname,'.')) {tx_c_append(fullpath,".so");}
126 : } else {
127 514 : tx_c_append(fullpath,c2);
128 514 : tx_c_append(fullpath,"/");
129 514 : tx_c_append(fullpath,libname);
130 514 : if(!strchr(libname,'.')) {tx_c_append(fullpath,".so");}
131 : }
132 514 : c=c+1;
133 514 : c2=c;
134 514 : retval = dlopen(tx_share_buf(fullpath),RTLD_LOCAL|RTLD_LAZY);
135 514 : if(retval == NULL) {
136 0 : MIN_NOTICE ("Library [%s] not opened because: %s"
137 : ,tx_share_buf(fullpath),dlerror());
138 0 : tx_c_copy(fullpath,"");
139 0 : retval = INITPTR;
140 : } else {
141 514 : MIN_INFO ("Library [%s] opened"
142 : ,tx_share_buf(fullpath));
143 514 : break;
144 : }
145 0 : } while(c!=INITPTR);
146 514 : tx_destroy(&fullpath);
147 514 : if(retval==INITPTR) {
148 0 : MIN_WARN ("There is no valid library [%s] under paths: [%s]"
149 : ,libname,path);
150 : }
151 514 : DELETE(path);
152 514 : return retval;
153 : }
154 : /* ------------------------------------------------------------------------- */
155 : /* ======================== FUNCTIONS ====================================== */
156 : /* ------------------------------------------------------------------------- */
157 : int tl_open (test_libl_t *tlibl, const char *lib_name)
158 187 : {
159 : void *test_lib;
160 : void(*init_func)();
161 : ptr2internals ty,ve;
162 : ptr2internals2 da,te;
163 187 : ptr2case get_fun = (ptr2case)INITPTR;
164 187 : ptr2run run_fun = (ptr2run)INITPTR;
165 187 : tlibl->get_cases_fun_ = (ptr2case)INITPTR;
166 187 : tlibl->run_case_fun_ = (ptr2run)INITPTR;
167 187 : tlibl->test_library_ = INITPTR;
168 187 : memset(tlibl->type_,'\0',16);
169 187 : tlibl->version_ = -1;
170 187 : memset(tlibl->date_,'\0',12);
171 187 : memset(tlibl->time_,'\0',9);
172 :
173 187 : test_lib = tl_load_lib(lib_name);
174 187 : if (test_lib == INITPTR) { return 1; }
175 :
176 186 : tlibl->test_library_ = test_lib;
177 :
178 : /* Get version and type */
179 186 : ty = (ptr2internals)dlsym(tlibl->test_library_,"get_module_type");
180 186 : if(ty!=NULL) {
181 38 : switch(ty())
182 : {
183 : case 0x1:
184 0 : STRCPY(tlibl->type_,"Hardcoded",9);
185 0 : break;
186 : case 0x2:
187 0 : STRCPY(tlibl->type_,"Normal",6);
188 0 : break;
189 : case 0x3:
190 38 : STRCPY(tlibl->type_,"MINUnit",8);
191 38 : break;
192 : case 0x4:
193 0 : STRCPY(tlibl->type_,"TestClass",9);
194 0 : break;
195 : case 0x5:
196 0 : STRCPY(tlibl->type_,"LuaTestClass",12);
197 0 : break;
198 : default:
199 0 : STRCPY(tlibl->type_,"Unknown",7);
200 : }
201 : } else {
202 148 : STRCPY(tlibl->type_,"Unknown",7);
203 : }
204 186 : ve = (ptr2internals)dlsym(tlibl->test_library_,"get_module_version");
205 186 : if(ve!=NULL) { tlibl->version_=ve(); }
206 186 : da = (ptr2internals2)dlsym(tlibl->test_library_,"get_module_date");
207 186 : if(da!=NULL) { STRCPY(tlibl->date_,da(),11); }
208 148 : else { STRCPY(tlibl->date_,"Unknown",7); }
209 186 : te = (ptr2internals2)dlsym(tlibl->test_library_,"get_module_time");
210 186 : if(te!=NULL) { STRCPY(tlibl->time_,te(),8); }
211 148 : else { STRCPY(tlibl->time_,"Unknown",7); }
212 186 : MIN_INFO ("Module: %s, Version: %d, Build: %s %s"
213 : ,tlibl->type_,tlibl->version_,tlibl->date_,tlibl->time_);
214 :
215 :
216 186 : get_fun = (ptr2case)dlsym (test_lib, "tm_get_test_cases");
217 186 : if (get_fun == NULL) {
218 0 : MIN_ERROR ("get_fun unresolved in Test Library %s: %s",
219 : lib_name, dlerror());
220 0 : return 1;
221 : }
222 :
223 186 : run_fun = (ptr2run)dlsym (test_lib, "tm_run_test_case");
224 186 : if (run_fun == NULL) {
225 0 : MIN_ERROR ("run_fun unresolved in Test Library %s: %s",
226 : lib_name, dlerror());
227 0 : return 1;
228 : }
229 :
230 186 : init_func = (void(*)())dlsym(test_lib, "tm_initialize");
231 186 : if (init_func != NULL) init_func();
232 186 : tlibl->get_cases_fun_ = get_fun;
233 186 : tlibl->run_case_fun_ = run_fun;
234 :
235 186 : STRCPY(tlibl->fname_, lib_name, 255);
236 :
237 186 : return 0;
238 : }
239 : /* ------------------------------------------------------------------------- */
240 : void* tl_open_tc( const char* file )
241 514 : {
242 514 : void* retval = INITPTR;
243 : ptr2internals ty,ve;
244 : ptr2internals2 da,te;
245 514 : int flen = 0;
246 :
247 : char type[16];
248 514 : int version=-1;
249 : char date[12];
250 : char time[9];
251 514 : memset(type,'\0',16);
252 514 : memset(date,'\0',12);
253 514 : memset(time,'\0',9);
254 :
255 : /* error checking */
256 514 : if( file == INITPTR ) { goto EXIT; }
257 514 : flen = strlen(file);
258 514 : if( flen == 0 ) { goto EXIT; }
259 :
260 514 : retval = tl_load_lib(file);
261 514 : if(retval==INITPTR) { return retval; }
262 :
263 : /* Get version and type */
264 514 : ty = (ptr2internals)dlsym(retval,"get_module_type");
265 514 : if(ty!=NULL) {
266 234 : switch(ty())
267 : {
268 : case 0x1:
269 0 : STRCPY(type,"Hardcoded",9);
270 0 : break;
271 : case 0x2:
272 0 : STRCPY(type,"Normal",6);
273 0 : break;
274 : case 0x3:
275 0 : STRCPY(type,"MINUnit",8);
276 0 : break;
277 : case 0x4:
278 234 : STRCPY(type,"TestClass",9);
279 234 : break;
280 : case 0x5:
281 0 : STRCPY(type,"LuaTestClass",12);
282 0 : break;
283 : default:
284 0 : STRCPY(type,"Unknown",7);
285 : }
286 : } else {
287 280 : STRCPY(type,"Unknown",7);
288 : }
289 514 : ve = (ptr2internals)dlsym(retval,"get_module_version");
290 514 : if(ve!=NULL) { version=ve(); }
291 514 : da = (ptr2internals2)dlsym(retval,"get_module_date");
292 514 : if(da!=NULL) { STRCPY(date,da(),11); }
293 280 : else { STRCPY(date,"Unknown",7); }
294 514 : te = (ptr2internals2)dlsym(retval,"get_module_time");
295 514 : if(te!=NULL) { STRCPY(time,te(),8); }
296 280 : else { STRCPY(time,"Unknown",7); }
297 514 : MIN_INFO ("Module: %s, Version: %d, Build: %s %s"
298 : ,type,version,date,time);
299 514 : EXIT:
300 514 : return retval;
301 : }
302 : /* ------------------------------------------------------------------------- */
303 : int tl_close (test_libl_t *tlibl)
304 92 : {
305 92 : if (tlibl == INITPTR || tlibl->test_library_ == INITPTR) {
306 1 : MIN_ERROR ("%s: invalid pointer\n", tl_close);
307 1 : return 1;
308 : }
309 :
310 : void(*close_func)() = (void(*)())dlsym(tlibl->test_library_
311 91 : ,"tm_finalize");
312 91 : if (close_func != NULL) close_func();
313 :
314 :
315 91 : if (dlclose (tlibl->test_library_)) {
316 0 : MIN_ERROR ("%s: error while closing the test library %s\n",
317 : dlerror());
318 0 : return 1;
319 : }
320 :
321 :
322 91 : tlibl->test_library_ = INITPTR;
323 91 : tlibl->get_cases_fun_ = INITPTR;
324 91 : tlibl->run_case_fun_ = INITPTR;
325 :
326 91 : return 0;
327 : }
328 : /* ------------------------------------------------------------------------- */
329 : int tl_is_ok (test_libl_t *tlibl)
330 17 : {
331 17 : if (tlibl == INITPTR) {
332 0 : return 0;
333 : }
334 :
335 17 : if (!tlibl->test_library_ ||
336 : tlibl->test_library_ == INITPTR)
337 1 : return 0;
338 :
339 16 : if (!tlibl->get_cases_fun_ ||
340 : tlibl->get_cases_fun_ == INITPTR)
341 0 : return 0;
342 :
343 16 : if (!tlibl->run_case_fun_ ||
344 : tlibl->run_case_fun_ == INITPTR)
345 0 : return 0;
346 :
347 16 : return 1;
348 : }
349 : /* ------------------------------------------------------------------------- */
350 : /* ================= OTHER EXPORTED FUNCTIONS ============================== */
351 : /* None */
352 :
353 : /* ------------------------------------------------------------------------- */
354 : /* ================= TESTS FOR LOCAL FUNCTIONS ============================= */
355 : #ifdef MIN_UNIT_TEST
356 : #include "tllib.tests"
357 : #endif /* MIN_UNIT_TEST */
358 : /* End of file */
|