thesis: Complete 3.2
This commit is contained in:
@@ -36,20 +36,20 @@ Figure~\ref{fig:control-flow} illustrates the control flow for manipulating func
|
||||
\end{sdblock}
|
||||
|
||||
\begin{sdblock}{Modified Call}{}
|
||||
\begin{call}{p}{malloc(x)}{i}{return a}
|
||||
\begin{call}{p}{malloc(x)}{i}{return b}
|
||||
\mess{i}{{``malloc(x)''}}{s}
|
||||
\mess{s}{``modify y''}{i}
|
||||
\begin{call}{i}{malloc(y)}{l}{return a}
|
||||
\begin{call}{i}{malloc(y)}{l}{return b}
|
||||
\end{call}
|
||||
\mess{i}{``return a''}{s}
|
||||
\mess{i}{``return b''}{s}
|
||||
\end{call}
|
||||
\end{sdblock}
|
||||
|
||||
\begin{sdblock}{Mocked Call}{}
|
||||
\begin{call}{p}{malloc(x)}{i}{return z}
|
||||
\begin{call}{p}{malloc(x)}{i}{return c}
|
||||
\mess{i}{{``malloc(x)''}}{s}
|
||||
\mess{s}{``fail'' / ``return z''}{i}
|
||||
\mess{i}{``return z''}{s}
|
||||
\mess{s}{``fail'' / ``return c''}{i}
|
||||
\mess{i}{``return c''}{s}
|
||||
\end{call}
|
||||
\end{sdblock}
|
||||
\end{sequencediagram}
|
||||
@@ -91,22 +91,33 @@ The server responds in one of four possible ways:
|
||||
|
||||
This message informs the server about the resulting return value.
|
||||
The server does not acknowledge this message.
|
||||
The contents of this message type correspond the second line of an intercepted function call (see Section~\ref{sec:automated-testing-on-intercepted-function-calls}).
|
||||
The contents of this message type correspond to the second line of an intercepted function call (see Section~\ref{sec:automated-testing-on-intercepted-function-calls}).
|
||||
|
||||
|
||||
\section{Automated Testing using Function Call Manipulation}\label{sec:automated-testing-using-function-call-manipulation}
|
||||
|
||||
As seen in Figure~\ref{fig:control-flow} function call manipulation allows for mocking individual calls.
|
||||
Mocking may be used to see how the program behaves, when individual calls to function fail or return an unusual, but valid, value.
|
||||
Mocking may be used to see how the program behaves when individual calls to function fail or return an unusual, but valid, value.
|
||||
The simplest way to automatically test programs is to run them multiple times and on each run let a single function call fail.
|
||||
The resulting sequence of function calls now may be put together to a call sequence graph (or tree).
|
||||
By analysing this call graph, it is possible to decide, if a program correctly terminated when faced with a failed function call.
|
||||
This may be the case, when the following function calls differ from those which were recorded on a default run (without any mocked function calls).
|
||||
By analyzing this call graph, it is possible to decide if a program correctly terminated when faced with a failed function call.
|
||||
This may be the case when the following function calls differ from those which were recorded on a default run (without any mocked function calls).
|
||||
|
||||
|
||||
\subsection{Testing Return Value Checks}\label{subsec:testing-return-value-checks}
|
||||
|
||||
Lorem Ipsum.
|
||||
Figure~\ref{fig:call-sequence} shows the simplified and collapsed call sequence graph of prior example in Section~\ref{sec:intercepting-example}.
|
||||
Each edge between two nodes without any label indicates the next function call on a normal run of the program.
|
||||
Edges labeled with ``fail'' indicate the next function call after a mocked failed call.
|
||||
In reality, there are multiple failing paths, each for every possible error return value, but in this example they all yield the same resulting path, therefore, they have been collapsed.
|
||||
|
||||
To test, if a programmer always checked the return value of a function and acted accordingly, this resulting call sequence graph now may be analyzed.
|
||||
This test seems trivial at first.
|
||||
The simplest approach is to verify that after a failing function call only ``cleanup'' function calls (\texttt{free}, \texttt{close}, \texttt{exit}, \dots) follow.
|
||||
For simple programs, this assumption may hold, but there are many exceptions.
|
||||
For example, what if the program recognizes the failed call correctly as failed but recovers and continues to operate normally?
|
||||
Or what if the ``cleanup'' path is very complex and includes function calls not prior marked as valid cleanup functions?
|
||||
However, for simple programs (like those mentioned in\todo{Goals}) the simplest approach from above suffices.
|
||||
|
||||
\begin{figure}
|
||||
\begin{tikzpicture}[node distance=15mm, thick, main/.style = {draw, circle}, text centered]
|
||||
@@ -156,7 +167,16 @@ Lorem Ipsum.
|
||||
\end{figure}
|
||||
|
||||
|
||||
\subsection{Testing Interrupts}\label{subsec:testing-interrupts}
|
||||
\subsection{Testing Correct Handling of Interrupts}\label{subsec:testing-interrupts}
|
||||
|
||||
Lorem Ipsum.
|
||||
EINTR.
|
||||
Many functions (like \texttt{read}, \texttt{write}, or \texttt{sem\_wait}) are interruptable by signals.
|
||||
When this happens, they return a value indicating an error and set \texttt{errno} to \texttt{EINTR}.
|
||||
Usually, the program is expected to repeat the call until it gets a real return value or error other than \texttt{EINTR}.
|
||||
Therefore, testing correct handling of interrupts is a different type of test in contrast to general tests on return value checks as seen in Subsection~\ref{subsec:testing-return-value-checks}.
|
||||
|
||||
It is relatively simple to test if a program correctly handles interrupts.
|
||||
On any function call, that may yield \texttt{EINTR} mock the call and return exactly that error.
|
||||
Afterward, check if the same function is called again.
|
||||
To increase confidence in the result, one may repeat this process multiple times.
|
||||
As in the test in Subsection~\ref{subsec:testing-return-value-checks}, the handling of the interrupt may involve calls to other functions, so this method is not always the right choice.
|
||||
But for simple programs, it totally suffices.
|
||||
|
||||
Reference in New Issue
Block a user