{"id":3562,"date":"2017-11-21T16:42:01","date_gmt":"2017-11-22T00:42:01","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=3562"},"modified":"2017-11-21T16:45:17","modified_gmt":"2017-11-22T00:45:17","slug":"analyzing-code-coverage-for-linux-test-projects","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/profiler\/linux\/coverage\/","title":{"rendered":"Analyzing Code Coverage for Linux Test Projects"},"content":{"rendered":"<p>This tutorial shows how to use VisualGDB to quickly analyze the code coverage of your Linux Unit Test projects. We will create a basic test project based on the GoogleTest framework and show how to quickly find functions with incomplete coverage. We will also show how to use the call information displayed by VisualGDB to quickly find potential causes for bugs.<\/p>\n<p>Before you begin, install VisualGDB 5.3 or later.<\/p>\n<ol>\n<li>Start Visual Studio and open the VisualGDB Linux Project Wizard:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/01-prj1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3563\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/01-prj1.png\" alt=\"01-prj\" width=\"941\" height=\"653\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/01-prj1.png 941w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/01-prj1-300x208.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/01-prj1-392x272.png 392w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/01-prj1-130x90.png 130w\" sizes=\"(max-width: 941px) 100vw, 941px\" \/><\/a><\/li>\n<li>On the first page of the wizard select &#8220;Unit test project -&gt; Use MSBuild&#8221; and pick your test framework. In this example we will use GoogleTest:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/02-test.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3564\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/02-test.png\" alt=\"02-test\" width=\"822\" height=\"662\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/02-test.png 822w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/02-test-300x242.png 300w\" sizes=\"(max-width: 822px) 100vw, 822px\" \/><\/a><\/li>\n<li>On the next page select the remote computer you want to target. In this tutorial we will build the code directly on Linux and VisualGDB will automatically collect and analyze code coverage reports and transfer them to Windows. Once you have selected the remote computer, click &#8220;Next&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/03-machine.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3565\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/03-machine.png\" alt=\"03-machine\" width=\"773\" height=\"662\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/03-machine.png 773w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/03-machine-300x257.png 300w\" sizes=\"(max-width: 773px) 100vw, 773px\" \/><\/a><\/li>\n<li>Proceed with the default source access settings (upload modified sources via SSH) and click &#8220;Finish&#8221; to create the project:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/04-source.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3566\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/04-source.png\" alt=\"04-source\" width=\"773\" height=\"662\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/04-source.png 773w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/04-source-300x257.png 300w\" sizes=\"(max-width: 773px) 100vw, 773px\" \/><\/a><\/li>\n<li>VisualGDB will create a basic project including 3 unit tests based on the GoogleTest framework. Locate and open the &lt;Project Name&gt;Tests.cpp file that contains the generated tests:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/05-created.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3567\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/05-created.png\" alt=\"05-created\" width=\"1195\" height=\"791\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/05-created.png 1195w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/05-created-300x199.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/05-created-1024x678.png 1024w\" sizes=\"(max-width: 1195px) 100vw, 1195px\" \/><\/a><\/li>\n<li>We will now create a very basic queue class capable of enqueuing and dequeuing elements one-by-one and will then add a unit test validating it. Replace the contents of the &#8220;tests&#8221; file with the following code:\n<pre class=\"\">#include &lt;gtest\/gtest.h&gt;\r\n#include &lt;stdio.h&gt;\r\n#include &lt;memory.h&gt;\r\n\r\ntemplate &lt;class _Element&gt; class Queue\r\n{\r\nprivate:\r\n\u00a0\u00a0\u00a0 _Element *m_pData = nullptr;\r\n\u00a0\u00a0\u00a0 int m_ReadOffset = 0, m_WriteOffset = 0, m_Allocated = 0;\r\n\u00a0\u00a0 \u00a0\r\npublic:\r\n\u00a0\u00a0\u00a0 Queue(int reservedCount = 4)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (reservedCount)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_Allocated = reservedCount;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_pData = (_Element *)malloc(reservedCount * sizeof(_Element));\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 ~Queue()\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (m_pData)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 free(m_pData);\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 int GetCount()\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return m_WriteOffset - m_ReadOffset;\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 void Enqueue(const _Element *pElement)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (GetCount() &gt;= m_Allocated)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_Allocated *= 2;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_pData = (_Element *)realloc(m_pData, m_Allocated * sizeof(_Element));\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (m_ReadOffset)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 int base = m_ReadOffset;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 memmove(m_pData, m_pData + base, (m_Allocated - base) * sizeof(_Element));\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_ReadOffset -= base;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_WriteOffset -= base;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_pData[m_WriteOffset++] = *pElement;\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 bool Dequeue(_Element *pElement)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (m_ReadOffset &gt;= m_WriteOffset)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return false;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 *pElement = m_pData[m_ReadOffset++];\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return true;\r\n\u00a0\u00a0\u00a0 }\r\n};<\/pre>\n<p>Then add a basic test that will enqueue 3 elements and then dequeue them:<\/p>\n<pre class=\"\">TEST(QueueTests, BasicTest)\r\n{\r\n\u00a0\u00a0\u00a0 Queue&lt;int&gt; queue;\r\n\u00a0\u00a0\u00a0 for (int i = 0; i &lt; 3; i++)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 queue.Enqueue(&amp;i);\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 for (int i = 0; i &lt; 3; i++)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 int tmp;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ASSERT_TRUE(queue.Dequeue(&amp;tmp));\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ASSERT_EQ(i, tmp);\r\n\u00a0\u00a0\u00a0 }\r\n}<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/06-basic.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3568\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/06-basic.png\" alt=\"06-basic\" width=\"1195\" height=\"791\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/06-basic.png 1195w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/06-basic-300x199.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/06-basic-1024x678.png 1024w\" sizes=\"(max-width: 1195px) 100vw, 1195px\" \/><\/a><\/li>\n<li>Now you can use the Test Explorer window to run the test and verify that it succeeds:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/t1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3587\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/t1.png\" alt=\"t1\" width=\"1195\" height=\"791\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/t1.png 1195w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/t1-300x199.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/t1-1024x678.png 1024w\" sizes=\"(max-width: 1195px) 100vw, 1195px\" \/><\/a><\/li>\n<li>The fact that the test succeeded means that the scenarios covered by the test work as expected, however it doesn&#8217;t indicate how much of the programs&#8217; code was actually tested. Code coverage reports fill this gap by providing detailed statistics on functions, blocks and lines executed during the test run. Open VisualGDB Project Properties, go to the Code Coverage page and enable the &#8220;Build code coverage reports&#8221; checkbox. VisualGDB will suggest automatically enabling code coverage instrumentation:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/07-coverage.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3569\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/07-coverage.png\" alt=\"07-coverage\" width=\"1195\" height=\"791\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/07-coverage.png 1195w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/07-coverage-300x199.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/07-coverage-1024x678.png 1024w\" sizes=\"(max-width: 1195px) 100vw, 1195px\" \/><\/a><\/li>\n<li>Instrumenting your program for code coverage will add significant run-time overhead, making your program slower than the non-instrumented version. You can then temporarily disable it via Visual Studio Project Properties -&gt; Instrumentation -&gt; Generate Code Coverage Reports (the option in VisualGDB Project Properties will stop VisualGDB from downloading and parsing the report files, but won&#8217;t disable the instrumentation):<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/08-cover.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3570\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/08-cover.png\" alt=\"08-cover\" width=\"822\" height=\"558\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/08-cover.png 822w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/08-cover-300x204.png 300w\" sizes=\"(max-width: 822px) 100vw, 822px\" \/><\/a>As the instrumentation settings are stored separately for each configuration, you can create a separate configuration via VisualGDB Project Properties and use it solely for checking code coverage so that your regular test performance won&#8217;t be affected.<\/li>\n<li>It is also recommended to disable code coverage instrumentation for the files from the test framework itself. This will slightly improve the performance and remove unnecessary information from the coverage reports. You can do this by selecting those files in Solution Explorer, opening Visual Studio Properties and disabling report generation under Configuration Properties -&gt; C\/C++ -&gt; Instrumentation:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/09-nocover.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3571\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/09-nocover.png\" alt=\"09-nocover\" width=\"1195\" height=\"791\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/09-nocover.png 1195w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/09-nocover-300x199.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/09-nocover-1024x678.png 1024w\" sizes=\"(max-width: 1195px) 100vw, 1195px\" \/><\/a>Note that the settings under the <strong>C\/C++-&gt;Instrumentation<\/strong> only affect the compiler (but not the linker). If you are editing global project settings manually, use the <strong>Configuration Properties-&gt;Instrumentation<\/strong> page instead:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/10-run.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3572\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/10-run.png\" alt=\"10-run\" width=\"1195\" height=\"791\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/10-run.png 1195w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/10-run-300x199.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/10-run-1024x678.png 1024w\" sizes=\"(max-width: 1195px) 100vw, 1195px\" \/><\/a><\/li>\n<li>Run the test again. When it is completed, open the coverage report viewer via Test-&gt;VisualGDB Code Coverage Reports:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/11-showcover.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3573\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/11-showcover.png\" alt=\"11-showcover\" width=\"1195\" height=\"791\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/11-showcover.png 1195w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/11-showcover-300x199.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/11-showcover-1024x678.png 1024w\" sizes=\"(max-width: 1195px) 100vw, 1195px\" \/><\/a><\/li>\n<li>VisualGDB will display the list of functions along with their invocation count and coverage statistics. It will also highlight the covered lines directly in the source code:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/12-report.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3574\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/12-report.png\" alt=\"12-report\" width=\"1195\" height=\"791\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/12-report.png 1195w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/12-report-300x199.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/12-report-1024x678.png 1024w\" sizes=\"(max-width: 1195px) 100vw, 1195px\" \/><\/a><\/li>\n<li>Click on the &#8220;lines&#8221; column to sort the functions by the fraction of covered lines, then enter &#8220;file:tests.cpp&#8221; in the &#8220;filter&#8221; field to limit the displayed functions to your main source file:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/13-sort.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3575\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/13-sort.png\" alt=\"13-sort\" width=\"1195\" height=\"791\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/13-sort.png 1195w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/13-sort-300x199.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/13-sort-1024x678.png 1024w\" sizes=\"(max-width: 1195px) 100vw, 1195px\" \/><\/a>You can hover the mouse over the &#8216;filter&#8217; field to view help on supported filter expressions.<\/li>\n<li>The report will show that the <strong>Queue&lt;int&gt;::Enqueue()<\/strong> method has only 45% line. Double-click on it to navigate to its definition in the code:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/14-missing.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3576\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/14-missing.png\" alt=\"14-missing\" width=\"1195\" height=\"791\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/14-missing.png 1195w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/14-missing-300x199.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/14-missing-1024x678.png 1024w\" sizes=\"(max-width: 1195px) 100vw, 1195px\" \/><\/a>The coverage report quickly shows that the following branches are not covered:\n<ul>\n<li>The branch checking whether the queue is empty before dequeuing<\/li>\n<li>The branch checking whether enough memory is allocated before enqueuing more elements<\/li>\n<li>The branch moving the enqueued elements to the beginning of the buffer before adding more (the current implementation is not optimal, but clearly demonstrates 2 different conditions)<\/li>\n<\/ul>\n<\/li>\n<li>The easiest branch to cover is the empty queue check. Adjust the test method as follows, build the project and re-run the test:\n<pre class=\"\">TEST(QueueTests, BasicTest)\r\n{\r\n\u00a0\u00a0\u00a0 Queue&lt;int&gt; queue;\r\n\u00a0\u00a0\u00a0 for (int i = 0; i &lt; 3; i++)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 queue.Enqueue(&amp;i);\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 for (int i = 0; i &lt; 4; i++)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 int tmp;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 bool done = queue.Dequeue(&amp;tmp);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (i == 3)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ASSERT_FALSE(done);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ASSERT_TRUE(done);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ASSERT_EQ(i, tmp);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 }\r\n}<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/15-empty.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3577\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/15-empty.png\" alt=\"15-empty\" width=\"1195\" height=\"791\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/15-empty.png 1195w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/15-empty-300x199.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/15-empty-1024x678.png 1024w\" sizes=\"(max-width: 1195px) 100vw, 1195px\" \/><\/a><\/li>\n<li>Covering both reallocation and moving requires interleaving enqueuing and dequeuing operations and increasing the batch sizes. To do this, replace the test code with the following:\n<pre class=\"\">void EnqueueConsecutive(Queue&lt;int&gt; &amp;queue, int first, int count)\r\n{\r\n\u00a0\u00a0\u00a0 for (int i = 0; i &lt; count; i++)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 int tmp = i + first;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 queue.Enqueue(&amp;tmp);\r\n\u00a0\u00a0\u00a0 }\r\n}\r\n\r\nvoid DequeueConsecutive(Queue&lt;int&gt; &amp;queue, int first, int count)\r\n{\r\n\u00a0\u00a0\u00a0 for (int i = 0; i &lt; count; i++)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 int tmp;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ASSERT_TRUE(queue.Dequeue(&amp;tmp));\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ASSERT_EQ(i + first, tmp);\r\n\u00a0\u00a0\u00a0 }\r\n}\r\n\r\nvoid CheckEndOfQueue(Queue&lt;int&gt; &amp;queue)\r\n{\r\n\u00a0\u00a0\u00a0 int tmp;\r\n\u00a0\u00a0\u00a0 ASSERT_FALSE(queue.Dequeue(&amp;tmp));\r\n}\r\n\r\nTEST(QueueTests, BasicTest)\r\n{\r\n\u00a0\u00a0\u00a0 Queue&lt;int&gt; queue;\r\n\u00a0\u00a0\u00a0 EnqueueConsecutive(queue, 0, 3);\r\n\u00a0\u00a0\u00a0 DequeueConsecutive(queue, 0, 3);\r\n\u00a0\u00a0\u00a0 CheckEndOfQueue(queue);\r\n}<\/pre>\n<p>Then build and run the tests to ensure that all the code is now covered:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/16-covered.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3578\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/16-covered.png\" alt=\"16-covered\" width=\"1195\" height=\"791\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/16-covered.png 1195w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/16-covered-300x199.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/16-covered-1024x678.png 1024w\" sizes=\"(max-width: 1195px) 100vw, 1195px\" \/><\/a>Note that the test coverage reports always show the coverage for the tests scheduled during a test run. I.e. if you only run 1 test out of 2, the functions checked by the second tests will be shown as not covered.<\/li>\n<li>Now we will show how VisualGDB manages the coverage reports internally. Open the project folder in Windows Explorer and go to the CoverageReports subdirectory:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/17-reports.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3579\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/17-reports.png\" alt=\"17-reports\" width=\"786\" height=\"593\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/17-reports.png 786w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/17-reports-300x226.png 300w\" sizes=\"(max-width: 786px) 100vw, 786px\" \/><\/a>Each <strong>.scovreport<\/strong> file corresponds to one coverage report from one test run.<\/li>\n<li>You can delete the old report files either manually, or in the Coverage Report viewer. VisualGDB will also automatically remove the old report files when their amount exceeds the limit specified via global settings: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/cleanup1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3590\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/cleanup1.png\" alt=\"cleanup\" width=\"1195\" height=\"791\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/cleanup1.png 1195w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/cleanup1-300x199.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/cleanup1-1024x678.png 1024w\" sizes=\"(max-width: 1195px) 100vw, 1195px\" \/><\/a><\/li>\n<li>If the coverage reports appear inconsistent, open VisualGDB settings (from Tools-&gt;Options) and enable the &#8220;Keep raw coverage reports&#8221; setting:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/19-raw.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3581\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/19-raw.png\" alt=\"19-raw\" width=\"793\" height=\"542\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/19-raw.png 793w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/19-raw-300x205.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/19-raw-130x90.png 130w\" sizes=\"(max-width: 793px) 100vw, 793px\" \/><\/a><\/li>\n<li>VisualGDB will then keep the original gcov report files downloaded for each session:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/20-rawfiles.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3582\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/20-rawfiles.png\" alt=\"20-rawfiles\" width=\"786\" height=\"593\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/20-rawfiles.png 786w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/20-rawfiles-300x226.png 300w\" sizes=\"(max-width: 786px) 100vw, 786px\" \/><\/a><\/li>\n<li>You can check the consistency of the reports by looking at the <strong>job.txt<\/strong> and the <strong>.gcov<\/strong> files referenced from it:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/21-txtfiles.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3583\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/21-txtfiles.png\" alt=\"21-txtfiles\" width=\"1195\" height=\"357\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/21-txtfiles.png 1195w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/21-txtfiles-300x90.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/21-txtfiles-1024x306.png 1024w\" sizes=\"(max-width: 1195px) 100vw, 1195px\" \/><\/a>The job.txt file contains lines starting with &#8220;&gt;&#8221; that specify the base source directories followed by paths of .gcov files listing line and function coverage (VisualGDB automatically runs the <a href=\"https:\/\/gcc.gnu.org\/onlinedocs\/gcc\/Gcov.html\">gcov<\/a> tool to generate .gcov files from .gcda and .gcno files). If the .gcov files appear inconsistent, check that you are using a recent version of the compiler.<\/li>\n<li>Finally we will show how to use the code coverage to quickly spot inconsistencies in the program behavior. We will add a very basic smart pointer class and try to use it with our custom queue:\n<pre class=\"\">class SmartPointer\r\n{\r\nprivate:\r\n\u00a0\u00a0\u00a0 char *m_Pointer;\r\n\u00a0\u00a0 \u00a0\r\npublic:\r\n\u00a0\u00a0\u00a0 SmartPointer()\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_Pointer = nullptr;\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 SmartPointer(const SmartPointer &amp;right)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (right.m_Pointer)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_Pointer = strdup(right.m_Pointer);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_Pointer = nullptr;\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 void operator=(const SmartPointer &amp;right)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (m_Pointer)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 free(m_Pointer);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (right.m_Pointer)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_Pointer = strdup(right.m_Pointer);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_Pointer = nullptr;\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 ~SmartPointer()\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (m_Pointer)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 free(m_Pointer);\r\n\u00a0\u00a0\u00a0 }\r\n};\r\n\r\nTEST(QueueTests, SmartPointerTest)\r\n{\r\n\u00a0\u00a0\u00a0 Queue&lt;SmartPointer&gt; queue;\r\n\u00a0\u00a0\u00a0 SmartPointer sp;\r\n\u00a0\u00a0\u00a0 for (int i = 0; i &lt; 10; i++)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 queue.Enqueue(&amp;sp);\r\n}<\/pre>\n<p>If you run the test now, VisualGDB will trigger an &#8220;invalid memory access&#8221; error in the assignment operator:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/22-crash.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3584\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/22-crash.png\" alt=\"22-crash\" width=\"1195\" height=\"791\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/22-crash.png 1195w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/22-crash-300x199.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/22-crash-1024x678.png 1024w\" sizes=\"(max-width: 1195px) 100vw, 1195px\" \/><\/a><\/li>\n<li>Try commenting it out and run the test again. Note how the code coverage shows 10 invocations of the <strong>operator=()<\/strong>, but only one invocation of the constructor:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/23-cov.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3585\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/23-cov.png\" alt=\"23-cov\" width=\"1195\" height=\"791\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/23-cov.png 1195w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/23-cov-300x199.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/23-cov-1024x678.png 1024w\" sizes=\"(max-width: 1195px) 100vw, 1195px\" \/><\/a><\/li>\n<li>As a result, <strong>operator=()<\/strong> is trying to free a pointer that was never initialized and contains garbage. You can address this by modifying the Queue() constructor to call the placement new each time it allocated an object, acting similarly to the new[] operator:\n<pre class=\"\">\u00a0\u00a0\u00a0 Queue(int reservedCount = 4)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (reservedCount)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_Allocated = reservedCount;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_pData = (_Element *)malloc(reservedCount * sizeof(_Element));\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for (int i = 0; i &lt; reservedCount; i++)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 new(&amp;m_pData[i]) _Element();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 }<\/pre>\n<p>The reallocation logic should also contain a call to placement new for each allocated object:<\/p>\n<pre class=\"\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (GetCount() &gt;= m_Allocated)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_Allocated *= 2;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_pData = (_Element *)realloc(m_pData, m_Allocated * sizeof(_Element));\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for (int i = m_Allocated \/ 2; i &lt; m_Allocated; i++)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 new(&amp;m_pData[i]) _Element();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }<\/pre>\n<\/li>\n<li>Build and run the project now to see that the tests pass. Note that now the Enqueue() method declaration corresponds to 2 physical methods: <strong>Queue&lt;int&gt;::Enqueue()<\/strong> and <strong>Queue&lt;SmartPointer&gt;::Enqueue()<\/strong>. VisualGDB can distinguish between them and will show you the detailed statistics once you click on the &#8220;2\/2 variants covered&#8221; link above the method declaration:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/24-popup.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3586\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/24-popup.png\" alt=\"24-popup\" width=\"1195\" height=\"791\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/24-popup.png 1195w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/24-popup-300x199.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/11\/24-popup-1024x678.png 1024w\" sizes=\"(max-width: 1195px) 100vw, 1195px\" \/><\/a><\/li>\n<\/ol>\n<p>You can find the source code for the program shown in this tutorial in our <a href=\"https:\/\/github.com\/sysprogs\/tutorials\/tree\/master\/visualgdb\/profiler\/linux\/coverage\">Github repository<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to use VisualGDB to quickly analyze the code coverage of your Linux Unit Test projects. We<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[152],"tags":[156,33,129],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/3562"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=3562"}],"version-history":[{"count":5,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/3562\/revisions"}],"predecessor-version":[{"id":3594,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/3562\/revisions\/3594"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=3562"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=3562"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=3562"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}