coverage: various bug fixes and simpler usage 97/21597/3
Clément DAVID [Thu, 15 Oct 2020 12:12:04 +0000 (14:12 +0200)]
Change-Id: Idec51de34280de0d3f3fb6124324750f20999384

scilab/CHANGES.md
scilab/modules/coverage/help/en_US/covStart.xml
scilab/modules/coverage/sci_gateway/cpp/sci_covStart.cpp
scilab/modules/coverage/src/cpp/CoverModule.cpp
scilab/modules/coverage/src/cpp/CoverResult.cpp
scilab/modules/coverage/tests/unit_tests/covStart.tst [new file with mode: 0644]

index 891403f..b093213 100644 (file)
@@ -291,6 +291,7 @@ Bug Fixes
 * [#14488](https://bugzilla.scilab.org/14488): The `frameflag=9` and `strf=".9."` values of these `plot2d` options were no longer accepted. Their documentation was ambiguous.
 * [#14718](https://bugzilla.scilab.org/14718): `user` is removed for a while but was still documented.
 * [#14873](https://bugzilla.scilab.org/14873): `setfield` page: The output and the 6.0 history were documented only on the en_US version. The input was wrongly restricted to matrices, while any Scilab object is acceptable. The specific role of `setfield` for mlists was not really described nor illustrated. The example did not include any call to setfield.
+* [#15012](https://bugzilla.scilab.org/15012): `covStart(["isempty" ; "isscalar"])` crashed Scilab. 
 * [#15163](https://bugzilla.scilab.org/15163): `getdate` page: The time referential was obscure: a) UTC for Unix Time Convention vs Coordinated Universal Time. b) unclear influence of the time zone.
 * [#15280](https://bugzilla.scilab.org/15280): `gsort` was unable to sort any hypermatrix along dimensions > "r"|"c".
 * [#15839](https://bugzilla.scilab.org/15839): `gsort`: the only sparse possible input were real or complex vectors, and only with the `g` method.
@@ -300,6 +301,8 @@ Bug Fixes
 * [#16106](https://bugzilla.scilab.org/16106): Xcos sciblk4 user-defined blocks did not handle opar and odstate/oz correctly.
 * [#16122](https://bugzilla.scilab.org/16122): concat polynomials with <> var did not raise an error.
 * [#16151](https://bugzilla.scilab.org/16151): `isequal(1:$, 2:$)` returned `%T`.
+* [#16193](https://bugzilla.scilab.org/16193): `covStart()` clear previous coverage information. `profileEnable()` could be use to append a macro later on. 
+* [#16196](https://bugzilla.scilab.org/16196): `covStart()` help page was incomplete about the API usage. 
 * [#16274](https://bugzilla.scilab.org/16274): assert_checkequal() did not considered equal matching Nan or void elements in (nested) containers.
 * [#16337](https://bugzilla.scilab.org/16337): The 3rd output of `[U,km,ku] = unique(..)` was not implemented.
 * [#16342](https://bugzilla.scilab.org/16342): `strcat()` was much slower in Scilab 6.0.2.
@@ -326,7 +329,7 @@ Bug Fixes
 * [#16465](https://bugzilla.scilab.org/16465): Scinotes OpenRecent menu was not updated when it should.
 * [#16473](https://bugzilla.scilab.org/16473): Deleting rows in a sparse squared the matrix with padding zeros (Scilab 6 regression).
 * [#16474](https://bugzilla.scilab.org/16474): `imult(%z)` crashed Scilab.
-* [#16496](https://bugzilla.scilab.org/16496): The `getdate` page should be rewritten: a) `getdate("s")` does NOT take leap seconds into account. b) `D=getdate(X)` is vectorized, accepts fractional seconds and returns them in [0,1) in D(10) instead of milliseconds. Moreover, the time referential of the result was unclear (time zone, daylight saving offset).
+* [#16496](https://bugzilla.scilab.org/16496): The `getdate` page should be rewritten: a) `getdate("s")` does NOT take leap seconds into account. b) `D=getdate(X)` is vectorized, accepts fractional seconds and returns them in `[0,1)` in D(10) instead of milliseconds. Moreover, the time referential of the result was unclear (time zone, daylight saving offset).
 * [#16512](https://bugzilla.scilab.org/16512): 1 ./ uint8(0) crashes Scilab (idem with int8, uint16, int16, uint32, int32, uint64, int64).
 * [#16517](https://bugzilla.scilab.org/16517): `getdate("s")` truncated the actual time to integer seconds. `getdate(u)(10)` returned fractional seconds instead of milliseconds as `getdate()`.
 * [#16522](https://bugzilla.scilab.org/16522): `bitget(x,pos)` and `bitset(x,pos)` results could be wrong when `pos` is an encoded integer.
index 764224c..bbe2416 100644 (file)
     <refsynopsisdiv>
         <title>Syntax</title>
         <synopsis>
-          covStart(paths
-          covStart(lib)
-          covStart([path ; lib])
           covStart(macro)
-          covStart("all")
+          covStart([dirs names])
+          covStart(lib), covStart("all")
+          counters = covStart(...)
        </synopsis>
     </refsynopsisdiv>
     <refsection>
         <title>Arguments</title>
         <variablelist>
             <varlistentry>
-                <term>paths</term>
+                <term>macro</term>
                 <listitem>
-                    <para>string paths to identify macros</para>
+                    <para>a specific function (as a string name or a function value).</para>
                 </listitem>
             </varlistentry>
             <varlistentry>
-                <term>lib</term>
+                <term>dirs</term>
                 <listitem>
-                    <para>a library or a string which is a library name</para>
+                    <para>a column vector of strings. Directory paths to identify macros. All <literal>.sci</literal> file stored in these directories and loaded within Scilab are instrumented.</para>
                 </listitem>
             </varlistentry>
             <varlistentry>
-                <term>macro</term>
+                <term>names</term>
                 <listitem>
-                    <para>a specific function (as a string name or a function value)</para>
+                    <para>a column vector of strings. Per directory name to display on the HTML output.</para>
                 </listitem>
             </varlistentry>
             <varlistentry>
-                <term>"all"</term>
+                <term>lib</term>
                 <listitem>
-                    <para>special argument to instrument all the loaded macros</para>
+                    <para>a library or a string which is a Scilab library name for instrumenting a Scilab-provided library. Can be <literal>"all"</literal> to instrument all the currently loaded Scilab-provided libraries.</para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>counters</term>
+                <listitem>
+                    <para>Count of all the instrumentation points.</para>
                 </listitem>
             </varlistentry>
         </variablelist>
     <refsection>
         <title>Description</title>
         <para>
-            Instruments the passed arguments to store runtime informations on execution. These informations can be latter exported by calling <literal>covWrite</literal>. To remove any instrumentation data <literal>covStop</literal> can be used.
+            Instruments the passed arguments to store runtime informations on execution. These informations can be latter exported by calling <literal>covWrite</literal> or <literal>profileGetInfo</literal>. To remove any instrumentation data <literal>covStop</literal> can be used.
+        </para>
+        <para>
+            You can either select a single function, user-defined libraries (as macros directories) or Scilab-provided libraries. The <literal>"all"</literal> analysis is useful to have a global overview and later specific informations can be produced for one or a set of identified functions.
         </para>
         <para>
-            You can either select a set of function or all the available one on a specific call. The <literal>"all"</literal> analysis is useful to have a global overview and later specific informations can be produced for one or a set of identified functions.
+            Each time the function is called, it clears the previous instrumented counters. The associated <literal>profileEnable</literal> and <literal>profileDisable</literal> functions could be used to fine-tune your selection without clearing everything.
         </para>
     </refsection>
     <refsection>
@@ -66,6 +74,36 @@ for i=1:1e5; isempty(i); end           // run
 covWrite("html", "TMPDIR/coverage")    // write runtime information to a directory
 covStop();                             // remove any instrumentation
     ]]></programlisting>
+        <programlisting role="example"><![CDATA[
+// load the libraries before instrumeting them
+loadXcosLibs();
+loadScicos();
+
+// Pass [dirs names] to list the libraries and associate names
+covStart(["SCI\modules\xcos\macros"                 "xcos" ; ..
+          "SCI\modules\scicos\macros\scicos_auto"   "scicos_auto" ; ..
+          "SCI\modules\scicos\macros\scicos_scicos" "scicos_scicos" ; ..
+          "SCI\modules\scicos\macros\scicos_utils"  "scicos_utils"]);
+
+// run the bench
+importXcosDiagram("modules\xcos\demos\Cont.Disc-Observer.zcos");
+scicos_simulate(scs_m, list(), "nw");
+
+// write the output
+covWrite("html", "TMPDIR/coverage2");
+covStop();
+    ]]></programlisting>
+        <programlisting role="example"><![CDATA[
+// instrument the Scilab "elementary_functions" library
+covStart("elementary_functions")
+
+// run
+ones(100,200) .\. ones(1000,2000)
+
+// write the output as HTML
+covWrite("html", "TMPDIR/coverage3")
+covStop();
+    ]]></programlisting>
     </refsection>
     <refsection role="see also">
         <title>See also</title>
@@ -76,6 +114,15 @@ covStop();                             // remove any instrumentation
             <member>
                 <link linkend="covWrite">covWrite</link>
             </member>
+            <member>
+                <link linkend="profileGetInfo">profileGetInfo</link>
+            </member>
+            <member>
+                <link linkend="profileEnable">profileEnable</link>
+            </member>
+            <member>
+                <link linkend="profileDisable">profileDisable</link>
+            </member>
         </simplelist>
     </refsection>
 </refentry>
index b3a6af8..71d3332 100644 (file)
@@ -39,13 +39,13 @@ types::Function::ReturnValue sci_covStart(types::typed_list &in, int _iRetCount,
 {
     if (in.size() != 1)
     {
-        Scierror(999, _("%s: Wrong number of input arguments: %d expected.\n"), "covStart" , 1);
+        Scierror(999, _("%s: Wrong number of input arguments: %d expected.\n"), "covStart", 1);
         return types::Function::Error;
     }
 
     if (!in[0]->isMacro() && !in[0]->isMacroFile() && (!in[0]->isString() || (in[0]->getAs<types::String>()->getCols() != 2 && in[0]->getAs<types::String>()->getCols() != 1)))
     {
-        Scierror(999, _("%s: Wrong type for input argument #%d: A two-columns string matrix expected.\n"), "covStart" , 1);
+        Scierror(999, _("%s: Wrong type for input argument #%d: A two-columns string matrix expected.\n"), "covStart", 1);
         return types::Function::Error;
     }
 
@@ -54,7 +54,7 @@ types::Function::ReturnValue sci_covStart(types::typed_list &in, int _iRetCount,
         types::String * strs = in[0]->getAs<types::String>();
         const unsigned int rows = strs->getRows();
 
-        if (strs->getSize() == 2)
+        if (strs->getCols() == 2)
         {
             std::vector<std::pair<std::wstring, std::wstring>> paths_mods;
             paths_mods.reserve(rows);
@@ -91,5 +91,8 @@ types::Function::ReturnValue sci_covStart(types::typed_list &in, int _iRetCount,
         }
     }
 
+    coverage::CoverModule* const instance = coverage::CoverModule::getInstance();
+    out.emplace_back(new types::Double(instance->getCounters().size()));
+
     return types::Function::OK;
 }
index 6e748ec..1bd135a 100644 (file)
@@ -20,6 +20,8 @@
 #include <libxml/xmlreader.h>
 #include <libxml/xpath.h>
 
+#include <algorithm>
+
 #include "CovHTMLCodePrinter.hxx"
 #include "CoverModule.hxx"
 #include "allexp.hxx"
@@ -46,6 +48,18 @@ extern "C"
 #define DEFAULT_FILESPEC L"*"
 #endif
 
+namespace
+{
+std::wstring expandPathVariable(const std::wstring& p )
+{
+
+    wchar_t* localPath = expandPathVariableW((wchar_t*)p.c_str());
+    std::wstring l(localPath);
+    FREE(localPath);
+    return l;
+}
+}
+
 namespace coverage
 {
 
@@ -85,13 +99,53 @@ CoverModule::~CoverModule()
 
 const std::vector<std::pair<std::wstring, std::wstring>> CoverModule::getModule(const std::vector<std::wstring>& moduleNames)
 {
+    if (moduleNames.size() == 0)
+    {
+        // nothing to do, return empty
+        return {};
+    }
+
+    if (std::all_of(moduleNames.begin(), moduleNames.end(),
+                    [](const std::wstring & p)
+{
+    return isdirW(expandPathVariable(p).c_str()) == TRUE;
+    }))
+    {
+        // all the provided modulesNames are directories, name them and remove "\macros"
+        std::vector<std::pair<std::wstring, std::wstring>> paths;
+
+        // remove any potential "\macros" suffix
+        for (const auto& name : moduleNames)
+        {
+            const std::wstring remove(std::wstring(DIR_SEPARATORW) + std::wstring(L"macros"));
+            std::wstring localName;
+            size_t n = name.rfind(remove);
+            if (n > 0)
+            {
+                localName = name.substr(0, n) + name.substr(n + remove.length());
+            }
+            else
+            {
+                localName = name;
+            }
+            n = localName.rfind(DIR_SEPARATORW);
+            if (n > 0)
+            {
+                localName = localName.substr(n + 1, localName.length() - n);
+            }
+
+            paths.emplace_back(expandPathVariable(name), std::move(localName));
+        }
+        return paths;
+    }
+
+    // Look for the names as Scilab-related libraries
     const std::wstring _path = std::wstring(L"SCI") + DIR_SEPARATORW + L"modules" + DIR_SEPARATORW;
-    wchar_t* __path = expandPathVariableW((wchar_t*)_path.c_str());
-    const std::wstring path(__path);
-    FREE(__path);
+    const std::wstring path(expandPathVariable(_path));
 
     if (moduleNames.size() == 1 && moduleNames.back() == L"all")
     {
+        // "all" keyword, parse all the Scilab library files
         int size = -1;
         wchar_t** files = findfilesW(path.c_str(), DEFAULT_FILESPEC, &size, FALSE);
         if (size > 0 && files)
@@ -113,6 +167,7 @@ const std::vector<std::pair<std::wstring, std::wstring>> CoverModule::getModule(
     }
     else
     {
+        // a list of Scilab libraries
         std::vector<std::pair<std::wstring, std::wstring>> paths;
         for (const auto& name : moduleNames)
         {
@@ -126,14 +181,15 @@ void CoverModule::getMacros(const std::vector<std::pair<std::wstring, std::wstri
 {
     for (const auto& p : paths_mods)
     {
-        std::wstring _path = p.first + DIR_SEPARATORW + L"macros";
-        getMacrosFromDir(_path, p.second);
+        getMacrosFromDir(p.first, p.second);
     }
 }
 
 void CoverModule::getMacrosFromDir(const std::wstring& path, const std::wstring& module)
 {
-    std::wstring _path = path + DIR_SEPARATORW + L"lib";
+    const std::wstring resolvedPath(expandPathVariable(path));
+
+    std::wstring _path = resolvedPath + DIR_SEPARATORW + L"lib";
     getMacros(_path, module);
 
     int size = -1;
@@ -157,9 +213,7 @@ void CoverModule::getMacrosFromDir(const std::wstring& path, const std::wstring&
 void CoverModule::getMacros(const std::wstring& path, const std::wstring& module)
 {
     std::unordered_set<std::wstring> _macros;
-    wchar_t* pwstPathLib = expandPathVariableW((wchar_t*)path.c_str());
-    std::wstring libPath(pwstPathLib);
-    FREE(pwstPathLib);
+    std::wstring libPath(expandPathVariable(path));
 
     char* libFile = wide_string_to_UTF8(libPath.c_str());
 
@@ -312,7 +366,9 @@ std::vector<Counter>::const_iterator CoverModule::lower_bound(const std::vector<
     for (auto it = first; it < last; it++)
     {
         if (it->getMacro() == value)
+        {
             return it;
+        }
     }
 
     return last;
@@ -324,7 +380,9 @@ std::vector<Counter>::const_iterator CoverModule::upper_bound(const std::vector<
     for (auto it = lower_bound(first, last, value); it < last; it++)
     {
         if (it->getMacro() != value)
+        {
             return it;
+        }
     }
 
     return last;
index c3f95d9..77d7263 100644 (file)
@@ -556,7 +556,7 @@ std::wstring CoverResult::getStringTime(const uint64_t time) const
     {
         // between 0 and 10^6 ns
         std::wostringstream out;
-        out << ((double)time / 1000.) << L" µs";
+        out << ((double)time / 1000.) << L" &mu;s";
         return out.str();
     }
     else if (time < 1000000000UL)
diff --git a/scilab/modules/coverage/tests/unit_tests/covStart.tst b/scilab/modules/coverage/tests/unit_tests/covStart.tst
new file mode 100644 (file)
index 0000000..7aa1b1e
--- /dev/null
@@ -0,0 +1,27 @@
+// =============================================================================\r
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab\r
+// Copyright (C) 2020 - ESI Group - Clement DAVID\r
+//\r
+//  This file is distributed under the same license as the Scilab package.\r
+// =============================================================================\r
+//\r
+// <-- CLI SHELL MODE -->\r
+// <-- NO CHECK REF -->\r
+//\r
+\r
+// only check API there and ensure there is some instrumentation in progress\r
+\r
+info = covStart("SCI/modules/xcos");\r
+assert_checktrue(info > 0);\r
+\r
+info = covStart(["SCI/modules/xcos/macros" "xcoslib" ; ..\r
+                 "SCI/modules/scicos/macros/scicos_auto" "scicos_autolib" ; ..\r
+                 "SCI/modules/scicos/macros/scicos_scicos" "scicos_scicoslib" ; ..\r
+                 "SCI/modules/scicos/macros/scicos_utils" "scicos_utilslib"]);\r
+assert_checktrue(info > 0);\r
+\r
+info = covStart("elementary_functions");\r
+assert_checktrue(info > 0);\r
+\r
+info = covStart("all");\r
+assert_checktrue(info > 0);\r