a tiny mvc framework for php using php-activerecord
1<?php
2use ActiveRecord\Column;
3
4class AdapterTest extends DatabaseTest
5{
6 const InvalidDb = '__1337__invalid_db__';
7
8 public function set_up($connection_name=null)
9 {
10 if (($connection_name && !in_array($connection_name, PDO::getAvailableDrivers())) ||
11 ActiveRecord\Config::instance()->get_connection($connection_name) == 'skip')
12 $this->mark_test_skipped($connection_name . ' drivers are not present');
13
14 parent::set_up($connection_name);
15 }
16
17 public function test_i_has_a_default_port_unless_im_sqlite()
18 {
19 if ($this->conn instanceof ActiveRecord\SqliteAdapter)
20 return;
21
22 $c = $this->conn;
23 $this->assert_true($c::$DEFAULT_PORT > 0);
24 }
25
26 public function test_should_set_adapter_variables()
27 {
28 $this->assert_not_null($this->conn->protocol);
29 }
30
31 public function test_null_connection_string_uses_default_connection()
32 {
33 $this->assert_not_null(ActiveRecord\Connection::instance(null));
34 $this->assert_not_null(ActiveRecord\Connection::instance(''));
35 $this->assert_not_null(ActiveRecord\Connection::instance());
36 }
37
38 /**
39 * @expectedException ActiveRecord\DatabaseException
40 */
41 public function test_invalid_connection_protocol()
42 {
43 ActiveRecord\Connection::instance('terribledb://user:pass@host/db');
44 }
45
46 /**
47 * @expectedException ActiveRecord\DatabaseException
48 */
49 public function test_no_host_connection()
50 {
51 if (!$GLOBALS['slow_tests'])
52 throw new ActiveRecord\DatabaseException("");
53
54 ActiveRecord\Connection::instance("{$this->conn->protocol}://user:pass");
55 }
56
57 /**
58 * @expectedException ActiveRecord\DatabaseException
59 */
60 public function test_connection_failed_invalid_host()
61 {
62 if (!$GLOBALS['slow_tests'])
63 throw new ActiveRecord\DatabaseException("");
64
65 ActiveRecord\Connection::instance("{$this->conn->protocol}://user:pass/1.1.1.1/db");
66 }
67
68 /**
69 * @expectedException ActiveRecord\DatabaseException
70 */
71 public function test_connection_failed()
72 {
73 ActiveRecord\Connection::instance("{$this->conn->protocol}://baduser:badpass@127.0.0.1/db");
74 }
75
76 /**
77 * @expectedException ActiveRecord\DatabaseException
78 */
79 public function test_connect_failed()
80 {
81 ActiveRecord\Connection::instance("{$this->conn->protocol}://zzz:zzz@127.0.0.1/test");
82 }
83
84 public function test_connect_with_port()
85 {
86 $config = ActiveRecord\Config::instance();
87 $name = $config->get_default_connection();
88 $url = parse_url($config->get_connection($name));
89 $conn = $this->conn;
90 $port = $conn::$DEFAULT_PORT;
91
92 if ($this->conn->protocol != 'sqlite')
93 ActiveRecord\Connection::instance("{$url['scheme']}://{$url['user']}:{$url['pass']}@{$url['host']}:$port{$url['path']}");
94 }
95
96 /**
97 * @expectedException ActiveRecord\DatabaseException
98 */
99 public function test_connect_to_invalid_database()
100 {
101 ActiveRecord\Connection::instance("{$this->conn->protocol}://test:test@127.0.0.1/" . self::InvalidDb);
102 }
103
104 public function test_date_time_type()
105 {
106 $columns = $this->conn->columns('authors');
107 $this->assert_equals('datetime',$columns['created_at']->raw_type);
108 $this->assert_equals(Column::DATETIME,$columns['created_at']->type);
109 $this->assert_true($columns['created_at']->length > 0);
110 }
111
112 public function test_date()
113 {
114 $columns = $this->conn->columns('authors');
115 $this->assert_equals('date',$columns['some_date']->raw_type);
116 $this->assert_equals(Column::DATE,$columns['some_date']->type);
117 $this->assert_true($columns['some_date']->length >= 7);
118 }
119
120 public function test_columns_no_inflection_on_hash_key()
121 {
122 $author_columns = $this->conn->columns('authors');
123 $this->assert_true(array_key_exists('author_id',$author_columns));
124 }
125
126 public function test_columns_nullable()
127 {
128 $author_columns = $this->conn->columns('authors');
129 $this->assert_false($author_columns['author_id']->nullable);
130 $this->assert_true($author_columns['parent_author_id']->nullable);
131 }
132
133 public function test_columns_pk()
134 {
135 $author_columns = $this->conn->columns('authors');
136 $this->assert_true($author_columns['author_id']->pk);
137 $this->assert_false($author_columns['parent_author_id']->pk);
138 }
139
140 public function test_columns_sequence()
141 {
142 if ($this->conn->supports_sequences())
143 {
144 $author_columns = $this->conn->columns('authors');
145 $this->assert_equals('authors_author_id_seq',$author_columns['author_id']->sequence);
146 }
147 }
148
149 public function test_columns_default()
150 {
151 $author_columns = $this->conn->columns('authors');
152 $this->assert_equals('default_name',$author_columns['name']->default);
153 }
154
155 public function test_columns_type()
156 {
157 $author_columns = $this->conn->columns('authors');
158 $this->assert_equals('varchar',substr($author_columns['name']->raw_type,0,7));
159 $this->assert_equals(Column::STRING,$author_columns['name']->type);
160 $this->assert_equals(25,$author_columns['name']->length);
161 }
162
163 public function test_columns_text()
164 {
165 $author_columns = $this->conn->columns('authors');
166 $this->assert_equals('text',$author_columns['some_text']->raw_type);
167 $this->assert_equals(null,$author_columns['some_text']->length);
168 }
169
170 public function test_columns_time()
171 {
172 $author_columns = $this->conn->columns('authors');
173 $this->assert_equals('time',$author_columns['some_time']->raw_type);
174 $this->assert_equals(Column::TIME,$author_columns['some_time']->type);
175 }
176
177 public function test_query()
178 {
179 $sth = $this->conn->query('SELECT * FROM authors');
180
181 while (($row = $sth->fetch()))
182 $this->assert_not_null($row);
183
184 $sth = $this->conn->query('SELECT * FROM authors WHERE author_id=1');
185 $row = $sth->fetch();
186 $this->assert_equals('Tito',$row['name']);
187 }
188
189 /**
190 * @expectedException ActiveRecord\DatabaseException
191 */
192 public function test_invalid_query()
193 {
194 $this->conn->query('alsdkjfsdf');
195 }
196
197 public function test_fetch()
198 {
199 $sth = $this->conn->query('SELECT * FROM authors WHERE author_id IN(1,2,3)');
200 $i = 0;
201 $ids = array();
202
203 while (($row = $sth->fetch()))
204 {
205 ++$i;
206 $ids[] = $row['author_id'];
207 }
208
209 $this->assert_equals(3,$i);
210 $this->assert_equals(array(1,2,3),$ids);
211 }
212
213 public function test_query_with_params()
214 {
215 $x=array('Bill Clinton','Tito');
216 $sth = $this->conn->query('SELECT * FROM authors WHERE name IN(?,?) ORDER BY name DESC',$x);
217 $row = $sth->fetch();
218 $this->assert_equals('Tito',$row['name']);
219
220 $row = $sth->fetch();
221 $this->assert_equals('Bill Clinton',$row['name']);
222
223 $row = $sth->fetch();
224 $this->assert_equals(null,$row);
225 }
226
227 public function test_insert_id_should_return_explicitly_inserted_id()
228 {
229 $this->conn->query('INSERT INTO authors(author_id,name) VALUES(99,\'name\')');
230 $this->assert_true($this->conn->insert_id() > 0);
231 }
232
233 public function test_insert_id()
234 {
235 $this->conn->query("INSERT INTO authors(name) VALUES('name')");
236 $this->assert_true($this->conn->insert_id() > 0);
237 }
238
239 public function test_insert_id_with_params()
240 {
241 $x = array('name');
242 $this->conn->query('INSERT INTO authors(name) VALUES(?)',$x);
243 $this->assert_true($this->conn->insert_id() > 0);
244 }
245
246 public function test_inflection()
247 {
248 $columns = $this->conn->columns('authors');
249 $this->assert_equals('parent_author_id',$columns['parent_author_id']->inflected_name);
250 }
251
252 public function test_escape()
253 {
254 $s = "Bob's";
255 $this->assert_not_equals($s,$this->conn->escape($s));
256 }
257
258 public function test_columnsx()
259 {
260 $columns = $this->conn->columns('authors');
261 $names = array('author_id','parent_author_id','name','updated_at','created_at','some_date','some_time','some_text','encrypted_password','mixedCaseField');
262
263 if ($this->conn instanceof ActiveRecord\OciAdapter)
264 $names = array_filter(array_map('strtolower',$names),function($s) { $s !== 'some_time'; });
265
266 foreach ($names as $field)
267 $this->assert_true(array_key_exists($field,$columns));
268
269 $this->assert_equals(true,$columns['author_id']->pk);
270 $this->assert_equals('int',$columns['author_id']->raw_type);
271 $this->assert_equals(Column::INTEGER,$columns['author_id']->type);
272 $this->assert_true($columns['author_id']->length > 1);
273 $this->assert_false($columns['author_id']->nullable);
274
275 $this->assert_equals(false,$columns['parent_author_id']->pk);
276 $this->assert_true($columns['parent_author_id']->nullable);
277
278 $this->assert_equals('varchar',substr($columns['name']->raw_type,0,7));
279 $this->assert_equals(Column::STRING,$columns['name']->type);
280 $this->assert_equals(25,$columns['name']->length);
281 }
282
283 public function test_columns_decimal()
284 {
285 $columns = $this->conn->columns('books');
286 $this->assert_equals(Column::DECIMAL,$columns['special']->type);
287 $this->assert_true($columns['special']->length >= 10);
288 }
289
290 private function limit($offset, $limit)
291 {
292 $ret = array();
293 $sql = 'SELECT * FROM authors ORDER BY name ASC';
294 $this->conn->query_and_fetch($this->conn->limit($sql,$offset,$limit),function($row) use (&$ret) { $ret[] = $row; });
295 return ActiveRecord\collect($ret,'author_id');
296 }
297
298 public function test_limit()
299 {
300 $this->assert_equals(array(2,1),$this->limit(1,2));
301 }
302
303 public function test_limit_to_first_record()
304 {
305 $this->assert_equals(array(3),$this->limit(0,1));
306 }
307
308 public function test_limit_to_last_record()
309 {
310 $this->assert_equals(array(1),$this->limit(2,1));
311 }
312
313 public function test_limit_with_null_offset()
314 {
315 $this->assert_equals(array(3),$this->limit(null,1));
316 }
317
318 public function test_limit_with_nulls()
319 {
320 $this->assert_equals(array(),$this->limit(null,null));
321 }
322
323 public function test_fetch_no_results()
324 {
325 $sth = $this->conn->query('SELECT * FROM authors WHERE author_id=65534');
326 $this->assert_equals(null,$sth->fetch());
327 }
328
329 public function test_tables()
330 {
331 $this->assert_true(count($this->conn->tables()) > 0);
332 }
333
334 public function test_query_column_info()
335 {
336 $this->assert_greater_than(0,count($this->conn->query_column_info("authors")));
337 }
338
339 public function test_query_table_info()
340 {
341 $this->assert_greater_than(0,count($this->conn->query_for_tables()));
342 }
343
344 public function test_query_table_info_must_return_one_field()
345 {
346 $sth = $this->conn->query_for_tables();
347 $this->assert_equals(1,count($sth->fetch()));
348 }
349
350 public function test_transaction_commit()
351 {
352 $original = $this->conn->query_and_fetch_one("select count(*) from authors");
353
354 $this->conn->transaction();
355 $this->conn->query("insert into authors(author_id,name) values(9999,'blahhhhhhhh')");
356 $this->conn->commit();
357
358 $this->assert_equals($original+1,$this->conn->query_and_fetch_one("select count(*) from authors"));
359 }
360
361 public function test_transaction_rollback()
362 {
363 $original = $this->conn->query_and_fetch_one("select count(*) from authors");
364
365 $this->conn->transaction();
366 $this->conn->query("insert into authors(author_id,name) values(9999,'blahhhhhhhh')");
367 $this->conn->rollback();
368
369 $this->assert_equals($original,$this->conn->query_and_fetch_one("select count(*) from authors"));
370 }
371
372 public function test_show_me_a_useful_pdo_exception_message()
373 {
374 try {
375 $this->conn->query('select * from an_invalid_column');
376 $this->fail();
377 } catch (Exception $e) {
378 $this->assert_equals(1,preg_match('/(an_invalid_column)|(exist)/',$e->getMessage()));
379 }
380 }
381
382 public function test_quote_name_does_not_over_quote()
383 {
384 $c = $this->conn;
385 $q = $c::$QUOTE_CHARACTER;
386 $qn = function($s) use ($c) { return $c->quote_name($s); };
387
388 $this->assert_equals("{$q}string", $qn("{$q}string"));
389 $this->assert_equals("string{$q}", $qn("string{$q}"));
390 $this->assert_equals("{$q}string{$q}", $qn("{$q}string{$q}"));
391 }
392
393 public function test_datetime_to_string()
394 {
395 $datetime = '2009-01-01 01:01:01 EST';
396 $this->assert_equals($datetime,$this->conn->datetime_to_string(date_create($datetime)));
397 }
398
399 public function test_date_to_string()
400 {
401 $datetime = '2009-01-01';
402 $this->assert_equals($datetime,$this->conn->date_to_string(date_create($datetime)));
403 }
404}
405?>