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