Merge branch 'phase04' into main
This commit is contained in:
commit
6e62a7dba2
@ -0,0 +1,67 @@
|
||||
package com.alibaba.fastjson.parser;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class CheckTimeTests {
|
||||
private boolean checkTime(JSONScanner scanner, char h0, char h1, char m0, char m1, char s0, char s1) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||
Method checkTime = JSONScanner.class.getDeclaredMethod("checkTime", char.class, char.class, char.class, char.class, char.class, char.class);
|
||||
checkTime.setAccessible(true);
|
||||
return (Boolean)checkTime.invoke(scanner, h0, h1, m0, m1, s0, s1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void CheckTime_IC_Test() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
|
||||
JSONScanner scanner = new JSONScanner("");
|
||||
|
||||
// (h0 == '0') && (h1 < '0' || h1 > '9')
|
||||
// First nested predicate
|
||||
Assert.assertFalse(checkTime(scanner, '0', '+', '0', '0', '0', '0'));
|
||||
Assert.assertFalse(checkTime(scanner, '0', '?', '0', '0', '0', '0'));
|
||||
Assert.assertFalse(checkTime(scanner, '?', '5', '0', '0', '0', '0'));
|
||||
|
||||
// Second nested predicate
|
||||
Assert.assertFalse(checkTime(scanner, '1', '+', '0', '0', '0', '0'));
|
||||
Assert.assertFalse(checkTime(scanner, '1', '?', '0', '0', '0', '0'));
|
||||
Assert.assertFalse(checkTime(scanner, '?', '5', '0', '0', '0', '0'));
|
||||
|
||||
// Third nested predicate
|
||||
Assert.assertFalse(checkTime(scanner, '2', '+', '0', '0', '0', '0'));
|
||||
Assert.assertFalse(checkTime(scanner, '2', '5', '0', '0', '0', '0'));
|
||||
Assert.assertFalse(checkTime(scanner, '?', '5', '0', '0', '0', '0'));
|
||||
|
||||
// (m0 >= '0' && m0 <= '5') && (m1 < '0' || m1 > '9')
|
||||
// First nested predicate
|
||||
Assert.assertFalse(checkTime(scanner, '1', '3', '+', '5', '0', '0'));
|
||||
Assert.assertFalse(checkTime(scanner, '1', '3', '6', '5', '0', '0'));
|
||||
Assert.assertFalse(checkTime(scanner, '1', '3', '4', '+', '0', '0'));
|
||||
Assert.assertFalse(checkTime(scanner, '1', '3', '4', '?', '0', '0'));
|
||||
|
||||
// (m0 == '6') && (m1 != '0')
|
||||
// not P, not Q, P and Q
|
||||
// Second nested predicate
|
||||
Assert.assertFalse(checkTime(scanner, '1', '3', '6', '1', '0', '0'));
|
||||
Assert.assertTrue(checkTime(scanner, '1', '3', '5', '0', '0', '0'));
|
||||
|
||||
// (s0 >= '0' && s0 <= '5') && (s1 < '0' || s1 > '9')
|
||||
// First nested predicate
|
||||
Assert.assertFalse(checkTime(scanner, '1', '3', '5', '0', '+', '5'));
|
||||
Assert.assertFalse(checkTime(scanner, '1', '3', '5', '0', '6', '5'));
|
||||
Assert.assertFalse(checkTime(scanner, '1', '3', '5', '0', '4', '+'));
|
||||
Assert.assertFalse(checkTime(scanner, '1', '3', '5', '0', '4', '?'));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void CheckTime_Branch_Test() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
|
||||
JSONScanner scanner = new JSONScanner("");
|
||||
|
||||
// (h0 == '0') && (h1 < '0' || h1 > '9')
|
||||
// Missing branches
|
||||
Assert.assertTrue(checkTime(scanner, '0', '5', '0', '0', '0', '0'));
|
||||
Assert.assertTrue(checkTime(scanner, '2', '4', '0', '0', '0', '0'));
|
||||
Assert.assertTrue(checkTime(scanner, '1', '4', '6', '0', '6', '0'));
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ name = MichaelChen
|
||||
|
||||
solutionname = Solution_Phase$(phase)_$(name)
|
||||
target = $(solutionname)_V$(version).zip
|
||||
package = $(solutionname).pdf AbstractStringBuilder.java
|
||||
package = $(solutionname).pdf AbstractStringBuilder.java CheckTimeTests.java
|
||||
latexmkflags =
|
||||
|
||||
.PHONY : all dev
|
||||
|
@ -5,6 +5,16 @@
|
||||
\usepackage{listings}
|
||||
\usepackage{enumitem}
|
||||
\usepackage{subcaption}
|
||||
\usepackage[acronym]{glossaries}
|
||||
|
||||
\newacronym{dnf}{DNF}{disjunctive normal form}
|
||||
\newacronym{utp}{UTP}{unique true point}
|
||||
\newacronym{nfp}{NFP}{near false point}
|
||||
\newacronym{pc}{PC}{predicate coverage}
|
||||
\newacronym{cc}{CC}{clause coverage}
|
||||
\newacronym{acc}{ACC}{active clause coverage}
|
||||
\newacronym{icc}{ICC}{inactive clause coverage}
|
||||
|
||||
|
||||
\usepackage{pgf}
|
||||
\usepackage{tikz}
|
||||
@ -63,8 +73,8 @@
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\def\name{[Add name here]}
|
||||
\def\group{[Add group here]}
|
||||
\def\name{Michael Chen}
|
||||
\def\group{Group 01 (fastjson)}
|
||||
|
||||
\begin{document}
|
||||
\projectinfo{4}{Software Testing - Logic Coverage\small}{\today}{\name}{\group}
|
||||
@ -78,32 +88,32 @@
|
||||
\begin{enumerate}
|
||||
\item \textit{Predicate}, \textit{Clause}, \textit{Literal}, and \textit{Term}
|
||||
\begin{answer}
|
||||
[TODO: Add answer here]
|
||||
A predicate from a functional perspective is a function with arbitrary inputs and boolean output containing one or more clauses that are combined with logical operators. A clause is also a kind of predicate, but in it's atomar form, in that it does not contain any further logical operators. Clauses can be built from operations of the programming language, variables and literals. Literals are clauses or their negations. A term is a conjunction of literals. Predicates that are disjunctions of terms are in their \gls{dnf}.
|
||||
\end{answer}
|
||||
|
||||
\item \textit{Unique True Point} and \textit{Near False Point}
|
||||
\begin{answer}
|
||||
[TODO: Add answer here]
|
||||
A \gls{utp} of a \gls{dnf} is a truth assignment where exactly one of its implicants is true. Given a clause, an \gls{nfp} is a truth assignment where the predicate is false, but if the clause is inverted it's implicant, and thus the predicate, become true.
|
||||
\end{answer}
|
||||
|
||||
\item \textit{Prime Implicant} and \textit{Redundant Implicant}
|
||||
\begin{answer}
|
||||
[TODO: Add answer here]
|
||||
An term is a prime implicant when all it's literals are necessary to make the predicate true, i.e. if you were to remove any single literal of the term it would no longer be an implicant. The opposite of that is a term where all it's literals could be removed and the predicate value would stay the same, making the implicant redundant.
|
||||
\end{answer}
|
||||
\end{enumerate}
|
||||
\item What is the difference between \textit{Semantic} and \textit{Syntactic Logic Coverage}? Explain both approaches, as well as \textit{one} concrete criterion for each of them.
|
||||
\begin{answer}
|
||||
[TODO: Add answer here]
|
||||
\Gls{pc} and \gls{cc} are examples for semantic logic coverage criteria, which are based on the meaning of the expressions. Here the test requirements are built from the evaluations of parts of the predicate. \Glspl{utp} is an example for syntactic logic coverage, which are based on forms of the expressions. This specific criterion is based on the fact that it's predicates are in \gls{dnf} form and thus implicants can be easily identified.
|
||||
\end{answer}
|
||||
|
||||
\item Explain the terms \textit{Reachability} and \textit{Controllability}. What are their consequences for a source-code based logic coverage approach?
|
||||
\begin{answer}
|
||||
[TODO: Add answer here]
|
||||
Reachability and controllability are concerned with the selection of input values to satisfy specific test requirements. The former is concerned with choosing inputs in a way that the program flow evaluates the expression under test. Controllability is concerned with assigning the inputs such that, given the flow of the program until the expression, internal variables are assigned correctly, because not all literals of expressions are necessarily direct input variables.
|
||||
\end{answer}
|
||||
|
||||
\item Both \textit{Active Clause Coverage} (ACC) and \textit{Inactive Clause Coverage} (ICC) feature a \textit{General} and a \textit{Restricted} version of their concepts. Briefly describe the changes that both variations introduce to the basic concept.
|
||||
\begin{answer}
|
||||
[TODO: Add answer here]
|
||||
In the general version of these criteria the minor clauses allowed to change for different requirements, while in the restricted version they have to stay the same for dífferent valuations of the current major clause.
|
||||
\end{answer}
|
||||
|
||||
\end{enumerate}
|
||||
@ -116,42 +126,85 @@
|
||||
\begin{enumerate}[topsep=0pt, leftmargin=*]
|
||||
\item Name and briefly describe the specific lines that (directly or indirectly) influence the boolean results of the predicates and clauses in line \textit{10}, \textit{12}, \textit{17}, \textit{20}, \textit{22}, \textit{30}, and \textit{32}.
|
||||
\begin{answer}
|
||||
[TODO: Add answer here]
|
||||
In this table I listed all dependencies the predicates.
|
||||
\begin{center}
|
||||
\begin{tabular}{r|c|c}
|
||||
Line & Directly & Indirectly \\ \hline \hline
|
||||
\textit{10} & \texttt{s} \\
|
||||
\textit{12} & \texttt{start}, \texttt{end}, \texttt{s} \\
|
||||
\textit{17} & \texttt{len} & \texttt{start}, \texttt{end} \\
|
||||
\textit{20} & \texttt{value}, \texttt{newCount} & \texttt{count}, \texttt{len}, (\texttt{start}, \texttt{end}) \\
|
||||
\textit{22} & \texttt{i}, \texttt{end} & \texttt{start} \\
|
||||
\textit{30} & \texttt{newCapacity} & \texttt{value} \\
|
||||
\textit{32} & \texttt{minimumCapacity}, \texttt{newCapacity} & \texttt{value}
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{answer}
|
||||
|
||||
\item To which extent are the predicates influenced by internal states? Which conclusions do you draw for the application of logic coverage criteria to source code in general?
|
||||
\begin{answer}
|
||||
[TODO: Add answer here]
|
||||
The predicates in this examples are not influenced by the internal state of the object that much, except for the buffer size check of the character array. The internal state of the function influences the variables a lot, because the input parameters are used in operations that declare new internal variables. Finding variables for logic coverage from source code is a rather easy task, however finding input parameters to cover the test requirements is a very difficult task and sometimes not even possible.
|
||||
\end{answer}
|
||||
|
||||
\item Provide a set of tests that cover the following predicates and clauses:
|
||||
\begin{enumerate}
|
||||
\item \texttt{(start < 0) || (end < 0) || (start > end) || (end > s.length())} (l.12) based on the \textit{Correlated Active Clause Coverage} (CACC) criterion
|
||||
\begin{answer}
|
||||
[TODO: Add answer here]
|
||||
|
||||
\begin{lstlisting}[language=Java,belowskip=-0.8\baselineskip]
|
||||
/* Add code here */
|
||||
@Test
|
||||
public void caccBoundCheck() {
|
||||
String s = "01234";
|
||||
// base case
|
||||
new StringBuilder(4).append(s, 0, s.length());
|
||||
// start < 0
|
||||
new StringBuilder(4).append(s, -1, s.length());
|
||||
// start > end
|
||||
new StringBuilder(4).append(s, 6, s.length());
|
||||
// end > s.length()
|
||||
new StringBuilder(4).append(s, 0, s.length() + 1);
|
||||
// end < 0
|
||||
new StringBuilder(4).append(s, -2, -1);
|
||||
}
|
||||
\end{lstlisting}
|
||||
% or: \lstinputlisting[language=Java,belowskip=-0.8\baselineskip]{file_name.java}
|
||||
\end{answer}
|
||||
|
||||
\item \texttt{newCount > value.length} (l.20) for an evaluation to both \textit{true} and \textit{false}
|
||||
\begin{answer}
|
||||
[TODO: Add answer here]
|
||||
This predicate determines if the buffer needs to be expanded. To achieve this we can input more and less than the current capacity.
|
||||
|
||||
\begin{lstlisting}[language=Java,belowskip=-0.8\baselineskip]
|
||||
/* Add code here */
|
||||
@Test
|
||||
public void requireExpansion() {
|
||||
String s = "01234";
|
||||
// Predicate is true, so buffer will expand
|
||||
new StringBuilder(4).append(s, 0, s.length());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requireExpansion() {
|
||||
String s = "01234";
|
||||
// Predicate is false, so buffer will not expand
|
||||
new StringBuilder(5).append(s, 0, s.length());
|
||||
}
|
||||
\end{lstlisting}
|
||||
% or: \lstinputlisting[language=Java,belowskip=-0.8\baselineskip]{file_name.java}
|
||||
\end{answer}
|
||||
|
||||
\item \texttt{newCapacity < 0} (l.30) and \texttt{minimumCapacity > newCapacity} (l.32) for an evaluation to \textit{true}. Which requirement(s) does \texttt{value} have to meet so that \texttt{newCapacity < 0} will be satisfied?
|
||||
\begin{answer}
|
||||
[TODO: Add answer here]
|
||||
In order for \texttt{newCapacity < 0} to be satisfied, the monotonously increasing value of \texttt{value.length} (buffer size) has to overflow the integer size and become negative. The lowest value that could happen would be $2^30 - 1 = 1073741823$, which would allocate more than 1 gigabyte of memory for the buffer.
|
||||
|
||||
\begin{lstlisting}[language=Java,belowskip=-0.8\baselineskip]
|
||||
/* Add code here */
|
||||
@Test
|
||||
public void newCapOverflow() {
|
||||
new StringBuilder(1073741823).expandCapacity(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lowerThanMin() {
|
||||
new StringBuilder(2).expandCapacity(7);
|
||||
}
|
||||
\end{lstlisting}
|
||||
% or: \lstinputlisting[language=Java,belowskip=-0.8\baselineskip]{file_name.java}
|
||||
\end{answer}
|
||||
@ -167,12 +220,20 @@
|
||||
\begin{enumerate}[topsep=0pt, leftmargin=*]
|
||||
\item Pick a method of your given project which contains at least \textbf{2} predicates, with one of these predicates containing at least \textbf{3} clauses. If you cannot find a three-clause-predicate in your code, you can decide to take a nested structure of \textit{if-else} and/or nested \textit{while} expressions instead (at least \textbf{2} levels of nesting). In that case, explain the differences for the application of your logic coverage criteria for nested structures as compared to "flat" predicates.
|
||||
\begin{answer}
|
||||
[TODO: Add answer here]
|
||||
\texttt{boolean checkTime(char h0, char h1, char m0, char m1, char s0, char s1)} is a function that checks whether a given time in \texttt{HH:MM:SS} format is a valid time. For nested \textit{if-else} you can append the outer predicates as conjunctions because in order to reach the given line all outer predicates have to be true by definition of the branching. This is similar to \texttt{while} and \texttt{for} loops where the predicate is the loop invariant which holds for every loop execution.
|
||||
\end{answer}
|
||||
|
||||
\item Using the \textit{EclEmma} tool from phase 03, measure and note down the \textit{instruction}, \textit{branch} and \textit{line coverage} values of the existing test suite regarding your selected method.
|
||||
\begin{answer}
|
||||
[TODO: Add answer here]
|
||||
In this table I listed the current coverage data.
|
||||
\begin{center}
|
||||
\begin{tabular}{r|c|c}
|
||||
Metric & Covered & Percentage \\ \hline \hline
|
||||
Instructions & 38 & $44.7\%$ \\
|
||||
Branches & 12 & $28.6\%$ \\
|
||||
Lines & 8 & $32.0\%$ \\
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{answer}
|
||||
|
||||
\item Create a set of tests that satisfy \textit{three} of the following logic criteria (pick one concrete criterion from each of your three selected bullet points):
|
||||
@ -184,22 +245,27 @@
|
||||
\item \textit{Multiple Unique True Point Coverage} (MUTP), \textit{Unique True Point and Near False Point Pair Coverage} (CUTPNFP), \textit{Multiple Near False Point Coverage} (MNFP)
|
||||
\end{itemize}
|
||||
\begin{answer}
|
||||
[TODO: Add answer here]
|
||||
Firstly \textit{Implicant Coverage} (IC): \texttt{h0 == '0' \&\& (h1 < '0' || h1 > '9')} as $P \land (Q \lor R)$ has the DNF $(Q \land P) \lor (R \land P)$ and its negation $\neg P \lor (\neg Q \land \neg R)$. Those DNFs have implicants $Q \land P, R \land P, \neg P, \neg Q \land \neg R$. A possible test requirement for IC would be (in form \texttt{(h0, h1)}): \texttt{('0', '+')}, \texttt{('0', '?')}, \texttt{('?', '5')}.
|
||||
|
||||
\begin{lstlisting}[language=Java,belowskip=-0.8\baselineskip]
|
||||
/* Add code here */
|
||||
\end{lstlisting}
|
||||
% or: \lstinputlisting[language=Java,belowskip=-0.8\baselineskip]{file_name.java}
|
||||
\lstinputlisting[firstline=16,lastline=55,language=Java,belowskip=-0.8\baselineskip]{CheckTimeTests.java}
|
||||
\end{answer}
|
||||
|
||||
\item Document for each individual test the coverage criterion / criteria it contributes to.
|
||||
\begin{answer}
|
||||
[TODO: Add answer here]
|
||||
In this table I listed the coverage of the IC test suite.
|
||||
\begin{center}
|
||||
\begin{tabular}{r|c|c}
|
||||
Metric & Covered & Percentage \\ \hline \hline
|
||||
Instructions & 85 & $100\%$ \\
|
||||
Branches & 38 & $90.5\%$ \\
|
||||
Lines & 25 & $100\%$ \\
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{answer}
|
||||
|
||||
\item Finally, recheck your method with the new, extended test suite regarding the \textit{instruction}, \textit{branch} and \textit{line coverage} criteria, and explain \textit{how} their values have / have not changed.
|
||||
\begin{answer}
|
||||
[TODO: Add answer here]
|
||||
Finally with an additional edge case I achieved complete coverage with every metric.
|
||||
\end{answer}
|
||||
|
||||
\end{enumerate}
|
||||
|
Loading…
Reference in New Issue
Block a user