Tutorial 3, Q1 Answers Consider the following simple program (in no particular language) to find the smallest prime factor of a number: smallest(int p) /* precondition p > 1 */ a) { int q = 2; while(p mod q > 0 AND q < sqrt(p) ) b) q := q+1 ; if (p mod q = 0) then print(q,''is the smallest factor'') else print(p, ``is prime'') ; } Draw the control for this program and (if it helps) the structural treeform of this program. Calculate: – number of nodes – number of edges – number of simple paths – all paths with k=2 Program smallest(int p) (*p>1*) { int q = 2; while(p mod q > 0 AND q < sqrt p) do q := q+1 ; if (p mod q = 0) then print(q,’is factor’) else print(p,’is prime’) ; } Tree CFG 1 S 2 3 4 A1 S A2 S 5 6 L3 C5 7 8 A4 A6 A7 S8 A2 Number of Nodes: S7 • FA() = 2 • Fs(m1,m2) = m1 + m2 - 1 A2 S6 • FC(m1,m2) = m1 + m2 • FL(m1) = m1 + 1 L3 A2 C4 A2 A2 S9 A1 Number of Edges: S8 • FA() = 1 • Fs(m1,m2) = m1 + m2 A1 S7 • FC(m1,m2) = m1 + m2 +2 • FL(m1) = m1 + 2 L3 A1 C4 A1 A1 Number of simple paths A simple path is one in which no edge is traversed more than once S4 A1 • • • • S4 A1 S4 L2 A1 C2 A1 A1 nsp(A) = 1 nsp(S(P1,P2)) = nsp(P1) x nsp(P2) nsp(C(P1,P2)) = nsp(P1) + nsp(P2) nsp(L(P1)) = nsp(P1)+1 Number of All Paths (k=2) • ap(A) = 1 • ap(S(P1,P2)) = ap(P1) x ap(P2) • ap(C(P1,P2)) = ap(P1) + ap(P2) • ap(L(P1)) = ap(P1)2+ ap(P1)+ 1 S6 A1 S6 A1 S6 L3 A1 C2 A1 A1 Tutorial 3, Q2 Consider the following simple program (in no particular language) to find the smallest prime factor of a number: smallest(int p) /* precondition p > 1 */ { int q = 2; while(p mod q > 0 AND q < sqrt(p) ) q := q+1 ; if (p mod q = 0) then print(q,''is the smallest factor'') else print(p, ``is prime'') ; } a) Draw the control for this program and annotate the nodes to indicate the definitions/uses of variables p and q. b) Label the nodes and give All DU Paths for p and q. c) Give a test suite which gives 100% coverage for All DU paths. d) Which of these paths are required for: AU, APU+C, ACU+P, APU, ACU, and AD coverage. e) Explain whether or not the “all predicate uses" test set is sufficient for branch coverage of this program? Program smallest(int p) (*p>1*) { int q = 2; while(p mod q > 0 AND q < sqrt p) do q := q+1 ; if (p mod q = 0) then print(q,’is factor’) else print(p,’is prime’) ; } Usage CFG p 1 d up 4 5 6 7 8 up uc,d up up uc uc paths For p d 2 3 q All DU 123 12343 1235 123435 12357 1234357 For q 23 234 235 2356 43 434 435 4356 Required paths p 123 12343 1235 123435 12357 1234357 q 23 234 235 2356 43 434 435 4356 Test Actual path Test Output Input p=3 p=5 123578 12343578 3 is prime 5 is prime Badly drawn wiggly line indicates paths which subsume other paths P=2 123568 2 is factor P=11 1234343578 11 is prime p=9 12343568 3 is factor Other coverages: So to cover all du paths we need to have 5 test cases: p=3 and p=5 and p = 2, p=9 and p=11. Now to cover AU, we need only execute a single du path between each pair (d,u) that starts at a definition, d and ends at a use, u. However, we need to ensure that we have done this for both variables in the program. Let’s consider the variable p first. Of the du paths, we have 123 and 12343, but both these exercise the same pair (1,3) so just 123 will do. Also we don’t need both 1235 and 123435, just 1235 would do. Finally, we don’t need 12357 and 1234357, just 12357 will do. In conclusion, we see that we only need 12357 to cover all uses of the variable p. There is only one definition of the variable p (at node 1) and the case which passes through 12357 hits all three uses of the variable p at 3, 5, and 7. Therefore, to cover all uses of the variable p, we need only execute 123578 (p=3). Notice how all du paths requires us (in this case) to go through the loop, whereas (for the variable p) AU does not. That is because there was a choice of du paths for each du pair, where one went through the loop and one did not. However, AU will force us to go through loops if the only du path from a definition to a use goes through a loop. This is the case with the variable q in this example, as we shall see. Let’s look at the AU criterion for the variable q. To understand the difference between All du paths coverage and AU coverage, we need to be clear in our mind about the distinction between a du path and a du pair. The start and end node of a DU path is a Definition and a Use respectively. The definition and use, together, form a du pair. We notice that the 8 du paths identified for q all have different du pairs. That is, there are 8 distinct du pairs for q, each of which corresponds to one of the du paths. This means that covering all uses of q will be the same as covering all du paths for q. Therefore we need the same three test inputs to achieve this. •For APU, we do not need to cover the computational uses of variables, but we must cover the predicate uses. Therefore, we could choose the same three test cases that we chose for AU, but this would be wasteful; we can manage with only two test cases for APU. I will show you how. Notice that, for variable q, we still need to cover the pair (2,5) without passing through 4 and also the pair (4,5), so we must have at least two test cases. However, because we do not need to also cover node 6 (the computational use of the variable q), we can use the path 123578 to cover the pair (2,5) for the variable q. This case, 123578, will also cover all predicate uses of the variable p. So now we only need add a case for the pairs (4,3) and (4,5). Either of 12343568 (p=9) or 12343578 (p=5) would do. •For ACU, we need to cover the computational use of the variable p. In fact, every test case that goes through node 7 does this. However, we need to cover all computational uses of the variable q also. To do this we need to go through node 6. Clearly this cannot re-use the test case for the variable p, since that has to go through node 7 and we cannot go through both nodes 7 and node 6 in the same test case. Now, for variable q, there are two definitions that reach the computational use at node 6, these are the definitions at nodes 2 and 4. The last criterion is easy: •For AD, we need only hit all definitions of all variables that reach some use (of any kind – either predicate or computation). These occur at nodes 1,2 and 4, so any test case that goes through all three nodes will do. We could choose, 12343578 (p=5) for example. APU versus Branch Cover All predicate uses (as defined in the lecture) is not sufficient for branch coverage as it only requires each predicate to be tested in one direction, whereas branch coverage requires each predicate to be taken in both directions. For this program, as there are no predicates inside the body of the loop, 100% APU coverage is possible without entering the loop, whilst branch cover requires loop body to be executed.