Skip to content

Commit e30da66

Browse files
author
martin
committed
Tests for the new functionality in goto-analyzer
1 parent ee6c32e commit e30da66

File tree

12 files changed

+290
-0
lines changed

12 files changed

+290
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include <assert.h>
2+
3+
int main(int argc, char **argv)
4+
{
5+
int branch;
6+
int x = 0;
7+
8+
if(branch)
9+
{
10+
x = 1;
11+
}
12+
else
13+
{
14+
x = -1;
15+
}
16+
17+
// Merging a constant domain here will make this unprovable
18+
assert(x != 0);
19+
20+
// Some subtle points here...
21+
// The history tracks paths, it is up to the domain to track the
22+
// path conditon / consequences of that path.
23+
//
24+
// We have two paths:
25+
// branch == ?, x == 1
26+
// branch == 0, x == -1
27+
//
28+
// As the domain in the first case can't express branch != 0
29+
// we will wind up with three paths here, including a spurious
30+
// one with branch == 0, x == 1.
31+
if(branch)
32+
{
33+
assert(x == 1);
34+
}
35+
else
36+
{
37+
assert(x == -1);
38+
}
39+
40+
// Working around the domain issues...
41+
// (This doesn't increase the number of paths)
42+
if(x == 1)
43+
{
44+
x--;
45+
}
46+
else
47+
{
48+
x++;
49+
}
50+
51+
// Should be true in all 3 paths
52+
assert(x == 0);
53+
54+
return 0;
55+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
main.c
3+
--verify --recursive-interprocedural --branching 0 --constants --one-domain-per-history
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.assertion.1\] .* assertion x != 0: SUCCESS$
7+
^\[main.assertion.2\] .* assertion x == 1: SUCCESS$
8+
^\[main.assertion.3\] .* assertion x == -1: FAILURE \(if reachable\)$
9+
^\[main.assertion.4\] .* assertion x == 0: SUCCESS$
10+
--
11+
^warning: ignoring
12+
--
13+
This demonstrates the "lazy merging" that comes from tracking the history of branching
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include <assert.h>
2+
3+
int main(int argc, char **argv)
4+
{
5+
int branching_array[5];
6+
int x = 1;
7+
8+
if(branching_array[0])
9+
{
10+
++x;
11+
}
12+
// Two paths...
13+
assert(x > 0);
14+
15+
if(branching_array[1])
16+
{
17+
++x;
18+
}
19+
// Four paths...
20+
assert(x > 0);
21+
22+
if(branching_array[2])
23+
{
24+
++x;
25+
}
26+
// Eight paths...
27+
assert(x > 0);
28+
29+
if(branching_array[3])
30+
{
31+
++x;
32+
}
33+
// Paths merge so there will be some paths that will set x to \top
34+
// and so this will be flagged as unknown
35+
assert(x > 0);
36+
// In principle it would be possible to merge paths in such a way
37+
// that the those with similar domains are merged and this would be
38+
// able to be proved. The local_control_flow_history code doesn't
39+
// do this though.
40+
41+
return 0;
42+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
main.c
3+
--verify --recursive-interprocedural --branching 12 --constants --one-domain-per-history
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.assertion.1\] .* assertion x > 0: SUCCESS$
7+
^\[main.assertion.2\] .* assertion x > 0: SUCCESS$
8+
^\[main.assertion.3\] .* assertion x > 0: SUCCESS$
9+
^\[main.assertion.4\] .* assertion x > 0: UNKNOWN$
10+
--
11+
^warning: ignoring
12+
--
13+
This demonstrates hitting the path limit and the merging of paths
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <assert.h>
2+
3+
int main(int argc, char **argv)
4+
{
5+
int total = 0;
6+
int n = 50;
7+
int i;
8+
9+
for(i = 0; i < n; ++i)
10+
{
11+
total += i;
12+
}
13+
14+
assert(total == (n * (n - 1) / 2));
15+
16+
return 0;
17+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
--verify --recursive-interprocedural --loop-unwind 0 --constants --one-domain-per-history
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.assertion.1\] .* assertion total == \(n \* \(n - 1\) / 2\): SUCCESS$
7+
--
8+
^warning: ignoring
9+
--
10+
A basic test of loop unwinding.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include <assert.h>
2+
3+
int main(int argc, char **argv)
4+
{
5+
int total;
6+
int n;
7+
int i;
8+
9+
total = 0;
10+
n = 8;
11+
for(i = 0; i < n; ++i)
12+
{
13+
total += i;
14+
}
15+
16+
// Unknown due to the limit on unwindings
17+
assert(total == (n * (n - 1) / 2));
18+
19+
// Condense down to one path...
20+
21+
total = 0;
22+
n = 16;
23+
for(i = 0; i < n; ++i)
24+
{
25+
total += i;
26+
}
27+
28+
// Creates a merge path but only one user of it
29+
assert(total == (n * (n - 1) / 2));
30+
31+
total = 0;
32+
n = 32;
33+
for(i = 0; i < n; ++i)
34+
{
35+
total += i;
36+
}
37+
38+
// Provable
39+
assert(total == (n * (n - 1) / 2));
40+
41+
return 0;
42+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
CORE
2+
main.c
3+
--verify --recursive-interprocedural --loop-unwind 17 --constants --one-domain-per-history
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.assertion.1\] .* assertion total == \(n \* \(n - 1\) / 2\): SUCCESS$
7+
^\[main.assertion.2\] .* assertion total == \(n \* \(n - 1\) / 2\): SUCCESS$
8+
^\[main.assertion.3\] .* assertion total == \(n \* \(n - 1\) / 2\): UNKNOWN$
9+
--
10+
^warning: ignoring
11+
--
12+
A basic test of the loop unwinding limit.
13+
You might think this has an off-by-one error but to process a loop 16 times
14+
you have to visit the loop guard 17 times. Setting the loop limit to 16 will
15+
cause the last two visits to merge loosing the precision needed to prove the
16+
conjecture.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include <assert.h>
2+
3+
int main(int argc, char **argv)
4+
{
5+
int total;
6+
int n;
7+
int i;
8+
int branching[4];
9+
10+
total = 0;
11+
n = 4;
12+
for(i = 0; i < n; ++i)
13+
{
14+
if(branching[i])
15+
{
16+
total += i;
17+
}
18+
}
19+
20+
assert(total <= (n * (n - 1) / 2));
21+
22+
return 0;
23+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
main.c
3+
--verify --recursive-interprocedural --loop-unwind-and-branching 32 --constants --one-domain-per-history
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.assertion.1\] .* assertion total <= \(n \* \(n - 1\) / 2\): SUCCESS$
7+
--
8+
^warning: ignoring
9+
--
10+
Test tracking all local control-flow history.
11+
Note the exponential rise in the number of paths!
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include <assert.h>
2+
3+
#define CODE_BLOCK \
4+
int i; \
5+
float flotal = 0; \
6+
for(i = 0; i < n; ++i) \
7+
{ \
8+
flotal += i; \
9+
} \
10+
assert(flotal == (n * (n - 1) / 2))
11+
12+
void do_the_loop(int n)
13+
{
14+
CODE_BLOCK;
15+
}
16+
17+
int main(int argc, char **argv)
18+
{
19+
int j;
20+
21+
// Will give unknown unless the bound is over 25
22+
for(j = 0; j < 5; j++)
23+
{
24+
int n = 5;
25+
CODE_BLOCK;
26+
}
27+
28+
// Paths in the loop will merge but that is OK
29+
// because the value of n is the important bit
30+
for(j = 0; j < 1000; j++)
31+
{
32+
int n = 10;
33+
do_the_loop(n);
34+
}
35+
36+
return 0;
37+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
main.c
3+
--verify --recursive-interprocedural --loop-unwind-and-branching 12 --constants --one-domain-per-history
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.assertion.1\] .* assertion flotal == \(n \* \(n - 1\) / 2\): UNKNOWN$
7+
^\[do_the_loop.assertion.1\] .* assertion flotal == \(n \* \(n - 1\) / 2\): SUCCESS$
8+
--
9+
^warning: ignoring
10+
--
11+
Demonstrate the function local behaviour of this history

0 commit comments

Comments
 (0)