Documentation Source Text

Check-in [076b02c111]

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

Comment:Add initial words for the assert.html document. Clearly label the document as a work-in-progress for now.
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
Text clarification and typo fixes on the copyright.html page. check-in: 8a0f41df1a user: drh tags: branch-3.22
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
Fix typo in the vtab.html document. check-in: ec9c8be989 user: drh tags: branch-3.22
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Added pages/

            1  +<title>The Use Of assert() In SQLite</title>
            2  +
            3  +<table_of_contents>
            4  +
            5  +<h1 style="color:red;">Work In Progress - Do Not Link!</h1>
            6  +<p style="color:red;font-size:150%;">
            7  +This document is a work-in-progress and is not yet ready for release.
            8  +Please do not link to it, yet.
            9  +</p>
           10  +
           11  +<h1>Assert() And Other Assert()-like Macros In SQLite</h1>
           12  +
           13  +<p>
           14  +The assert(X) macro is 
           15  +[|part of standard C], in the the
           16  +&lt;assert.h&gt; header file.
           17  +SQLite adds three other assert()-like macros named NEVER(X), ALWAYS(X),
           18  +and testcase(X).
           19  +
           20  +<ul>
           21  +<li><p><b>assert(X)</b> &rarr;
           22  +The assert(X) statement indicates that the condition X is always true.
           23  +In other words, X is an invariant.  The assert(X) macro works like a
           24  +procedure in that it has no return value.
           25  +
           26  +<li><p><b>ALWAYS(X)</b> &rarr;
           27  +The ALWAYS(X) function indicates that condition X is always true as far
           28  +as the developers know, but there is not proof the X is true, or the
           29  +proof is complex and error-prone, or the proof depends on implementation
           30  +details that are likely to change in the future.  ALWAYS(X) behaves like
           31  +a function that returns the boolean value X, and is intended to be used
           32  +within the conditional of an "if" statement.
           33  +
           34  +<li><p><b>NEVER(X)</b> &rarr;
           35  +The NEVER(X) function indicates that condition X is never true.  This
           36  +is the negative analog of the ALWAYS(X) function.
           37  +
           38  +<li><p><b>testcase(X)</b> &rarr;
           39  +The testcase(X) statement indicates that X is sometimes true and sometimes
           40  +false.  In other words, testcase(X) indicates that X is definitely not an
           41  +invariant.  Since SQLite uses 100% [MC/DC testing], the presence of a
           42  +testcase(X) macro indicates that not only is it possible for X to be either
           43  +true or false, but there are test cases to demonstrate this.
           44  +</ul>
           45  +
           46  +<p>
           47  +SQLite version 3.22.0 ([dateof:3.22.0]) contains 5290 assert() macros,
           48  +839 testcase() macros, 88 ALWAYS() macros, and 63 NEVER() macros.
           49  +
           50  +<h2>Philosophy of assert()</h2>
           51  +
           52  +<p>In SQLite, the presence of assert(X) means that the developers have
           53  +a proof that X is always true.  Readers can depend upon X being true to
           54  +help them reason about the code.  An assert(X) is a strong statement
           55  +about the truth of X.  There is no doubt.
           56  +
           57  +<p>The ALWAYS(X) and NEVER(X) macros are a weaker statement about the
           58  +truth of X.  The presence of ALWAYS(X) or NEVER(X) means that the developers
           59  +believe X is always or never true, but there is no proof, or the proof
           60  +is complex and error-prone, or the proof depends on other aspects 
           61  +of the system that seem likely to change.
           62  +
           63  +<p>In other systems, developers sometimes use assert(X) in a way that is
           64  +similar to the use of ALWAYS(X) in SQLite.  Developers will add an
           65  +assert(X) as a 
           66  +[|tacit acknowledgement that they
           67  +do not fully believe that X is always true].
           68  +We believe that this use of assert(X) is wrong and violates the intent
           69  +and purpose of having assert(X) available in C in the first place.
           70  +An assert(X) should not be seen as a safety-net or top-rope used to
           71  +guard against mistakes.  Nor is assert(X) appropriate for defense-in-depth.
           72  +An ALWAYS(X) macro, or something similar, should be used in those cases
           73  +because ALWAYS(X) is followed by code to actually deal with the problem.
           74  +
           75  +<p>The [|Go programming language] omits assert().
           76  +The Go developers
           77  +[|recognize this is contentious].
           78  +Disallowing assert() is essentially telling developers that they are
           79  +not allowed to expression invariants.  It is as if the developers of
           80  +Go do not want coders to prove that the software is correct.
           81  +The SQLite developers believe that the lack of assert() disqualifies
           82  +Go as a language for serious development work.
           83  +
           84  +<h2>Different Behaviors According To Build Type</h2>
           85  +
           86  +<p>Three separate builds are used to validate the SQLite software.
           87  +A functionality testing build is used to validate the source code.
           88  +A coverage testing build is used to validate the test suite, to confirm
           89  +that the test suite provides 100% MC/DC.  The release build is used
           90  +to validate the machine code.  
           91  +All tests must give the same answer in all three
           92  +builds. See the [testing|"How SQLite Is Tested"] document for more detail.
           93  +
           94  +<p>The assert() macros behave differently according to how SQLite is built.
           95  +
           96  +<center>
           97  +<table border=1>
           98  +<tr><th><th>Functionality Testing<th>Coverage Testing<th>Release</tr>
           99  +<tr><th valign="top">assert(X)
          100  +<td>abort() if X is false
          101  +<td>no-op
          102  +<td>no-op
          103  +</tr>
          104  +<tr><th valign="top">ALWAYS(X)
          105  +<td>abort() if X is false
          106  +<td>always true
          107  +<td>pass through the value X
          108  +</tr>
          109  +<tr><th valign="top">NEVER(X)
          110  +<td>abort() if X is true
          111  +<td>always false
          112  +<td>pass through the value X
          113  +</tr>
          114  +<tr><th valign="top">testcase(X)
          115  +<td>no-op
          116  +<td>do some harmless work if X is true
          117  +<td>no-op
          118  +</tr>
          119  +</table>
          120  +</center>
          121  +
          122  +<p>The default behavior of assert(X) in standard C is that it is enabled
          123  +for release builds.  We find this acceptable in general.  However, the
          124  +SQLite code base has many assert() statements in performance-sensitive
          125  +areas of the code.  Leaving assert(X) turned causes SQLite to run about
          126  +three times slower.  Also, SQLite strives to provide 100% MC/DC in an
          127  +as-delivered configuration, which is obviously impossible if assert(X)
          128  +statements are enabled.  For these reasons, assert(X) is a no-op for
          129  +release builds in SQLite.