# CBMC as unit testing

Think of CBMC as a form of unit testing: If you can write a unit test, then you can write a CBMC proof. One of the things we can do with unit testing is to run a function on a set of inputs, and to compare the result with the expected result. Think of CBMC as a unit tester that runs the function on all possible inputs.

Here is a
function `quartile`

from quartile.c
that returns the quartile of an integer between 0 and 99.

```
int quartile(int x) {
int y;
if (x < 0 || x > 99) return 0;
if (x < 50)
if (x < 25)
y = 1;
else
y = 2;
else
if (x < 75)
y = 3;
else
y = 4;
return y;
}
```

Here a unit test from unit-test.c that tests
`quartile`

using a number from the first quartile.

```
#include <assert.h>
int quartile(int x);
int main() {
int x = 1;
int result = quartile(x);
assert(result == 1);
}
```

We can build the unit test with `gcc`

and run it.
When we do, the unit test runs successfully,
and the assertion does not fail:

```
gcc quartile.c unit-test.c -o unit-test
./unit-test
```

We can also build the unit test with `goto-cc`

, which is a drop-in
replacement for `gcc`

that comes with CBMC. Now we can use CBMC to
run the unit test, and again the assertion does not fail:

```
goto-cc quartile.c unit-test.c -o unit-test
cbmc ./unit-test
```

```
** Results:
unit-test.c function main
[main.assertion.1] line 8 assertion result == 1: SUCCESS
** 0 of 1 failed (1 iterations)
VERIFICATION SUCCESSFUL
```

For examples as simple as this,
we can actually run CBMC directly on the source files
(without explicitly invoking `goto-cc`

):

```
cbmc quartile.c unit-test.c
```

```
** Results:
unit-test.c function main
[main.assertion.1] line 8 assertion result == 1: SUCCESS
** 0 of 1 failed (1 iterations)
VERIFICATION SUCCESSFUL
```

But now we can do something interesting with CBMC.
The unit test currently initializes the variable `x`

to 1,
and CBMC considers 1 to be the initial value of `x`

. If
we remove the initializer, CBMC allows any integer value to be
the initial value of `x`

. This is a general rule: If CBMC encounters
an uninitialized variable, then CBMC allows any value from the variable's
type to be the variable's initial value.
We say that CBMC treats uninitialized variables as having unconstrained
initial values.

If we rewrite the unit test

```
#include <assert.h>
int quartile(int x);
int main() {
int x; // The value of x is now any value of type int
int result = quartile(x);
assert(result == 1);
}
```

and rerun CBMC

```
cbmc quartile.c unit-test.c
```

```
** Results:
unit-test.c function main
[main.assertion.1] line 8 assertion result == 1: FAILURE
** 1 of 1 failed (2 iterations)
VERIFICATION FAILED
```

we can see that the assertion has failed. We can ask CBMC to produce an error trace that demonstrates one way in which the assertion can fail

```
cbmc quartile.c unit-test.c --trace
```

```
** Results:
unit-test.c function main
[main.assertion.1] line 8 assertion result == 1: FAILURE
Trace for main.assertion.1:
State 21 file unit-test.c function main line 6 thread 0
----------------------------------------------------
x=-2147483547 (10000000 00000000 00000000 01100101)
State 22 file unit-test.c function main line 7 thread 0
----------------------------------------------------
result=0 (00000000 00000000 00000000 00000000)
State 26 file unit-test.c function main line 7 thread 0
----------------------------------------------------
x=-2147483547 (10000000 00000000 00000000 01100101)
State 27 file quartile.c function quartile line 2 thread 0
----------------------------------------------------
y=0 (00000000 00000000 00000000 00000000)
State 33 file unit-test.c function main line 7 thread 0
----------------------------------------------------
result=0 (00000000 00000000 00000000 00000000)
Violated property:
file unit-test.c function main line 8 thread 0
assertion result == 1
!((signed long int)(signed long int)!(result == 1) != 0l)
** 1 of 1 failed (2 iterations)
VERIFICATION FAILED
```

and we see that in the first step of this error trace the variable `x`

is initialized to the integer value `x=-2147483547`

.

Well, that's not quite what we intended, but we don't expect `quartile`

to return 1 on every integer, just on integers in the first quartile.
We can constrain `x`

to be an integer in the first quartile by adding
an assumption to the unit test:

```
#include <assert.h>
int quartile(int x);
int main() {
int x;
__CPROVER_assume(0 <= x && x < 25); // this is a precondition
int result = quartile(x);
assert(result == 1); // this is a postcondition
}
```

Rerunning CBMC, we see that the assertion is always true:

```
cbmc quartile.c unit-test.c
```

```
** Results:
unit-test.c function main
[main.assertion.1] line 9 assertion result == 1: SUCCESS
** 0 of 1 failed (1 iterations)
VERIFICATION SUCCESSFUL
```

Let's pause for a moment to notice that we have already done something
interesting.
We have proved that the function `quartile`

returns 1 when it is called
on any integer in the first quartile.
We have partially specified the behavior of the function using
a precondition (the assumption that `x`

is in the first quartile)
and a postcondition (the assertion that the return value is `1`

).
If the function is called with an input that satisfies the precondition,
then the function returns with a value that satisfies the postcondition.
Of course, we have only partially specified the behavior of the function.
What happens when it is called with an integer in the second
quartile? The specification doesn't say. But we have taken
the first step toward specification and verification of our function.