Coverage Updates
I have created this page to maintain all the updates of the Coverage Analysis Project that I have taken up as part of Google Summer of Code 2009. This project will contain a comprehensive coverage of the procedure followed to tackle each of the test cases and the scope of the patches that were generated. Wasting no more time, let's get straight to business.
All the patches can be found here.
Patch 1: To Tackle rtems_interrupt_level_attribute test case.
This case was the first one listed on Explanations.txt as TEST SIMPLE. My mentor, Dr. Joel Sherrill and I have agreed that we need to tackle all the TEST SIMPLE cases first so that we gain confidence and the uncovered ranges count also comes down. This case involves writing a new test case to cover the subroutine rtems_interrupt_level_attribute that is defined in the file attr.c located in the cpukit/rtems/src directory under the rtems source tree.
The Explanations.txt file said:
attr.c:31
TEST SIMPLE - call rtems_interrupt_level_attribute
From this message we can derive that the rtems_interrupt_level_attribute is not being called right now and we need to write a new test case to call it. The file mentioned is attr.c.
Steps followed:
1. Locate the file:
find ~/rtems -name attr.c -print
2. Open the file and study the contents:
After opening the file, we can see that the file contains the definition of the subroutine "rtems_interrupt_level_attribute". From the Explanations.txt we learn that this subroutine is not being called and we need to write a test case to call this subroutine.
3. Find out where to add the test case to:
"grep" is god! Using grep we locate where most of the test cases for interrupts are written. I must admit here that I didn't do this myself. I asked Joel and he guided me to the ~rtems/testsuites/sptests/sp37 directory. sp37 contains most of the interrupt based test cases. Joel also mentioned that grep is a good friend to locate such things.
4. Add the test case:
The file sp37/init.c contains all the test cases in this context. It contains a set of subroutines that test various interrupt test cases. Analysing the messages from the test run, and using grep we can locate 2 subroutines that are relevant in this context. They are the test_interrupt_inline() and the Init() subroutines. The test_interrupt_inline() subroutine is used to call all the inline subroutines and the Init() subroutine is the starting point of execution for all the sp37 tests. We need to add the calls to the rtems_interrupt_level_attribute in both these routines.
5. Verify if the test case is working properly:
This has to be done by running the tests and generating the reports. In this case the calls also have to be verified if they are returning the right set of values. This is done by comparing the value returned by the subroutine call and the macro RTEMS_INTERRUPT_LEVEL_ATTRIBUTE. The same was done and thus the patch was generated.
This test case covered 8 previously uncovered bytes from the RTEMS code base. The stats can be found at the Coverage Baseline and the Patch Description documents. Access provided on request.
Joel's reaction after the patch was submitted: "All this for 8 bytes. But the routine in question is 100% covered from what I see. You can see how you like to do batches now. :)"
Patch 2: To tackle the heapresizeblock.c test case
Again a TEST SIMPLE case.
The Explanations.txt file says this:
heapresizeblock.c:158
TEST SIMPLE - looks like shrink block but so small the unused area gets freed
The explanation isn't all that obvious but then we need to follow the set of steps for it to make sense.
1. Locate the file:
find ~/rtems -name heapresizeblock.c -print
2. Open the file and study the contents:
The code is pretty overwhelming, but the Explanations.txt file provides us with a line number. Studying the code in this vicinity tells us that it deals with resizing of the memory heap(you'd think thats obvious from the name :P). The subroutine defined here is _Heap_Resize_block(). The block around line 158 deals with a particular case where a certain block is split and the unused part is small enough to be freed - now the explanation makes sense.
3. Find out where to add the test case:
Using grep we can locate that the heap test cases are written in the ~/rtems/testsuites/libtests/malloctest directory.
4. Add the test case:
All the heap related test cases are written in this file. Searching for the _Heap_Resize_block() subroutine reveals that this subroutine is called in the test_heap_cases_1() subroutine. This routine contains a list of test cases to test the _Heap_Resize_block() subroutine. We need to add a new test case here that will satisfy the condition in the line 158 of heapresizeblock.c file and thus enter into the if block and thus cover the code in it. From Joel's advice I understand the condition which will make the control enter the if block. Thus the test case is written.
5. Verify the test case is working properly:
When I ran the test I observed that the case was actually not being covered. I tried hard to locate the problem but failed. Then I sent the diff over to Joel who pointed out how silly I was being. The memory allocated for the heap on the whole was 1024 bytes and I was trying to allocate 2 blocks of 1024 from that heap and thus the test case failed miserably. He also sent over the corrected code, which I then updated and tested and finally sent over the patch.
The stats as before are available on the Coverage Baseline and the Patch Description.
Patch 3: Heap Walk Test cases - Phase I
This is a set of TEST SIMPLE cases.
The Explanations.txt doesn't have much explanation about these cases. The heapwalk is a large set of uncovered cases. Its the second largest range of uncovered code. The set of heapwalk cases will be split over phases and tackled. I have been working on heapwalk from the past 3 weeks with not much success. Now I will be taking a break from the heapwalk cases and will take up other cases for a while before returning to heapwalk. Also in the meanwhile we can get a better explanation of the test cases in heapwalk.
One more thing to note here, I have changed the development BSP from arm - edb7312 to sparc - sis. Using sis provides the additional advantage of using gdb. Hence the change.
1. Locate the file:
find ~/rtems -name heapwalk.c -print
2. Open the file and study the contents:
Studying the contents we see that the first case is with the if block that checks for the source<0 condition. The source is an argument thats passed to the _Heap_Walk subroutine. Generally this value is 0x01 but in order for the if block to be executed, we need to pass the source value as negative.
The next case is the heap_prev_block_used condition. Here the if block checks if the heap_prev_block_used flag is set. If the flag is not set then it raises an error. It is ensured that the flag is always set because the _Heap_Walk subroutine is always called after the _Heap_Initialize subroutine which sets this flag. In order for this flag not to be set we need to call the _Heap_Walk subroutine before without calling the _Heap_Initialize subroutine.
3. Find out where to add the test case:
A new test shell had to be created for the heapwalk test cases. Joel created this test shell under libtests with the basic init.c and the.scn files. The test cases are to be added at
rtems/testsuites/libtests/heapwalk/init.c
4. Add the test case:
The tests are added as separate subroutines for each of the above test cases.
The source<0 test case is written in the subroutine - test_negative_source_value()
The heap_prev_used_block test case is written in the subroutine - void test_prev_block_flag_check()
5. Verify the test case is working properly:
The test cases were verified by running and stepping through the code using gdb.
The stats as before are available on the Coverage Baseline and the Patch Description
Patch 4: To tackle the prwlocktimedwrlock.c test case
Again a TEST SIMPLE case.
The reports.txt file says this:
Need to deal with timeout cases (past and future)
1. Locate the file:
find ~/rtems -name prwlocktimedwrlock.c -print
2. Open the file and study the contents:
The report.txt suggests that the code uncovered is on line nos. 89 and 90. Lines 89 and 90 have a switch case that returns different flags based on the value of status. It appears that the value status POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST is not being checked and the corresponding code is not being executed. There is a similar case on prwlocktimedrdlock.c also.
3. Find out where to add the test case:
Using grep we can locate that rwlock tests are written in the testsuite/psxtests/psxrwlock01/test.c
4. Add the test case:
Here I tackled the rdlock test case first which was pretty simple considering that I just had to initialize abstime with a time in the past and call rdlock. This worked but then it just covered 40 of the 44 bytes and left a case of just 1 instruction uncovered which was weird. This test case was then tackled by Joel and the entire 44 bytes got covered. The same procedure was followed to tackle the wrlock case and the 44 bytes from that also got covered. Releasing the lock first and then obtaining the lock again solved the 4 bytes branch instruction problem.
5. Verify the test case is working properly:
The test case was verified using gdb by breaking at the line which was not covered and then stepping through the code until I was sure that the code was being covered.
The stats as before are available on the Coverage Baseline and the Patch Description.
Patch 5: To tackle the corerwlockrelease.c test case
Again a TEST SIMPLE case.
The reports.txt file says this:
Explanation:
This is a case where you are releasing an RWLock that is already released.
So this should be a very simple test case.
Indeed the test case is simple.
1. Locate the file:
find ~/rtems -name corerwlockrelease.c -print
2. Open the file and study the contents:
The report suggests that the uncovered code lies on line nos. 53 and 54. Studying the code in corerwlockrelease tells us that the code thats not being executed is after the if condition that checks if the lock has already been released "if ( the_rwlock->current_state == CORE_RWLOCK_UNLOCKED)". This tells us that we have to release an already released lock.
3. Find out where to add the test case:
Using grep we can locate that rwlock tests are written in the testsuite/psxtests/psxrwlock01/test.c
4. Add the test case:
I added the test case with one call to the rwlock_init subroutine and 2 calls to the rwlock_unlock subroutine.
5. Verify the test case is working properly:
Using gdb and breaking and stepping through the code revealed that the test was not actually being executed. I had added a puts("Covered") code just after the line that needed to be covered and that seemed to be causing the problem. Since the execution at corerwrelease.c would stop and taking a backtrace revealed that the problem was with the puts and once that was removed things seemed to be working fine.
The stats as before are available on the Coverage Baseline and the Patch Description.
Yay!! With the above 2 patches all the rwlock cases have been covered!

