]> git.saurik.com Git - apple/security.git/blob - utilities/Regressions/su-40-secdb.c
Security-55471.14.tar.gz
[apple/security.git] / utilities / Regressions / su-40-secdb.c
1 //
2 // su-40-secdb.c
3 // utilities
4 //
5 // Created by Michael Brouwer on 11/15/12.
6 // Copyright (c) 2012 Apple Inc. All rights reserved.
7 //
8
9 #include <utilities/SecCFRelease.h>
10 #include <utilities/SecDb.h>
11
12 #include <CoreFoundation/CoreFoundation.h>
13
14 #include "utilities_regressions.h"
15 #include <time.h>
16
17 #define kTestCount 31
18
19 static int count_func(SecDbRef db, const char *name, CFIndex *max_conn_count, bool (*perform)(SecDbRef db, CFErrorRef *error, void (^perform)(SecDbConnectionRef dbconn))) {
20 __block int count = 0;
21 __block int max_count = 0;
22 *max_conn_count = 0;
23 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
24 dispatch_group_t group = dispatch_group_create();
25
26 for (int i = 0; i < 100; ++i) {
27 dispatch_group_async(group, queue, ^{
28 CFIndex conn_count = SecDbIdleConnectionCount(db);
29 if (conn_count > *max_conn_count) {
30 *max_conn_count = conn_count;
31 }
32
33 CFErrorRef error = NULL;
34 if (!perform(db, &error, ^void (SecDbConnectionRef dbconn) {
35 count++;
36 if (count > max_count) {
37 max_count = count;
38 }
39 struct timespec ts = { .tv_nsec = 200000 };
40 nanosleep(&ts, NULL);
41 count--;
42 })) {
43 fail("perform %s %@", name, error);
44 CFReleaseNull(error);
45 }
46 });
47 }
48 dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
49 dispatch_release(group);
50 return max_count;
51 }
52
53 static void count_connections(SecDbRef db) {
54 __block CFIndex max_conn_count = 0;
55 dispatch_group_t group = dispatch_group_create();
56 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
57 dispatch_group_async(group, queue, ^{
58 cmp_ok(count_func(db, "writers", &max_conn_count, SecDbPerformWrite), <=, kSecDbMaxWriters, "max writers is %d", kSecDbMaxWriters);
59 TODO: {
60 todo("can't guarantee all threads used");
61 is(count_func(db, "writers", &max_conn_count, SecDbPerformWrite), kSecDbMaxWriters, "max writers is %d", kSecDbMaxWriters);
62 }
63 });
64 dispatch_group_async(group, queue, ^{
65 cmp_ok(count_func(db, "readers", &max_conn_count, SecDbPerformRead), <=, kSecDbMaxReaders, "max readers is %d", kSecDbMaxReaders);
66 TODO: {
67 todo("can't guarantee all threads used");
68 is(count_func(db, "readers", &max_conn_count, SecDbPerformRead), kSecDbMaxReaders, "max readers is %d", kSecDbMaxReaders);
69 }
70 });
71 dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
72 dispatch_release(group);
73 cmp_ok(max_conn_count, <=, kSecDbMaxIdleHandles, "max idle connection count is %d", kSecDbMaxIdleHandles);
74 TODO: {
75 todo("can't guarantee all threads idle");
76 is(max_conn_count, kSecDbMaxIdleHandles, "max idle connection count is %d", kSecDbMaxIdleHandles);
77 }
78
79 }
80
81 static void tests(void)
82 {
83 CFTypeID typeID = SecDbGetTypeID();
84 CFStringRef tid = CFCopyTypeIDDescription(typeID);
85 ok(CFEqual(CFSTR("SecDb"), tid), "tid matches");
86 CFReleaseNull(tid);
87
88 typeID = SecDbConnectionGetTypeID();
89 tid = CFCopyTypeIDDescription(typeID);
90 ok(CFEqual(CFSTR("SecDbConnection"), tid), "tid matches");
91 CFReleaseNull(tid);
92
93 const char *home_var = getenv("HOME");
94 CFStringRef dbName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s/Library/Keychains/su-40-sqldb.db"), home_var ? home_var : "");
95
96 SecDbRef db = SecDbCreate(dbName, NULL);
97 ok(db, "SecDbCreate");
98
99 __block CFErrorRef error = NULL;
100 ok(SecDbPerformWrite(db, &error, ^void (SecDbConnectionRef dbconn) {
101 ok(SecDbExec(dbconn, CFSTR("CREATE TABLE tablea(key TEXT,value BLOB);"), &error),
102 "exec: %@", error);
103 ok(SecDbExec(dbconn, CFSTR("INSERT INTO tablea(key,value)VALUES(1,2);"), &error),
104 "exec: %@", error);
105
106 CFStringRef sql = CFSTR("INSERT INTO tablea(key,value)VALUES(?,?);");
107 ok(SecDbPrepare(dbconn, sql, &error, ^void (sqlite3_stmt *stmt) {
108 ok_status(sqlite3_bind_text(stmt, 1, "key1", 4, NULL), "bind_text[1]");
109 ok_status(sqlite3_bind_blob(stmt, 2, "value1", 6, NULL), "bind_blob[2]");
110 ok(SecDbStep(dbconn, stmt, &error, NULL), "SecDbStep: %@", error);
111 CFReleaseNull(error);
112 }), "SecDbPrepare: %@", error);
113 CFReleaseNull(error);
114
115 sql = CFSTR("SELECT key,value FROM tablea;");
116 ok(SecDbPrepare(dbconn, sql, &error, ^void (sqlite3_stmt *stmt) {
117 ok(SecDbStep(dbconn, stmt, &error, ^(bool *stop) {
118 const unsigned char *key = sqlite3_column_text(stmt, 1);
119 pass("got a row key: %s", key);
120 // A row happened, we're done
121 *stop = true;
122 }), "SecDbStep: %@", error);
123 CFReleaseNull(error);
124 }), "SecDbPrepare: %@", error);
125 CFReleaseNull(error);
126
127 ok(SecDbTransaction(dbconn, kSecDbExclusiveTransactionType, &error, ^(bool *commit) {
128 ok(SecDbExec(dbconn, CFSTR("INSERT INTO tablea (key,value)VALUES(13,21);"), &error),
129 "exec: %@", error);
130 ok(SecDbExec(dbconn, CFSTR("INSERT INTO tablea (key,value)VALUES(2,5);"), &error),
131 "exec: %@", error);
132 }), "SecDbTransaction: %@", error);
133
134 ok(SecDbPrepare(dbconn, sql, &error, ^void (sqlite3_stmt *stmt) {
135 ok(SecDbStep(dbconn, stmt, &error, ^(bool *stop) {
136 const unsigned char *key = sqlite3_column_text(stmt, 1);
137 pass("got a row key: %s", key);
138 }), "SecDbStep: %@", error);
139 CFReleaseNull(error);
140 sqlite3_reset(stmt);
141 ok(SecDbStep(dbconn, stmt, &error, ^(bool *stop) {
142 const unsigned char *key = sqlite3_column_text(stmt, 1);
143 pass("got a row key: %s", key);
144 *stop = true;
145 }), "SecDbStep: %@", error);
146 CFReleaseNull(error);
147
148 }), "SecDbPrepare: %@", error);
149
150 ok(SecDbExec(dbconn, CFSTR("DROP TABLE tablea;"), &error),
151 "exec: %@", error);
152 }), "SecDbPerformWrite: %@", error);
153 CFReleaseNull(error);
154
155 count_connections(db);
156
157 CFReleaseNull(db);
158 }
159
160 int su_40_secdb(int argc, char *const *argv)
161 {
162 plan_tests(kTestCount);
163 tests();
164
165 return 0;
166 }
167
168 #if 0
169 // The following still need tests.
170 ok(SecDbTransaction(dbconn, kSecDbNoneTransactionType, &error, ^bool {}), "");
171 ok(SecDbTransaction(dbconn, kSecDbImmediateTransactionType, &error, ^bool {}), "");
172 ok(SecDbTransaction(dbconn, kSecDbNormalTransactionType, &error, ^bool {}), "");
173 ok(SecDbPerformRead(SecDbRef db, CFErrorRef *error, void ^(SecDbConnectionRef dbconn){}), "");
174 SecDbCheckpoint(SecDbConnectionRef dbconn);
175 #endif