0ecca6230627fd051575f8faa8a4dd2a838f9cf6
[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-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   execMode      = "";
509   platform      = "all";
510   language      = "any";
511   try_catch     = %T;
512   error_output  = "check";
513   reference     = "check";
514   xcosNeeded    = %F;
515
516   //some paths
517   tmp_tst     = pathconvert( TMPDIR + "/" + _testName + ".tst", %F);
518   tmp_dia     = pathconvert( TMPDIR + "/" + _testName + ".dia.tmp", %F);
519   tmp_res     = pathconvert( TMPDIR + "/" + _testName + ".res", %F);
520   tmp_err     = pathconvert( TMPDIR + "/" + _testName + ".err", %F);
521   path_dia    = pathconvert( TMPDIR + "/" + _testName + ".dia", %F);
522
523   path_dia_ref  = _testPath + _testName + ".dia.ref";
524 // Reference file management OS by OS
525   if getos() == 'Windows' then
526     altreffile  = [ _testPath + _testName + ".win.dia.ref" ];
527   elseif getos() == 'Darwin' then
528     altreffile  = [ _testPath + _testName + ".unix.dia.ref" ; _testPath + _testName + ".macosx.dia.ref" ];
529   elseif getos() == 'Linux' then
530     altreffile  = [ _testPath + _testName + ".unix.dia.ref" ; _testPath + _testName + ".linux.dia.ref" ];
531   else
532     altreffile  = [ _testPath + _testName + ".unix.dia.ref" ];
533   end
534
535   for i=1:size(altreffile,"*")
536     if isfile(altreffile(i)) then
537       path_dia_ref = altreffile(i);
538     end
539   end
540
541   //output structure
542   status.id = 0;
543   status.message = "";
544   status.details = "";
545
546   //Reset standard globals
547   rand("seed",0);
548   rand("uniform");
549
550   //load file
551   testFile = _testPath + _testName + ".tst";
552   sciFile = mgetl(testFile);
553
554   //read options
555   if ~isempty(grep(sciFile, "<-- NOT FIXED -->")) then
556     status.id = 10;
557     status.message = "skipped: not yet fixed";
558     return;
559   end
560
561   if ~isempty(grep(sciFile, "<-- REOPENED -->")) then
562     status.id = 10;
563     status.message = "skipped: Bug reopened";
564     return;
565   end
566
567 // platform
568   if ~isempty(grep(sciFile, "<-- WINDOWS ONLY -->")) & getos() <> "Windows" then
569     status.id = 10;
570     status.message = "skipped: Windows only";
571     return;
572   end
573
574   if ~isempty(grep(sciFile, "<-- LINUX ONLY -->")) & getos() <> "Linux" then
575     status.id = 10;
576     status.message = "skipped: Linux only";
577     return;
578   end
579
580   if ~isempty(grep(sciFile, "<-- MACOSX ONLY -->")) & getos() <> "Darwin" then
581     status.id = 10;
582     status.message = "skipped: MacOSX only";
583     return;
584   end
585
586 // Test execution
587   if ~isempty(grep(sciFile, "<-- INTERACTIVE TEST -->")) then
588     status.id = 10;
589     status.message = "skipped: interactive test";
590     return;
591   end
592
593   if ~isempty(grep(sciFile, "<-- LONG TIME EXECUTION -->")) & ~_module.longtime then
594     status.id = 10;
595     status.message = "skipped: Long time duration";
596     return;
597   end
598
599   if ~isempty(grep(sciFile, "<-- TEST WITH GRAPHIC -->")) then
600     if _module.wanted_mode == "NWNI" then
601       status.id = 10;
602       status.message = "skipped: Test with graphic";
603       return;
604     end
605
606     graphic = %T;
607     jvm = %T;
608     execMode = "NW";
609   end
610
611   if (~isempty(grep(sciFile, "<-- JVM NOT MANDATORY -->")) | ~isempty(grep(sciFile, "<-- CLI SHELL MODE -->"))) then
612     jvm = %F;
613     execMode = "NWNI";
614   end
615
616   if ~isempty(grep(sciFile, "<-- XCOS TEST -->")) then
617     xcosNeeded = %T;
618     jvm = %T;
619   end
620
621 // Language
622   if ~isempty(grep(sciFile, "<-- FRENCH IMPOSED -->")) then
623     language = "fr_FR";
624   end
625
626
627   if ~isempty(grep(sciFile, "<-- ENGLISH IMPOSED -->")) then
628     language = "en_US";
629   end
630
631 // Test building
632   if ~isempty(grep(sciFile, "<-- NO TRY CATCH -->")) then
633     try_catch = %F;
634   end
635
636 // Test result
637   if ~isempty(grep(sciFile, "<-- NO CHECK ERROR OUTPUT -->")) then
638     error_output = "skip";
639   end
640
641   if ~isempty(grep(sciFile, "<-- NO CHECK REF -->")) then
642     reference = "skip";
643   end
644
645   //build real test file
646
647 // Do some modification in tst file
648 //replace "pause,end" by "bugmes();quit;end"
649 sciFile = strsubst(sciFile, "pause,end", "bugmes();quit;end");
650 sciFile = strsubst(sciFile, "pause, end", "bugmes();quit;end");
651 sciFile = strsubst(sciFile, "pause;end", "bugmes();quit;end");
652 sciFile = strsubst(sciFile, "pause; end", "bugmes();quit;end");
653
654 //to avoid suppression of input --> with prompts
655 sciFile = strsubst(sciFile, "-->", "@#>");
656 //remove halt calls
657 sciFile = strsubst(sciFile, "halt();", "");
658
659 // Build test header
660 head = [
661     "// <-- HEADER START -->";
662     "mode(3);" ;
663     "lines(28,72);";
664     "lines(0);" ;
665     "function %onprompt" ;
666     "   quit;" ;
667     "endfunction" ;
668     "deff(''[]=bugmes()'',''write(%io(2),''''error on test'''')'');";
669     "predef(''all'');";
670     "tmpdirToPrint = msprintf(''TMPDIR1=''''%s''''\n'',TMPDIR);"
671     ];
672
673 if xcosNeeded then
674   head = [
675     head;
676     "prot=funcprot(); funcprot(0);";
677     "loadXcosLibs(); loadScicos();";
678     "funcprot(prot);";
679          ];
680 end
681
682 if try_catch then
683   head = [ head ; "try" ];
684 end
685
686 head = [
687     head;
688     "diary(''" + tmp_dia + "'');";
689     "write(%io(2),tmpdirToPrint);";
690     "// <-- HEADER END -->"
691        ];
692
693 // Build test footer
694 tail = [ "// <-- FOOTER START -->" ];
695
696 if try_catch then
697   tail = [ 
698       tail;
699       "catch";
700       "   errmsg = ""<--""+""Error on the test script file""+""-->"";";
701       "   printf(""%s\n"",errmsg);";
702       "   lasterror()";
703       "end";
704          ];
705 end
706
707 tail = [ tail; "diary(0);" ];
708
709 if graphic then
710   tail = [ tail; "xdel(winsid());sleep(1000);" ];
711 end
712
713 tail = [ tail; "exit(0);" ; "// <-- FOOTER END -->" ];
714
715 //Build final test
716 sciFile = [head ; sciFile ; tail];
717
718
719 //Build command to execute
720
721 //scilab path
722 if (getos() <> 'Windows') & ~isfile(SCI+"/bin/scilab") then
723   SCI_BIN = strsubst(SCI,'share/scilab','');
724 else
725   SCI_BIN = SCI;
726 end
727
728 //mode
729 if _module.wanted_mode == "NW" then
730   mode_arg = "-nw";
731 elseif _module.wanted_mode == "NWNI" then
732   mode_arg = "-nwni";
733 else
734   if execMode == "NWNI" then
735     mode_arg = "-nwni";
736   elseif execMode == "NW" then
737     mode_arg = "-nw";
738   else
739     mode_arg = "-nw";
740   end
741 end
742
743 //language
744 if language == "any" then
745   language_arg = "";
746 elseif getos() == 'Windows' then
747   language_arg = "-l "+ language;
748 else
749   language_arg = "LANG=" + language + " ";
750 end
751
752 loader_path = pathconvert(fullfile(_module.moduleName, 'loader.sce'), %f);
753
754 // Build final command
755 if getos() == 'Windows' then
756   if (isdir(_module.moduleName) & isfile(loader_path)) // external module not in Scilab
757     test_cmd = "( """ + SCI_BIN + "\bin\scilex.exe" + """" + " " + mode_arg + " " + language_arg + " -nb -e ""exec(""""" + loader_path + """"");exec(""""" + tmp_tst + """"");"" > """ + tmp_res + """ ) 2> """ + tmp_err + """";
758   else // standard module
759     test_cmd = "( """ + SCI_BIN + "\bin\scilex.exe" + """" + " " + mode_arg + " " + language_arg + " -nb -f """ + tmp_tst + """ > """ + tmp_res + """ ) 2> """ + tmp_err + """";
760   end
761 else
762   if (isdir(_module.moduleName) & isfile(loader_path))
763     test_cmd = "( " + language_arg + " " + SCI_BIN + "/bin/scilab " + mode_arg + " -nb -e ""exec(''" + loader_path + "'');exec(''" + tmp_tst +"'');""" + " > " + tmp_res + " ) 2> " + tmp_err;
764   else
765     test_cmd = "( " + language_arg + " " + SCI_BIN + "/bin/scilab " + mode_arg + " -nb -f " + tmp_tst + " > " + tmp_res + " ) 2> " + tmp_err;
766   end
767 end
768
769 //clean previous tmp files
770 if isfile(tmp_tst) then
771   deletefile(tmp_tst);
772 end
773
774 if isfile(tmp_dia) then
775   deletefile(tmp_dia);
776 end
777
778 if isfile(tmp_res) then
779   deletefile(tmp_res);
780 end
781
782 if isfile(tmp_err) then
783   deletefile(tmp_err);
784 end
785
786 //create tmp test file
787 mputl(sciFile, tmp_tst);
788
789 //execute test
790 host(test_cmd);
791
792 //Check errors
793 if (error_output == "check") & (_module.error_output == "check") then
794   if getos() == "Darwin" then
795     tmp_errfile_info = fileinfo(tmp_err);
796     msg = "JavaVM: requested Java version (1.5) not available. Using Java at ""/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home"" instead."
797
798     if ~isempty(tmp_errfile_info) then
799       txt = mgetl(tmp_err);
800       txt(txt==msg) = [];
801       if isempty(txt) then
802         deletefile(tmp_err);
803       else // Remove messages due to JOGL2 RC8
804         toRemove = grep(txt, "__NSAutoreleaseNoPool()");
805         txt(toRemove) = [];
806         if isempty(txt) then
807           deletefile(tmp_err);
808         end
809       end
810     end
811   end
812
813   // Ignore JOGL2 debug message
814   if getos() == "Linux" then
815     tmp_errfile_info = fileinfo(tmp_err);
816     msg = "Info: XInitThreads() called for concurrent Thread support"
817
818     if ~isempty(tmp_errfile_info) then
819       txt = mgetl(tmp_err);
820       txt(txt==msg) = [];
821       if isempty(txt) then
822         deletefile(tmp_err);
823       end
824     end
825   end
826
827   tmp_errfile_info = fileinfo(tmp_err);
828
829   if isfile(tmp_err) & tmp_errfile_info(1) <> 0 then
830     status.id = 5;
831     status.message = "failed: error_output not empty\n   Use ''no_check_error_output'' option to disable this check.";
832     status.details = checkthefile(tmp_err);
833     return;
834   end
835 end
836
837 //Process output files
838
839 //Get the dia file
840 if isfile(tmp_dia) then
841   dia = mgetl(tmp_dia);
842 else
843   status.id = 6;
844   status.message = "failed: Cannot find the dia file: " + tmp_dia + "\nCheck if the Scilab used correctly starts";
845   status.details = checkthefile(tmp_dia);
846   return;
847 end
848
849 // To get TMPDIR value
850 tmpdir1_line = grep(dia, "TMPDIR1");
851 execstr(dia(tmpdir1_line));
852
853 //Check for execution errors
854 if try_catch & grep(dia,"<--Error on the test script file-->") <> [] then
855   details = [ checkthefile(tmp_dia); ..
856               launchthecommand(testFile)];
857   status.id = 3;
858   status.message = "failed: premature end of the test script";
859   status.details = details;
860   if params.show_error == %t then
861     status.details = [ status.details; dia($-10:$) ]
862   end
863
864   return;
865 end
866
867 // Remove Header and Footer
868 dia = remove_headers(dia);
869
870 //Check for execution errors
871 dia_tmp = dia;
872
873 // remove commented lines
874 dia_tmp(grep(dia_tmp, "//")) = [];
875
876 if try_catch & grep(dia_tmp, "!--error") <> [] then
877   details = [ checkthefile(tmp_dia); ..
878               launchthecommand(testFile) ];
879   status.id = 1;
880   status.message = "failed: the string (!--error) has been detected";
881   status.details = details;
882   return;
883 end
884
885
886 if grep(dia_tmp,"error on test")<>[] then
887   details = [ checkthefile(tmp_dia); ..
888               launchthecommand(testFile) ];
889   status.id = 2;
890   status.message = "failed: one or several tests failed";
891   status.details = details;
892   if params.show_error == %t then
893     status.details = [ status.details; dia($-min(10, size(dia, "*")-1):$) ]
894   end
895   return;
896 end
897
898
899 if tmpdir1_line == [] then
900   status.id = 6;
901   status.message = "failed: the dia file is not correct";
902   status.details = checkthefile(tmp_dia);
903   return;
904 end
905
906
907 // Check the reference file only if check_ref (i.e. for the whole
908 // test sequence) is true and this_check_ref (i.e. for the specific current .tst)
909 // is true.
910
911 if (reference=="check") & (_module.reference=="check")  then
912   if isfile(path_dia_ref) == %f then
913     status.id = 5;
914     status.message = "failed: the ref file doesn''t exist\n   Use ''no_check_ref'' option to disable this check.";
915     status.details = createthefile(path_dia_ref);
916     return;
917   end
918 end
919
920 // Comparaison ref <--> dia
921
922 if ( (reference=="check") & (_module.reference=="check") ) | (_module.reference=="create") then
923 //  Do some modification in  dia file
924
925   dia(grep(dia, "write(%io(2), tmpdirToPrint")) = [];
926   dia(grep(dia, "TMPDIR1")) = [];
927   dia(grep(dia, "diary(0)")) = [];
928
929   if getos() == "Darwin" then // TMPDIR is a symblic link
930     dia = strsubst(dia,"/private" + TMPDIR1, "TMPDIR");
931     dia = strsubst(dia,"/private" + TMPDIR, "TMPDIR");
932   end
933   dia = strsubst(dia,TMPDIR ,"TMPDIR");
934   dia = strsubst(dia,TMPDIR1, "TMPDIR");
935
936   if getos() == 'Windows' then
937     dia = strsubst(dia, strsubst(TMPDIR, "\","/"), "TMPDIR");
938     dia = strsubst(dia, strsubst(TMPDIR1, "\","/"), "TMPDIR");
939     dia = strsubst(dia, strsubst(TMPDIR, "/","\"), "TMPDIR");
940     dia = strsubst(dia, strsubst(TMPDIR1, "/","\"), "TMPDIR");
941     dia = strsubst(dia, strsubst(getshortpathname(TMPDIR), "\","/"), "TMPDIR");
942     dia = strsubst(dia, strsubst(getshortpathname(TMPDIR1), "\","/"), "TMPDIR");
943     dia = strsubst(dia, getshortpathname(TMPDIR), "TMPDIR");
944     dia = strsubst(dia, getshortpathname(TMPDIR1), "TMPDIR");
945   end
946
947   dia = strsubst(dia, SCI, "SCI");
948
949   if getos() == 'Windows' then
950     dia = strsubst(dia, strsubst(SCI, "\","/"), "SCI");
951     dia = strsubst(dia, strsubst(SCI, "/","\"), "SCI");
952     dia = strsubst(dia, strsubst(getshortpathname(SCI), "\","/"), "SCI");
953     dia = strsubst(dia, getshortpathname(SCI), "SCI");
954   end
955
956   //suppress the prompts
957   dia = strsubst(dia, "-->", "");
958   dia = strsubst(dia, "@#>", "-->");
959   dia = strsubst(dia, "-1->", "");
960
961   //standardise  number display
962
963 // strsubst(dia, " .", "0.");
964 // strsubst(dia, "-.", "-0.")
965 // strsubst(dia, "E+", "D+");
966 // strsubst(dia, "E-", "D-");
967
968   //not to change the ref files
969   dia = strsubst(dia ,"bugmes();return", "bugmes();quit");
970
971   if _module.reference=="create" then
972 // Delete previous .dia.ref file
973     if isfile(path_dia_ref) then
974       deletefile(path_dia_ref)
975     end
976
977     mputl(dia, path_dia_ref);
978     status.id = 20;
979     status.message = "passed: ref created";
980     return;
981   else
982 // write down the resulting dia file
983     mputl(dia, path_dia);
984
985     //Check for diff with the .ref file
986     [u,ierr] = mopen(path_dia_ref, "r");
987     if ierr== 0 then //ref file exists
988       ref=mgetl(u);
989       mclose(u)
990
991 // suppress blank (diff -nw)
992       dia = strsubst(dia, ' ', '')
993       ref = strsubst(ref, ' ', '')
994
995       dia(find(dia == '')) = [];
996       ref(find(ref == '')) = [];
997
998       dia(find(dia == '')) = [];
999       ref(find(ref == '')) = [];
1000
1001       dia(find(part(dia, (1:2)) == "//")) = [];
1002       ref(find(part(ref, (1:2)) == "//")) = [];
1003
1004       if or(ref <> dia) then
1005         status.id = 4;
1006         status.message = "failed: dia and ref are not equal";
1007         status.details = comparethefiles(path_dia, path_dia_ref);
1008         return;
1009       end
1010
1011     else
1012       error(sprintf(gettext("The ref file (%s) doesn''t exist"), path_dia_ref));
1013     end
1014   end
1015 end
1016 endfunction
1017
1018 // checkthefile
1019 function msg = checkthefile( filename )
1020 // Returns a 2-by-1 matrix of strings, containing a message such as:
1021 //   Check the following file :
1022 //   - C:\path\scilab\modules\optimization\tests\unit_testseldermeadeldermead_configure.tst
1023 // Workaround for bug #4827
1024   msg(1) = "   Check the following file :"
1025   msg(2) = "   - "+filename
1026 endfunction
1027
1028 // launchthecommand
1029 function msg = launchthecommand( filename )
1030 // Returns a 2-by-1 matrix of strings, containing a message such as:
1031 //   Or launch the following command :
1032 //   - exec("C:\path\scilab\modules\optimization\tests\unit_testseldermeadeldermead_configure.tst")
1033 // Workaround for bug #4827
1034   msg(1) = "   Or launch the following command :"
1035   msg(2) = "   - exec(""" + fullpath(filename) + """);"
1036 endfunction
1037
1038 // => remove header from the diary txt
1039 function dia_out = remove_headers(dia_in)
1040   dia_out = dia_in;
1041   body_start = grep(dia_out,"// <-- HEADER END -->");
1042   if body_start <> [] then
1043     dia_out(1:body_start(1)) = [];
1044   end
1045
1046   body_end   = grep(dia_out,"// <-- FOOTER START -->");
1047   if body_end <> [] then
1048     [dia_nl,dia_nc] = size(dia);
1049     dia_out(body_end(1):dia_nl) = [];
1050   end
1051 endfunction
1052
1053 //createthefile
1054 function msg = createthefile ( filename )
1055 // Returns a 2-by-1 matrix of strings, containing a message such as:
1056 //   Add or create the following file :
1057 //   - C:\path\scilab\modules\optimization\tests\unit_testseldermeadeldermead_configure.dia.ref
1058 // Workaround for bug #4827
1059   msg(1) = "   Add or create the following file: "
1060   msg(2) = "   - "+filename
1061 endfunction
1062
1063 // comparethefiles
1064 function msg = comparethefiles ( filename1 , filename2 )
1065 // Returns a 3-by-1 matrix of strings, containing a message such as:
1066 //   Compare the following files :
1067 //   - C:\path\scilab\modules\optimization\tests\unit_testseldermeadeldermead_configure.dia
1068 //   - C:\path\scilab\modules\optimization\tests\unit_testseldermeadeldermead_configure.dia.ref
1069 // Workaround for bug #4827
1070   msg(1) = "   Compare the following files:"
1071   msg(2) = "   - "+filename1
1072   msg(3) = "   - "+filename2
1073   if params.show_diff == %t then
1074     if getos() == "Windows" then
1075         diffTool = SCI + "\tools\diff\diff.exe";
1076     else
1077         diffTool = "diff";
1078     end
1079     targetFile=TMPDIR + filesep() + "tempdiff.diff";
1080     unix(diffTool + " -u " + filename1 + " " + filename2 + " > " + targetFile);
1081     // unix_g is failing to return the output into a variable
1082     msg=[msg; mgetl(targetFile)]
1083     deletefile(targetFile);
1084   end
1085 endfunction
1086
1087 function directories = getDirectories(directory)
1088   directories = directory;
1089   items = gsort(listfiles(directory),"lr","i");
1090
1091   for i=1:size(items,"*")
1092     if isdir(directory + items(i)) then
1093       directories = [directories; getDirectories(directory + items(i) + filesep())];
1094     end
1095   end
1096 endfunction
1097
1098 function name = splitModule(name)
1099   if ~isempty( regexp(stripblanks(name),"/\|/") ) then
1100     name = stripblanks( strsubst( strsplit(name,regexp(stripblanks(name),"/\|/")) , "/\|$/","","r" ) );
1101   end
1102 endfunction
1103
1104 function example = test_examples()
1105   example = [ sprintf("Examples :\n\n") ];
1106   example = [ example ; sprintf("// Launch all tests\n") ];
1107   example = [ example ; sprintf("test_run();\n") ];
1108   example = [ example ; sprintf("test_run([]);\n") ];
1109   example = [ example ; sprintf("test_run([],[]);\n") ];
1110   example = [ example ; "" ];
1111   example = [ example ; sprintf("// Test one or several module\n") ];
1112   example = [ example ; sprintf("test_run(''core'');\n") ];
1113   example = [ example ; sprintf("test_run(''core'',[]);\n") ];
1114   example = [ example ; sprintf("test_run([''core'',''string'']);\n") ];
1115   example = [ example ; "" ];
1116   example = [ example ; sprintf("// Launch one or several test in a specified module\n") ];
1117   example = [ example ; sprintf("test_run(''core'',[''trycatch'',''opcode'']);\n") ];
1118   example = [ example ; "" ];
1119   example = [ example ; sprintf("// With options\n") ];
1120   example = [ example ; sprintf("test_run([],[],''no_check_ref'');\n") ];
1121   example = [ example ; sprintf("test_run([],[],''no_check_error_output'');\n") ];
1122   example = [ example ; sprintf("test_run([],[],''create_ref'');\n") ];
1123   example = [ example ; sprintf("test_run([],[],''list'');\n") ];
1124   example = [ example ; sprintf("test_run([],[],''help'');\n") ];
1125   example = [ example ; sprintf("test_run([],[],[''no_check_ref'',''mode_nw'']);\n") ];
1126   example = [ example ; "" ];
1127 endfunction
1128
1129 function newOption = clean_option(var, option)
1130   newOption = var;
1131   newOption(newOption == option) = [];
1132 endfunction
1133
1134 function result = check_option(var, option)
1135   result = or(var == option);
1136 endfunction
1137
1138 function value = assign_option(var, option, truevalue, falsevalue)
1139   if check_option(var, option) then
1140     value = truevalue;
1141   else
1142     value = falsevalue;
1143   end
1144 endfunction
1145
1146
1147 function exportToXUnitFormat(exportToFile, testsuites)
1148
1149   if isfile(exportToFile) then
1150     // File already existing. Append the results
1151     doc = xmlRead(exportToFile);
1152     appendIntoFile = %t;
1153     node = xmlXPath(doc, "//testsuites");
1154     if node.size == 0 then
1155       error(msprintf(gettext("The file ''%s'' is not following the XUnit XML format. Root tag expected ''testsuites''.\n"),exportToFile))
1156       end
1157   else
1158     doc = xmlDocument(exportToFile);
1159
1160     appendIntoFile = %f;
1161   end
1162   root = xmlElement(doc, "testsuites");
1163
1164   for i=1:size(testsuites, "*") // Export module by module
1165     module = testsuites(i);
1166     testsuite = xmlElement(doc,"testsuite");
1167     testsuite.attributes.name = module.name;
1168
1169     testsuite.attributes.time  = string(module.time);
1170
1171     testsuite.attributes.tests = string(module.tests);
1172     testsuite.attributes.errors = string(module.errors);
1173
1174     for j=1:size(module.testcase,"*") // Export test by test
1175       testsuite.children(j) = xmlElement(doc,"testcase");
1176       unitTest = module.testcase(j);
1177       testsuite.children(j).attributes.name = unitTest.name;
1178
1179       if isfield(unitTest,"failure") & size(unitTest.failure,"*") >= 1 then
1180         testsuite.children(j).children(1) = xmlElement(doc,"failure");
1181         testsuite.children(j).children(1).attributes.type = unitTest.failure.type;
1182         testsuite.children(j).children(1).content = unitTest.failure.content;
1183       end
1184     end
1185
1186     if appendIntoFile then
1187       // We will add the new elements into 'testsuites'
1188       c=node(1).children;
1189       nb=size(c,"*");
1190       c(nb + 1)=testsuite; // Add the new results into the list of results
1191       root.children=c;
1192     else
1193       root.children(i)=testsuite
1194     end
1195   end // list of modules
1196
1197   doc.root=root
1198
1199   xmlWrite(doc);
1200 endfunction
1201