Ignore EGL warning (Ubuntu).
[scilab.git] / scilab / modules / development_tools / macros / test_run.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) 2007-2008 - INRIA - Pierre MARECHAL
3 // Copyright (C) 2009-2011 - DIGITEO - Michael Baudin
4 // Copyright (C) 2010-2012 - DIGITEO - Antoine ELIAS
5 // Copyright (C) 2011 - DIGITEO - Allan CORNET
6 //
7 // This file must be used under the terms of the CeCILL.
8 // This source file is licensed as described in the file COPYING, which
9 // you should have received as part of this distribution.  The terms
10 // are also available at
11 // http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
12
13 // test_run  --
14 //   Launch unit tests.
15
16 function test_run_result = test_run(varargin)
17     lhs     = argn(1);
18     rhs     = argn(2);
19     test_run_result = %f;
20     // =========================================================================
21     // Print test_run help
22     // =========================================================================
23     if (rhs >= 3) & (~ isempty(grep(varargin(3),"help"))) then
24         example = test_examples();
25         printf("%s\n",example);
26         return;
27     end
28
29     status.detailled_failures     = "";
30     status.testsuites             = [];
31     status.test_count             = 0;
32     status.test_passed_count      = 0;
33     status.test_failed_count      = 0;
34     status.test_skipped_count     = 0;
35     status.totalTime              = 0;
36     status.list                   = [];
37
38     params.longtime               = %f;
39     params.wanted_mode            = "";
40     params.error_output           = "check";
41     params.reference              = "check";
42     params.testTypes              = "all_tests";
43     params.skip_mat               = [];
44     params.tests_mat              = [];
45     params.test_passed_percent    = 0;
46     params.test_failed_percent    = 0;
47     params.test_skipped_percent   = 0;
48     params.full_summary           = %t;
49     params.show_diff              = %f;
50     params.show_error             = %f;
51
52     // =======================================================
53     // Management of the kind of tests to run and the options
54     // =======================================================
55     if rhs >= 3 then
56
57         option_mat = varargin(3);
58         if (check_option(option_mat, "unit_tests") & check_option(option_mat, "nonreg_tests")) | check_option(option_mat, "all_tests") then
59             params.testTypes = "all_tests";
60         elseif check_option(option_mat, "unit_tests") then
61             params.testTypes = "unit_tests";
62         elseif check_option(option_mat, "nonreg_tests") then
63             params.testTypes = "nonreg_tests";
64         end
65
66         option_mat = clean_option(option_mat, "unit_tests");
67         option_mat = clean_option(option_mat, "nonreg_tests");
68         option_mat = clean_option(option_mat, "all_tests");
69
70         // Skip tests
71         params.skip_mat     = assign_option(option_mat, "skip_tests", varargin(2), params.skip_mat);
72         option_mat          = clean_option(option_mat, "skip_tests");
73
74         // Mode
75         params.wanted_mode  = assign_option(option_mat, "mode_nw", "NW", params.wanted_mode);
76         option_mat          = clean_option(option_mat, "mode_nw");
77
78         params.wanted_mode  = assign_option(option_mat, "mode_nwni", "NWNI", params.wanted_mode);
79         option_mat          = clean_option(option_mat, "mode_nwni");
80
81         // Reference
82         params.reference    = assign_option(option_mat, "no_check_ref", "skip", params.reference);
83         option_mat          = clean_option(option_mat, "no_check_ref");
84
85         params.reference    = assign_option(option_mat, "create_ref", "create", params.reference);
86         option_mat          = clean_option(option_mat, "create_ref");
87
88         params.reference    = assign_option(option_mat, "list", "list", params.reference);
89         option_mat          = clean_option(option_mat, "list");
90
91         // Error Output
92         params.error_output = assign_option(option_mat, "no_check_error_output", "skip", params.error_output);
93         option_mat          = clean_option(option_mat, "no_check_error_output");
94
95         // Enable long-time tests
96         params.longtime     = assign_option(option_mat, "disable_lt", %f, params.longtime);
97         option_mat          = clean_option(option_mat, "disable_lt");
98
99         params.longtime     = assign_option(option_mat, "enable_lt", %t, params.longtime);
100         option_mat          = clean_option(option_mat, "enable_lt");
101
102         // Summary display management
103         params.full_summary = assign_option(option_mat, "short_summary", %f, params.full_summary);
104         option_mat          = clean_option(option_mat, "short_summary");
105
106         params.show_diff = assign_option(option_mat, "show_diff", %t, params.show_diff);
107         option_mat          = clean_option(option_mat, "show_diff");
108
109         params.show_error = assign_option(option_mat, "show_error", %t, params.show_error);
110         option_mat          = clean_option(option_mat, "show_error");
111
112         if option_mat <> [] then
113             printf("\nUnrecognized option(s): \n\n");
114             for i=1:size(option_mat, "*")
115                 printf("  - ""%s""\n", option_mat(i));
116             end
117
118             return;
119         end
120
121         if rhs == 4 then
122             params.exportFile = varargin(4);
123             // Doing the XML export, force the display of the error and diff
124             params.show_diff = %t;
125             params.show_error = %t;
126         end
127     end
128
129
130     if params.reference <> "list" & params.full_summary then
131         printf("   TMPDIR = %s\n",TMPDIR);
132         printf("\n");
133     end
134     // =======================================================
135     // Management of the tests to run
136     // =======================================================
137     if (rhs == 0) ..
138         | ((rhs == 1) & (varargin(1)==[])) ..
139         | (((rhs == 2)|(rhs == 3)|(rhs == 4)) & (varargin(1)==[]) & (varargin(2)==[])) then
140
141
142         // No input argument
143         // test_run()
144         // test_run([])
145         // => Launch each test of each module
146
147         module_list = getmodules();
148         module_list = gsort(module_list,"lr","i");
149
150         test_count = size(module_list,"*");
151         for i=1:test_count
152             if params.reference <> "list" then
153                 printf("   %03d/%03d - [%s] : \n\n", i, test_count, module_list(i));
154             end
155
156             params.tests_mat    = [];
157             params.moduleName   =  module_list(i);
158
159             result              = test_module(params);
160
161             if params.reference <> "list" then
162                 status.detailled_failures   = [status.detailled_failures; result.detailled_failures];
163                 status.testsuites(size(status.testsuites,"*")+1) = result.testsuite
164                 status.test_skipped_count   = status.test_skipped_count + result.test_skipped_count;
165
166                 // Do not take in account skipped tests
167                 status.test_count           = status.test_count + result.test_count - status.test_skipped_count;
168                 status.test_passed_count    = status.test_passed_count + result.test_passed_count;
169                 status.test_failed_count    = status.test_failed_count + result.test_failed_count;
170                 status.totalTime            = status.totalTime + result.totalTime;
171                 printf("\n");
172             else
173                 status.test_count           = status.test_count + result.test_count;
174                 status.list                 = [status.list; result.list];
175             end
176         end
177
178     elseif (rhs == 1) ..
179         | ((rhs == 2) & (varargin(2)==[])) ..
180         | ((rhs == 3) & (varargin(2)==[])) ..
181         | ((rhs == 4) & (varargin(2)==[])) ..
182         | ( ~ isempty(params.skip_mat)) then
183
184         // One input argument
185         // test_run(<module_name>)
186         // test_run([<module_name_1>,<module_name_2>])
187         // varargin(1) = [<module_name_1>,<module_name_2>]
188
189         module_mat = varargin(1);
190
191         test_count = size(module_mat,"*");
192         for i = 1:test_count
193             if params.reference <> "list" then
194                 printf("   %03d/%03d - [%s] : \n\n", i, test_count, module_mat(i));
195             end
196
197             params.tests_mat    = [];
198             params.moduleName   =  module_mat(i);
199
200             result              = test_module(params);
201
202             status.test_count   = status.test_count + result.test_count;
203             if params.reference <> "list" then
204                 status.detailled_failures       = [status.detailled_failures; result.detailled_failures];
205                 status.testsuites(size(status.testsuites,"*")+1) = result.testsuite
206
207                 status.test_skipped_count   = status.test_skipped_count + result.test_skipped_count;
208                 status.test_passed_count    = status.test_passed_count + result.test_passed_count;
209                 status.test_failed_count    = status.test_failed_count + result.test_failed_count;
210                 status.totalTime            = status.totalTime + result.totalTime;
211
212                 printf("\n");
213             else
214                 status.test_count           = status.test_count + result.test_count;
215                 status.list                 = [status.list; result.list];
216             end
217         end
218         // Do not take in account skipped tests
219         status.test_count = status.test_count - status.test_skipped_count;
220     elseif or(rhs==[2 3 4]) then
221         // Two input arguments
222         // test_run(<module_name>,<test_name>)
223         // test_run(<module_name>,[<test_name_1>,<test_name_2>] )
224
225         // varargin(1) = <module_name> ==> string 1x1
226         // varargin(2) = <test_name_1> ==> mat nl x nc
227
228         params.tests_mat    = varargin(2);
229         params.moduleName   = varargin(1);
230
231         if ((or(size(params.moduleName) <> [1,1])) & (params.tests_mat <> [])) then
232             example = test_examples();
233             err   = ["" ; msprintf(gettext("%s: Wrong size for input argument."),"test_run") ; "" ; example ];
234             printf("%s\n",err);
235             return;
236         end
237
238         result = test_module(params);
239
240         if params.reference <> "list" then
241             status.totalTime            = result.totalTime;
242             status.detailled_failures   = [status.detailled_failures; result.detailled_failures];
243             status.testsuites(size(status.testsuites,"*")+1) = result.testsuite
244             status.test_skipped_count   = status.test_skipped_count + result.test_skipped_count;
245
246             // Do not take in account skipped tests
247             status.test_count           = status.test_count + result.test_count - status.test_skipped_count;
248             status.test_passed_count    = status.test_passed_count + result.test_passed_count;
249             status.test_failed_count    = status.test_failed_count + result.test_failed_count;
250         else
251             status.test_count           = status.test_count + result.test_count;
252             status.list                 = [status.list; result.list];
253         end
254     else
255         error(msprintf(gettext("%s: Wrong number of input arguments."),"test_run"));
256     end
257
258     if params.reference == "list" then
259         test_count = size(status.list, "r");
260         for i=1:test_count
261             printf("   %4.d - [%s] %s\n", i, status.list(i, 1), status.list(i,2));
262         end
263         return;
264     end
265
266     // percent computation
267     if status.test_count <> 0 then
268         test_passed_percent  = status.test_passed_count  / status.test_count * 100;
269         test_failed_percent  = status.test_failed_count  / status.test_count * 100;
270     else
271         test_passed_percent  = 0;
272         test_failed_percent  = 0;
273     end
274
275     if isfield(params, "exportFile") then
276         exportToXUnitFormat(params.exportFile, status.testsuites);
277     end
278
279     if params.full_summary then
280         printf("\n");
281         printf("   --------------------------------------------------------------------------\n");
282         printf("   Summary\n\n");
283         printf("   tests           %4d - 100 %%\n", status.test_count);
284         printf("   passed          %4d - %3d %%\n", status.test_passed_count, test_passed_percent);
285         printf("   failed          %4d - %3d %%\n", status.test_failed_count, test_failed_percent);
286         printf("   skipped         %4d\n", status.test_skipped_count);
287         printf("   length             %4.2f sec\n", status.totalTime);
288         printf("   --------------------------------------------------------------------------\n");
289
290         if isfield(params, "exportFile") then
291             printf("   Export to          %s\n", params.exportFile);
292             printf("   --------------------------------------------------------------------------\n");
293         end
294
295         if status.test_failed_count > 0 then
296             printf("   Details\n\n");
297             printf("%s\n",status.detailled_failures);
298             printf("\n");
299             printf("   --------------------------------------------------------------------------\n");
300         end
301     else
302         printf("\n");
303         printf("   --------------------------------------------------------------------------\n");
304         printf("   Tests: %4d, ", status.test_count);
305         printf("   Passed: %4d, ", status.test_passed_count);
306         printf("   Failed: %4d, ", status.test_failed_count);
307         printf("   Skipped: %4d\n", status.test_skipped_count);
308         printf("   --------------------------------------------------------------------------\n");
309     end
310
311     //   Returns %t if no error has been detected
312     //   Returns %f if any error has been detected
313     test_run_result = (status.test_failed_count == 0);
314
315 endfunction
316
317
318
319 function status = test_module(_params)
320     name = splitModule(_params.moduleName);
321
322     if with_module(name(1)) then
323         // It's a scilab internal module
324         module.path = pathconvert(SCI + "/modules/" + name(1), %F);
325     elseif or(librarieslist() == "atomslib") & atomsIsLoaded(name(1)) then
326         // It's an ATOMS module
327         module.path = pathconvert(atomsGetLoadedPath(name(1)) , %F, %T);
328     elseif isdir(name(1)) then
329         // It's an external module
330         module.path = pathconvert(name(1), %F);
331     else
332         // It's an error
333         error(sprintf(gettext("%s is not an installed module or toolbox"), name(1)));
334     end
335
336     //get tests from path
337     my_types = ["unit_tests","nonreg_tests"];
338
339     directories = [];
340     for i=1:size(my_types,"*")
341         if (_params.testTypes == "all_tests") | (_params.testTypes == my_types(i)) then
342             directory_path = module.path + "/tests/" + my_types(i);
343             for j=2:size(name,"*")
344                 directory_path = directory_path + filesep() + name(j);
345             end
346
347             if isdir(directory_path) then
348                 directories = [directories;getDirectories(directory_path + filesep())];
349             end
350         end
351     end
352
353     tests = [];
354     if( _params.tests_mat == [])
355         for i=1:size(directories, "*")
356             currentDir = directories(i);
357             tests_mat = gsort(basename(listfiles(currentDir + filesep() + "*.tst")),"lr","i");
358
359             for j = 1:size(tests_mat, "*")
360                 if or(tests_mat(j) == _params.skip_mat) == %f then
361                     tests($+1, [1,2]) = [currentDir, tests_mat(j)];
362                 end
363             end
364         end
365     else
366         //not empty tests_mat
367         for i = 1:size(_params.tests_mat, "*")
368             bFind = %f;
369             for j = 1:size(directories, "*")
370                 currentDir = directories(j);
371                 testFile = currentDir + filesep() + _params.tests_mat(i) + ".tst";
372                 if isfile(testFile) then
373                     tests($+1, [1,2]) = [currentDir, _params.tests_mat(i)];
374                     bFind = %t;
375                 end
376             end
377
378             if bFind == %f then
379                 error(sprintf(gettext("The test ""%s"" is not available from the ""%s"" module"), _params.tests_mat(i), name(1)));
380             end
381         end
382     end
383
384     //initialize counter
385     detailled_failures      = "";
386     test_count          = size(tests, "r");
387     test_passed_count   = 0;
388     test_failed_count   = 0;
389     test_skipped_count  = 0;
390
391     moduleName          = _params.moduleName;
392     // Improve the display of the module
393     if isdir(moduleName) then
394         if part(moduleName,1:length(SCI)) == SCI then
395             moduleName = "SCI" + part(moduleName,length(SCI)+1:length(moduleName));
396         elseif part(moduleName,1:length(SCIHOME)) == SCIHOME then
397             moduleName = "SCIHOME" + part(moduleName,length(SCIHOME)+1:length(moduleName));
398         end
399     end
400
401     // For the XML export
402     testsuite.name=moduleName
403     testsuite.time=0
404     testsuite.tests=0
405     testsuite.errors=0
406
407     //don't test only return list of tests.
408     if _params.reference == "list" then
409         for i = 1:test_count
410             if size(name, "*") > 1 then
411                 displayModuleName = sprintf("%s", name(1));
412                 for j=2:size(name, "*")
413                     displayModuleName = displayModuleName + sprintf("|%s", name(j));
414                 end
415             else
416                 displayModuleName = sprintf("%s", name(1));
417             end
418             tests(i,1) = displayModuleName;
419         end
420         status.list         = tests;
421         status.test_count   = test_count;
422         return;
423     end
424
425     tic();
426     for i = 1:test_count
427         printf("   %03d/%03d - ",i, test_count);
428
429         if size(name, "*") > 1 then
430             displayModuleName = sprintf("[%s", name(1));
431             for j=2:size(name, "*")
432                 displayModuleName = displayModuleName + sprintf("|%s", name(j));
433             end
434             displayModuleName = displayModuleName + sprintf("] %s", tests(i,2));
435         else
436             displayModuleName = sprintf("[%s] %s", name(1), tests(i,2));
437         end
438
439         printf("%s", displayModuleName);
440         if length(displayModuleName) >= 50 then
441             printf(" ");
442         end
443         for j = length(displayModuleName):50
444             printf(".");
445         end
446
447         result = test_single(_params, tests(i,1), tests(i,2));
448
449         testsuite.tests = testsuite.tests + 1
450
451         testsuite.testcase(i).name=tests(i,2);
452         //    testsuite.testcase(i).time= DONT HAVE YET
453
454         if result.id == 0 then
455             printf("passed\n");
456             test_passed_count = test_passed_count + 1;
457         else
458             msg = sprintf(result.message);
459             printf("%s \n", msg(1));
460             for kline = 2:size(msg, "*")
461                 printf(part(" ", 1:62) + "%s \n", msg(2));
462             end
463
464             if result.id < 10 then
465                 //failed
466                 test_failed_count = test_failed_count + 1;
467                 detailled_failures = [ detailled_failures ; sprintf("   TEST : [%s] %s", _params.moduleName, tests(i,2))];
468                 detailled_failures = [ detailled_failures ; sprintf("   %s", result.message) ];
469                 detailled_failures = [ detailled_failures ; result.details ];
470                 detailled_failures = [ detailled_failures ; "" ];
471
472                 testsuite.errors = testsuite.errors + 1
473                 testsuite.testcase(i).failure.type=result.message
474                 testsuite.testcase(i).failure.content=result.details
475
476             elseif (result.id >= 10) & (result.id < 20) then
477                 // skipped
478                 test_skipped_count = test_skipped_count + 1;
479             end
480         end
481     end
482
483     status.totalTime = toc();
484
485     testsuite.time=status.totalTime;
486
487     clearglobal TICTOC;
488     status.test_passed_count  = test_passed_count;
489     status.test_failed_count  = test_failed_count;
490     status.test_skipped_count = test_skipped_count;
491
492     // Summary
493     status.test_count     = test_count;
494     status.detailled_failures   = detailled_failures;
495     status.testsuite   = testsuite;
496 endfunction
497
498 function status = test_single(_module, _testPath, _testName)
499     //option flag
500
501     skip          = %F;
502     interactive   = %F;
503     notyetfixed   = %F;
504     longtime      = %F;
505     reopened      = %F;
506     jvm           = %T;
507     graphic       = %F;
508     mpi           = %F;
509     execMode      = "";
510     platform      = "all";
511     language      = "any";
512     try_catch     = %T;
513     error_output  = "check";
514     reference     = "check";
515     xcosNeeded    = %F;
516
517     //some paths
518     tmp_tst     = pathconvert( TMPDIR + "/" + _testName + ".tst", %F);
519     tmp_dia     = pathconvert( TMPDIR + "/" + _testName + ".dia.tmp", %F);
520     tmp_res     = pathconvert( TMPDIR + "/" + _testName + ".res", %F);
521     tmp_err     = pathconvert( TMPDIR + "/" + _testName + ".err", %F);
522     path_dia    = pathconvert( TMPDIR + "/" + _testName + ".dia", %F);
523
524     path_dia_ref  = _testPath + _testName + ".dia.ref";
525     // Reference file management OS by OS
526     if getos() == "Windows" then
527         [branch info] = getversion();
528         if info(2) == "x86" then // Look for a 32bits-specific reference file
529             altreffile  = [ _testPath + _testName + ".win.dia.ref" ; _testPath + _testName + ".win32.dia.ref" ];
530         else
531             altreffile  = [ _testPath + _testName + ".win.dia.ref" ];
532         end
533     elseif getos() == "Darwin" then
534         altreffile  = [ _testPath + _testName + ".unix.dia.ref" ; _testPath + _testName + ".macosx.dia.ref" ];
535     elseif getos() == "Linux" then
536         [branch info] = getversion();
537         if info(2) == "x86" then // Look for a 32bits-specific reference file
538             altreffile  = [ _testPath + _testName + ".unix.dia.ref" ; _testPath + _testName + ".linux.dia.ref" ; _testPath + _testName + ".linux32.dia.ref" ];
539         else
540             altreffile  = [ _testPath + _testName + ".unix.dia.ref" ; _testPath + _testName + ".linux.dia.ref" ];
541         end
542     else
543         altreffile  = [ _testPath + _testName + ".unix.dia.ref" ];
544     end
545
546     for i=1:size(altreffile,"*")
547         if isfile(altreffile(i)) then
548             path_dia_ref = altreffile(i);
549         end
550     end
551
552     //output structure
553     status.id = 0;
554     status.message = "";
555     status.details = "";
556
557     //Reset standard globals
558     rand("seed",0);
559     rand("uniform");
560
561     //load file
562     testFile = _testPath + _testName + ".tst";
563     sciFile = mgetl(testFile);
564
565     //read options
566     if ~isempty(grep(sciFile, "<-- NOT FIXED -->")) then
567         status.id = 10;
568         status.message = "skipped: not yet fixed";
569         return;
570     end
571
572     if ~isempty(grep(sciFile, "<-- REOPENED -->")) then
573         status.id = 10;
574         status.message = "skipped: Bug reopened";
575         return;
576     end
577
578     // platform
579     if ~isempty(grep(sciFile, "<-- WINDOWS ONLY -->")) & getos() <> "Windows" then
580         status.id = 10;
581         status.message = "skipped: Windows only";
582         return;
583     end
584
585     if ~isempty(grep(sciFile, "<-- UNIX ONLY -->")) & getos() == "Windows" then
586         status.id = 10;
587         status.message = "skipped: Unix only";
588         return;
589     end
590
591     if ~isempty(grep(sciFile, "<-- LINUX ONLY -->")) & getos() <> "Linux" then
592         status.id = 10;
593         status.message = "skipped: Linux only";
594         return;
595     end
596
597     if ~isempty(grep(sciFile, "<-- MACOSX ONLY -->")) & getos() <> "Darwin" then
598         status.id = 10;
599         status.message = "skipped: MacOSX only";
600         return;
601     end
602
603     // Test execution
604     if ~isempty(grep(sciFile, "<-- INTERACTIVE TEST -->")) then
605         status.id = 10;
606         status.message = "skipped: interactive test";
607         return;
608     end
609
610     if ~isempty(grep(sciFile, "<-- LONG TIME EXECUTION -->")) & ~_module.longtime then
611         status.id = 10;
612         status.message = "skipped: Long time duration";
613         return;
614     end
615
616     if ~isempty(grep(sciFile, "<-- TEST WITH GRAPHIC -->")) then
617         if _module.wanted_mode == "NWNI" then
618             status.id = 10;
619             status.message = "skipped: Test with graphic";
620             return;
621         end
622
623         graphic = %T;
624         jvm = %T;
625         execMode = "NW";
626     end
627
628     if (~isempty(grep(sciFile, "<-- JVM NOT MANDATORY -->")) | ~isempty(grep(sciFile, "<-- CLI SHELL MODE -->"))) then
629         jvm = %F;
630         execMode = "NWNI";
631     end
632
633     MPITestPos=grep(sciFile, "<-- MPI TEST")
634     if ~isempty(MPITestPos) then
635         mpi_node=msscanf(sciFile(MPITestPos), "// <-- MPI TEST %d -->")
636         if mpi_node == [] then
637             // No node found ? No worries, default to 2
638             mpi_node = 2
639         end
640         mpi = %t;
641         execMode = "NWNI";
642         reference = "skip";
643     end
644     clear MPITestPos
645
646     if ~isempty(grep(sciFile, "<-- XCOS TEST -->")) then
647         if _module.wanted_mode == "NWNI" then
648             status.id = 10;
649             status.message = "skipped: Test with xcos";
650             return;
651         end
652         xcosNeeded = %T;
653         jvm = %T;
654     end
655
656     // Language
657     if ~isempty(grep(sciFile, "<-- FRENCH IMPOSED -->")) then
658         language = "fr_FR";
659     end
660
661
662     if ~isempty(grep(sciFile, "<-- ENGLISH IMPOSED -->")) then
663         language = "en_US";
664     end
665
666     // Test building
667     if ~isempty(grep(sciFile, "<-- NO TRY CATCH -->")) then
668         try_catch = %F;
669     end
670
671     // Test result
672     if ~isempty(grep(sciFile, "<-- NO CHECK ERROR OUTPUT -->")) then
673         error_output = "skip";
674     end
675
676     if ~isempty(grep(sciFile, "<-- NO CHECK REF -->")) then
677         reference = "skip";
678     end
679
680     //build real test file
681
682     // Do some modification in tst file
683     //replace "pause,end" by "bugmes();quit;end"
684     sciFile = strsubst(sciFile, "pause,end", "bugmes();quit;end");
685     sciFile = strsubst(sciFile, "pause, end", "bugmes();quit;end");
686     sciFile = strsubst(sciFile, "pause;end", "bugmes();quit;end");
687     sciFile = strsubst(sciFile, "pause; end", "bugmes();quit;end");
688
689     //to avoid suppression of input --> with prompts
690     sciFile = strsubst(sciFile, "-->", "@#>");
691     //remove halt calls
692     sciFile = strsubst(sciFile, "halt();", "");
693
694     // Build test header
695     head = [
696     "// <-- HEADER START -->";
697     "mode(3);" ;
698     "lines(28,72);";
699     "lines(0);" ;
700     "function %onprompt" ;
701     "   quit;" ;
702     "endfunction" ;
703     "function []=bugmes(), printf(''error on test'');endfunction"
704     "predef(''all'');";
705     "tmpdirToPrint = msprintf(''TMPDIR1=''''%s'''';//\n'',TMPDIR);"
706     ];
707
708     if xcosNeeded then
709         head = [
710         head;
711         "prot=funcprot(); funcprot(0);";
712         "loadXcosLibs(); loadScicos();";
713         "funcprot(prot);";
714         ];
715     end
716
717     if try_catch then
718         head = [ head ; "try" ];
719     end
720
721     head = [
722     head;
723     "diary(''" + tmp_dia + "'');";
724     "printf(''%s\n'',tmpdirToPrint);";
725     "// <-- HEADER END -->"
726     ];
727
728     // Build test footer
729     tail = [ "// <-- FOOTER START -->" ];
730
731     if try_catch then
732         tail = [
733         tail;
734         "catch";
735         "   errmsg = ""<--""+""Error on the test script file""+""-->"";";
736         "   printf(""%s\n"",errmsg);";
737         "   lasterror()";
738         "end";
739         ];
740     end
741
742     tail = [ tail; "diary(0);" ];
743
744     if graphic then
745         tail = [ tail; "xdel(winsid());sleep(1000);" ];
746     end
747
748     tail = [ tail; "exit(0);" ; "// <-- FOOTER END -->" ];
749
750     //Build final test
751     sciFile = [head ; sciFile ; tail];
752
753
754     //Build command to execute
755
756     //scilab path
757     if (getos() <> "Windows") & ~isfile(SCI+"/bin/scilab") then
758         SCI_BIN = strsubst(SCI,"share/scilab","");
759     else
760         SCI_BIN = SCI;
761     end
762
763     //mode
764     if _module.wanted_mode == "NW" then
765         mode_arg = "-nw";
766     elseif _module.wanted_mode == "NWNI" then
767         mode_arg = "-nwni";
768     else
769         if execMode == "NWNI" then
770             mode_arg = "-nwni";
771         elseif execMode == "NW" then
772             mode_arg = "-nw";
773         else
774             mode_arg = "-nw";
775         end
776     end
777
778     if mpi == %t then
779         prefix_bin="mpirun -c " + string(mpi_node) + "  -bynode"
780     else
781         prefix_bin=""
782     end
783
784
785     //language
786     if language == "any" then
787         language_arg = "";
788     elseif getos() == "Windows" then
789         language_arg = "-l "+ language;
790     else
791         language_arg = "LANG=" + language + " ";
792     end
793
794     loader_path = pathconvert(fullfile(_module.moduleName, "loader.sce"), %f);
795
796     // Build final command
797     if getos() == "Windows" then
798         if (isdir(_module.moduleName) & isfile(loader_path)) // external module not in Scilab
799             test_cmd = "( """ + SCI_BIN + "\bin\scilex.exe" + """" + " " + mode_arg + " " + language_arg + " -nb -e ""exec(""""" + loader_path + """"");exec(""""" + tmp_tst + """"");"" > """ + tmp_res + """ ) 2> """ + tmp_err + """";
800         else // standard module
801             test_cmd = "( """ + SCI_BIN + "\bin\scilex.exe" + """" + " " + mode_arg + " " + language_arg + " -nb -f """ + tmp_tst + """ > """ + tmp_res + """ ) 2> """ + tmp_err + """";
802         end
803     else
804         if (isdir(_module.moduleName) & isfile(loader_path))
805             test_cmd = "( " + language_arg + " " + SCI_BIN + "/bin/scilab " + mode_arg + " -nb -e ""exec(''" + loader_path + "'');exec(''" + tmp_tst +"'');""" + " > " + tmp_res + " ) 2> " + tmp_err;
806         else
807             test_cmd = "( " + language_arg + " " + prefix_bin + " " + SCI_BIN + "/bin/scilab " + mode_arg + " -nb -f " + tmp_tst + " > " + tmp_res + " ) 2> " + tmp_err;
808         end
809     end
810
811     //clean previous tmp files
812     if isfile(tmp_tst) then
813         deletefile(tmp_tst);
814     end
815
816     if isfile(tmp_dia) then
817         deletefile(tmp_dia);
818     end
819
820     if isfile(tmp_res) then
821         deletefile(tmp_res);
822     end
823
824     if isfile(tmp_err) then
825         deletefile(tmp_err);
826     end
827
828     //create tmp test file
829     mputl(sciFile, tmp_tst);
830
831     //execute test
832     returnStatus = host(test_cmd);
833     //Check return status
834     if (returnStatus <> 0)
835         status.id = 5;
836         status.message = "failed: Slave Scilab exited with error code " + string(returnStatus);
837         return;
838     end
839
840     //Check errors
841     if (error_output == "check") & (_module.error_output == "check") then
842         if getos() == "Darwin" then
843             tmp_errfile_info = fileinfo(tmp_err);
844             msg = "JavaVM: requested Java version (1.5) not available. Using Java at ""/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home"" instead."
845
846             if ~isempty(tmp_errfile_info) then
847                 txt = mgetl(tmp_err);
848                 txt(txt==msg) = [];
849                 if isempty(txt) then
850                     deletefile(tmp_err);
851                 else // Remove messages due to JOGL2 RC8
852                     toRemove = grep(txt, "__NSAutoreleaseNoPool()");
853                     txt(toRemove) = [];
854                     if isempty(txt) then
855                         deletefile(tmp_err);
856                     end
857                 end
858             end
859         end
860
861         if getos() == "Linux" then // Ignore JOGL2 debug message
862             tmp_errfile_info = fileinfo(tmp_err);
863             msg = "Info: XInitThreads() called for concurrent Thread support"
864
865             if ~isempty(tmp_errfile_info) then
866                 txt = mgetl(tmp_err);
867                 txt(txt==msg) = [];
868                 if isempty(txt) then
869                     deletefile(tmp_err);
870                 else // Remove messages due to warning message from library
871                     toRemove = grep(txt, "libEGL warning: failed to find any driver");
872                     txt(toRemove) = [];
873
874                     if ~isempty(txt) then
875                         toRemove = grep(txt, "extension ""RANDR"" missing on display");
876                         txt(toRemove) = [];
877                     end
878
879                     if isempty(txt) then
880                         deletefile(tmp_err);
881                     end
882                 end
883             end
884         end
885
886         if getos() == "Windows" then // Ignore JOGL 2.1.4 debug message
887             tmp_errfile_info = fileinfo(tmp_err);
888             msg = "Info: GLDrawableHelper.reshape: pre-exisiting GL error 0x500"
889
890             if ~isempty(tmp_errfile_info) then
891                 txt = mgetl(tmp_err);
892                 txt(txt==msg) = [];
893                 if isempty(txt) then
894                     deletefile(tmp_err);
895                 end
896             end
897         end
898
899         tmp_errfile_info = fileinfo(tmp_err);
900
901         if isfile(tmp_err) & tmp_errfile_info(1) <> 0 then
902             status.id = 5;
903             status.message = "failed: error_output not empty\n   Use ''no_check_error_output'' option to disable this check.";
904             status.details = checkthefile(tmp_err);
905             return;
906         end
907     end
908
909     //Process output files
910
911     //Get the dia file
912     if isfile(tmp_dia) then
913         dia = mgetl(tmp_dia);
914     else
915         status.id = 6;
916         status.message = "failed: Cannot find the dia file: " + tmp_dia + "\nCheck if the Scilab used correctly starts";
917         status.details = checkthefile(tmp_dia);
918         return;
919     end
920
921     // To get TMPDIR value
922     tmpdir1_line = grep(dia, "TMPDIR1");
923     execstr(dia(tmpdir1_line));
924
925     //Check for execution errors
926     if try_catch & grep(dia,"<--Error on the test script file-->") <> [] then
927         details = [ checkthefile(tmp_dia); ..
928         launchthecommand(testFile)];
929         status.id = 3;
930         status.message = "failed: premature end of the test script";
931         status.details = details;
932         if params.show_error == %t then
933             status.details = [ status.details; dia($-10:$) ]
934         end
935
936         return;
937     end
938
939     // Remove Header and Footer
940     dia = remove_headers(dia);
941
942     //Check for execution errors
943     dia_tmp = dia;
944
945     // remove commented lines
946     dia_tmp(grep(dia_tmp, "//")) = [];
947
948     if try_catch & grep(dia_tmp, "!--error") <> [] then
949         details = [ checkthefile(tmp_dia); ..
950         launchthecommand(testFile) ];
951         status.id = 1;
952         status.message = "failed: the string (!--error) has been detected";
953         status.details = details;
954         return;
955     end
956
957
958     if grep(dia_tmp,"error on test")<>[] then
959         details = [ checkthefile(tmp_dia); ..
960         launchthecommand(testFile) ];
961         status.id = 2;
962         status.message = "failed: one or several tests failed";
963         status.details = details;
964         if params.show_error == %t then
965             status.details = [ status.details; dia($-min(10, size(dia, "*")-1):$) ]
966         end
967         return;
968     end
969
970
971     if tmpdir1_line == [] then
972         status.id = 6;
973         status.message = "failed: the dia file is not correct";
974         status.details = checkthefile(tmp_dia);
975         return;
976     end
977
978
979     // Check the reference file only if check_ref (i.e. for the whole
980     // test sequence) is true and this_check_ref (i.e. for the specific current .tst)
981     // is true.
982
983     if (reference=="check") & (_module.reference=="check")  then
984         if isfile(path_dia_ref) == %f then
985             status.id = 5;
986             status.message = "failed: the ref file doesn''t exist\n   Use ''no_check_ref'' option to disable this check.";
987             status.details = createthefile(path_dia_ref);
988             return;
989         end
990     end
991
992     // Comparaison ref <--> dia
993
994     if ( (reference=="check") & (_module.reference=="check") ) | (_module.reference=="create") then
995         //  Do some modification in  dia file
996
997         dia(grep(dia, "write(%io(2), tmpdirToPrint")) = [];
998         dia(grep(dia, "TMPDIR1")) = [];
999         dia(grep(dia, "diary(0)")) = [];
1000
1001         if getos() == "Darwin" then // TMPDIR is a symblic link
1002             dia = strsubst(dia,"/private" + TMPDIR1, "TMPDIR");
1003             dia = strsubst(dia,"/private" + TMPDIR, "TMPDIR");
1004         end
1005         dia = strsubst(dia,TMPDIR ,"TMPDIR");
1006         dia = strsubst(dia,TMPDIR1, "TMPDIR");
1007
1008         if getos() == "Windows" then
1009             dia = strsubst(dia, strsubst(TMPDIR, "\","/"), "TMPDIR");
1010             dia = strsubst(dia, strsubst(TMPDIR1, "\","/"), "TMPDIR");
1011             dia = strsubst(dia, strsubst(TMPDIR, "/","\"), "TMPDIR");
1012             dia = strsubst(dia, strsubst(TMPDIR1, "/","\"), "TMPDIR");
1013             dia = strsubst(dia, strsubst(getshortpathname(TMPDIR), "\","/"), "TMPDIR");
1014             dia = strsubst(dia, strsubst(getshortpathname(TMPDIR1), "\","/"), "TMPDIR");
1015             dia = strsubst(dia, getshortpathname(TMPDIR), "TMPDIR");
1016             dia = strsubst(dia, getshortpathname(TMPDIR1), "TMPDIR");
1017         end
1018
1019         dia = strsubst(dia, SCI, "SCI");
1020
1021         if getos() == "Windows" then
1022             dia = strsubst(dia, strsubst(SCI, "\","/"), "SCI");
1023             dia = strsubst(dia, strsubst(SCI, "/","\"), "SCI");
1024             dia = strsubst(dia, strsubst(getshortpathname(SCI), "\","/"), "SCI");
1025             dia = strsubst(dia, getshortpathname(SCI), "SCI");
1026         end
1027
1028         //suppress the prompts
1029         dia = strsubst(dia, "-->", "");
1030         dia = strsubst(dia, "@#>", "-->");
1031         dia = strsubst(dia, "-1->", "");
1032
1033         //standardise  number display
1034
1035         // strsubst(dia, " .", "0.");
1036         // strsubst(dia, "-.", "-0.")
1037         // strsubst(dia, "E+", "D+");
1038         // strsubst(dia, "E-", "D-");
1039
1040         //not to change the ref files
1041         dia = strsubst(dia ,"bugmes();return", "bugmes();quit");
1042
1043         if _module.reference=="create" then
1044             // Delete previous .dia.ref file
1045             if isfile(path_dia_ref) then
1046                 deletefile(path_dia_ref)
1047             end
1048
1049             mputl(dia, path_dia_ref);
1050             status.id = 20;
1051             status.message = "passed: ref created";
1052             return;
1053         else
1054             // write down the resulting dia file
1055             mputl(dia, path_dia);
1056
1057             //Check for diff with the .ref file
1058             [u,ierr] = mopen(path_dia_ref, "r");
1059             if ierr== 0 then //ref file exists
1060                 ref=mgetl(u);
1061                 mclose(u)
1062
1063                 // suppress blank (diff -nw)
1064                 dia = strsubst(dia, " ", "")
1065                 ref = strsubst(ref, " ", "")
1066
1067                 dia(find(dia == "")) = [];
1068                 ref(find(ref == "")) = [];
1069
1070                 dia(find(dia == "")) = [];
1071                 ref(find(ref == "")) = [];
1072
1073                 dia(find(part(dia, (1:2)) == "//")) = [];
1074                 ref(find(part(ref, (1:2)) == "//")) = [];
1075
1076                 if or(ref <> dia) then
1077                     status.id = 4;
1078                     status.message = "failed: dia and ref are not equal";
1079                     status.details = comparethefiles(path_dia, path_dia_ref);
1080                     return;
1081                 end
1082
1083             else
1084                 error(sprintf(gettext("The ref file (%s) doesn''t exist"), path_dia_ref));
1085             end
1086         end
1087     end
1088 endfunction
1089
1090 // checkthefile
1091 function msg = checkthefile( filename )
1092     // Returns a 2-by-1 matrix of strings, containing a message such as:
1093     //   Check the following file :
1094     //   - C:\path\scilab\modules\optimization\tests\unit_testseldermeadeldermead_configure.tst
1095     // Workaround for bug #4827
1096     msg(1) = "   Check the following file :"
1097     msg(2) = "   - "+filename
1098     if params.show_error == %t then
1099         msg=[msg; mgetl(filename)]
1100     end
1101 endfunction
1102
1103 // launchthecommand
1104 function msg = launchthecommand( filename )
1105     // Returns a 2-by-1 matrix of strings, containing a message such as:
1106     //   Or launch the following command :
1107     //   - exec("C:\path\scilab\modules\optimization\tests\unit_testseldermeadeldermead_configure.tst")
1108     // Workaround for bug #4827
1109     msg(1) = "   Or launch the following command :"
1110     msg(2) = "   - exec(""" + fullpath(filename) + """);"
1111 endfunction
1112
1113 // => remove header from the diary txt
1114 function dia_out = remove_headers(dia_in)
1115     dia_out = dia_in;
1116     body_start = grep(dia_out,"// <-- HEADER END -->");
1117     if body_start <> [] then
1118         dia_out(1:body_start(1)) = [];
1119     end
1120
1121     body_end   = grep(dia_out,"// <-- FOOTER START -->");
1122     if body_end <> [] then
1123         [dia_nl,dia_nc] = size(dia);
1124         dia_out(body_end(1):dia_nl) = [];
1125     end
1126 endfunction
1127
1128 //createthefile
1129 function msg = createthefile ( filename )
1130     // Returns a 2-by-1 matrix of strings, containing a message such as:
1131     //   Add or create the following file :
1132     //   - C:\path\scilab\modules\optimization\tests\unit_testseldermeadeldermead_configure.dia.ref
1133     // Workaround for bug #4827
1134     msg(1) = "   Add or create the following file: "
1135     msg(2) = "   - "+filename
1136 endfunction
1137
1138 // comparethefiles
1139 function msg = comparethefiles ( filename1 , filename2 )
1140     // Returns a 3-by-1 matrix of strings, containing a message such as:
1141     //   Compare the following files :
1142     //   - C:\path\scilab\modules\optimization\tests\unit_testseldermeadeldermead_configure.dia
1143     //   - C:\path\scilab\modules\optimization\tests\unit_testseldermeadeldermead_configure.dia.ref
1144     // Workaround for bug #4827
1145     msg(1) = "   Compare the following files:"
1146     msg(2) = "   - "+filename1
1147     msg(3) = "   - "+filename2
1148     if params.show_diff == %t then
1149         if getos() == "Windows" then
1150             diffTool = SCI + "\tools\diff\diff.exe";
1151         else
1152             diffTool = "diff";
1153         end
1154         targetFile=TMPDIR + filesep() + "tempdiff.diff";
1155         unix(diffTool + " -u " + filename1 + " " + filename2 + " > " + targetFile);
1156         // unix_g is failing to return the output into a variable
1157         msg=[msg; mgetl(targetFile)]
1158         deletefile(targetFile);
1159     end
1160 endfunction
1161
1162 function directories = getDirectories(directory)
1163     directories = directory;
1164     items = gsort(listfiles(directory),"lr","i");
1165
1166     for i=1:size(items,"*")
1167         if isdir(directory + items(i)) then
1168             directories = [directories; getDirectories(directory + items(i) + filesep())];
1169         end
1170     end
1171 endfunction
1172
1173 function name = splitModule(name)
1174     if ~isempty( regexp(stripblanks(name),"/\|/") ) then
1175         name = stripblanks( strsubst( strsplit(name,regexp(stripblanks(name),"/\|/")) , "/\|$/","","r" ) );
1176     end
1177 endfunction
1178
1179 function example = test_examples()
1180     example = [ sprintf("Examples :\n\n") ];
1181     example = [ example ; sprintf("// Launch all tests\n") ];
1182     example = [ example ; sprintf("test_run();\n") ];
1183     example = [ example ; sprintf("test_run([]);\n") ];
1184     example = [ example ; sprintf("test_run([],[]);\n") ];
1185     example = [ example ; "" ];
1186     example = [ example ; sprintf("// Test one or several module\n") ];
1187     example = [ example ; sprintf("test_run(''core'');\n") ];
1188     example = [ example ; sprintf("test_run(''core'',[]);\n") ];
1189     example = [ example ; sprintf("test_run([''core'',''string'']);\n") ];
1190     example = [ example ; "" ];
1191     example = [ example ; sprintf("// Launch one or several test in a specified module\n") ];
1192     example = [ example ; sprintf("test_run(''core'',[''trycatch'',''opcode'']);\n") ];
1193     example = [ example ; "" ];
1194     example = [ example ; sprintf("// With options\n") ];
1195     example = [ example ; sprintf("test_run([],[],''no_check_ref'');\n") ];
1196     example = [ example ; sprintf("test_run([],[],''no_check_error_output'');\n") ];
1197     example = [ example ; sprintf("test_run([],[],''create_ref'');\n") ];
1198     example = [ example ; sprintf("test_run([],[],''list'');\n") ];
1199     example = [ example ; sprintf("test_run([],[],''help'');\n") ];
1200     example = [ example ; sprintf("test_run([],[],[''no_check_ref'',''mode_nw'']);\n") ];
1201     example = [ example ; "" ];
1202 endfunction
1203
1204 function newOption = clean_option(var, option)
1205     newOption = var;
1206     newOption(newOption == option) = [];
1207 endfunction
1208
1209 function result = check_option(var, option)
1210     result = or(var == option);
1211 endfunction
1212
1213 function value = assign_option(var, option, truevalue, falsevalue)
1214     if check_option(var, option) then
1215         value = truevalue;
1216     else
1217         value = falsevalue;
1218     end
1219 endfunction
1220
1221
1222 function exportToXUnitFormat(exportToFile, testsuites)
1223
1224     if isfile(exportToFile) then
1225         // File already existing. Append the results
1226         doc = xmlRead(exportToFile);
1227         appendIntoFile = %t;
1228         node = xmlXPath(doc, "//testsuites");
1229         if node.size == 0 then
1230             error(msprintf(gettext("The file ''%s'' is not following the XUnit XML format. Root tag expected ''testsuites''.\n"),exportToFile))
1231         end
1232     else
1233         doc = xmlDocument(exportToFile);
1234
1235         appendIntoFile = %f;
1236     end
1237     root = xmlElement(doc, "testsuites");
1238
1239     for i=1:size(testsuites, "*") // Export module by module
1240         module = testsuites(i);
1241         testsuite = xmlElement(doc,"testsuite");
1242         testsuite.attributes.name = module.name;
1243
1244         testsuite.attributes.time  = string(module.time);
1245
1246         testsuite.attributes.tests = string(module.tests);
1247         testsuite.attributes.errors = string(module.errors);
1248
1249         for j=1:size(module.testcase,"*") // Export test by test
1250             testsuite.children(j) = xmlElement(doc,"testcase");
1251             unitTest = module.testcase(j);
1252             testsuite.children(j).attributes.name = unitTest.name;
1253
1254             if isfield(unitTest,"failure") & size(unitTest.failure,"*") >= 1 then
1255                 testsuite.children(j).children(1) = xmlElement(doc,"failure");
1256                 testsuite.children(j).children(1).attributes.type = unitTest.failure.type;
1257                 testsuite.children(j).children(1).content = unitTest.failure.content;
1258             end
1259         end
1260
1261         if appendIntoFile then
1262             // We will add the new elements into 'testsuites'
1263             c=node(1).children;
1264             nb=size(c,"*");
1265             c(nb + 1)=testsuite; // Add the new results into the list of results
1266             root.children=c;
1267         else
1268             root.children(i)=testsuite
1269         end
1270     end // list of modules
1271
1272     doc.root=root
1273
1274     xmlWrite(doc);
1275 endfunction