diff --git a/project_task_sheets/phase_04/project_phase04_tasks/CheckTimeTests.java b/project_task_sheets/phase_04/project_phase04_tasks/CheckTimeTests.java new file mode 100644 index 0000000..5c9ee02 --- /dev/null +++ b/project_task_sheets/phase_04/project_phase04_tasks/CheckTimeTests.java @@ -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')); + } +} diff --git a/project_task_sheets/phase_04/project_phase04_tasks/Makefile b/project_task_sheets/phase_04/project_phase04_tasks/Makefile index 67e73e5..61a0791 100644 --- a/project_task_sheets/phase_04/project_phase04_tasks/Makefile +++ b/project_task_sheets/phase_04/project_phase04_tasks/Makefile @@ -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 diff --git a/project_task_sheets/phase_04/project_phase04_tasks/Solution_Phase04_MichaelChen.tex b/project_task_sheets/phase_04/project_phase04_tasks/Solution_Phase04_MichaelChen.tex index 012f4d9..a514884 100644 --- a/project_task_sheets/phase_04/project_phase04_tasks/Solution_Phase04_MichaelChen.tex +++ b/project_task_sheets/phase_04/project_phase04_tasks/Solution_Phase04_MichaelChen.tex @@ -220,12 +220,20 @@ public void lowerThanMin() { \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): @@ -237,22 +245,27 @@ public void lowerThanMin() { \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}