1/*
2** 2007 March 29
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** This file contains obscure tests of the C-interface required
14** for completeness. Test code is written in C for these cases
15** as there is not much point in binding to Tcl.
16*/
17#include "sqliteInt.h"
18#include "tcl.h"
19#include <stdlib.h>
20#include <string.h>
21
22/*
23** c_collation_test
24*/
25static int c_collation_test(
26  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
27  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
28  int objc,              /* Number of arguments */
29  Tcl_Obj *CONST objv[]  /* Command arguments */
30){
31  const char *zErrFunction = "N/A";
32  sqlite3 *db;
33
34  int rc;
35  if( objc!=1 ){
36    Tcl_WrongNumArgs(interp, 1, objv, "");
37    return TCL_ERROR;
38  }
39
40  /* Open a database. */
41  rc = sqlite3_open(":memory:", &db);
42  if( rc!=SQLITE_OK ){
43    zErrFunction = "sqlite3_open";
44    goto error_out;
45  }
46
47  rc = sqlite3_create_collation(db, "collate", 456, 0, 0);
48  if( rc!=SQLITE_MISUSE ){
49    sqlite3_close(db);
50    zErrFunction = "sqlite3_create_collation";
51    goto error_out;
52  }
53
54  sqlite3_close(db);
55  return TCL_OK;
56
57error_out:
58  Tcl_ResetResult(interp);
59  Tcl_AppendResult(interp, "Error testing function: ", zErrFunction, 0);
60  return TCL_ERROR;
61}
62
63/*
64** c_realloc_test
65*/
66static int c_realloc_test(
67  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
68  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
69  int objc,              /* Number of arguments */
70  Tcl_Obj *CONST objv[]  /* Command arguments */
71){
72  void *p;
73  const char *zErrFunction = "N/A";
74
75  if( objc!=1 ){
76    Tcl_WrongNumArgs(interp, 1, objv, "");
77    return TCL_ERROR;
78  }
79
80  p = sqlite3_malloc(5);
81  if( !p ){
82    zErrFunction = "sqlite3_malloc";
83    goto error_out;
84  }
85
86  /* Test that realloc()ing a block of memory to a negative size is
87  ** the same as free()ing that memory.
88  */
89  p = sqlite3_realloc(p, -1);
90  if( p ){
91    zErrFunction = "sqlite3_realloc";
92    goto error_out;
93  }
94
95  return TCL_OK;
96
97error_out:
98  Tcl_ResetResult(interp);
99  Tcl_AppendResult(interp, "Error testing function: ", zErrFunction, 0);
100  return TCL_ERROR;
101}
102
103
104/*
105** c_misuse_test
106*/
107static int c_misuse_test(
108  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
109  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
110  int objc,              /* Number of arguments */
111  Tcl_Obj *CONST objv[]  /* Command arguments */
112){
113  const char *zErrFunction = "N/A";
114  sqlite3 *db = 0;
115  sqlite3_stmt *pStmt;
116  int rc;
117
118  if( objc!=1 ){
119    Tcl_WrongNumArgs(interp, 1, objv, "");
120    return TCL_ERROR;
121  }
122
123  /* Open a database. Then close it again. We need to do this so that
124  ** we have a "closed database handle" to pass to various API functions.
125  */
126  rc = sqlite3_open(":memory:", &db);
127  if( rc!=SQLITE_OK ){
128    zErrFunction = "sqlite3_open";
129    goto error_out;
130  }
131  sqlite3_close(db);
132
133
134  rc = sqlite3_errcode(db);
135  if( rc!=SQLITE_MISUSE ){
136    zErrFunction = "sqlite3_errcode";
137    goto error_out;
138  }
139
140  pStmt = (sqlite3_stmt*)1234;
141  rc = sqlite3_prepare(db, 0, 0, &pStmt, 0);
142  if( rc!=SQLITE_MISUSE ){
143    zErrFunction = "sqlite3_prepare";
144    goto error_out;
145  }
146  assert( pStmt==0 ); /* Verify that pStmt is zeroed even on a MISUSE error */
147
148  pStmt = (sqlite3_stmt*)1234;
149  rc = sqlite3_prepare_v2(db, 0, 0, &pStmt, 0);
150  if( rc!=SQLITE_MISUSE ){
151    zErrFunction = "sqlite3_prepare_v2";
152    goto error_out;
153  }
154  assert( pStmt==0 );
155
156#ifndef SQLITE_OMIT_UTF16
157  pStmt = (sqlite3_stmt*)1234;
158  rc = sqlite3_prepare16(db, 0, 0, &pStmt, 0);
159  if( rc!=SQLITE_MISUSE ){
160    zErrFunction = "sqlite3_prepare16";
161    goto error_out;
162  }
163  assert( pStmt==0 );
164  pStmt = (sqlite3_stmt*)1234;
165  rc = sqlite3_prepare16_v2(db, 0, 0, &pStmt, 0);
166  if( rc!=SQLITE_MISUSE ){
167    zErrFunction = "sqlite3_prepare16_v2";
168    goto error_out;
169  }
170  assert( pStmt==0 );
171#endif
172
173  return TCL_OK;
174
175error_out:
176  Tcl_ResetResult(interp);
177  Tcl_AppendResult(interp, "Error testing function: ", zErrFunction, 0);
178  return TCL_ERROR;
179}
180
181/*
182** Register commands with the TCL interpreter.
183*/
184int Sqlitetest9_Init(Tcl_Interp *interp){
185  static struct {
186     char *zName;
187     Tcl_ObjCmdProc *xProc;
188     void *clientData;
189  } aObjCmd[] = {
190     { "c_misuse_test",    c_misuse_test, 0 },
191     { "c_realloc_test",   c_realloc_test, 0 },
192     { "c_collation_test", c_collation_test, 0 },
193  };
194  int i;
195  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
196    Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
197        aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
198  }
199  return TCL_OK;
200}
201