Documentation Source Text

Check-in [076b02c111]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add initial words for the assert.html document. Clearly label the document as a work-in-progress for now.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | branch-3.22
Files: files | file ages | folders
SHA3-256: 076b02c1119338ad1f1b0046954592a6f5d9184d702df454656504ac27dff1aa
User & Date: drh 2018-02-13 15:40:22.366
Context
2018-02-17
17:08
Text clarification and typo fixes on the copyright.html page. (check-in: 8a0f41df1a user: drh tags: branch-3.22)
2018-02-13
15:40
Add initial words for the assert.html document. Clearly label the document as a work-in-progress for now. (check-in: 076b02c111 user: drh tags: branch-3.22)
2018-02-07
20:35
Fix typo in the vtab.html document. (check-in: ec9c8be989 user: drh tags: branch-3.22)
Changes
Side-by-Side Diff Ignore Whitespace Patch
Added pages/assert.in.

































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<title>The Use Of assert() In SQLite</title>

<table_of_contents>

<h1 style="color:red;">Work In Progress - Do Not Link!</h1>
<p style="color:red;font-size:150%;">
This document is a work-in-progress and is not yet ready for release.
Please do not link to it, yet.
</p>

<h1>Assert() And Other Assert()-like Macros In SQLite</h1>

<p>
The assert(X) macro is 
[https://en.wikipedia.org/wiki/Assert.h|part of standard C], in the the
&lt;assert.h&gt; header file.
SQLite adds three other assert()-like macros named NEVER(X), ALWAYS(X),
and testcase(X).

<ul>
<li><p><b>assert(X)</b> &rarr;
The assert(X) statement indicates that the condition X is always true.
In other words, X is an invariant.  The assert(X) macro works like a
procedure in that it has no return value.

<li><p><b>ALWAYS(X)</b> &rarr;
The ALWAYS(X) function indicates that condition X is always true as far
as the developers know, but there is not proof the X is true, or the
proof is complex and error-prone, or the proof depends on implementation
details that are likely to change in the future.  ALWAYS(X) behaves like
a function that returns the boolean value X, and is intended to be used
within the conditional of an "if" statement.

<li><p><b>NEVER(X)</b> &rarr;
The NEVER(X) function indicates that condition X is never true.  This
is the negative analog of the ALWAYS(X) function.

<li><p><b>testcase(X)</b> &rarr;
The testcase(X) statement indicates that X is sometimes true and sometimes
false.  In other words, testcase(X) indicates that X is definitely not an
invariant.  Since SQLite uses 100% [MC/DC testing], the presence of a
testcase(X) macro indicates that not only is it possible for X to be either
true or false, but there are test cases to demonstrate this.
</ul>

<p>
SQLite version 3.22.0 ([dateof:3.22.0]) contains 5290 assert() macros,
839 testcase() macros, 88 ALWAYS() macros, and 63 NEVER() macros.

<h2>Philosophy of assert()</h2>

<p>In SQLite, the presence of assert(X) means that the developers have
a proof that X is always true.  Readers can depend upon X being true to
help them reason about the code.  An assert(X) is a strong statement
about the truth of X.  There is no doubt.

<p>The ALWAYS(X) and NEVER(X) macros are a weaker statement about the
truth of X.  The presence of ALWAYS(X) or NEVER(X) means that the developers
believe X is always or never true, but there is no proof, or the proof
is complex and error-prone, or the proof depends on other aspects 
of the system that seem likely to change.

<p>In other systems, developers sometimes use assert(X) in a way that is
similar to the use of ALWAYS(X) in SQLite.  Developers will add an
assert(X) as a 
[https://blog.regehr.org/archives/1576|tacit acknowledgement that they
do not fully believe that X is always true].
We believe that this use of assert(X) is wrong and violates the intent
and purpose of having assert(X) available in C in the first place.
An assert(X) should not be seen as a safety-net or top-rope used to
guard against mistakes.  Nor is assert(X) appropriate for defense-in-depth.
An ALWAYS(X) macro, or something similar, should be used in those cases
because ALWAYS(X) is followed by code to actually deal with the problem.

<p>The [https://golang.org|Go programming language] omits assert().
The Go developers
[https://golang.org/doc/faq#assertions|recognize this is contentious].
Disallowing assert() is essentially telling developers that they are
not allowed to expression invariants.  It is as if the developers of
Go do not want coders to prove that the software is correct.
The SQLite developers believe that the lack of assert() disqualifies
Go as a language for serious development work.

<h2>Different Behaviors According To Build Type</h2>

<p>Three separate builds are used to validate the SQLite software.
A functionality testing build is used to validate the source code.
A coverage testing build is used to validate the test suite, to confirm
that the test suite provides 100% MC/DC.  The release build is used
to validate the machine code.  
All tests must give the same answer in all three
builds. See the [testing|"How SQLite Is Tested"] document for more detail.

<p>The assert() macros behave differently according to how SQLite is built.

<center>
<table border=1>
<tr><th><th>Functionality Testing<th>Coverage Testing<th>Release</tr>
<tr><th valign="top">assert(X)
<td>abort() if X is false
<td>no-op
<td>no-op
</tr>
<tr><th valign="top">ALWAYS(X)
<td>abort() if X is false
<td>always true
<td>pass through the value X
</tr>
<tr><th valign="top">NEVER(X)
<td>abort() if X is true
<td>always false
<td>pass through the value X
</tr>
<tr><th valign="top">testcase(X)
<td>no-op
<td>do some harmless work if X is true
<td>no-op
</tr>
</table>
</center>

<p>The default behavior of assert(X) in standard C is that it is enabled
for release builds.  We find this acceptable in general.  However, the
SQLite code base has many assert() statements in performance-sensitive
areas of the code.  Leaving assert(X) turned causes SQLite to run about
three times slower.  Also, SQLite strives to provide 100% MC/DC in an
as-delivered configuration, which is obviously impossible if assert(X)
statements are enabled.  For these reasons, assert(X) is a no-op for
release builds in SQLite.