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