1<?php
2/**
3 * Base for PHPUnit scenarios.
4 *
5 * PHP version 5
6 *
7 * @category Kolab
8 * @package  Kolab_Test
9 * @author   Gunnar Wrobel <wrobel@pardus.de>
10 * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
11 * @link     http://pear.horde.org/index.php?package=Share
12 */
13
14/**
15 * Base for PHPUnit scenarios.
16 *
17 * Copyright 2008-2016 Horde LLC (http://www.horde.org/)
18 *
19 * See the enclosed file COPYING for license information (LGPL). If you
20 * did not receive this file, see http://www.horde.org/licenses/lgpl21.
21 *
22 * @category Kolab
23 * @package  Kolab_Test
24 * @author   Gunnar Wrobel <wrobel@pardus.de>
25 * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
26 * @link     http://pear.horde.org/index.php?package=Share
27 */
28class Horde_Kolab_Server_Integration_Scenario extends PHPUnit_Extensions_Story_TestCase
29{
30    /** The mock environment */
31    const ENVIRONMENT_MOCK = 'mock';
32
33    /** The real server environment */
34    const ENVIRONMENT_REAL = 'real';
35
36    /**
37     * The environments we provide to the test.
38     *
39     * @var array
40     */
41    protected $_environments;
42
43    /**
44     * Uid of added objects. Should be removed on tearDown.
45     *
46     * @var array
47     */
48    public $added;
49
50    /**
51     * Handle a "given" step.
52     *
53     * @param array  &$world    Joined "world" of variables.
54     * @param string $action    The description of the step.
55     * @param array  $arguments Additional arguments to the step.
56     *
57     * @return mixed The outcome of the step.
58     */
59    public function runGiven(&$world, $action, $arguments)
60    {
61        switch($action) {
62        case 'several injectors':
63            foreach ($this->getEnvironments() as $environment) {
64                $this->prepareInjector($environment);
65            }
66            break;
67        case 'several Kolab servers':
68        case 'the test environments':
69            $this->initializeEnvironments();
70            break;
71        case 'an empty Kolab server':
72            $world['server'] = $this->prepareKolabServer(self::ENVIRONMENT_MOCK);
73            break;
74        case 'a basic Kolab server':
75            $world['server'] = $this->prepareBasicKolabServer($world);
76            break;
77        default:
78            return $this->notImplemented($action);
79        }
80    }
81
82    /**
83     * Handle a "when" step.
84     *
85     * @param array  &$world    Joined "world" of variables.
86     * @param string $action    The description of the step.
87     * @param array  $arguments Additional arguments to the step.
88     *
89     * @return mixed The outcome of the step.
90     */
91    public function runWhen(&$world, $action, $arguments)
92    {
93        switch($action) {
94        case 'adding a Kolab server object':
95            $world['result']['add'] = $this->addToServers($arguments[0]);
96            break;
97        case 'adding an invalid Kolab server object':
98            try {
99                $world['result']['add'] = $this->addToServers($arguments[0]);
100            } catch (Horde_Kolab_Server_Exception $e) {
101                $world['result']['add'] = $e;
102            }
103            break;
104        case 'adding an object list':
105            foreach ($arguments[0] as $object) {
106                try {
107                    $world['result']['add'][] = $this->addToServers($object);
108                } catch (Horde_Kolab_Server_Exception $e) {
109                    $world['result']['add'] = $e;
110                    return;
111                }
112            }
113            $world['result']['add'] = true;
114            break;
115        case 'adding a distribution list':
116            $world['result']['add'] = $this->addToServers($this->provideDistributionList());
117            break;
118        case 'listing all users':
119            $world['list'] = $this->listObjectsOnServer('Horde_Kolab_Server_Object_Kolab_User');
120            break;
121        case 'listing all groups':
122            $world['list'] = $this->listObjectsOnServer('Horde_Kolab_Server_Object_Kolabgroupofnames');
123            break;
124        case 'listing all objects of type':
125            $world['list'] = $this->listObjectsOnServer($arguments[0]);
126            break;
127        case 'retrieving a hash list with all objects of type':
128            $world['list'] = array();
129            foreach ($this->world['injector'] as $injector) {
130                $server = $injector->getInstance('Horde_Kolab_Server');
131                $world['list'][] = $server->listHash($arguments[0]);
132            }
133            break;
134        default:
135            return $this->notImplemented($action);
136        }
137    }
138
139    /**
140     * Handle a "then" step.
141     *
142     * @param array  &$world    Joined "world" of variables.
143     * @param string $action    The description of the step.
144     * @param array  $arguments Additional arguments to the step.
145     *
146     * @return mixed The outcome of the step.
147     */
148    public function runThen(&$world, $action, $arguments)
149    {
150        switch($action) {
151        case 'the result should be an object of type':
152            if (!isset($world['result'])) {
153                $this->fail('Did not receive a result!');
154            }
155            $this->assertRecursiveType($world['result'], $arguments[0]);
156            break;
157        case 'the result indicates success.':
158            if (!isset($world['result'])) {
159                $this->fail('Did not receive a result!');
160            }
161            $this->assertNoError($world['result']);
162            break;
163        case 'the result should indicate an error with':
164            if (!isset($world['result'])) {
165                $this->fail('Did not receive a result!');
166            }
167            foreach ($world['result'] as $result) {
168                if ($result instanceof Horde_Kolab_Server_Exception) {
169                    $this->assertEquals($arguments[0], $result->getMessage());
170                } else {
171                    $this->assertEquals($arguments[0], 'Action succeeded without an error.');
172                }
173            }
174            break;
175        case 'the list has a number of entries equal to':
176            if ($world['list'] instanceof Horde_Kolab_Server_Exception) {
177                $this->assertEquals('', $world['list']->getMessage());
178            } else {
179                $this->assertEquals($arguments[0], count($world['list']));
180            }
181            break;
182        case 'the list is an empty array':
183            if ($world['list'] instanceof Horde_Kolab_Server_Exception) {
184                $this->assertEquals('', $world['list']->getMessage());
185            } else {
186                $this->assertEquals(array(array()), $world['list']);
187            }
188            break;
189        case 'the provided list and the result list match with regard to these attributes':
190            if ($world['list'] instanceof Horde_Kolab_Server_Exception) {
191                $this->assertEquals('', $world['list']->getMessage());
192            } else {
193                $provided_vals = array();
194                foreach ($arguments[2] as $provided_element) {
195                    if (isset($provided_element[$arguments[0]])) {
196                        $provided_vals[] = $provided_element[$arguments[0]];
197                    } else {
198                        $this->fail(sprintf('The provided element %s does have no value for %s.',
199                                            print_r($provided_element, true),
200                                            print_r($arguments[0])));
201                    }
202                }
203                $result_vals = array();
204                foreach ($world['list'] as $result_set) {
205                    foreach ($result_set as $result_element) {
206                        if (isset($result_element[$arguments[1]])) {
207                            $result_vals[] = $result_element[$arguments[1]];
208                        } else {
209                            $this->fail(sprintf('The result element %s does have no value for %s.',
210                                                print_r($result_element, true),
211                                                print_r($arguments[1])));
212                        }
213                    }
214                    $this->assertEquals(array(),
215                                        array_diff($provided_vals, $result_vals));
216                }
217            }
218            break;
219        case 'each element in the result list has an attribute':
220            if ($world['list'] instanceof Horde_Kolab_Server_Exception) {
221                $this->assertEquals('', $world['list']->getMessage());
222            } else {
223                $result_vals = array();
224                foreach ($world['list'] as $result_set) {
225                    foreach ($result_set as $result_element) {
226                        if (!isset($result_element[$arguments[0]])) {
227                            $this->fail(sprintf('The result element %s does have no value for %s.',
228                                                print_r($result_element, true),
229                                                print_r($arguments[0], true)));
230                        }
231                    }
232                }
233            }
234            break;
235        case 'each element in the result list has an attribute set to a given value':
236            if ($world['list'] instanceof Horde_Kolab_Server_Exception) {
237                $this->assertEquals('', $world['list']->getMessage());
238            } else {
239                $result_vals = array();
240                foreach ($world['list'] as $result_set) {
241                    foreach ($result_set as $result_element) {
242                        if (!isset($result_element[$arguments[0]])) {
243                            $this->fail(sprintf('The result element %s does have no value for %s.',
244                                                print_r($result_element, true),
245                                                print_r($arguments[0], true)));
246                        }
247                        if ($result_element[$arguments[0]] != $arguments[1]) {
248                            $this->fail(sprintf('The result element %s has an unexpected value %s for %s.',
249                                                print_r($result_element, true),
250                                                print_r($result_element[$arguments[0]], true),
251                                                print_r($arguments[0], true)));
252                        }
253                    }
254                }
255            }
256            break;
257        case 'the login was successful':
258            $this->assertNoError($world['login']);
259            $this->assertTrue($world['login']);
260            break;
261        case 'the list contains a number of elements equal to':
262            $this->assertEquals($arguments[0], count($world['list']));
263            break;
264        default:
265            return $this->notImplemented($action);
266        }
267    }
268
269    /**
270     * Identify the environments we want to run our tests in.
271     *
272     * @return array The selected environments.
273     */
274    public function getEnvironments()
275    {
276        if (empty($this->_environments)) {
277            /** The mock environment provides our basic test scenario */
278            $this->_environments = array(self::ENVIRONMENT_MOCK);
279            $testing = getenv('KOLAB_TEST');
280            if (!empty($testing)) {
281                $this->_environments[] = array(self::ENVIRONMENT_REAL);
282            }
283        }
284        return $this->_environments;
285    }
286
287    /**
288     * Specifically set the environments we wish to support.
289     *
290     * @param array $environments The selected environments.
291     *
292     * @return NULL
293     */
294    public function setEnvironments($environments)
295    {
296        $this->_environments = $environments;
297    }
298
299    /**
300     * Initialize the environments.
301     *
302     * @param string $environment The name of the environment.
303     *
304     * @return NULL
305     */
306    public function initializeEnvironments()
307    {
308        foreach ($this->getEnvironments() as $environment) {
309            $this->initializeEnvironment($environment);
310        }
311    }
312
313    /**
314     * Prepare an injector for the given environment.
315     *
316     * @param string $environment The name of the environment.
317     *
318     * @return NULL
319     */
320    public function prepareInjector($environment)
321    {
322        if (!isset($this->world['injector'][$environment])) {
323            $this->world['injector'][$environment] = new Horde_Injector(new Horde_Injector_TopLevel());
324        }
325    }
326
327    /**
328     * Prepare the log handler for the given environment.
329     *
330     * @param string $environment The name of the environment.
331     *
332     * @return NULL
333     */
334    public function prepareLogger($environment)
335    {
336        $logger  = new Horde_Log_Logger();
337        $handler = new Horde_Log_Handler_Mock();
338        $logger->addHandler($handler);
339
340        $this->world['injector'][$environment]->setInstance('Horde_Log_Logger',
341                                                            $logger);
342    }
343
344    /**
345     * Prepare the server configuration for the given environment.
346     *
347     * @param string $environment The name of the environment.
348     *
349     * @return NULL
350     */
351    public function prepareKolabServerConfiguration($environment)
352    {
353        switch ($environment) {
354        case self::ENVIRONMENT_MOCK:
355            /** Prepare a Kolab test server */
356            $config = new stdClass;
357            $config->driver = 'test';
358            $config->params = array(
359                'basedn'   => 'dc=example,dc=org',
360                'hashtype' => 'plain'
361            );
362            $this->world['injector'][$environment]->setInstance('Horde_Kolab_Server_Config', $config);
363            break;
364        default:
365            throw new Horde_Exception('Not implemented!');
366        }
367    }
368
369    /**
370     * Prepare the server for the given environment.
371     *
372     * @param string $environment The name of the environment.
373     *
374     * @return NULL
375     */
376    public function prepareKolabServer($environment)
377    {
378        $this->world['injector'][$environment]->bindFactory('Horde_Kolab_Server_Structure',
379                                                            'Horde_Kolab_Server_Factory',
380                                                            'getStructure');
381        $this->world['injector'][$environment]->bindFactory('Horde_Kolab_Server',
382                                                            'Horde_Kolab_Server_Factory',
383                                                            'getServer');
384    }
385
386    /**
387     * Get a server from a specific environment.
388     *
389     * @param string $environment The name of the environment.
390     *
391     * @return Horde_Kolab_Server The server.
392     */
393    public function getKolabServer($environment)
394    {
395        return $this->world['injector'][$environment]->getInstance('Horde_Kolab_Server');
396    }
397
398    /**
399     * Initialize the given environment.
400     *
401     * @param string $environment The name of the environment.
402     *
403     * @return NULL
404     */
405    public function initializeEnvironment($environment)
406    {
407        $this->prepareInjector($environment);
408        $this->prepareLogger($environment);
409        $this->prepareKolabServerConfiguration($environment);
410        $this->prepareKolabServer($environment);
411    }
412
413    /**
414     * Shortcut to get a Kolab mock server.
415     *
416     * @return Horde_Kolab_Server The server.
417     */
418    public function getKolabMockServer()
419    {
420        $this->initializeEnvironment(self::ENVIRONMENT_MOCK);
421        return $this->getKolabServer(self::ENVIRONMENT_MOCK);
422    }
423
424    /**
425     * Retrieves the available servers. This assumes all environments have been
426     * initialied.
427     *
428     * @return array The list of test servers.
429     */
430    public function getKolabServers()
431    {
432        $servers = array();
433        foreach ($this->getEnvironments() as $environment) {
434            $servers[] = $this->getKolabServer($environment);
435        }
436        return $servers;
437    }
438
439    /**
440     * Add an object to a server and remember it for the tear down method.
441     *
442     * @param Horde_Kolab_Server $server The server to add the object to.
443     * @param array              $object  The object data to store.
444     *
445     * @return Horde_Kolab_Server_Object The resulting object.
446     */
447    public function addToServer(Horde_Kolab_Server $server, array $object)
448    {
449        $object = $server->add($object);
450        $this->added[] = array($server, $object->getUid());
451        return $object;
452    }
453
454    /**
455     * Add an object to the registered servers.
456     *
457     * @param array $object The object data to store.
458     *
459     * @return array An array of objects.
460     */
461    public function addToServers(array $object)
462    {
463        $result = array();
464        foreach ($this->world['injector'] as $injector) {
465            $server = $injector->getInstance('Horde_Kolab_Server');
466            $result[] = $this->addToServer($server, $object);
467        }
468        return $result;
469    }
470
471    /**
472     * Fill a Kolab Server with test users.
473     *
474     * @param Horde_Kolab_Server $server The server to fill.
475     *
476     * @return NULL
477     */
478    public function addBasicUsersToServer($server)
479    {
480        $result = $this->addToServer($server, $this->provideBasicUserOne());
481        $this->assertNoError($result);
482        $result = $this->addToServer($server, $this->provideBasicUserTwo());
483        $this->assertNoError($result);
484        $result = $this->addToServer($server, $this->provideBasicAddress());
485        $this->assertNoError($result);
486        $result = $this->addToServer($server, $this->provideBasicAdmin());
487        $this->assertNoError($result);
488        $result = $this->addToServer($server, $this->provideBasicDomainMaintainer());
489        $this->assertNoError($result);
490        $result = $this->addToServer($server, $this->provideGroupWithoutMembers());
491        $this->assertNoError($result);
492        $result = $this->addToServer($server, $this->provideBasicGroupOne());
493        $this->assertNoError($result);
494        $result = $this->addToServer($server, $this->provideBasicMaintainer());
495        $this->assertNoError($result);
496        $result = $this->addToServer($server, $this->provideBasicSharedFolder());
497        $this->assertNoError($result);
498    }
499
500    /**
501     * List objects on the registered servers.
502     *
503     * @param array $type The type of objects to list.
504     *
505     * @return array An array of objects.
506     */
507    public function listObjectsOnServer($type)
508    {
509        $result = array();
510        foreach ($this->world['injector'] as $injector) {
511            $server = $injector->getInstance('Horde_Kolab_Server');
512            $objects = $server->listObjects($type);
513            $result[] = $objects;
514        }
515        return $result;
516    }
517
518    /**
519     * Return a test user.
520     *
521     * @return array The test user.
522     */
523    public function provideBasicUserOne()
524    {
525        return array('givenName' => 'Gunnar',
526                      'sn' => 'Wrobel',
527                      'type' => 'Horde_Kolab_Server_Object_Kolab_User',
528                      'mail' => 'wrobel@example.org',
529                      'uid' => 'wrobel',
530                      'userPassword' => 'none',
531                      'kolabHomeServer' => 'home.example.org',
532                      'kolabImapServer' => 'imap.example.org',
533                      'kolabFreeBusyServer' => 'https://fb.example.org/freebusy',
534                      'kolabInvitationPolicy' => array('ACT_REJECT_IF_CONFLICTS'),
535                      'alias' => array('gunnar@example.org',
536                                       'g.wrobel@example.org'),
537                );
538    }
539
540    /**
541     * Return a test user.
542     *
543     * @return array The test user.
544     */
545    public function provideBasicUserTwo()
546    {
547        return array('givenName' => 'Test',
548                     'sn' => 'Test',
549                     'type' => 'Horde_Kolab_Server_Object_Kolab_User',
550                     'mail' => 'test@example.org',
551                     'uid' => 'test',
552                     'userPassword' => 'test',
553                     'kolabHomeServer' => 'home.example.org',
554                     'kolabImapServer' => 'home.example.org',
555                     'kolabFreeBusyServer' => 'https://fb.example.org/freebusy',
556                     'alias' => array('t.test@example.org'),
557                     'kolabDelegate' => 'wrobel@example.org',);
558    }
559
560    /**
561     * Return a test address.
562     *
563     * @return array The test address.
564     */
565    public function provideBasicAddress()
566    {
567        return array('type' => 'Horde_Kolab_Server_Object_Kolab_Address',
568                     Horde_Kolab_Server_Object_Kolab_Administrator::ATTRIBUTE_GIVENNAME    => 'Test',
569                     'Sn'           => 'Address',
570                     Horde_Kolab_Server_Object_Kolab_Administrator::ATTRIBUTE_MAIL         => 'address@example.org',
571        );
572    }
573
574    /**
575     * Return a test administrator.
576     *
577     * @return array The test administrator.
578     */
579    public function provideBasicAdmin()
580    {
581        return array('type' => 'Horde_Kolab_Server_Object_Kolab_Administrator',
582                     Horde_Kolab_Server_Object_Kolab_Administrator::ATTRIBUTE_GIVENNAME    => 'The',
583                     'Sn'           => 'Administrator',
584                     Horde_Kolab_Server_Object_Kolab_Administrator::ATTRIBUTE_SID          => 'admin',
585                     'Userpassword' => 'none',
586        );
587    }
588
589    /**
590     * Return a test maintainer.
591     *
592     * @return array The test maintainer.
593     */
594    public function provideBasicMaintainer()
595    {
596        return array('type' => 'Horde_Kolab_Server_Object_Kolab_Maintainer',
597                     Horde_Kolab_Server_Object_Kolab_Maintainer::ATTRIBUTE_GIVENNAME    => 'Main',
598                     'Sn'           => 'Tainer',
599                     Horde_Kolab_Server_Object_Kolab_Maintainer::ATTRIBUTE_SID          => 'maintainer',
600                     'Userpassword' => 'none',
601        );
602    }
603
604    /**
605     * Return a test domain maintainer.
606     *
607     * @return array The test domain maintainer.
608     */
609    public function provideBasicDomainMaintainer()
610    {
611        return array('type' => 'Horde_Kolab_Server_Object_Kolab_Domainmaintainer',
612                     Horde_Kolab_Server_Object_Kolab_Domainmaintainer::ATTRIBUTE_GIVENNAME    => 'Domain',
613                     'Sn'           => 'Maintainer',
614                     Horde_Kolab_Server_Object_Kolab_Domainmaintainer::ATTRIBUTE_SID          => 'domainmaintainer',
615                     'Userpassword' => 'none',
616                     Horde_Kolab_Server_Object_Kolab_Domainmaintainer::ATTRIBUTE_DOMAIN       => array('example.com'),
617
618        );
619    }
620
621    /**
622     * Return a test shared folder.
623     *
624     * @return array The test shared folder.
625     */
626    public function provideBasicSharedFolder()
627    {
628        return array('type' => 'Horde_Kolab_Server_Object_Kolabsharedfolder',
629                     Horde_Kolab_Server_Object_Kolabsharedfolder::ATTRIBUTE_CN         => 'shared@example.org',
630                     Horde_Kolab_Server_Object_Kolabsharedfolder::ATTRIBUTE_HOMESERVER => 'example.org',
631        );
632    }
633
634    /**
635     * Provide a set of valid groups.
636     *
637     * @return array The array of groups.
638     */
639    public function groupLists()
640    {
641        $groups = $this->validGroups();
642        $result = array();
643        foreach ($groups as $group) {
644            $result[] = array($group);
645        }
646        return $result;
647    }
648
649    /**
650     * Provide a set of valid groups.
651     *
652     * @return array The array of groups.
653     */
654    public function validGroups()
655    {
656        return array(
657            array(
658                $this->provideGroupWithoutMembers(),
659            ),
660            array(
661                $this->provideBasicGroupOne(),
662            ),
663            array(
664                $this->provideBasicGroupTwo(),
665            ),
666        );
667    }
668
669    /**
670     * Return a test group.
671     *
672     * @return array The test group.
673     */
674    public function provideGroupWithoutMembers()
675    {
676        return array('type' => 'Horde_Kolab_Server_Object_Kolabgroupofnames',
677                     Horde_Kolab_Server_Object_Kolab_Distlist::ATTRIBUTE_MAIL   => 'empty.group@example.org',
678                     Horde_Kolab_Server_Object_Kolab_Distlist::ATTRIBUTE_MEMBER => array());
679    }
680
681    /**
682     * Return a test group.
683     *
684     * @return array The test group.
685     */
686    public function provideBasicGroupOne()
687    {
688        return array('type' => 'Horde_Kolab_Server_Object_Kolabgroupofnames',
689                     Horde_Kolab_Server_Object_Kolab_Distlist::ATTRIBUTE_MAIL   => 'group@example.org',
690                     Horde_Kolab_Server_Object_Kolab_Distlist::ATTRIBUTE_MEMBER => array('cn=Test Test,dc=example,dc=org',
691                                                                                         'cn=Gunnar Wrobel,dc=example,dc=org')
692        );
693    }
694
695    /**
696     * Return a test group.
697     *
698     * @return array The test group.
699     */
700    public function provideBasicGroupTwo()
701    {
702        return array('type' => 'Horde_Kolab_Server_Object_Kolabgroupofnames',
703                     Horde_Kolab_Server_Object_Kolab_Distlist::ATTRIBUTE_MAIL   => 'group2@example.org',
704                     Horde_Kolab_Server_Object_Kolab_Distlist::ATTRIBUTE_MEMBER => array('cn=Gunnar Wrobel,dc=example,dc=org')
705        );
706    }
707
708    public function provideDistributionList()
709    {
710        return array('type' => 'Horde_Kolab_Server_Object_Kolab_Distlist',
711                     Horde_Kolab_Server_Object_Kolab_Distlist::ATTRIBUTE_MAIL   => 'distlist@example.org',
712                     Horde_Kolab_Server_Object_Kolab_Distlist::ATTRIBUTE_MEMBER => array('cn=Test Test,dc=example,dc=org',
713                                                                                         'cn=Gunnar Wrobel,dc=example,dc=org')
714        );
715    }
716
717    public function provideInvalidUserWithoutPassword()
718    {
719        return array('givenName' => 'Test',
720                     'sn' => 'Test',
721                     'type' => 'Horde_Kolab_Server_Object_Kolab_User',
722                     'mail' => 'test@example.org');
723    }
724
725    public function provideInvalidUserWithoutGivenName()
726    {
727        return array('sn' => 'Test',
728                     'userPassword' => 'none',
729                     'type' => 'Horde_Kolab_Server_Object_Kolab_User',
730                     'mail' => 'test@example.org');
731    }
732
733    public function provideInvalidUserWithoutLastName()
734    {
735        return array('givenName' => 'Test',
736                     'userPassword' => 'none',
737                     'type' => 'Horde_Kolab_Server_Object_Kolab_User',
738                     'mail' => 'test@example.org');
739    }
740
741    public function provideInvalidUserWithoutMail()
742    {
743        return array('givenName' => 'Test',
744                     'sn' => 'Test',
745                     'userPassword' => 'none',
746                     'type' => 'Horde_Kolab_Server_Object_Kolab_User');
747    }
748
749    public function provideInvalidUsers()
750    {
751        return array(
752            array(
753                $this->provideInvalidUserWithoutPassword(),
754                'The value for "userPassword" is missing!'
755            ),
756            array(
757                $this->provideInvalidUserWithoutGivenName(),
758                'Either the last name or the given name is missing!'
759            ),
760            array(
761                $this->provideInvalidUserWithoutLastName(),
762                'Either the last name or the given name is missing!'
763            ),
764            array(
765                $this->provideInvalidUserWithoutMail(),
766                'The value for "mail" is missing!'
767            ),
768        );
769    }
770
771    /** @todo: Prefix the stuff below with provide...() */
772
773    public function validUsers()
774    {
775        return array(
776            array(
777                $this->provideBasicUserOne(),
778            ),
779            array(
780                $this->provideBasicUserTwo(),
781            ),
782        );
783    }
784
785    public function validAddresses()
786    {
787        return array(
788            array(
789                $this->provideBasicAddress(),
790            ),
791        );
792    }
793
794    public function validAdmins()
795    {
796        return array(
797            array(
798                $this->provideBasicAdmin(),
799            ),
800        );
801    }
802
803    public function validMaintainers()
804    {
805        return array(
806            array(
807                $this->provideBasicMaintainer(),
808            )
809        );
810    }
811
812    public function validDomainMaintainers()
813    {
814        return array(
815            array(
816                $this->provideBasicDomainMaintainer(),
817            )
818        );
819    }
820
821    public function validSharedFolders()
822    {
823        return array(
824            array('cn' => 'Shared',
825                  'type' => 'Horde_Kolab_Server_Object_Kolabsharedfolder'
826            ),
827        );
828    }
829
830
831    public function userLists()
832    {
833        return array(
834        );
835    }
836
837    public function userListByLetter()
838    {
839        return array(
840        );
841    }
842
843    public function userListByAttribute()
844    {
845        return array(
846        );
847    }
848
849    public function userAdd()
850    {
851        return array(
852        );
853    }
854
855    public function invalidMails()
856    {
857        return array(
858        );
859    }
860
861    public function largeList()
862    {
863        return array(
864        );
865    }
866
867    protected function fetchByCn($server, $cn)
868    {
869        $cn_result = $server->uidForCn($cn);
870        $this->assertNoError($cn_result);
871
872        $object = $server->fetch($cn_result);
873        $this->assertNoError($object);
874
875        return $object;
876    }
877
878    /**
879     * Ensure that the variable contains no Horde_Kolab_Server_Exception and
880     * fail if it does.
881     *
882     * @param mixed $var The variable to check.
883     *
884     * @return NULL.
885     */
886    public function assertNoError($var)
887    {
888        if (is_array($var)) {
889            foreach ($var as $element) {
890                $this->assertNoError($element);
891            }
892        } elseif ($var instanceof Exception) {
893            $this->assertEquals('', $var->getMessage());
894        } else if ($var instanceof PEAR_Error) {
895            $this->assertEquals('', $var->getMessage());
896        }
897    }
898
899    /**
900     * Ensure that the variable contains a Horde_Kolab_Server_Exception and fail
901     * if it does not. Optionally compare the error message with the provided
902     * message and fail if both do not match.
903     *
904     * @param mixed  $var The variable to check.
905     * @param string $msg The expected error message.
906     *
907     * @return NULL.
908     */
909    public function assertError($var, $msg = null)
910    {
911        if (!$var instanceof PEAR_Error) {
912            $this->assertInstanceOf('Horde_Kolab_Server_Exception', $var);
913            if (isset($msg)) {
914                $this->assertEquals($msg, $var->getMessage());
915            }
916        } else {
917            if (isset($msg)) {
918                $this->assertEquals($msg, $var->getMessage());
919            }
920        }
921    }
922
923    /**
924     * Assert that creating a new object operation yields some predictable
925     * attribute results.
926     *
927     * @param Horde_Kolab_Server         $server The server the object resides on.
928     * @param array                      $store  The information to save.
929     * @param array                      $fetch  The expected results.
930     *
931     * @return NULL.
932     */
933    protected function assertAdd(Horde_Kolab_Server $server,
934                                 array $store, array $fetch)
935    {
936        $object = $server->add($store);
937        $this->assertNoError($object);
938
939        $this->added[] = array($server, $object->getUid());
940        $object = $server->fetch($object->getUid());
941
942        foreach ($fetch as $attribute => $expect) {
943            $this->assertEquals($expect, $object->get($attribute));
944        }
945        return $object;
946    }
947
948    /**
949     * Test simple attributes.
950     *
951     * @dataProvider provideServers
952     *
953     * @return NULL
954     */
955    public function assertSimpleAttributes(Horde_Kolab_Server_Object $object,
956                                           Horde_Kolab_Server $server, array $list)
957    {
958        foreach ($list as $item) {
959            $this->assertSimpleSequence($object, $server,
960                                        $item,
961                                        array($item, 'öäü/)(="§%$&§§$\'*', '', array('a', 'b'), '0'),
962                                        true);
963        }
964    }
965
966    /**
967     * Test easy attributes.
968     *
969     * @dataProvider provideServers
970     *
971     * @return NULL
972     */
973    public function assertEasyAttributes(Horde_Kolab_Server_Object $object,
974                                         Horde_Kolab_Server $server, array $list)
975    {
976        foreach ($list as $key => $items) {
977            $this->assertSimpleSequence($object, $server,
978                                        $key,
979                                        $items,
980                                        true);
981        }
982    }
983
984    /**
985     * Assert that a save() operation yields some predictable attribute results.
986     *
987     * @param Horde_Kolab_Server_Object $object    The object to work on.
988     * @param Horde_Kolab_Server        $server    The server the object resides on.
989     * @param string                    $attribute The attribute to work on.
990     * @param array                     $sequence  The sequence of values to set and expect.
991     *
992     * @return NULL.
993     */
994    protected function assertSimpleSequence(Horde_Kolab_Server_Object $object,
995                                            Horde_Kolab_Server $server,
996                                            $attribute, array $sequence,
997                                            $pop_arrays = false)
998    {
999        foreach ($sequence as $value) {
1000            $this->assertStoreFetch($object, $server,
1001                                    array($attribute => $value),
1002                                    array($attribute => $value),
1003                                    $pop_arrays);
1004        }
1005    }
1006
1007    /**
1008     * Assert that a save() operation yields some predictable attribute results.
1009     *
1010     * @param Horde_Kolab_Server_Object  $object The object to work on.
1011     * @param Horde_Kolab_Server         $server The server the object resides on.
1012     * @param array                      $store  The information to save.
1013     * @param array                      $fetch  The expected results.
1014     *
1015     * @return NULL.
1016     */
1017    protected function assertStoreFetch(Horde_Kolab_Server_Object $object,
1018                                        Horde_Kolab_Server $server,
1019                                        array $store, array $fetch,
1020                                        $pop_arrays = false)
1021    {
1022        $result = $object->save($store);
1023        $this->assertNoError($result);
1024
1025        $object = $server->fetch($object->getUid());
1026
1027        foreach ($fetch as $attribute => $expect) {
1028            $actual = $object->get($attribute, false);
1029            if ($pop_arrays && is_array($actual) && count($actual) == 1) {
1030                $actual = array_pop($actual);
1031            }
1032            $this->assertEquals($expect,
1033                                $actual);
1034        }
1035    }
1036
1037    public function assertRecursiveType($results, $type)
1038    {
1039        if (is_array($results)) {
1040            foreach ($results as $result) {
1041                $this->assertRecursiveType($result, $type);
1042            }
1043        } else {
1044            if ($results instanceof Exception) {
1045                $this->assertEquals('', $results->getMessage());
1046            } else {
1047                $this->assertInstanceOf($type, $results);
1048            }
1049        }
1050    }
1051
1052    /**
1053     * Setup function.
1054     *
1055     * @return NULL.
1056     */
1057    protected function setUp()
1058    {
1059        $this->added = array();
1060        $this->markTestIncomplete('Needs to be fixed');
1061    }
1062
1063    /**
1064     * Cleanup function.
1065     *
1066     * @return NULL.
1067     */
1068    protected function tearDown()
1069    {
1070        if (isset($this->added)) {
1071            $added = array_reverse($this->added);
1072            foreach ($added as $add) {
1073                $result = $add[0]->delete($add[1]);
1074                $this->assertNoError($result);
1075            }
1076        }
1077    }
1078}
1079