Subversion Repositories oidplus

Rev

Rev 511 | Rev 783 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
557 daniel-mar 1
#!/usr/bin/env php
374 daniel-mar 2
<?php
3
 
4
/*
5
 * OIDplus 2.0
511 daniel-mar 6
 * Copyright 2019 - 2021 Daniel Marschall, ViaThinkSoft
374 daniel-mar 7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
 
21
// This script is used to detect problems with your database plugin
22
// ATTENTION: PLEASE DO NOT USE THIS SCRIPT ON A PRODUCTIVE DATABASE,
23
// BECAUSE IT ADDS AND CHANGES DATA DURING THE TESTING.
24
 
25
# ---
26
 
27
require_once __DIR__ . '/../includes/oidplus.inc.php';
28
 
29
$num_errs = 0;
30
$num_succ = 0;
31
 
502 daniel-mar 32
if (PHP_SAPI != 'cli') echo '<pre>';
33
 
374 daniel-mar 34
echo "OIDplus Database plugin testcases\n\n";
35
 
36
OIDplus::init(true, true);
37
 
38
# Test MySQL
502 daniel-mar 39
try {
40
	OIDplus::baseConfig()->setValue('DATABASE_PLUGIN', 'MySQL');
41
	OIDplus::init(true, true);
42
	$db = OIDplus::db();
43
	OIDplus::init(true, true);
44
	if (function_exists('mysqli_fetch_all')) {
45
		OIDplus::baseConfig()->setValue('MYSQL_FORCE_MYSQLND_SUPPLEMENT', false);
46
		echo "[With MySQLnd support] ";
47
		dotest($db);
48
		OIDplus::baseConfig()->setValue('MYSQL_FORCE_MYSQLND_SUPPLEMENT', true);
49
	}
50
	echo "[Without MySQLnd support] ";
374 daniel-mar 51
	dotest($db);
502 daniel-mar 52
} catch (Exception $e) {
53
	echo "MySQL:\n";
54
	echo redtext($e->getMessage())."\n\n";
374 daniel-mar 55
}
56
 
57
# Test PDO
502 daniel-mar 58
try {
59
	OIDplus::baseConfig()->setValue('DATABASE_PLUGIN', 'PDO');
60
	OIDplus::init(true, true);
61
	$db = OIDplus::db();
62
	dotest($db);
63
} catch (Exception $e) {
64
	echo "PDO:\n";
65
	echo redtext($e->getMessage())."\n\n";
66
}
374 daniel-mar 67
 
68
# Test ODBC
502 daniel-mar 69
try {
70
	OIDplus::baseConfig()->setValue('DATABASE_PLUGIN', 'ODBC');
71
	OIDplus::init(true, true);
72
	$db = OIDplus::db();
73
	dotest($db);
74
} catch (Exception $e) {
75
	echo "ODBC:\n";
76
	echo redtext($e->getMessage())."\n\n";
77
}
374 daniel-mar 78
 
79
# Test PgSQL
502 daniel-mar 80
try {
81
	OIDplus::baseConfig()->setValue('DATABASE_PLUGIN', 'PgSQL');
82
	OIDplus::init(true, true);
83
	$db = OIDplus::db();
84
	dotest($db);
85
} catch (Exception $e) {
86
	echo "PgSQL:\n";
87
	echo redtext($e->getMessage())."\n\n";
88
}
374 daniel-mar 89
 
90
# Test SQLite3
502 daniel-mar 91
try {
92
	OIDplus::baseConfig()->setValue('DATABASE_PLUGIN', 'SQLite');
93
	OIDplus::init(true, true);
94
	$db = OIDplus::db();
95
	dotest($db);
96
} catch (Exception $e) {
97
	echo "SQLite3:\n";
98
	echo redtext($e->getMessage())."\n\n";
99
}
374 daniel-mar 100
 
101
# ---
102
 
502 daniel-mar 103
if (PHP_SAPI != 'cli') {
104
	die('</pre>');
105
} else {
106
	exit($num_errs > 0 ? 1 : 0);
107
}
374 daniel-mar 108
 
109
# ---
110
 
111
function dotest($db) {
112
	echo "Database: " . get_class($db) . "\n";
113
	try {
114
		$db->connect();
115
	} catch (Exception $e) {
116
		echo "Connection ".redtext("FAILED")." (check userdata/baseconfig/config.inc.php): ".$e->getMessage()."\n\n";
117
		return;
118
	}
119
	echo "Detected slang: " . $db->getSlang()::id()."\n";
120
	$db->query("delete from ###objects where parent = 'test:1'");
121
	$db->query("insert into ###objects (id, parent, title, description, confidential) values ('test:1.1', 'test:1', '', '', '0')");
122
	$db->query("insert into ###objects (id, parent, title, description, confidential) values ('test:1.2', 'test:1', '', '', '0')");
123
	try {
124
		// --- "SQL Date" handling
125
 
126
		try {
127
			$res = $db->query("update ###objects set created = ".$db->sqlDate()." where id = 'test:1.1'");
128
			echo "SQLDate (".$db->sqlDate().') '.greentext('PASSED')."\n";
129
		} catch (Exception $e) {
130
			echo "SQLDate (".$db->sqlDate().') '.redtext('FAILED')."\n";
131
		}
132
 
133
		// --- "Num rows" handling
502 daniel-mar 134
 
135
		$res = $db->query("select id from ###objects where parent = ? order by id", array('test:XXXXXXXXX'));
136
		try {
137
			$num_rows = $res->num_rows();
138
		} catch (Exception $e) {
139
			$num_rows = $e->getMessage();
140
		}
141
		echo "Num rows empty: " . ($num_rows===0 ? greentext('PASSED') : redtext('FAILED'))." ($num_rows)\n";
374 daniel-mar 142
 
143
		$res = $db->query("select id from ###objects where parent = ? order by id", array('test:1'));
502 daniel-mar 144
		try {
145
			$num_rows = $res->num_rows();
146
		} catch (Exception $e) {
147
			$num_rows = $e->getMessage();
148
		}
149
		echo "Num rows: " . ($num_rows===2 ? greentext('PASSED') : redtext('FAILED'))." ($num_rows)\n";
374 daniel-mar 150
 
151
		$res->fetch_array();
502 daniel-mar 152
		try {
153
			$num_rows = $res->num_rows();
154
		} catch (Exception $e) {
155
			$num_rows = $e->getMessage();
156
		}
157
		echo "Num rows after something fetched: " . ($num_rows===2 ? greentext('PASSED') : redtext('FAILED'))." ($num_rows)\n";
374 daniel-mar 158
 
159
		$nextid = $res->fetch_array()['id'];
160
		echo "Num rows does not change cursor: " . ($nextid == 'test:1.2' ? greentext('PASSED') : redtext('FAILED'))."\n";
161
 
162
		$next = $res->fetch_array();
163
		echo "Fetch after EOF gives null: " . (is_null($next) ? greentext('PASSED') : redtext('FAILED'))."\n";
164
 
165
		// --- Simultanous prepared statements
502 daniel-mar 166
 
167
		$errmsg = '';
168
		try {
169
			$res = $db->query("select id from ###objects where parent = ? order by id", array('test:1'));
170
			$passed = false;
171
			//$res->num_rows(); // sponge
172
			while ($row = $res->fetch_array()) {
173
				$res2 = $db->query("select id from ###objects where parent = ? order by id", array($row['id']));
174
				while ($row2 = $res2->fetch_array()) {
175
				}
176
				if ($row['id'] == 'test:1.2') {
177
					$passed = true;
178
				}
374 daniel-mar 179
			}
502 daniel-mar 180
		} catch (Exception $e) {
181
			$passed = false;
182
			$errmsg = ' ('.$e->getMessage().')';
374 daniel-mar 183
		}
502 daniel-mar 184
		echo "Simultanous prepared statements: ".($passed ? greentext('PASSED') : redtext('FAILED'))."$errmsg\n";
185
 
186
		if (!$passed) {
187
			// We cannot continue because the connection is in a state that cannot be recovered easily
188
			echo "Cancelled!\n\n";
189
			return;
190
		}
191
 
374 daniel-mar 192
		// --- Exception handling
193
 
194
		try {
502 daniel-mar 195
			$db->query("SELECT * from ABCDEF");
374 daniel-mar 196
			echo "Exception for DirectQuery: ".redtext('FAILED').", no Exception thrown\n";
197
		} catch (Exception $e) {
198
			if (strpos($e->getMessage(), 'ABCDEF') !== false) {
199
				echo "Exception for DirectQuery: ".greentext('PASSED')."\n";
200
			} else {
201
				echo "Exception for DirectQuery: ".redtext('FAILED').", does probably not contain DBMS error string\n";
202
			}
203
		}
204
 
205
		$msg = $db->error();
206
		if (strpos($msg, 'ABCDEF') !== false) {
207
			echo "Error-Function after failed direct query: ".greentext('PASSED')."\n";
208
		} else {
209
			echo "Error-Function after failed direct query: ".redtext('FAILED').", does probably not contain DBMS error string ($msg)\n";
210
		}
211
 
212
		try {
502 daniel-mar 213
			$db->query("SELECT * from FEDCBA", array(''));
374 daniel-mar 214
			echo "Exception for PreparedQuery: ".redtext('FAILED').", no Exception thrown\n";
215
		} catch (Exception $e) {
216
			if (strpos($e->getMessage(), 'FEDCBA') !== false) {
217
				echo "Exception for PreparedQuery: ".greentext('PASSED')."\n";
218
			} else {
219
				echo "Exception for PreparedQuery: ".redtext('FAILED').", does probably not contain DBMS error string\n";
220
			}
221
		}
222
 
223
		$msg = $db->error();
224
		if (strpos($msg, 'FEDCBA') !== false) {
225
			echo "Error-Function after failed prepared query: ".greentext('PASSED')."\n";
226
		} else {
227
			echo "Error-Function after failed prepared query: ".redtext('FAILED').", does probably not contain DBMS error string ($msg)\n";
228
		}
229
 
230
		$db->query("select 1");
231
		$msg = $db->error();
232
		if (!$msg) {
233
			echo "Error-Function gets cleared after non-failed query: ".greentext('PASSED')."\n";
234
		} else {
235
			echo "Error-Function gets cleared after non-failed query: ".redtext('FAILED').", does probably not contain DBMS error string\n";
236
		}
237
 
238
		// --- Boolean handling
239
 
240
		$db->query("update ###objects set confidential = ? where id = 'test:1.1'", array(true));
241
		$res = $db->query("select confidential from ###objects where id = 'test:1.1'");
242
		$val = $res->fetch_object()->confidential;
502 daniel-mar 243
		echo "Boolean handling TRUE with prepared statement (fetch): " . ($val ? greentext('PASSED') : redtext('FAILED'))."\n";
244
		$res = $db->query("select * from ###objects where id = 'test:1.1' and confidential = ?", array(true));
245
		$val = $res->fetch_object();
246
		echo "Boolean handling TRUE with prepared statement (where): " . ($val ? greentext('PASSED') : redtext('FAILED'))."\n";
374 daniel-mar 247
 
248
		$db->query("update ###objects set confidential = ? where id = 'test:1.1'", array(false));
249
		$res = $db->query("select confidential from ###objects where id = 'test:1.1'");
250
		$val = $res->fetch_object()->confidential;
502 daniel-mar 251
		echo "Boolean handling FALSE with prepared statement (fetch): " . (!$val ? greentext('PASSED') : redtext('FAILED'))."\n";
252
		$res = $db->query("select * from ###objects where id = 'test:1.1' and confidential = ?", array(false));
253
		$val = $res->fetch_object();
254
		echo "Boolean handling FALSE with prepared statement (where): " . ($val ? greentext('PASSED') : redtext('FAILED'))."\n";
374 daniel-mar 255
 
502 daniel-mar 256
		$db->query("update ###objects set confidential = '1' where id = 'test:1.1'"); // NOTE: DO NOT USE THIS IN THE SOURCE CODE! Always use prepared statements for constant booleans
374 daniel-mar 257
		$res = $db->query("select confidential from ###objects where id = 'test:1.1'");
258
		$val = $res->fetch_object()->confidential;
502 daniel-mar 259
		echo "Boolean handling TRUE with normal statement (fetch): " . ($val ? greentext('PASSED') : redtext('FAILED'))."\n";
260
		$res = $db->query("select * from ###objects where id = 'test:1.1' and confidential = 1"); // NOTE: DO NOT USE THIS IN THE SOURCE CODE! Always use prepared statements for constant booleans
261
		$val = $res->fetch_object();
262
		echo "Boolean handling TRUE with normal statement (where): " . ($val ? greentext('PASSED') : redtext('FAILED'))."\n";
374 daniel-mar 263
 
502 daniel-mar 264
		$db->query("update ###objects set confidential = '0' where id = 'test:1.1'"); // NOTE: DO NOT USE THIS IN THE SOURCE CODE! Always use prepared statements for constant booleans
374 daniel-mar 265
		$res = $db->query("select confidential from ###objects where id = 'test:1.1'");
266
		$val = $res->fetch_object()->confidential;
502 daniel-mar 267
		echo "Boolean handling FALSE with normal statement (fetch): " . (!$val ? greentext('PASSED') : redtext('FAILED'))."\n";
268
		$res = $db->query("select * from ###objects where id = 'test:1.1' and confidential = 0"); // NOTE: DO NOT USE THIS IN THE SOURCE CODE! Always use prepared statements for constant booleans
269
		$val = $res->fetch_object();
270
		echo "Boolean handling FALSE with normal statement (where): " . ($val ? greentext('PASSED') : redtext('FAILED'))."\n";
271
 
374 daniel-mar 272
		// --- Check if transactions work
502 daniel-mar 273
 
274
		if ($db->transaction_supported()) {
275
			echo "Transaction support: " . greentext('Supported') ."\n";
374 daniel-mar 276
 
502 daniel-mar 277
			$db->query("update ###objects set title = 'A' where id = 'test:1.1'");
278
			$db->transaction_begin();
279
			$db->query("update ###objects set title = 'B' where id = 'test:1.1'");
280
			$db->transaction_rollback();
281
			$res = $db->query("select title from ###objects where id = 'test:1.1'");
282
			$val = $res->fetch_object()->title;
283
			echo "Transaction rollback: " . ($val == 'A' ? greentext('PASSED') : redtext('FAILED'))."\n";
374 daniel-mar 284
 
502 daniel-mar 285
			$db->query("update ###objects set title = 'A' where id = 'test:1.1'");
286
			$db->transaction_begin();
287
			$db->query("update ###objects set title = 'B' where id = 'test:1.1'");
288
			$db->transaction_commit();
289
			$res = $db->query("select title from ###objects where id = 'test:1.1'");
290
			$val = $res->fetch_object()->title;
291
			echo "Transaction commit: " . ($val == 'B' ? greentext('PASSED') : redtext('FAILED'))."\n";
292
		} else {
293
			echo "Transaction support: " . redtext('Not supported') ."\n";
294
		}
374 daniel-mar 295
 
296
		// --- Check natOrder feature
297
 
298
		$db->query("delete from ###objects where parent = 'test:1'");
299
		$db->query("insert into ###objects (id, parent, title, description, confidential) values ('oid:3.1.10', 'test:1', '', '', '0')");
300
		$db->query("insert into ###objects (id, parent, title, description, confidential) values ('oid:3.1.2', 'test:1', '', '', '0')");
301
		$res = $db->query("select id from ###objects where parent = ? order by ".$db->natOrder('id'), array('test:1'));
502 daniel-mar 302
		//$res->num_rows(); // sponge
374 daniel-mar 303
		$val = $res->fetch_object()->id;
304
		echo "Natural OID Sorting (< 16 Bit): " . ($val == 'oid:3.1.2' ? greentext('PASSED') : redtext('FAILED'))."\n";
305
 
306
		$db->query("delete from ###objects where parent = 'test:1'");
307
		$db->query("insert into ###objects (id, parent, title, description, confidential) values ('oid:2.25.317919736312109525688528068157180855579', 'test:1', '', '', '0')");
308
		$db->query("insert into ###objects (id, parent, title, description, confidential) values ('oid:2.25.67919736312109525688528068157180855579', 'test:1', '', '', '0')");
309
		$res = $db->query("select id from ###objects where parent = ? order by ".$db->natOrder('id'), array('test:1'));
502 daniel-mar 310
		//$res->num_rows(); // sponge
374 daniel-mar 311
		$val = $res->fetch_object()->id;
312
		echo "Natural OID Sorting (128 Bit): " . ($val == 'oid:2.25.67919736312109525688528068157180855579' ? greentext('PASSED') : redtext('FAILED'))."\n";
313
 
314
		$db->query("delete from ###objects where parent = 'test:1'");
315
		$db->query("insert into ###objects (id, parent, title, description, confidential) values ('abc:3.1.10', 'test:1', '', '', '0')");
316
		$db->query("insert into ###objects (id, parent, title, description, confidential) values ('abc:3.1.2', 'test:1', '', '', '0')");
317
		$res = $db->query("select id from ###objects where parent = ? order by ".$db->natOrder('id'), array('test:1'));
502 daniel-mar 318
		//$res->num_rows(); // sponge
374 daniel-mar 319
		$val = $res->fetch_object()->id;
320
		echo "Non-Natural Sorting for Non-OIDs: " . ($val == 'abc:3.1.10' ? greentext('PASSED') : redtext('FAILED'))."\n";
321
 
322
		// --- Test insert_id()
323
 
324
		$db->query("delete from ###log_object where object = 'test:1'");
325
		$cur = $db->insert_id();
326
		echo "Insert ID on non-insert: " . ($cur == 0 ? greentext('PASSED') : redtext('FAILED'))." ($cur)\n";
502 daniel-mar 327
		$db->query("insert into ###log_object (log_id, severity, object) values (1000, 0, 'test:1')");
374 daniel-mar 328
		$prev = $db->insert_id();
502 daniel-mar 329
		$db->query("insert into ###log_object (log_id, severity, object) values (2000, 1, 'test:1')");
374 daniel-mar 330
		$cur = $db->insert_id();
331
		echo "Insert ID on actual inserts: " . ($cur == $prev+1 ? greentext('PASSED') : redtext('FAILED'))." ($prev => $cur)\n";
332
		if ($cur != $prev+1);
333
		$db->query("delete from ###log_object where object = 'test:1'");
334
		$cur = $db->insert_id();
335
		echo "Non-Insert query will reset insert ID: " . ($cur == 0 ? greentext('PASSED') : redtext('FAILED'))." ($cur)\n";
336
 
337
	} finally {
502 daniel-mar 338
		try {
339
			$db->query("delete from ###objects where parent = 'test:1'");
340
		}catch(Exception $e) {}
374 daniel-mar 341
	}
342
	$db->disconnect();
343
	echo "\n";
344
}
345
 
346
function redtext($str) {
347
	global $num_errs;
348
	$num_errs++;
502 daniel-mar 349
	return PHP_SAPI == 'cli' ? "\033[31m$str\033[0m" : '<font color="red">'.$str.'</font>';
374 daniel-mar 350
}
351
 
352
function greentext($str) {
353
	global $num_succ;
354
	$num_succ++;
502 daniel-mar 355
	return PHP_SAPI == 'cli' ? "\033[32m$str\033[0m" : '<font color="green">'.$str.'</font>';
374 daniel-mar 356
}