]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/Irc/extlib/phergie/Tests/Phergie/Plugin/TestCase.php
Merge branch '0.9.x' of gitorious.org:statusnet/mainline into 1.0.x
[quix0rs-gnu-social.git] / plugins / Irc / extlib / phergie / Tests / Phergie / Plugin / TestCase.php
1 <?php
2 /**
3  * Phergie
4  *
5  * PHP version 5
6  *
7  * LICENSE
8  *
9  * This source file is subject to the new BSD license that is bundled
10  * with this package in the file LICENSE.
11  * It is also available through the world-wide-web at this URL:
12  * http://phergie.org/license
13  *
14  * @category  Phergie
15  * @package   Phergie_Tests
16  * @author    Phergie Development Team <team@phergie.org>
17  * @copyright 2008-2010 Phergie Development Team (http://phergie.org)
18  * @license   http://phergie.org/license New BSD License
19  * @link      http://pear.phergie.org/package/Phergie_Tests
20  */
21
22 /**
23  * Unit test suite for plugin classes.
24  *
25  * @category Phergie
26  * @package  Phergie_Tests
27  * @author   Phergie Development Team <team@phergie.org>
28  * @license  http://phergie.org/license New BSD License
29  * @link     http://pear.phergie.org/package/Phergie_Tests
30  */
31 abstract class Phergie_Plugin_TestCase extends PHPUnit_Framework_TestCase
32 {
33     /**
34      * Mock configuration
35      *
36      * @var Phergie_Config
37      */
38     protected $config;
39
40     /**
41      * Associative array for configuration setting values, accessed by the
42      * mock configuration object using a callback
43      *
44      * @var array
45      */
46     protected $settings = array();
47
48     /**
49      * Mock connection
50      *
51      * @var Phergie_Connection
52      */
53     protected $connection;
54
55     /**
56      * Mock event handler
57      *
58      * @var Phergie_Event_Handler
59      */
60     protected $events;
61
62     /**
63      * Mock plugin handler
64      *
65      * @var Phergie_Plugin_Handler
66      */
67     protected $plugins;
68
69     /**
70      * Plugin instance being tested
71      *
72      * @var Phergie_Plugin_Abstract
73      */
74     protected $plugin;
75
76     /**
77      * Full name of the plugin class being tested, may be explicitly
78      * specified in subclasses but is otherwise automatically derived from
79      * the test case class name
80      *
81      * @var string
82      */
83     protected $pluginClass;
84
85     /**
86      * User nick used in any events requiring one
87      *
88      * @var string
89      */
90     protected $nick = 'nick';
91
92     /**
93      * Event source used in any events requiring one
94      *
95      * @var string
96      */
97     protected $source = '#channel';
98
99     /**
100      * Initializes instance properties.
101      *
102      * @return void
103      */
104     public function setUp()
105     {
106         if (empty($this->pluginClass)) {
107             $this->pluginClass = preg_replace('/Test$/', '', get_class($this));
108         }
109
110         if (empty($this->plugin)) {
111             $this->plugin = new $this->pluginClass;
112         }
113
114         $this->plugin->setConfig($this->getMockConfig());
115         $this->plugin->setConnection($this->getMockConnection());
116         $this->plugin->setEventHandler($this->getMockEventHandler());
117         $this->plugin->setPluginHandler($this->getMockPluginHandler());
118     }
119
120     /**
121      * Destroys all initialized instance properties.
122      *
123      * @return void
124      */
125     public function tearDown()
126     {
127         unset(
128             $this->plugins,
129             $this->events,
130             $this->connection,
131             $this->config,
132             $this->plugin
133         );
134     }
135
136     /**
137      * Returns a mock configuration object.
138      *
139      * @return Phergie_Config
140      */
141     protected function getMockConfig()
142     {
143         if (empty($this->config)) {
144             $this->config = $this->getMock('Phergie_Config', array('offsetExists', 'offsetGet'));
145             $this->config
146                 ->expects($this->any())
147                 ->method('offsetExists')
148                 ->will($this->returnCallback(array($this, 'configOffsetExists')));
149             $this->config
150                 ->expects($this->any())
151                 ->method('offsetGet')
152                 ->will($this->returnCallback(array($this, 'configOffsetGet')));
153         }
154         return $this->config;
155     }
156
157     /**
158      * Returns whether a specific configuration setting has a value. Only
159      * intended for use by this class, but must be public for PHPUnit to
160      * call them.
161      *
162      * @param string $name Name of the setting
163      *
164      * @return boolean TRUE if the setting has a value, FALSE otherwise
165      */
166     public function configOffsetExists($name)
167     {
168         return isset($this->settings[$name]);
169     }
170
171     /**
172      * Returns the value of a specific configuration setting. Only intended
173      * for use by this class, but must be public for PHPUnit to call them.
174      *
175      * @param string $name Name of the setting
176      *
177      * @return mixed Value of the setting
178      */
179     public function configOffsetGet($name)
180     {
181         return $this->settings[$name];
182     }
183
184     /**
185      * Returns a mock connection object.
186      *
187      * @return Phergie_Connection
188      */
189     protected function getMockConnection()
190     {
191         if (empty($this->connection)) {
192             $this->connection = $this->getMock('Phergie_Connection');
193             $this->connection
194                 ->expects($this->any())
195                 ->method('getNick')
196                 ->will($this->returnValue($this->nick));
197         }
198         return $this->connection;
199     }
200
201     /**
202      * Returns a mock event handler object.
203      *
204      * @return Phergie_Event_Handler
205      */
206     protected function getMockEventHandler()
207     {
208         if (empty($this->events)) {
209             $this->events = $this->getMock('Phergie_Event_Handler', array('addEvent'));
210         }
211         return $this->events;
212     }
213
214     /**
215      * Returns a mock plugin handler object.
216      *
217      * @return Phergie_Plugin_Handler
218      */
219     protected function getMockPluginHandler()
220     {
221         if (empty($this->plugins)) {
222             $config = $this->getMockConfig();
223             $events = $this->getMockEventHandler();
224             $this->plugins = $this->getMock(
225                 'Phergie_Plugin_Handler',
226                 array(), // mock everything
227                 array($config, $events)
228             );
229         }
230         return $this->plugins;
231     }
232
233     /**
234      * Returns a mock event object.
235      *
236      * @param string $type   Event type
237      * @param array  $args   Optional associative array of event arguments
238      * @param string $nick   Optional user nick to associate with the event
239      * @param string $source Optional user nick or channel name to associate
240      *        with the event as its source
241      *
242      * @return Phergie_Event_Request
243      */
244     protected function getMockEvent($type, array $args = array(),
245         $nick = null, $source = null
246     ) {
247         $methods = array('getNick', 'getSource');
248         foreach (array_keys($args) as $arg) {
249             if (is_int($arg) || ctype_digit($arg)) {
250                 $methods[] = 'getArgument';
251             } else {
252                 $methods[] = 'get' . ucfirst($arg);
253             }
254         }
255
256         $event = $this->getMock(
257             'Phergie_Event_Request',
258             $methods
259         );
260
261         $nick = $nick ? $nick : $this->nick;
262         $event
263             ->expects($this->any())
264             ->method('getNick')
265             ->will($this->returnValue($nick));
266
267         $source = $source ? $source : $this->source;
268         $event
269             ->expects($this->any())
270             ->method('getSource')
271             ->will($this->returnValue($source));
272
273         foreach ($args as $key => $value) {
274             if (is_int($key) || ctype_digit($key)) {
275                 $event
276                     ->expects($this->any())
277                     ->method('getArgument')
278                     ->with($key)
279                     ->will($this->returnValue($value));
280             } else {
281                 $event
282                     ->expects($this->any())
283                     ->method('get' . ucfirst($key))
284                     ->will($this->returnValue($value));
285             }
286         }
287
288         return $event;
289     }
290
291     /**
292      * Sets the value of a configuration setting.
293      *
294      * @param string $setting Name of the setting
295      * @param mixed  $value   Value for the setting
296      *
297      * @return void
298      */
299     protected function setConfig($setting, $value)
300     {
301         $this->settings[$setting] = $value;
302     }
303
304     /**
305      * Returns the absolute path to the Phergie/Plugin directory. Useful in
306      * conjunction with getMockDatabase().
307      *
308      * @param string $subpath Optional path to append to the directory path
309      *
310      * @return string Directory path
311      */
312     protected function getPluginsPath($subpath = null)
313     {
314         $path = realpath(dirname(__FILE__) . '/../../../Phergie/Plugin');
315         if (!empty($subpath)) {
316             $path .= '/' . ltrim($subpath, '/');
317         }
318         return $path;
319     }
320
321     /**
322      * Modifies the event handler to include an expectation of an event
323      * being added by the plugin being tested. Note that this must be called
324      * BEFORE executing the plugin code intended to initiate the event.
325      *
326      * @param string $type Event type
327      * @param array  $args Optional enumerated array of event arguments
328      *
329      * @return void
330      */
331     protected function assertEmitsEvent($type, array $args = array())
332     {
333         $this->events
334             ->expects($this->at(0))
335             ->method('addEvent')
336             ->with($this->plugin, $type, $args);
337     }
338
339     /**
340      * Modifies the event handler to include an expectation of an event NOT
341      * being added by the plugin being tested. Note that this must be called
342      * BEFORE executing plugin code that may initiate the event.
343      *
344      * @param string $type Event type
345      * @param array  $args Optional enumerated array of event arguments
346      *
347      * @return void
348      */
349     protected function assertDoesNotEmitEvent($type, array $args = array())
350     {
351         // Ugly hack to get around an issue in PHPUnit
352         // @link http://github.com/sebastianbergmann/phpunit-mock-objects/issues/issue/5#issue/5/comment/343524
353         $callback = create_function(
354             '$plugin, $type, $args',
355             'if (get_class($plugin) == "' . $this->pluginClass . '"
356             && $type == "' . $type . '"
357             && $args == "' . var_export($args, true) . '") {
358                 trigger_error("Instance of ' . $this->pluginClass
359                 . ' unexpectedly emitted event of type ' . $type
360                 . '", E_USER_ERROR);
361             }'
362         );
363
364         $this->events
365             ->expects($this->any())
366             ->method('addEvent')
367             ->will($this->returnCallback($callback));
368     }
369
370     /**
371      * Modifies the plugin handler to include an expectation of a plugin
372      * being retrieved, indicating a dependency. Note that this must be
373      * called BEFORE executing the plugin code that may load that plugin
374      * dependency, which is usually located in onLoad().
375      *
376      * @param string $name Short name of the plugin required as a dependency
377      *
378      * @return void
379      */
380     public function assertRequiresPlugin($name)
381     {
382         $this->plugins
383             ->expects($this->atLeastOnce())
384             ->method('getPlugin')
385             ->with($name);
386     }
387
388     /**
389      * Creates an in-memory copy of a specified SQLite database file and
390      * returns a connection to it.
391      *
392      * @param string $path Path to the SQLite file to copy
393      *
394      * @return PDO Connection to the database copy
395      */
396     public function getMockDatabase($path)
397     {
398         $original = new PDO('sqlite:' . $path);
399         $copy = new PDO('sqlite::memory:');
400
401         $result = $original->query('SELECT sql FROM sqlite_master');
402         while ($sql = $result->fetchColumn()) {
403             $copy->exec($sql);
404         }
405
406         $tables = array();
407         $result = $original->query('SELECT name FROM sqlite_master WHERE type = "table"');
408         while ($table = $result->fetchColumn()) {
409             $tables[] = $table;
410         }
411
412         foreach ($tables as $table) {
413             $result = $original->query('SELECT * FROM ' . $table);
414             $insert = null;
415             $copy->beginTransaction();
416             while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
417                 $columns = array_keys($row);
418                 if (empty($insert)) {
419                     $insert = $copy->prepare(
420                         'INSERT INTO "' . $table . '" (' .
421                         '"' . implode('", "', $columns) . '"' .
422                         ') VALUES (' .
423                         ':' . implode(', :', $columns) .
424                         ')'
425                     );
426                 }
427                 $insert->execute($row);
428             }
429             $copy->commit();
430             unset($insert);
431         }
432
433         return $copy;
434     }
435 }