diff options
author | Joas Schilling <nickvergessen@owncloud.com> | 2016-05-25 16:04:15 +0200 |
---|---|---|
committer | Joas Schilling <nickvergessen@owncloud.com> | 2016-05-25 16:09:18 +0200 |
commit | 5882e21b3bff0afe2152eb3971d674bdb91e45a2 (patch) | |
tree | 39dee4b6791c25405b31f2df13b430e7d37c4767 /apps/dav/tests/unit/CardDAV | |
parent | 42ba61db044f1d08e22089fbc3badafbc35d5ea4 (diff) | |
download | nextcloud-server-5882e21b3bff0afe2152eb3971d674bdb91e45a2.tar.gz nextcloud-server-5882e21b3bff0afe2152eb3971d674bdb91e45a2.zip |
Update DAV unit tests to PSR-4
Diffstat (limited to 'apps/dav/tests/unit/CardDAV')
-rw-r--r-- | apps/dav/tests/unit/CardDAV/AddressBookImplTest.php | 288 | ||||
-rw-r--r-- | apps/dav/tests/unit/CardDAV/AddressBookTest.php | 139 | ||||
-rw-r--r-- | apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php | 216 | ||||
-rw-r--r-- | apps/dav/tests/unit/CardDAV/CardDavBackendTest.php | 632 | ||||
-rw-r--r-- | apps/dav/tests/unit/CardDAV/ContactsManagerTest.php | 43 | ||||
-rw-r--r-- | apps/dav/tests/unit/CardDAV/ConverterTest.php | 137 | ||||
-rw-r--r-- | apps/dav/tests/unit/CardDAV/Sharing/PluginTest.php | 81 | ||||
-rw-r--r-- | apps/dav/tests/unit/CardDAV/SyncServiceTest.php | 145 |
8 files changed, 1681 insertions, 0 deletions
diff --git a/apps/dav/tests/unit/CardDAV/AddressBookImplTest.php b/apps/dav/tests/unit/CardDAV/AddressBookImplTest.php new file mode 100644 index 00000000000..25da92bbf23 --- /dev/null +++ b/apps/dav/tests/unit/CardDAV/AddressBookImplTest.php @@ -0,0 +1,288 @@ +<?php +/** + * @author Björn Schießle <schiessle@owncloud.com> + * @author Thomas Müller <thomas.mueller@tmit.eu> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + + +namespace OCA\DAV\Tests\unit\CardDAV; + + +use OCA\DAV\CardDAV\AddressBook; +use OCA\DAV\CardDAV\AddressBookImpl; +use OCA\DAV\CardDAV\CardDavBackend; +use Sabre\VObject\Component\VCard; +use Sabre\VObject\Property\Text; +use Test\TestCase; + +class AddressBookImplTest extends TestCase { + + /** @var AddressBookImpl */ + private $addressBookImpl; + + /** @var array */ + private $addressBookInfo; + + /** @var AddressBook | \PHPUnit_Framework_MockObject_MockObject */ + private $addressBook; + + /** @var CardDavBackend | \PHPUnit_Framework_MockObject_MockObject */ + private $backend; + + /** @var VCard | \PHPUnit_Framework_MockObject_MockObject */ + private $vCard; + + public function setUp() { + parent::setUp(); + + $this->addressBookInfo = [ + 'id' => 42, + '{DAV:}displayname' => 'display name' + ]; + $this->addressBook = $this->getMockBuilder('OCA\DAV\CardDAV\AddressBook') + ->disableOriginalConstructor()->getMock(); + $this->backend = $this->getMockBuilder('\OCA\DAV\CardDAV\CardDavBackend') + ->disableOriginalConstructor()->getMock(); + $this->vCard = $this->getMock('Sabre\VObject\Component\VCard'); + + $this->addressBookImpl = new AddressBookImpl( + $this->addressBook, + $this->addressBookInfo, + $this->backend + ); + } + + public function testGetKey() { + $this->assertSame($this->addressBookInfo['id'], + $this->addressBookImpl->getKey()); + } + + public function testGetDisplayName() { + $this->assertSame($this->addressBookInfo['{DAV:}displayname'], + $this->addressBookImpl->getDisplayName()); + } + + public function testSearch() { + + /** @var \PHPUnit_Framework_MockObject_MockObject | AddressBookImpl $addressBookImpl */ + $addressBookImpl = $this->getMockBuilder('OCA\DAV\CardDAV\AddressBookImpl') + ->setConstructorArgs( + [ + $this->addressBook, + $this->addressBookInfo, + $this->backend + ] + ) + ->setMethods(['vCard2Array', 'readCard']) + ->getMock(); + + $pattern = 'pattern'; + $searchProperties = 'properties'; + + $this->backend->expects($this->once())->method('search') + ->with($this->addressBookInfo['id'], $pattern, $searchProperties) + ->willReturn( + [ + 'cardData1', + 'cardData2' + ] + ); + + $addressBookImpl->expects($this->exactly(2))->method('readCard') + ->willReturn($this->vCard); + $addressBookImpl->expects($this->exactly(2))->method('vCard2Array') + ->with($this->vCard)->willReturn('vCard'); + + $result = $addressBookImpl->search($pattern, $searchProperties, []); + $this->assertTrue((is_array($result))); + $this->assertSame(2, count($result)); + } + + /** + * @dataProvider dataTestCreate + * + * @param array $properties + */ + public function testCreate($properties) { + + $uid = 'uid'; + + /** @var \PHPUnit_Framework_MockObject_MockObject | AddressBookImpl $addressBookImpl */ + $addressBookImpl = $this->getMockBuilder('OCA\DAV\CardDAV\AddressBookImpl') + ->setConstructorArgs( + [ + $this->addressBook, + $this->addressBookInfo, + $this->backend + ] + ) + ->setMethods(['vCard2Array', 'createUid', 'createEmptyVCard']) + ->getMock(); + + $addressBookImpl->expects($this->once())->method('createUid') + ->willReturn($uid); + $addressBookImpl->expects($this->once())->method('createEmptyVCard') + ->with($uid)->willReturn($this->vCard); + $this->vCard->expects($this->exactly(count($properties))) + ->method('createProperty'); + $this->backend->expects($this->once())->method('createCard'); + $this->backend->expects($this->never())->method('updateCard'); + $this->backend->expects($this->never())->method('getCard'); + $addressBookImpl->expects($this->once())->method('vCard2Array') + ->with($this->vCard)->willReturn(true); + + $this->assertTrue($addressBookImpl->createOrUpdate($properties)); + } + + public function dataTestCreate() { + return [ + [[]], + [['FN' => 'John Doe']] + ]; + } + + public function testUpdate() { + + $uid = 'uid'; + $properties = ['UID' => $uid, 'FN' => 'John Doe']; + + /** @var \PHPUnit_Framework_MockObject_MockObject | AddressBookImpl $addressBookImpl */ + $addressBookImpl = $this->getMockBuilder('OCA\DAV\CardDAV\AddressBookImpl') + ->setConstructorArgs( + [ + $this->addressBook, + $this->addressBookInfo, + $this->backend + ] + ) + ->setMethods(['vCard2Array', 'createUid', 'createEmptyVCard', 'readCard']) + ->getMock(); + + $addressBookImpl->expects($this->never())->method('createUid'); + $addressBookImpl->expects($this->never())->method('createEmptyVCard'); + $this->backend->expects($this->once())->method('getCard') + ->with($this->addressBookInfo['id'], $uid . '.vcf') + ->willReturn(['carddata' => 'data']); + $addressBookImpl->expects($this->once())->method('readCard') + ->with('data')->willReturn($this->vCard); + $this->vCard->expects($this->exactly(count($properties))) + ->method('createProperty'); + $this->backend->expects($this->never())->method('createCard'); + $this->backend->expects($this->once())->method('updateCard'); + $addressBookImpl->expects($this->once())->method('vCard2Array') + ->with($this->vCard)->willReturn(true); + + $this->assertTrue($addressBookImpl->createOrUpdate($properties)); + } + + /** + * @dataProvider dataTestGetPermissions + * + * @param array $permissions + * @param int $expected + */ + public function testGetPermissions($permissions, $expected) { + $this->addressBook->expects($this->once())->method('getACL') + ->willReturn($permissions); + + $this->assertSame($expected, + $this->addressBookImpl->getPermissions() + ); + } + + public function dataTestGetPermissions() { + return [ + [[], 0], + [[['privilege' => '{DAV:}read']], 1], + [[['privilege' => '{DAV:}write']], 6], + [[['privilege' => '{DAV:}all']], 31], + [[['privilege' => '{DAV:}read'],['privilege' => '{DAV:}write']], 7], + [[['privilege' => '{DAV:}read'],['privilege' => '{DAV:}all']], 31], + [[['privilege' => '{DAV:}all'],['privilege' => '{DAV:}write']], 31], + [[['privilege' => '{DAV:}read'],['privilege' => '{DAV:}write'],['privilege' => '{DAV:}all']], 31], + [[['privilege' => '{DAV:}all'],['privilege' => '{DAV:}read'],['privilege' => '{DAV:}write']], 31], + ]; + } + + public function testDelete() { + $cardId = 1; + $cardUri = 'cardUri'; + $this->backend->expects($this->once())->method('getCardUri') + ->with($cardId)->willReturn($cardUri); + $this->backend->expects($this->once())->method('deleteCard') + ->with($this->addressBookInfo['id'], $cardUri) + ->willReturn(true); + + $this->assertTrue($this->addressBookImpl->delete($cardId)); + } + + public function testReadCard() { + $vCard = new VCard(); + $vCard->add(new Text($vCard, 'UID', 'uid')); + $vCardSerialized = $vCard->serialize(); + + $result = $this->invokePrivate($this->addressBookImpl, 'readCard', [$vCardSerialized]); + $resultSerialized = $result->serialize(); + + $this->assertSame($vCardSerialized, $resultSerialized); + } + + public function testCreateUid() { + /** @var \PHPUnit_Framework_MockObject_MockObject | AddressBookImpl $addressBookImpl */ + $addressBookImpl = $this->getMockBuilder('OCA\DAV\CardDAV\AddressBookImpl') + ->setConstructorArgs( + [ + $this->addressBook, + $this->addressBookInfo, + $this->backend + ] + ) + ->setMethods(['getUid']) + ->getMock(); + + $addressBookImpl->expects($this->at(0))->method('getUid')->willReturn('uid0'); + $addressBookImpl->expects($this->at(1))->method('getUid')->willReturn('uid1'); + + // simulate that 'uid0' already exists, so the second uid will be returned + $this->backend->expects($this->exactly(2))->method('getContact') + ->willReturnCallback( + function($id, $uid) { + return ($uid === 'uid0.vcf'); + } + ); + + $this->assertSame('uid1', + $this->invokePrivate($addressBookImpl, 'createUid', []) + ); + + } + + public function testCreateEmptyVCard() { + $uid = 'uid'; + $expectedVCard = new VCard(); + $expectedVCard->add(new Text($expectedVCard, 'UID', $uid)); + $expectedVCardSerialized = $expectedVCard->serialize(); + + $result = $this->invokePrivate($this->addressBookImpl, 'createEmptyVCard', [$uid]); + $resultSerialized = $result->serialize(); + + $this->assertSame($expectedVCardSerialized, $resultSerialized); + } + +} diff --git a/apps/dav/tests/unit/CardDAV/AddressBookTest.php b/apps/dav/tests/unit/CardDAV/AddressBookTest.php new file mode 100644 index 00000000000..7144c36140c --- /dev/null +++ b/apps/dav/tests/unit/CardDAV/AddressBookTest.php @@ -0,0 +1,139 @@ +<?php +/** + * @author Thomas Müller <thomas.mueller@tmit.eu> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\Tests\unit\CardDAV; + +use OCA\DAV\CardDAV\AddressBook; +use OCA\DAV\CardDAV\CardDavBackend; +use Sabre\DAV\PropPatch; +use Test\TestCase; + +class AddressBookTest extends TestCase { + + public function testDelete() { + /** @var \PHPUnit_Framework_MockObject_MockObject | CardDavBackend $backend */ + $backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend')->disableOriginalConstructor()->getMock(); + $backend->expects($this->once())->method('updateShares'); + $backend->expects($this->any())->method('getShares')->willReturn([ + ['href' => 'principal:user2'] + ]); + $calendarInfo = [ + '{http://owncloud.org/ns}owner-principal' => 'user1', + 'principaluri' => 'user2', + 'id' => 666 + ]; + $c = new AddressBook($backend, $calendarInfo); + $c->delete(); + } + + /** + * @expectedException \Sabre\DAV\Exception\Forbidden + */ + public function testDeleteFromGroup() { + /** @var \PHPUnit_Framework_MockObject_MockObject | CardDavBackend $backend */ + $backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend')->disableOriginalConstructor()->getMock(); + $backend->expects($this->never())->method('updateShares'); + $backend->expects($this->any())->method('getShares')->willReturn([ + ['href' => 'principal:group2'] + ]); + $calendarInfo = [ + '{http://owncloud.org/ns}owner-principal' => 'user1', + 'principaluri' => 'user2', + 'id' => 666 + ]; + $c = new AddressBook($backend, $calendarInfo); + $c->delete(); + } + + /** + * @expectedException \Sabre\DAV\Exception\Forbidden + */ + public function testPropPatch() { + /** @var \PHPUnit_Framework_MockObject_MockObject | CardDavBackend $backend */ + $backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend')->disableOriginalConstructor()->getMock(); + $calendarInfo = [ + '{http://owncloud.org/ns}owner-principal' => 'user1', + 'principaluri' => 'user2', + 'id' => 666 + ]; + $c = new AddressBook($backend, $calendarInfo); + $c->propPatch(new PropPatch([])); + } + + /** + * @dataProvider providesReadOnlyInfo + */ + public function testAcl($expectsWrite, $readOnlyValue, $hasOwnerSet) { + /** @var \PHPUnit_Framework_MockObject_MockObject | CardDavBackend $backend */ + $backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend')->disableOriginalConstructor()->getMock(); + $backend->expects($this->any())->method('applyShareAcl')->willReturnArgument(1); + $calendarInfo = [ + 'principaluri' => 'user2', + 'id' => 666, + 'uri' => 'default' + ]; + if (!is_null($readOnlyValue)) { + $calendarInfo['{http://owncloud.org/ns}read-only'] = $readOnlyValue; + } + if ($hasOwnerSet) { + $calendarInfo['{http://owncloud.org/ns}owner-principal'] = 'user1'; + } + $c = new AddressBook($backend, $calendarInfo); + $acl = $c->getACL(); + $childAcl = $c->getChildACL(); + + $expectedAcl = [[ + 'privilege' => '{DAV:}read', + 'principal' => $hasOwnerSet ? 'user1' : 'user2', + 'protected' => true + ], [ + 'privilege' => '{DAV:}write', + 'principal' => $hasOwnerSet ? 'user1' : 'user2', + 'protected' => true + ]]; + if ($hasOwnerSet) { + $expectedAcl[] = [ + 'privilege' => '{DAV:}read', + 'principal' => 'user2', + 'protected' => true + ]; + if ($expectsWrite) { + $expectedAcl[] = [ + 'privilege' => '{DAV:}write', + 'principal' => 'user2', + 'protected' => true + ]; + } + } + $this->assertEquals($expectedAcl, $acl); + $this->assertEquals($expectedAcl, $childAcl); + } + + public function providesReadOnlyInfo() { + return [ + 'read-only property not set' => [true, null, true], + 'read-only property is false' => [true, false, true], + 'read-only property is true' => [false, true, true], + 'read-only property not set and no owner' => [true, null, false], + 'read-only property is false and no owner' => [true, false, false], + 'read-only property is true and no owner' => [false, true, false], + ]; + }} diff --git a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php new file mode 100644 index 00000000000..0162924064d --- /dev/null +++ b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php @@ -0,0 +1,216 @@ +<?php +/** + * @author Thomas Müller <thomas.mueller@tmit.eu> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\Tests\unit\CardDAV; + +use OCA\DAV\CalDAV\BirthdayService; +use OCA\DAV\CalDAV\CalDavBackend; +use OCA\DAV\CardDAV\CardDavBackend; +use OCA\DAV\DAV\GroupPrincipalBackend; +use Sabre\VObject\Component\VCalendar; +use Sabre\VObject\Reader; +use Test\TestCase; + +class BirthdayServiceTest extends TestCase { + + /** @var BirthdayService */ + private $service; + /** @var CalDavBackend | \PHPUnit_Framework_MockObject_MockObject */ + private $calDav; + /** @var CardDavBackend | \PHPUnit_Framework_MockObject_MockObject */ + private $cardDav; + /** @var GroupPrincipalBackend | \PHPUnit_Framework_MockObject_MockObject */ + private $groupPrincialBackend; + + public function setUp() { + parent::setUp(); + + $this->calDav = $this->getMockBuilder('OCA\DAV\CalDAV\CalDavBackend')->disableOriginalConstructor()->getMock(); + $this->cardDav = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend')->disableOriginalConstructor()->getMock(); + $this->groupPrincialBackend = $this->getMockBuilder('OCA\DAV\DAV\GroupPrincipalBackend')->disableOriginalConstructor()->getMock(); + + $this->service = new BirthdayService($this->calDav, $this->cardDav, $this->groupPrincialBackend); + } + + /** + * @dataProvider providesVCards + * @param boolean $nullExpected + * @param string | null $data + */ + public function testBuildBirthdayFromContact($nullExpected, $data) { + $cal = $this->service->buildBirthdayFromContact($data); + if ($nullExpected) { + $this->assertNull($cal); + } else { + $this->assertInstanceOf('Sabre\VObject\Component\VCalendar', $cal); + $this->assertTrue(isset($cal->VEVENT)); + $this->assertEquals('FREQ=YEARLY', $cal->VEVENT->RRULE->getValue()); + $this->assertEquals('12345 (*1900)', $cal->VEVENT->SUMMARY->getValue()); + $this->assertEquals('TRANSPARENT', $cal->VEVENT->TRANSP->getValue()); + } + } + + public function testOnCardDeleted() { + $this->cardDav->expects($this->once())->method('getAddressBookById') + ->with(666) + ->willReturn([ + 'principaluri' => 'principals/users/user01', + 'uri' => 'default' + ]); + $this->calDav->expects($this->once())->method('getCalendarByUri') + ->with('principals/users/user01', 'contact_birthdays') + ->willReturn([ + 'id' => 1234 + ]); + $this->calDav->expects($this->once())->method('deleteCalendarObject')->with(1234, 'default-gump.vcf.ics'); + $this->cardDav->expects($this->once())->method('getShares')->willReturn([]); + + $this->service->onCardDeleted(666, 'gump.vcf'); + } + + /** + * @dataProvider providesCardChanges + */ + public function testOnCardChanged($expectedOp) { + $this->cardDav->expects($this->once())->method('getAddressBookById') + ->with(666) + ->willReturn([ + 'principaluri' => 'principals/users/user01', + 'uri' => 'default' + ]); + $this->calDav->expects($this->once())->method('getCalendarByUri') + ->with('principals/users/user01', 'contact_birthdays') + ->willReturn([ + 'id' => 1234 + ]); + $this->cardDav->expects($this->once())->method('getShares')->willReturn([]); + + /** @var BirthdayService | \PHPUnit_Framework_MockObject_MockObject $service */ + $service = $this->getMock('\OCA\DAV\CalDAV\BirthdayService', + ['buildBirthdayFromContact', 'birthdayEvenChanged'], [$this->calDav, $this->cardDav, $this->groupPrincialBackend]); + + if ($expectedOp === 'delete') { + $this->calDav->expects($this->once())->method('getCalendarObject')->willReturn(''); + $service->expects($this->once())->method('buildBirthdayFromContact')->willReturn(null); + $this->calDav->expects($this->once())->method('deleteCalendarObject')->with(1234, 'default-gump.vcf.ics'); + } + if ($expectedOp === 'create') { + $service->expects($this->once())->method('buildBirthdayFromContact')->willReturn(new VCalendar()); + $this->calDav->expects($this->once())->method('createCalendarObject')->with(1234, 'default-gump.vcf.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"); + } + if ($expectedOp === 'update') { + $service->expects($this->once())->method('buildBirthdayFromContact')->willReturn(new VCalendar()); + $service->expects($this->once())->method('birthdayEvenChanged')->willReturn(true); + $this->calDav->expects($this->once())->method('getCalendarObject')->willReturn([ + 'calendardata' => '']); + $this->calDav->expects($this->once())->method('updateCalendarObject')->with(1234, 'default-gump.vcf.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nEND:VCALENDAR\r\n"); + } + + $service->onCardChanged(666, 'gump.vcf', ''); + } + + /** + * @dataProvider providesBirthday + * @param $expected + * @param $old + * @param $new + */ + public function testBirthdayEvenChanged($expected, $old, $new) { + $new = Reader::read($new); + $this->assertEquals($expected, $this->service->birthdayEvenChanged($old, $new)); + } + + public function testGetAllAffectedPrincipals() { + $this->cardDav->expects($this->once())->method('getShares')->willReturn([ + [ + '{http://owncloud.org/ns}group-share' => false, + '{http://owncloud.org/ns}principal' => 'principals/users/user01' + ], + [ + '{http://owncloud.org/ns}group-share' => false, + '{http://owncloud.org/ns}principal' => 'principals/users/user01' + ], + [ + '{http://owncloud.org/ns}group-share' => false, + '{http://owncloud.org/ns}principal' => 'principals/users/user02' + ], + [ + '{http://owncloud.org/ns}group-share' => true, + '{http://owncloud.org/ns}principal' => 'principals/groups/users' + ], + ]); + $this->groupPrincialBackend->expects($this->once())->method('getGroupMemberSet') + ->willReturn([ + [ + 'uri' => 'principals/users/user01', + ], + [ + 'uri' => 'principals/users/user02', + ], + [ + 'uri' => 'principals/users/user03', + ], + ]); + $users = $this->invokePrivate($this->service, 'getAllAffectedPrincipals', [6666]); + $this->assertEquals([ + 'principals/users/user01', + 'principals/users/user02', + 'principals/users/user03' + ], $users); + } + + public function providesBirthday() { + return [ + [true, + '', + "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:12345\r\nDTSTAMP:20160218T133704Z\r\nDTSTART;VALUE=DATE:19000101\r\nDTEND;VALUE=DATE:19000102\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:12345's Birthday (1900)\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"], + [false, + "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:12345\r\nDTSTAMP:20160218T133704Z\r\nDTSTART;VALUE=DATE:19000101\r\nDTEND;VALUE=DATE:19000102\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:12345's Birthday (1900)\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n", + "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:12345\r\nDTSTAMP:20160218T133704Z\r\nDTSTART;VALUE=DATE:19000101\r\nDTEND;VALUE=DATE:19000102\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:12345's Birthday (1900)\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"], + [true, + "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:12345\r\nDTSTAMP:20160218T133704Z\r\nDTSTART;VALUE=DATE:19000101\r\nDTEND;VALUE=DATE:19000102\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:4567's Birthday (1900)\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n", + "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:12345\r\nDTSTAMP:20160218T133704Z\r\nDTSTART;VALUE=DATE:19000101\r\nDTEND;VALUE=DATE:19000102\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:12345's Birthday (1900)\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"], + [true, + "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:12345\r\nDTSTAMP:20160218T133704Z\r\nDTSTART;VALUE=DATE:19000101\r\nDTEND;VALUE=DATE:19000102\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:12345's Birthday (1900)\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n", + "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:12345\r\nDTSTAMP:20160218T133704Z\r\nDTSTART;VALUE=DATE:19000102\r\nDTEND;VALUE=DATE:19000102\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:12345's Birthday (1900)\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"] + ]; + } + + public function providesCardChanges(){ + return[ + ['delete'], + ['create'], + ['update'] + ]; + } + + public function providesVCards() { + return [ + [true, null], + [true, ''], + [true, 'yasfewf'], + [true, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n", "Dr. Foo Bar"], + [true, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:\r\nEND:VCARD\r\n", "Dr. Foo Bar"], + [true, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:someday\r\nEND:VCARD\r\n", "Dr. Foo Bar"], + [false, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:1900-01-01\r\nEND:VCARD\r\n", "Dr. Foo Bar"], + ]; + } +} diff --git a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php new file mode 100644 index 00000000000..7cae76ae62b --- /dev/null +++ b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php @@ -0,0 +1,632 @@ +<?php +/** + * @author Arthur Schiwon <blizzz@owncloud.com> + * @author Björn Schießle <schiessle@owncloud.com> + * @author Joas Schilling <nickvergessen@owncloud.com> + * @author Thomas Müller <thomas.mueller@tmit.eu> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\Tests\unit\CardDAV; + +use InvalidArgumentException; +use OCA\DAV\CardDAV\AddressBook; +use OCA\DAV\CardDAV\CardDavBackend; +use OCA\DAV\Connector\Sabre\Principal; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IDBConnection; +use Sabre\DAV\PropPatch; +use Sabre\VObject\Component\VCard; +use Sabre\VObject\Property\Text; +use Test\TestCase; + +/** + * Class CardDavBackendTest + * + * @group DB + * + * @package OCA\DAV\Tests\unit\CardDAV + */ +class CardDavBackendTest extends TestCase { + + /** @var CardDavBackend */ + private $backend; + + /** @var Principal | \PHPUnit_Framework_MockObject_MockObject */ + private $principal; + + /** @var IDBConnection */ + private $db; + + /** @var string */ + private $dbCardsTable = 'cards'; + + /** @var string */ + private $dbCardsPropertiesTable = 'cards_properties'; + + const UNIT_TEST_USER = 'principals/users/carddav-unit-test'; + const UNIT_TEST_USER1 = 'principals/users/carddav-unit-test1'; + const UNIT_TEST_GROUP = 'principals/groups/carddav-unit-test-group'; + + public function setUp() { + parent::setUp(); + + $this->principal = $this->getMockBuilder('OCA\DAV\Connector\Sabre\Principal') + ->disableOriginalConstructor() + ->setMethods(['getPrincipalByPath', 'getGroupMembership']) + ->getMock(); + $this->principal->method('getPrincipalByPath') + ->willReturn([ + 'uri' => 'principals/best-friend' + ]); + $this->principal->method('getGroupMembership') + ->withAnyParameters() + ->willReturn([self::UNIT_TEST_GROUP]); + + $this->db = \OC::$server->getDatabaseConnection(); + + $this->backend = new CardDavBackend($this->db, $this->principal, null); + + // start every test with a empty cards_properties and cards table + $query = $this->db->getQueryBuilder(); + $query->delete('cards_properties')->execute(); + $query = $this->db->getQueryBuilder(); + $query->delete('cards')->execute(); + + + $this->tearDown(); + } + + public function tearDown() { + parent::tearDown(); + + if (is_null($this->backend)) { + return; + } + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + foreach ($books as $book) { + $this->backend->deleteAddressBook($book['id']); + } + } + + public function testAddressBookOperations() { + + // create a new address book + $this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); + + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($books)); + $this->assertEquals('Example', $books[0]['{DAV:}displayname']); + + // update it's display name + $patch = new PropPatch([ + '{DAV:}displayname' => 'Unit test', + '{urn:ietf:params:xml:ns:carddav}addressbook-description' => 'Addressbook used for unit testing' + ]); + $this->backend->updateAddressBook($books[0]['id'], $patch); + $patch->commit(); + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($books)); + $this->assertEquals('Unit test', $books[0]['{DAV:}displayname']); + $this->assertEquals('Addressbook used for unit testing', $books[0]['{urn:ietf:params:xml:ns:carddav}addressbook-description']); + + // delete the address book + $this->backend->deleteAddressBook($books[0]['id']); + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + $this->assertEquals(0, count($books)); + } + + public function testAddressBookSharing() { + + $this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($books)); + $addressBook = new AddressBook($this->backend, $books[0]); + $this->backend->updateShares($addressBook, [ + [ + 'href' => 'principal:' . self::UNIT_TEST_USER1, + ], + [ + 'href' => 'principal:' . self::UNIT_TEST_GROUP, + ] + ], []); + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER1); + $this->assertEquals(1, count($books)); + + // delete the address book + $this->backend->deleteAddressBook($books[0]['id']); + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + $this->assertEquals(0, count($books)); + } + + public function testCardOperations() { + + /** @var CardDavBackend | \PHPUnit_Framework_MockObject_MockObject $backend */ + $backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend') + ->setConstructorArgs([$this->db, $this->principal, null]) + ->setMethods(['updateProperties', 'purgeProperties'])->getMock(); + + // create a new address book + $backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); + $books = $backend->getAddressBooksForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($books)); + $bookId = $books[0]['id']; + + $uri = $this->getUniqueID('card'); + // updateProperties is expected twice, once for createCard and once for updateCard + $backend->expects($this->at(0))->method('updateProperties')->with($bookId, $uri, ''); + $backend->expects($this->at(1))->method('updateProperties')->with($bookId, $uri, '***'); + // create a card + $backend->createCard($bookId, $uri, ''); + + // get all the cards + $cards = $backend->getCards($bookId); + $this->assertEquals(1, count($cards)); + $this->assertEquals('', $cards[0]['carddata']); + + // get the cards + $card = $backend->getCard($bookId, $uri); + $this->assertNotNull($card); + $this->assertArrayHasKey('id', $card); + $this->assertArrayHasKey('uri', $card); + $this->assertArrayHasKey('lastmodified', $card); + $this->assertArrayHasKey('etag', $card); + $this->assertArrayHasKey('size', $card); + $this->assertEquals('', $card['carddata']); + + // update the card + $backend->updateCard($bookId, $uri, '***'); + $card = $backend->getCard($bookId, $uri); + $this->assertEquals('***', $card['carddata']); + + // delete the card + $backend->expects($this->once())->method('purgeProperties')->with($bookId, $card['id']); + $backend->deleteCard($bookId, $uri); + $cards = $backend->getCards($bookId); + $this->assertEquals(0, count($cards)); + } + + public function testMultiCard() { + + $this->backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend') + ->setConstructorArgs([$this->db, $this->principal, null]) + ->setMethods(['updateProperties'])->getMock(); + + // create a new address book + $this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($books)); + $bookId = $books[0]['id']; + + // create a card + $uri0 = $this->getUniqueID('card'); + $this->backend->createCard($bookId, $uri0, ''); + $uri1 = $this->getUniqueID('card'); + $this->backend->createCard($bookId, $uri1, ''); + $uri2 = $this->getUniqueID('card'); + $this->backend->createCard($bookId, $uri2, ''); + + // get all the cards + $cards = $this->backend->getCards($bookId); + $this->assertEquals(3, count($cards)); + $this->assertEquals('', $cards[0]['carddata']); + $this->assertEquals('', $cards[1]['carddata']); + $this->assertEquals('', $cards[2]['carddata']); + + // get the cards + $cards = $this->backend->getMultipleCards($bookId, [$uri1, $uri2]); + $this->assertEquals(2, count($cards)); + foreach($cards as $card) { + $this->assertArrayHasKey('id', $card); + $this->assertArrayHasKey('uri', $card); + $this->assertArrayHasKey('lastmodified', $card); + $this->assertArrayHasKey('etag', $card); + $this->assertArrayHasKey('size', $card); + $this->assertEquals('', $card['carddata']); + } + + // delete the card + $this->backend->deleteCard($bookId, $uri0); + $this->backend->deleteCard($bookId, $uri1); + $this->backend->deleteCard($bookId, $uri2); + $cards = $this->backend->getCards($bookId); + $this->assertEquals(0, count($cards)); + } + + public function testDeleteWithoutCard() { + + $this->backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend') + ->setConstructorArgs([$this->db, $this->principal, null]) + ->setMethods([ + 'getCardId', + 'addChange', + 'purgeProperties', + 'updateProperties', + ]) + ->getMock(); + + // create a new address book + $this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($books)); + + $bookId = $books[0]['id']; + $uri = $this->getUniqueID('card'); + + // create a new address book + $this->backend->expects($this->once()) + ->method('getCardId') + ->with($bookId, $uri) + ->willThrowException(new \InvalidArgumentException()); + $this->backend->expects($this->exactly(2)) + ->method('addChange') + ->withConsecutive( + [$bookId, $uri, 1], + [$bookId, $uri, 3] + ); + $this->backend->expects($this->never()) + ->method('purgeProperties'); + + // create a card + $this->backend->createCard($bookId, $uri, ''); + + // delete the card + $this->assertTrue($this->backend->deleteCard($bookId, $uri)); + } + + public function testSyncSupport() { + + $this->backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend') + ->setConstructorArgs([$this->db, $this->principal, null]) + ->setMethods(['updateProperties'])->getMock(); + + // create a new address book + $this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($books)); + $bookId = $books[0]['id']; + + // fist call without synctoken + $changes = $this->backend->getChangesForAddressBook($bookId, '', 1); + $syncToken = $changes['syncToken']; + + // add a change + $uri0 = $this->getUniqueID('card'); + $this->backend->createCard($bookId, $uri0, ''); + + // look for changes + $changes = $this->backend->getChangesForAddressBook($bookId, $syncToken, 1); + $this->assertEquals($uri0, $changes['added'][0]); + } + + public function testSharing() { + $this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($books)); + + $exampleBook = new AddressBook($this->backend, $books[0]); + $this->backend->updateShares($exampleBook, [['href' => 'principal:principals/best-friend']], []); + + $shares = $this->backend->getShares($exampleBook->getResourceId()); + $this->assertEquals(1, count($shares)); + + // adding the same sharee again has no effect + $this->backend->updateShares($exampleBook, [['href' => 'principal:principals/best-friend']], []); + + $shares = $this->backend->getShares($exampleBook->getResourceId()); + $this->assertEquals(1, count($shares)); + + $books = $this->backend->getAddressBooksForUser('principals/best-friend'); + $this->assertEquals(1, count($books)); + + $this->backend->updateShares($exampleBook, [], ['principal:principals/best-friend']); + + $shares = $this->backend->getShares($exampleBook->getResourceId()); + $this->assertEquals(0, count($shares)); + + $books = $this->backend->getAddressBooksForUser('principals/best-friend'); + $this->assertEquals(0, count($books)); + } + + public function testUpdateProperties() { + + $bookId = 42; + $cardUri = 'card-uri'; + $cardId = 2; + + $backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend') + ->setConstructorArgs([$this->db, $this->principal, null]) + ->setMethods(['getCardId'])->getMock(); + + $backend->expects($this->any())->method('getCardId')->willReturn($cardId); + + // add properties for new vCard + $vCard = new VCard(); + $vCard->add(new Text($vCard, 'UID', $cardUri)); + $vCard->add(new Text($vCard, 'FN', 'John Doe')); + $this->invokePrivate($backend, 'updateProperties', [$bookId, $cardUri, $vCard->serialize()]); + + $query = $this->db->getQueryBuilder(); + $result = $query->select('*')->from('cards_properties')->execute()->fetchAll(); + + $this->assertSame(2, count($result)); + + $this->assertSame('UID', $result[0]['name']); + $this->assertSame($cardUri, $result[0]['value']); + $this->assertSame($bookId, (int)$result[0]['addressbookid']); + $this->assertSame($cardId, (int)$result[0]['cardid']); + + $this->assertSame('FN', $result[1]['name']); + $this->assertSame('John Doe', $result[1]['value']); + $this->assertSame($bookId, (int)$result[1]['addressbookid']); + $this->assertSame($cardId, (int)$result[1]['cardid']); + + // update properties for existing vCard + $vCard = new VCard(); + $vCard->add(new Text($vCard, 'FN', 'John Doe')); + $this->invokePrivate($backend, 'updateProperties', [$bookId, $cardUri, $vCard->serialize()]); + + $query = $this->db->getQueryBuilder(); + $result = $query->select('*')->from('cards_properties')->execute()->fetchAll(); + + $this->assertSame(1, count($result)); + + $this->assertSame('FN', $result[0]['name']); + $this->assertSame('John Doe', $result[0]['value']); + $this->assertSame($bookId, (int)$result[0]['addressbookid']); + $this->assertSame($cardId, (int)$result[0]['cardid']); + } + + public function testPurgeProperties() { + + $query = $this->db->getQueryBuilder(); + $query->insert('cards_properties') + ->values( + [ + 'addressbookid' => $query->createNamedParameter(1), + 'cardid' => $query->createNamedParameter(1), + 'name' => $query->createNamedParameter('name1'), + 'value' => $query->createNamedParameter('value1'), + 'preferred' => $query->createNamedParameter(0) + ] + ); + $query->execute(); + + $query = $this->db->getQueryBuilder(); + $query->insert('cards_properties') + ->values( + [ + 'addressbookid' => $query->createNamedParameter(1), + 'cardid' => $query->createNamedParameter(2), + 'name' => $query->createNamedParameter('name2'), + 'value' => $query->createNamedParameter('value2'), + 'preferred' => $query->createNamedParameter(0) + ] + ); + $query->execute(); + + $this->invokePrivate($this->backend, 'purgeProperties', [1, 1]); + + $query = $this->db->getQueryBuilder(); + $result = $query->select('*')->from('cards_properties')->execute()->fetchAll(); + $this->assertSame(1, count($result)); + $this->assertSame(1 ,(int)$result[0]['addressbookid']); + $this->assertSame(2 ,(int)$result[0]['cardid']); + + } + + public function testGetCardId() { + $query = $this->db->getQueryBuilder(); + + $query->insert('cards') + ->values( + [ + 'addressbookid' => $query->createNamedParameter(1), + 'carddata' => $query->createNamedParameter(''), + 'uri' => $query->createNamedParameter('uri'), + 'lastmodified' => $query->createNamedParameter(4738743), + 'etag' => $query->createNamedParameter('etag'), + 'size' => $query->createNamedParameter(120) + ] + ); + $query->execute(); + $id = $query->getLastInsertId(); + + $this->assertSame($id, + $this->invokePrivate($this->backend, 'getCardId', [1, 'uri'])); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testGetCardIdFailed() { + $this->invokePrivate($this->backend, 'getCardId', [1, 'uri']); + } + + /** + * @dataProvider dataTestSearch + * + * @param string $pattern + * @param array $properties + * @param array $expected + */ + public function testSearch($pattern, $properties, $expected) { + /** @var VCard $vCards */ + $vCards = []; + $vCards[0] = new VCard(); + $vCards[0]->add(new Text($vCards[0], 'UID', 'uid')); + $vCards[0]->add(new Text($vCards[0], 'FN', 'John Doe')); + $vCards[0]->add(new Text($vCards[0], 'CLOUD', 'john@owncloud.org')); + $vCards[1] = new VCard(); + $vCards[1]->add(new Text($vCards[1], 'UID', 'uid')); + $vCards[1]->add(new Text($vCards[1], 'FN', 'John M. Doe')); + + $vCardIds = []; + $query = $this->db->getQueryBuilder(); + for($i=0; $i<2; $i++) { + $query->insert($this->dbCardsTable) + ->values( + [ + 'addressbookid' => $query->createNamedParameter(0), + 'carddata' => $query->createNamedParameter($vCards[$i]->serialize(), IQueryBuilder::PARAM_LOB), + 'uri' => $query->createNamedParameter('uri' . $i), + 'lastmodified' => $query->createNamedParameter(time()), + 'etag' => $query->createNamedParameter('etag' . $i), + 'size' => $query->createNamedParameter(120), + ] + ); + $query->execute(); + $vCardIds[] = $query->getLastInsertId(); + } + + $query->insert($this->dbCardsPropertiesTable) + ->values( + [ + 'addressbookid' => $query->createNamedParameter(0), + 'cardid' => $query->createNamedParameter($vCardIds[0]), + 'name' => $query->createNamedParameter('FN'), + 'value' => $query->createNamedParameter('John Doe'), + 'preferred' => $query->createNamedParameter(0) + ] + ); + $query->execute(); + $query->insert($this->dbCardsPropertiesTable) + ->values( + [ + 'addressbookid' => $query->createNamedParameter(0), + 'cardid' => $query->createNamedParameter($vCardIds[0]), + 'name' => $query->createNamedParameter('CLOUD'), + 'value' => $query->createNamedParameter('John@owncloud.org'), + 'preferred' => $query->createNamedParameter(0) + ] + ); + $query->execute(); + $query->insert($this->dbCardsPropertiesTable) + ->values( + [ + 'addressbookid' => $query->createNamedParameter(0), + 'cardid' => $query->createNamedParameter($vCardIds[1]), + 'name' => $query->createNamedParameter('FN'), + 'value' => $query->createNamedParameter('John M. Doe'), + 'preferred' => $query->createNamedParameter(0) + ] + ); + $query->execute(); + + $result = $this->backend->search(0, $pattern, $properties); + + // check result + $this->assertSame(count($expected), count($result)); + $found = []; + foreach ($result as $r) { + foreach ($expected as $exp) { + if (strpos($r, $exp) > 0) { + $found[$exp] = true; + break; + } + } + } + + $this->assertSame(count($expected), count($found)); + } + + public function dataTestSearch() { + return [ + ['John', ['FN'], ['John Doe', 'John M. Doe']], + ['M. Doe', ['FN'], ['John M. Doe']], + ['Do', ['FN'], ['John Doe', 'John M. Doe']], + 'check if duplicates are handled correctly' => ['John', ['FN', 'CLOUD'], ['John Doe', 'John M. Doe']], + 'case insensitive' => ['john', ['FN'], ['John Doe', 'John M. Doe']] + ]; + } + + public function testGetCardUri() { + $query = $this->db->getQueryBuilder(); + $query->insert($this->dbCardsTable) + ->values( + [ + 'addressbookid' => $query->createNamedParameter(1), + 'carddata' => $query->createNamedParameter('carddata', IQueryBuilder::PARAM_LOB), + 'uri' => $query->createNamedParameter('uri'), + 'lastmodified' => $query->createNamedParameter(5489543), + 'etag' => $query->createNamedParameter('etag'), + 'size' => $query->createNamedParameter(120), + ] + ); + $query->execute(); + + $id = $query->getLastInsertId(); + + $this->assertSame('uri', $this->backend->getCardUri($id)); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testGetCardUriFailed() { + $this->backend->getCardUri(1); + } + + public function testGetContact() { + $query = $this->db->getQueryBuilder(); + for($i=0; $i<2; $i++) { + $query->insert($this->dbCardsTable) + ->values( + [ + 'addressbookid' => $query->createNamedParameter($i), + 'carddata' => $query->createNamedParameter('carddata' . $i, IQueryBuilder::PARAM_LOB), + 'uri' => $query->createNamedParameter('uri' . $i), + 'lastmodified' => $query->createNamedParameter(5489543), + 'etag' => $query->createNamedParameter('etag' . $i), + 'size' => $query->createNamedParameter(120), + ] + ); + $query->execute(); + } + + $result = $this->backend->getContact(0, 'uri0'); + $this->assertSame(7, count($result)); + $this->assertSame(0, (int)$result['addressbookid']); + $this->assertSame('uri0', $result['uri']); + $this->assertSame(5489543, (int)$result['lastmodified']); + $this->assertSame('etag0', $result['etag']); + $this->assertSame(120, (int)$result['size']); + } + + public function testGetContactFail() { + $this->assertEmpty($this->backend->getContact(0, 'uri')); + } + + public function testCollectCardProperties() { + $query = $this->db->getQueryBuilder(); + $query->insert($this->dbCardsPropertiesTable) + ->values( + [ + 'addressbookid' => $query->createNamedParameter(666), + 'cardid' => $query->createNamedParameter(777), + 'name' => $query->createNamedParameter('FN'), + 'value' => $query->createNamedParameter('John Doe'), + 'preferred' => $query->createNamedParameter(0) + ] + ) + ->execute(); + + $result = $this->backend->collectCardProperties(666, 'FN'); + $this->assertEquals(['John Doe'], $result); + } +} diff --git a/apps/dav/tests/unit/CardDAV/ContactsManagerTest.php b/apps/dav/tests/unit/CardDAV/ContactsManagerTest.php new file mode 100644 index 00000000000..775dc5d18a5 --- /dev/null +++ b/apps/dav/tests/unit/CardDAV/ContactsManagerTest.php @@ -0,0 +1,43 @@ +<?php +/** + * @author Thomas Müller <thomas.mueller@tmit.eu> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\Tests\unit\CardDAV; + +use OCA\DAV\CardDAV\CardDavBackend; +use OCA\DAV\CardDAV\ContactsManager; +use OCP\Contacts\IManager; +use Test\TestCase; + +class ContactsManagerTest extends TestCase { + public function test() { + /** @var IManager | \PHPUnit_Framework_MockObject_MockObject $cm */ + $cm = $this->getMockBuilder('OCP\Contacts\IManager')->disableOriginalConstructor()->getMock(); + $cm->expects($this->exactly(2))->method('registerAddressBook'); + /** @var CardDavBackend | \PHPUnit_Framework_MockObject_MockObject $backEnd */ + $backEnd = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend')->disableOriginalConstructor()->getMock(); + $backEnd->method('getAddressBooksForUser')->willReturn([ + [] + ]); + + $app = new ContactsManager($backEnd); + $app->setupContactsProvider($cm, 'user01'); + } +} diff --git a/apps/dav/tests/unit/CardDAV/ConverterTest.php b/apps/dav/tests/unit/CardDAV/ConverterTest.php new file mode 100644 index 00000000000..4b71d43cc43 --- /dev/null +++ b/apps/dav/tests/unit/CardDAV/ConverterTest.php @@ -0,0 +1,137 @@ +<?php +/** + * @author Roeland Jago Douma <rullzer@owncloud.com> + * @author Thomas Müller <thomas.mueller@tmit.eu> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\Tests\unit\CardDAV; + +use OCA\DAV\CardDAV\Converter; +use Test\TestCase; + +class ConverterTest extends TestCase { + + /** + * @dataProvider providesNewUsers + */ + public function testCreation($expectedVCard, $displayName = null, $eMailAddress = null, $cloudId = null) { + $user = $this->getUserMock($displayName, $eMailAddress, $cloudId); + + $converter = new Converter(); + $vCard = $converter->createCardFromUser($user); + $cardData = $vCard->serialize(); + + $this->assertEquals($expectedVCard, $cardData); + } + + public function providesNewUsers() { + return [ + ["BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO;ENCODING=b;TYPE=JPEG:MTIzNDU2Nzg5\r\nEND:VCARD\r\n"], + ["BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:Dr. Foo Bar\r\nN:Bar;Dr.;Foo;;\r\nPHOTO;ENCODING=b;TYPE=JPEG:MTIzNDU2Nzg5\r\nEND:VCARD\r\n", "Dr. Foo Bar"], + ["BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:Dr. Foo Bar\r\nN:Bar;Dr.;Foo;;\r\nEMAIL;TYPE=OTHER:foo@bar.net\r\nPHOTO;ENCODING=b;TYPE=JPEG:MTIzNDU2Nzg5\r\nEND:VCARD\r\n", "Dr. Foo Bar", "foo@bar.net"], + ["BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:Dr. Foo Bar\r\nN:Bar;Dr.;Foo;;\r\nCLOUD:foo@bar.net\r\nPHOTO;ENCODING=b;TYPE=JPEG:MTIzNDU2Nzg5\r\nEND:VCARD\r\n", "Dr. Foo Bar", null, "foo@bar.net"], + ]; + } + + /** + * @dataProvider providesNewUsers + */ + public function testUpdateOfUnchangedUser($expectedVCard, $displayName = null, $eMailAddress = null, $cloudId = null) { + $user = $this->getUserMock($displayName, $eMailAddress, $cloudId); + + $converter = new Converter(); + $vCard = $converter->createCardFromUser($user); + $updated = $converter->updateCard($vCard, $user); + $this->assertFalse($updated); + $cardData = $vCard->serialize(); + + $this->assertEquals($expectedVCard, $cardData); + } + + /** + * @dataProvider providesUsersForUpdateOfRemovedElement + */ + public function testUpdateOfRemovedElement($expectedVCard, $displayName = null, $eMailAddress = null, $cloudId = null) { + $user = $this->getUserMock($displayName, $eMailAddress, $cloudId); + + $converter = new Converter(); + $vCard = $converter->createCardFromUser($user); + + $user1 = $this->getMockBuilder('OCP\IUser')->disableOriginalConstructor()->getMock(); + $user1->method('getUID')->willReturn('12345'); + $user1->method('getDisplayName')->willReturn(null); + $user1->method('getEMailAddress')->willReturn(null); + $user1->method('getCloudId')->willReturn(null); + $user1->method('getAvatarImage')->willReturn(null); + + $updated = $converter->updateCard($vCard, $user1); + $this->assertTrue($updated); + $cardData = $vCard->serialize(); + + $this->assertEquals($expectedVCard, $cardData); + } + + public function providesUsersForUpdateOfRemovedElement() { + return [ + ["BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n", "Dr. Foo Bar"], + ["BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n", "Dr. Foo Bar", "foo@bar.net"], + ["BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n", "Dr. Foo Bar", null, "foo@bar.net"], + ]; + } + + /** + * @dataProvider providesNames + * @param $expected + * @param $fullName + */ + public function testNameSplitter($expected, $fullName) { + + $converter = new Converter(); + $r = $converter->splitFullName($fullName); + $r = implode(';', $r); + $this->assertEquals($expected, $r); + } + + public function providesNames() { + return [ + ['Sauron;;;;', 'Sauron'], + ['Baggins;Bilbo;;;', 'Bilbo Baggins'], + ['Tolkien;John;Ronald Reuel;;', 'John Ronald Reuel Tolkien'], + ]; + } + + /** + * @param $displayName + * @param $eMailAddress + * @param $cloudId + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function getUserMock($displayName, $eMailAddress, $cloudId) { + $image0 = $this->getMockBuilder('OCP\IImage')->disableOriginalConstructor()->getMock(); + $image0->method('mimeType')->willReturn('JPEG'); + $image0->method('data')->willReturn('123456789'); + $user = $this->getMockBuilder('OCP\IUser')->disableOriginalConstructor()->getMock(); + $user->method('getUID')->willReturn('12345'); + $user->method('getDisplayName')->willReturn($displayName); + $user->method('getEMailAddress')->willReturn($eMailAddress); + $user->method('getCloudId')->willReturn($cloudId); + $user->method('getAvatarImage')->willReturn($image0); + return $user; + } +} diff --git a/apps/dav/tests/unit/CardDAV/Sharing/PluginTest.php b/apps/dav/tests/unit/CardDAV/Sharing/PluginTest.php new file mode 100644 index 00000000000..1cbececdb33 --- /dev/null +++ b/apps/dav/tests/unit/CardDAV/Sharing/PluginTest.php @@ -0,0 +1,81 @@ +<?php +/** + * @author Thomas Müller <thomas.mueller@tmit.eu> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\Tests\unit\CardDAV\Sharing; + + +use OCA\DAV\DAV\Sharing\IShareable; +use OCA\DAV\DAV\Sharing\Plugin; +use OCA\DAV\Connector\Sabre\Auth; +use OCP\IRequest; +use Sabre\DAV\Server; +use Sabre\DAV\SimpleCollection; +use Sabre\HTTP\Request; +use Sabre\HTTP\Response; +use Test\TestCase; + +class PluginTest extends TestCase { + + /** @var Plugin */ + private $plugin; + /** @var Server */ + private $server; + /** @var IShareable | \PHPUnit_Framework_MockObject_MockObject */ + private $book; + + public function setUp() { + parent::setUp(); + + /** @var Auth | \PHPUnit_Framework_MockObject_MockObject $authBackend */ + $authBackend = $this->getMockBuilder('OCA\DAV\Connector\Sabre\Auth')->disableOriginalConstructor()->getMock(); + $authBackend->method('isDavAuthenticated')->willReturn(true); + + /** @var IRequest $request */ + $request = $this->getMockBuilder('OCP\IRequest')->disableOriginalConstructor()->getMock(); + $this->plugin = new Plugin($authBackend, $request); + + $root = new SimpleCollection('root'); + $this->server = new \Sabre\DAV\Server($root); + /** @var SimpleCollection $node */ + $this->book = $this->getMockBuilder('OCA\DAV\DAV\Sharing\IShareable')->disableOriginalConstructor()->getMock(); + $this->book->method('getName')->willReturn('addressbook1.vcf'); + $root->addChild($this->book); + $this->plugin->initialize($this->server); + } + + public function testSharing() { + + $this->book->expects($this->once())->method('updateShares')->with([[ + 'href' => 'principal:principals/admin', + 'commonName' => null, + 'summary' => null, + 'readOnly' => false + ]], ['mailto:wilfredo@example.com']); + + // setup request + $request = new Request(); + $request->addHeader('Content-Type', 'application/xml'); + $request->setUrl('addressbook1.vcf'); + $request->setBody('<?xml version="1.0" encoding="utf-8" ?><CS:share xmlns:D="DAV:" xmlns:CS="http://owncloud.org/ns"><CS:set><D:href>principal:principals/admin</D:href><CS:read-write/></CS:set> <CS:remove><D:href>mailto:wilfredo@example.com</D:href></CS:remove></CS:share>'); + $response = new Response(); + $this->plugin->httpPost($request, $response); + } +} diff --git a/apps/dav/tests/unit/CardDAV/SyncServiceTest.php b/apps/dav/tests/unit/CardDAV/SyncServiceTest.php new file mode 100644 index 00000000000..e5a2603c77a --- /dev/null +++ b/apps/dav/tests/unit/CardDAV/SyncServiceTest.php @@ -0,0 +1,145 @@ +<?php +/** + * @author Björn Schießle <schiessle@owncloud.com> + * @author Thomas Müller <thomas.mueller@tmit.eu> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\Tests\unit\CardDAV; + +use OCA\DAV\CardDAV\CardDavBackend; +use OCA\DAV\CardDAV\SyncService; +use OCP\IUser; +use OCP\IUserManager; +use Test\TestCase; + +class SyncServiceTest extends TestCase { + public function testEmptySync() { + $backend = $this->getBackendMock(0, 0, 0); + + $ss = $this->getSyncServiceMock($backend, []); + $return = $ss->syncRemoteAddressBook('', 'system', '1234567890', null, '1', 'principals/system/system', []); + $this->assertEquals('sync-token-1', $return); + } + + public function testSyncWithNewElement() { + $backend = $this->getBackendMock(1, 0, 0); + $backend->method('getCard')->willReturn(false); + + $ss = $this->getSyncServiceMock($backend, ['0' => [200 => '']]); + $return = $ss->syncRemoteAddressBook('', 'system', '1234567890', null, '1', 'principals/system/system', []); + $this->assertEquals('sync-token-1', $return); + } + + public function testSyncWithUpdatedElement() { + $backend = $this->getBackendMock(0, 1, 0); + $backend->method('getCard')->willReturn(true); + + $ss = $this->getSyncServiceMock($backend, ['0' => [200 => '']]); + $return = $ss->syncRemoteAddressBook('', 'system', '1234567890', null, '1', 'principals/system/system', []); + $this->assertEquals('sync-token-1', $return); + } + + public function testSyncWithDeletedElement() { + $backend = $this->getBackendMock(0, 0, 1); + + $ss = $this->getSyncServiceMock($backend, ['0' => [404 => '']]); + $return = $ss->syncRemoteAddressBook('', 'system', '1234567890', null, '1', 'principals/system/system', []); + $this->assertEquals('sync-token-1', $return); + } + + public function testEnsureSystemAddressBookExists() { + /** @var CardDavBackend | \PHPUnit_Framework_MockObject_MockObject $backend */ + $backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDAVBackend')->disableOriginalConstructor()->getMock(); + $backend->expects($this->exactly(1))->method('createAddressBook'); + $backend->expects($this->at(0))->method('getAddressBooksByUri')->willReturn(null); + $backend->expects($this->at(1))->method('getAddressBooksByUri')->willReturn([]); + + /** @var IUserManager $userManager */ + $userManager = $this->getMockBuilder('OCP\IUserManager')->disableOriginalConstructor()->getMock(); + $logger = $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(); + $ss = new SyncService($backend, $userManager, $logger); + $book = $ss->ensureSystemAddressBookExists('principals/users/adam', 'contacts', []); + } + + public function testUpdateAndDeleteUser() { + /** @var CardDavBackend | \PHPUnit_Framework_MockObject_MockObject $backend */ + $backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDAVBackend')->disableOriginalConstructor()->getMock(); + $logger = $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(); + + $backend->expects($this->once())->method('createCard'); + $backend->expects($this->once())->method('updateCard'); + $backend->expects($this->once())->method('deleteCard'); + + $backend->method('getCard')->willReturnOnConsecutiveCalls(false, [ + 'carddata' => "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.4.8//EN\r\nUID:test-user\r\nFN:test-user\r\nN:test-user;;;;\r\nEND:VCARD\r\n\r\n" + ]); + + /** @var IUserManager | \PHPUnit_Framework_MockObject_MockObject $userManager */ + $userManager = $this->getMockBuilder('OCP\IUserManager')->disableOriginalConstructor()->getMock(); + + /** @var IUser | \PHPUnit_Framework_MockObject_MockObject $user */ + $user = $this->getMockBuilder('OCP\IUser')->disableOriginalConstructor()->getMock(); + $user->method('getBackendClassName')->willReturn('unittest'); + $user->method('getUID')->willReturn('test-user'); + + $ss = new SyncService($backend, $userManager, $logger); + $ss->updateUser($user); + + $user->method('getDisplayName')->willReturn('A test user for unit testing'); + + $ss->updateUser($user); + + $ss->deleteUser($user); + } + + /** + * @param int $createCount + * @param int $updateCount + * @param int $deleteCount + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getBackendMock($createCount, $updateCount, $deleteCount) { + $backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDAVBackend')->disableOriginalConstructor()->getMock(); + $backend->expects($this->exactly($createCount))->method('createCard'); + $backend->expects($this->exactly($updateCount))->method('updateCard'); + $backend->expects($this->exactly($deleteCount))->method('deleteCard'); + return $backend; + } + + /** + * @param $backend + * @param $response + * @return SyncService|\PHPUnit_Framework_MockObject_MockObject + */ + private function getSyncServiceMock($backend, $response) { + $userManager = $this->getMockBuilder('OCP\IUserManager')->disableOriginalConstructor()->getMock(); + $logger = $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(); + /** @var SyncService | \PHPUnit_Framework_MockObject_MockObject $ss */ + $ss = $this->getMock('OCA\DAV\CardDAV\SyncService', ['ensureSystemAddressBookExists', 'requestSyncReport', 'download'], [$backend, $userManager, $logger]); + $ss->method('requestSyncReport')->withAnyParameters()->willReturn(['response' => $response, 'token' => 'sync-token-1']); + $ss->method('ensureSystemAddressBookExists')->willReturn(['id' => 1]); + $ss->method('download')->willReturn([ + 'body' => '', + 'statusCode' => 200, + 'headers' => [] + ]); + return $ss; + } + +} |