xref: /sqlite-3.40.0/src/test_vdbecov.c (revision afb3f3c7)
1 /*
2 ** 2019 April 02
3 **
4 ** The author disclaims copyright to this source code.  In place of
5 ** a legal notice, here is a blessing:
6 **
7 **    May you do good and not evil.
8 **    May you find forgiveness for yourself and forgive others.
9 **    May you share freely, never taking more than you give.
10 **
11 ******************************************************************************
12 **
13 */
14 #if SQLITE_TEST          /* This file is used for testing only */
15 
16 #include "sqlite3.h"
17 #include "sqliteInt.h"
18 #if defined(INCLUDE_SQLITE_TCL_H)
19 #  include "sqlite_tcl.h"
20 #else
21 #  include "tcl.h"
22 #endif
23 
24 #ifdef SQLITE_VDBE_COVERAGE
25 
26 static u8 aBranchArray[200000];
27 
test_vdbe_branch(void * pCtx,unsigned int iSrc,unsigned char iBranch,unsigned char iType)28 static void test_vdbe_branch(
29   void *pCtx,
30   unsigned int iSrc,
31   unsigned char iBranch,
32   unsigned char iType
33 ){
34   if( iSrc<sizeof(aBranchArray) ){
35     aBranchArray[iSrc] |= iBranch;
36   }
37 }
38 
appendToList(Tcl_Obj * pList,int iLine,int iPath,const char * zNever)39 static void appendToList(
40   Tcl_Obj *pList,
41   int iLine,
42   int iPath,
43   const char *zNever
44 ){
45   Tcl_Obj *pNew = Tcl_NewObj();
46   Tcl_IncrRefCount(pNew);
47   Tcl_ListObjAppendElement(0, pNew, Tcl_NewIntObj(iLine));
48   Tcl_ListObjAppendElement(0, pNew, Tcl_NewIntObj(iPath));
49   Tcl_ListObjAppendElement(0, pNew, Tcl_NewStringObj(zNever, -1));
50   Tcl_ListObjAppendElement(0, pList, pNew);
51   Tcl_DecrRefCount(pNew);
52 }
53 
54 
test_vdbe_coverage(ClientData cd,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])55 static int SQLITE_TCLAPI test_vdbe_coverage(
56   ClientData cd,
57   Tcl_Interp *interp,
58   int objc,
59   Tcl_Obj *CONST objv[]
60 ){
61   const char *aSub[] = { "start", "report", "stop", 0 };
62   int iSub = -1;
63   if( objc!=2 ){
64     Tcl_WrongNumArgs(interp, 1, objv, "sub-command");
65     return TCL_ERROR;
66   }
67 
68   if( Tcl_GetIndexFromObj(interp, objv[1], aSub, "sub-command", 0, &iSub) ){
69     return TCL_ERROR;
70   }
71 
72   Tcl_ResetResult(interp);
73   assert( iSub==0 || iSub==1 || iSub==2 );
74   switch( iSub ){
75     case 0:       /* start */
76       memset(aBranchArray, 0, sizeof(aBranchArray));
77       sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE, test_vdbe_branch, 0);
78       break;
79     case 1: {     /* report */
80       int i;
81       Tcl_Obj *pRes = Tcl_NewObj();
82       Tcl_IncrRefCount(pRes);
83       for(i=0; i<sizeof(aBranchArray); i++){
84         u8 b = aBranchArray[i];
85         int bFlag = ((b >> 4)==4);
86         if( b ){
87           if( (b & 0x01)==0 ){
88             appendToList(pRes, i, 0, bFlag ? "less than" : "falls through");
89           }
90           if( (b & 0x02)==0 ){
91             appendToList(pRes, i, 1, bFlag ? "equal" : "taken");
92           }
93           if( (b & 0x04)==0 ){
94             appendToList(pRes, i, 2, bFlag ? "greater-than" : "NULL");
95           }
96         }
97       }
98       Tcl_SetObjResult(interp, pRes);
99       Tcl_DecrRefCount(pRes);
100       break;
101     };
102 
103     default:      /* stop */
104       sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE, 0, 0);
105       break;
106   }
107 
108   return TCL_OK;
109 }
110 
111 #endif  /* SQLITE_VDBE_COVERAGE */
112 
Sqlitetestvdbecov_Init(Tcl_Interp * interp)113 int Sqlitetestvdbecov_Init(Tcl_Interp *interp){
114 #ifdef SQLITE_VDBE_COVERAGE
115   Tcl_CreateObjCommand(interp, "vdbe_coverage", test_vdbe_coverage, 0, 0);
116 #endif
117   return TCL_OK;
118 }
119 
120 #endif
121