diff --git a/lib/group/group.php b/lib/group/group.php
new file mode 100644
index 0000000000000000000000000000000000000000..6d0cb8f316beb4ca084d37d767ac3ac4aa4dbeea
--- /dev/null
+++ b/lib/group/group.php
@@ -0,0 +1,238 @@
+<?php
+
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Group;
+
+class Group {
+	/**
+	 * @var string $id
+	 */
+	private $id;
+
+	/**
+	 * @var \OC\User\User[] $users
+	 */
+	private $users;
+
+	/**
+	 * @var \OC_Group_Backend[] | \OC_Group_Database[] $backend
+	 */
+	private $backends;
+
+	/**
+	 * @var \OC\Hooks\PublicEmitter $emitter;
+	 */
+	private $emitter;
+
+	/**
+	 * @var \OC\User\Manager $userManager
+	 */
+	private $userManager;
+
+	/**
+	 * @param string $id
+	 * @param \OC_Group_Backend[] $backends
+	 * @param \OC\User\Manager $userManager
+	 * @param \OC\Hooks\PublicEmitter $emitter
+	 */
+	public function __construct($id, $backends, $userManager, $emitter = null) {
+		$this->id = $id;
+		$this->backends = $backends;
+		$this->userManager = $userManager;
+		$this->emitter = $emitter;
+	}
+
+	public function getGID() {
+		return $this->id;
+	}
+
+	/**
+	 * get all users in the group
+	 *
+	 * @return \OC\User\User[]
+	 */
+	public function getUsers() {
+		if ($this->users) {
+			return $this->users;
+		}
+
+		$users = array();
+		$userIds = array();
+		foreach ($this->backends as $backend) {
+			$diff = array_diff(
+				$backend->usersInGroup($this->id),
+				$userIds
+			);
+			if ($diff) {
+				$userIds = array_merge($userIds, $diff);
+			}
+		}
+
+		foreach ($userIds as $userId) {
+			$users[] = $this->userManager->get($userId);
+		}
+		$this->users = $users;
+		return $users;
+	}
+
+	/**
+	 * check if a user is in the group
+	 *
+	 * @param \OC\User\User $user
+	 * @return bool
+	 */
+	public function inGroup($user) {
+		foreach ($this->backends as $backend) {
+			if ($backend->inGroup($user->getUID(), $this->id)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * add a user to the group
+	 *
+	 * @param \OC\User\User $user
+	 */
+	public function addUser($user) {
+		if ($this->inGroup($user)) {
+			return;
+		}
+
+		if ($this->emitter) {
+			$this->emitter->emit('\OC\Group', 'preAddUser', array($this, $user));
+		}
+		foreach ($this->backends as $backend) {
+			if ($backend->implementsActions(OC_GROUP_BACKEND_ADD_TO_GROUP)) {
+				$backend->addToGroup($user->getUID(), $this->id);
+				if ($this->users) {
+					$this->users[] = $user;
+				}
+				if ($this->emitter) {
+					$this->emitter->emit('\OC\Group', 'addUser', array($this, $user));
+				}
+				return;
+			}
+		}
+	}
+
+	/**
+	 * remove a user from the group
+	 *
+	 * @param \OC\User\User $user
+	 */
+	public function removeUser($user) {
+		$result = false;
+		if ($this->emitter) {
+			$this->emitter->emit('\OC\Group', 'preRemoveUser', array($this, $user));
+		}
+		foreach ($this->backends as $backend) {
+			if ($backend->implementsActions(OC_GROUP_BACKEND_REMOVE_FROM_GOUP) and $backend->inGroup($user->getUID(), $this->id)) {
+				$backend->removeFromGroup($user->getUID(), $this->id);
+				$result = true;
+			}
+		}
+		if ($result) {
+			if ($this->emitter) {
+				$this->emitter->emit('\OC\Group', 'removeUser', array($this, $user));
+			}
+			if ($this->users) {
+				foreach ($this->users as $index => $groupUser) {
+					if ($groupUser->getUID() === $user->getUID()) {
+						unset($this->users[$index]);
+						return;
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * search for users in the group by userid
+	 *
+	 * @param string $search
+	 * @param int $limit
+	 * @param int $offset
+	 * @return \OC\User\User[]
+	 */
+	public function searchUsers($search = '', $limit = null, $offset = null) {
+		$users = array();
+		foreach ($this->backends as $backend) {
+			$userIds = $backend->usersInGroup($this->id, $search, $limit, $offset);
+			if (!is_null($limit)) {
+				$limit -= count($userIds);
+			}
+			if (!is_null($offset)) {
+				$offset -= count($userIds);
+			}
+			foreach ($userIds as $userId) {
+				$users[$userId] = $this->userManager->get($userId);
+			}
+			if (!is_null($limit) and $limit <= 0) {
+				return array_values($users);
+			}
+		}
+		return array_values($users);
+	}
+
+	/**
+	 * search for users in the group by displayname
+	 *
+	 * @param string $search
+	 * @param int $limit
+	 * @param int $offset
+	 * @return \OC\User\User[]
+	 */
+	public function searchDisplayName($search = '', $limit = null, $offset = null) {
+		$users = array();
+		foreach ($this->backends as $backend) {
+			if ($backend->implementsActions(OC_GROUP_BACKEND_GET_DISPLAYNAME)) {
+				$userIds = array_keys($backend->displayNamesInGroup($this->id, $search, $limit, $offset));
+			} else {
+				$userIds = $backend->usersInGroup($this->id, $search, $limit, $offset);
+			}
+			if (!is_null($limit)) {
+				$limit -= count($userIds);
+			}
+			if (!is_null($offset)) {
+				$offset -= count($userIds);
+			}
+			foreach ($userIds as $userId) {
+				$users[$userId] = $this->userManager->get($userId);
+			}
+			if (!is_null($limit) and $limit <= 0) {
+				return array_values($users);
+			}
+		}
+		return array_values($users);
+	}
+
+	/**
+	 * delete the group
+	 *
+	 * @return bool
+	 */
+	public function delete() {
+		$result = false;
+		if ($this->emitter) {
+			$this->emitter->emit('\OC\Group', 'preDelete', array($this));
+		}
+		foreach ($this->backends as $backend) {
+			if ($backend->implementsActions(OC_GROUP_BACKEND_DELETE_GROUP) and $backend->groupExists($this->id)) {
+				$result = true;
+				$backend->deleteGroup($this->id);
+			}
+		}
+		if ($result and $this->emitter) {
+			$this->emitter->emit('\OC\Group', 'delete', array($this));
+		}
+		return $result;
+	}
+}
diff --git a/lib/group/manager.php b/lib/group/manager.php
new file mode 100644
index 0000000000000000000000000000000000000000..7f96065c6d2deccfe2a740cb53c7201a777ad790
--- /dev/null
+++ b/lib/group/manager.php
@@ -0,0 +1,163 @@
+<?php
+
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Group;
+
+use OC\Hooks\PublicEmitter;
+
+/**
+ * Class Manager
+ *
+ * Hooks available in scope \OC\Group:
+ * - addUser(\OC\Group\Group $group, \OC\User\User $user)
+ * - preAddUser(\OC\Group\Group $group, \OC\User\User $user)
+ * - removeUser(\OC\Group\Group $group, \OC\User\User $user)
+ * - preRemoveUser(\OC\Group\Group $group, \OC\User\User $user)
+ * - delete(\OC\Group\Group $group)
+ * - preDelete(\OC\Group\Group $group)
+ * - create(\OC\Group\Group $group)
+ * - preCreate(string $groupId)
+ *
+ * @package OC\Group
+ */
+class Manager extends PublicEmitter {
+	/**
+	 * @var \OC_Group_Backend[] | \OC_Group_Database[] $backends
+	 */
+	private $backends = array();
+
+	/**
+	 * @var \OC\User\Manager $userManager
+	 */
+	private $userManager;
+
+	/**
+	 * @var \OC\Group\Group[]
+	 */
+	private $cachedGroups;
+
+	/**
+	 * @param \OC\User\Manager $userManager
+	 */
+	public function __construct($userManager) {
+		$this->userManager = $userManager;
+		$manager = $this;
+		$this->listen('\OC\Group', 'delete', function ($group) use (&$manager) {
+			/**
+			 * @var \OC\Group\Group $group
+			 */
+			unset($manager->cachedGroups[$group->getGID()]);
+		});
+	}
+
+	/**
+	 * @param \OC_Group_Backend $backend
+	 */
+	public function addBackend($backend) {
+		$this->backends[] = $backend;
+	}
+
+	public function clearBackends() {
+		$this->backends = array();
+		$this->cachedGroups = array();
+	}
+
+	/**
+	 * @param string $gid
+	 * @return \OC\Group\Group
+	 */
+	public function get($gid) {
+		if (isset($this->cachedGroups[$gid])) {
+			return $this->cachedGroups[$gid];
+		}
+		foreach ($this->backends as $backend) {
+			if ($backend->groupExists($gid)) {
+				return $this->createGroupObject($gid);
+			}
+		}
+		return null;
+	}
+
+	protected function createGroupObject($gid) {
+		$this->cachedGroups[$gid] = new Group($gid, $this->backends, $this->userManager, $this);
+		return $this->cachedGroups[$gid];
+	}
+
+	/**
+	 * @param string $gid
+	 * @return bool
+	 */
+	public function exists($gid) {
+		return !is_null($this->get($gid));
+	}
+
+	/**
+	 * @param string $gid
+	 * @return \OC\Group\Group
+	 */
+	public function create($gid) {
+		if (!$gid) {
+			return false;
+		} else if ($this->exists($gid)) {
+			return $this->get($gid);
+		} else {
+			$this->emit('\OC\Group', 'preCreate', array($gid));
+			foreach ($this->backends as $backend) {
+				if ($backend->implementsActions(OC_GROUP_BACKEND_CREATE_GROUP)) {
+					$backend->createGroup($gid);
+					$group = $this->createGroupObject($gid);
+					$this->emit('\OC\Group', 'create', array($group));
+					return $group;
+				}
+			}
+			return null;
+		}
+	}
+
+	/**
+	 * @param string $search
+	 * @param int $limit
+	 * @param int $offset
+	 * @return \OC\Group\Group[]
+	 */
+	public function search($search = '', $limit = null, $offset = null) {
+		$groups = array();
+		foreach ($this->backends as $backend) {
+			$groupIds = $backend->getGroups($search, $limit, $offset);
+			if (!is_null($limit)) {
+				$limit -= count($groupIds);
+			}
+			if (!is_null($offset)) {
+				$offset -= count($groupIds);
+			}
+			foreach ($groupIds as $groupId) {
+				$groups[$groupId] = $this->createGroupObject($groupId);
+			}
+			if (!is_null($limit) and $limit <= 0) {
+				return array_values($groups);
+			}
+		}
+		return array_values($groups);
+	}
+
+	/**
+	 * @param \OC\User\User $user
+	 * @return \OC\Group\Group[]
+	 */
+	public function getUserGroups($user) {
+		$groups = array();
+		foreach ($this->backends as $backend) {
+			$groupIds = $backend->getUserGroups($user->getUID());
+			foreach ($groupIds as $groupId) {
+				$groups[$groupId] = $this->createGroupObject($groupId);
+			}
+		}
+		return array_values($groups);
+	}
+}
diff --git a/lib/user.php b/lib/user.php
index 830f13bb8df6900304eb60d042d410ac844b54ef..908f2cbabfb454d35702ededfa492e2189d4cddc 100644
--- a/lib/user.php
+++ b/lib/user.php
@@ -39,7 +39,7 @@
 class OC_User {
 	public static $userSession = null;
 
-	private static function getUserSession() {
+	public static function getUserSession() {
 		if (!self::$userSession) {
 			$manager = new \OC\User\Manager();
 			self::$userSession = new \OC\User\Session($manager, \OC::$session);
@@ -83,7 +83,7 @@ class OC_User {
 	/**
 	 * @return \OC\User\Manager
 	 */
-	private static function getManager() {
+	public static function getManager() {
 		return self::getUserSession()->getManager();
 	}
 
diff --git a/lib/user/manager.php b/lib/user/manager.php
index d17cdf1a200790dcc815edfc1f231d1dcfd9e1d7..8dc9bfe27297a31cad756eeceaf3f74cd25ef095 100644
--- a/lib/user/manager.php
+++ b/lib/user/manager.php
@@ -30,6 +30,9 @@ class Manager extends PublicEmitter {
 	 */
 	private $backends = array();
 
+	/**
+	 * @var \OC\User\User[] $cachedUsers
+	 */
 	private $cachedUsers = array();
 
 	public function __construct() {
diff --git a/lib/user/user.php b/lib/user/user.php
index 55d7848a979c80e8b229cb41949e22f979709ad3..8115c43198cde309baac391334dca7ab1ef3ba56 100644
--- a/lib/user/user.php
+++ b/lib/user/user.php
@@ -44,7 +44,7 @@ class User {
 	 */
 	public function __construct($uid, $backend, $emitter = null) {
 		$this->uid = $uid;
-		if ($backend->implementsActions(OC_USER_BACKEND_GET_DISPLAYNAME)) {
+		if ($backend and $backend->implementsActions(OC_USER_BACKEND_GET_DISPLAYNAME)) {
 			$this->displayName = $backend->getDisplayName($uid);
 		} else {
 			$this->displayName = $uid;
diff --git a/tests/lib/group/group.php b/tests/lib/group/group.php
new file mode 100644
index 0000000000000000000000000000000000000000..116aefda81c17b01e4d3a0f17fd33d0d881dcd52
--- /dev/null
+++ b/tests/lib/group/group.php
@@ -0,0 +1,320 @@
+<?php
+
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace Test\Group;
+
+use OC\User\User;
+
+class Group extends \PHPUnit_Framework_TestCase {
+	/**
+	 * @return \PHPUnit_Framework_MockObject_MockObject | \OC\User\Manager
+	 */
+	protected function getUserManager() {
+		$userManager = $this->getMock('\OC\User\Manager');
+		$user1 = new User('user1', null);
+		$user2 = new User('user2', null);
+		$user3 = new User('user3', null);
+		$userManager->expects($this->any())
+			->method('get')
+			->will($this->returnValueMap(array(
+				array('user1', $user1),
+				array('user2', $user2),
+				array('user3', $user3)
+			)));
+		return $userManager;
+	}
+
+	public function testGetUsersSingleBackend() {
+		$backend = $this->getMock('OC_Group_Database');
+		$userManager = $this->getUserManager();
+		$group = new \OC\Group\Group('group1', array($backend), $userManager);
+
+		$backend->expects($this->once())
+			->method('usersInGroup')
+			->with('group1')
+			->will($this->returnValue(array('user1', 'user2')));
+
+		$users = $group->getUsers();
+
+		$this->assertEquals(2, count($users));
+		$user1 = $users[0];
+		$user2 = $users[1];
+		$this->assertEquals('user1', $user1->getUID());
+		$this->assertEquals('user2', $user2->getUID());
+	}
+
+	public function testGetUsersMultipleBackends() {
+		$backend1 = $this->getMock('OC_Group_Database');
+		$backend2 = $this->getMock('OC_Group_Database');
+		$userManager = $this->getUserManager();
+		$group = new \OC\Group\Group('group1', array($backend1, $backend2), $userManager);
+
+		$backend1->expects($this->once())
+			->method('usersInGroup')
+			->with('group1')
+			->will($this->returnValue(array('user1', 'user2')));
+
+		$backend2->expects($this->once())
+			->method('usersInGroup')
+			->with('group1')
+			->will($this->returnValue(array('user2', 'user3')));
+
+		$users = $group->getUsers();
+
+		$this->assertEquals(3, count($users));
+		$user1 = $users[0];
+		$user2 = $users[1];
+		$user3 = $users[2];
+		$this->assertEquals('user1', $user1->getUID());
+		$this->assertEquals('user2', $user2->getUID());
+		$this->assertEquals('user3', $user3->getUID());
+	}
+
+	public function testInGroupSingleBackend() {
+		$backend = $this->getMock('OC_Group_Database');
+		$userManager = $this->getUserManager();
+		$group = new \OC\Group\Group('group1', array($backend), $userManager);
+
+		$backend->expects($this->once())
+			->method('inGroup')
+			->with('user1', 'group1')
+			->will($this->returnValue(true));
+
+		$this->assertTrue($group->inGroup(new User('user1', null)));
+	}
+
+	public function testInGroupMultipleBackends() {
+		$backend1 = $this->getMock('OC_Group_Database');
+		$backend2 = $this->getMock('OC_Group_Database');
+		$userManager = $this->getUserManager();
+		$group = new \OC\Group\Group('group1', array($backend1, $backend2), $userManager);
+
+		$backend1->expects($this->once())
+			->method('inGroup')
+			->with('user1', 'group1')
+			->will($this->returnValue(false));
+
+		$backend2->expects($this->once())
+			->method('inGroup')
+			->with('user1', 'group1')
+			->will($this->returnValue(true));
+
+		$this->assertTrue($group->inGroup(new User('user1', null)));
+	}
+
+	public function testAddUser() {
+		$backend = $this->getMock('OC_Group_Database');
+		$userManager = $this->getUserManager();
+		$group = new \OC\Group\Group('group1', array($backend), $userManager);
+
+		$backend->expects($this->once())
+			->method('inGroup')
+			->with('user1', 'group1')
+			->will($this->returnValue(false));
+		$backend->expects($this->any())
+			->method('implementsActions')
+			->will($this->returnValue(true));
+
+		$backend->expects($this->once())
+			->method('addToGroup')
+			->with('user1', 'group1');
+
+		$group->addUser(new User('user1', null));
+	}
+
+	public function testAddUserAlreadyInGroup() {
+		$backend = $this->getMock('OC_Group_Database');
+		$userManager = $this->getUserManager();
+		$group = new \OC\Group\Group('group1', array($backend), $userManager);
+
+		$backend->expects($this->once())
+			->method('inGroup')
+			->with('user1', 'group1')
+			->will($this->returnValue(true));
+		$backend->expects($this->any())
+			->method('implementsActions')
+			->will($this->returnValue(true));
+
+		$backend->expects($this->never())
+			->method('addToGroup');
+
+		$group->addUser(new User('user1', null));
+	}
+
+	public function testRemoveUser() {
+		$backend = $this->getMock('OC_Group_Database');
+		$userManager = $this->getUserManager();
+		$group = new \OC\Group\Group('group1', array($backend), $userManager);
+
+		$backend->expects($this->once())
+			->method('inGroup')
+			->with('user1', 'group1')
+			->will($this->returnValue(true));
+		$backend->expects($this->any())
+			->method('implementsActions')
+			->will($this->returnValue(true));
+
+		$backend->expects($this->once())
+			->method('removeFromGroup')
+			->with('user1', 'group1');
+
+		$group->removeUser(new User('user1', null));
+	}
+
+	public function testRemoveUserNotInGroup() {
+		$backend = $this->getMock('OC_Group_Database');
+		$userManager = $this->getUserManager();
+		$group = new \OC\Group\Group('group1', array($backend), $userManager);
+
+		$backend->expects($this->once())
+			->method('inGroup')
+			->with('user1', 'group1')
+			->will($this->returnValue(false));
+		$backend->expects($this->any())
+			->method('implementsActions')
+			->will($this->returnValue(true));
+
+		$backend->expects($this->never())
+			->method('removeFromGroup');
+
+		$group->removeUser(new User('user1', null));
+	}
+
+	public function testRemoveUserMultipleBackends() {
+		$backend1 = $this->getMock('OC_Group_Database');
+		$backend2 = $this->getMock('OC_Group_Database');
+		$userManager = $this->getUserManager();
+		$group = new \OC\Group\Group('group1', array($backend1, $backend2), $userManager);
+
+		$backend1->expects($this->once())
+			->method('inGroup')
+			->with('user1', 'group1')
+			->will($this->returnValue(true));
+		$backend1->expects($this->any())
+			->method('implementsActions')
+			->will($this->returnValue(true));
+
+		$backend1->expects($this->once())
+			->method('removeFromGroup')
+			->with('user1', 'group1');
+
+		$backend2->expects($this->once())
+			->method('inGroup')
+			->with('user1', 'group1')
+			->will($this->returnValue(true));
+		$backend2->expects($this->any())
+			->method('implementsActions')
+			->will($this->returnValue(true));
+
+		$backend2->expects($this->once())
+			->method('removeFromGroup')
+			->with('user1', 'group1');
+
+		$group->removeUser(new User('user1', null));
+	}
+
+	public function testSearchUsers() {
+		$backend = $this->getMock('OC_Group_Database');
+		$userManager = $this->getUserManager();
+		$group = new \OC\Group\Group('group1', array($backend), $userManager);
+
+		$backend->expects($this->once())
+			->method('usersInGroup')
+			->with('group1', '2')
+			->will($this->returnValue(array('user2')));
+
+		$users = $group->searchUsers('2');
+
+		$this->assertEquals(1, count($users));
+		$user2 = $users[0];
+		$this->assertEquals('user2', $user2->getUID());
+	}
+
+	public function testSearchUsersMultipleBackends() {
+		$backend1 = $this->getMock('OC_Group_Database');
+		$backend2 = $this->getMock('OC_Group_Database');
+		$userManager = $this->getUserManager();
+		$group = new \OC\Group\Group('group1', array($backend1, $backend2), $userManager);
+
+		$backend1->expects($this->once())
+			->method('usersInGroup')
+			->with('group1', '2')
+			->will($this->returnValue(array('user2')));
+		$backend2->expects($this->once())
+			->method('usersInGroup')
+			->with('group1', '2')
+			->will($this->returnValue(array('user2')));
+
+		$users = $group->searchUsers('2');
+
+		$this->assertEquals(1, count($users));
+		$user2 = $users[0];
+		$this->assertEquals('user2', $user2->getUID());
+	}
+
+	public function testSearchUsersLimitAndOffset() {
+		$backend = $this->getMock('OC_Group_Database');
+		$userManager = $this->getUserManager();
+		$group = new \OC\Group\Group('group1', array($backend), $userManager);
+
+		$backend->expects($this->once())
+			->method('usersInGroup')
+			->with('group1', 'user', 1, 1)
+			->will($this->returnValue(array('user2')));
+
+		$users = $group->searchUsers('user', 1, 1);
+
+		$this->assertEquals(1, count($users));
+		$user2 = $users[0];
+		$this->assertEquals('user2', $user2->getUID());
+	}
+
+	public function testSearchUsersMultipleBackendsLimitAndOffset() {
+		$backend1 = $this->getMock('OC_Group_Database');
+		$backend2 = $this->getMock('OC_Group_Database');
+		$userManager = $this->getUserManager();
+		$group = new \OC\Group\Group('group1', array($backend1, $backend2), $userManager);
+
+		$backend1->expects($this->once())
+			->method('usersInGroup')
+			->with('group1', 'user', 2, 1)
+			->will($this->returnValue(array('user2')));
+		$backend2->expects($this->once())
+			->method('usersInGroup')
+			->with('group1', 'user', 1, 0)
+			->will($this->returnValue(array('user1')));
+
+		$users = $group->searchUsers('user', 2, 1);
+
+		$this->assertEquals(2, count($users));
+		$user2 = $users[0];
+		$user1 = $users[1];
+		$this->assertEquals('user2', $user2->getUID());
+		$this->assertEquals('user1', $user1->getUID());
+	}
+
+	public function testDelete() {
+		$backend = $this->getMock('OC_Group_Database');
+		$userManager = $this->getUserManager();
+		$group = new \OC\Group\Group('group1', array($backend), $userManager);
+
+		$backend->expects($this->once())
+			->method('deleteGroup')
+			->with('group1');
+		$backend->expects($this->once())
+			->method('groupExists')
+			->with('group1')
+			->will($this->returnValue(true));
+		$backend->expects($this->any())
+			->method('implementsActions')
+			->will($this->returnValue(true));
+
+		$group->delete();
+	}
+}
diff --git a/tests/lib/group/manager.php b/tests/lib/group/manager.php
new file mode 100644
index 0000000000000000000000000000000000000000..18f78c21a12568434c1b89fe255c4a4f4f68713f
--- /dev/null
+++ b/tests/lib/group/manager.php
@@ -0,0 +1,297 @@
+<?php
+
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace Test\Group;
+
+use OC\User\User;
+
+class Manager extends \PHPUnit_Framework_TestCase {
+	public function testGet() {
+		/**
+		 * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend
+		 */
+		$backend = $this->getMock('\OC_Group_Database');
+		$backend->expects($this->once())
+			->method('groupExists')
+			->with('group1')
+			->will($this->returnValue(true));
+
+		/**
+		 * @var \OC\User\Manager $userManager
+		 */
+		$userManager = $this->getMock('\OC\User\Manager');
+		$manager = new \OC\Group\Manager($userManager);
+		$manager->addBackend($backend);
+
+		$group = $manager->get('group1');
+		$this->assertNotNull($group);
+		$this->assertEquals('group1', $group->getGID());
+	}
+
+	public function testGetNoBackend() {
+		/**
+		 * @var \OC\User\Manager $userManager
+		 */
+		$userManager = $this->getMock('\OC\User\Manager');
+		$manager = new \OC\Group\Manager($userManager);
+
+		$this->assertNull($manager->get('group1'));
+	}
+
+	public function testGetNotExists() {
+		/**
+		 * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend
+		 */
+		$backend = $this->getMock('\OC_Group_Database');
+		$backend->expects($this->once())
+			->method('groupExists')
+			->with('group1')
+			->will($this->returnValue(false));
+
+		/**
+		 * @var \OC\User\Manager $userManager
+		 */
+		$userManager = $this->getMock('\OC\User\Manager');
+		$manager = new \OC\Group\Manager($userManager);
+		$manager->addBackend($backend);
+
+		$this->assertNull($manager->get('group1'));
+	}
+
+	public function testGetMultipleBackends() {
+		/**
+		 * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend1
+		 */
+		$backend1 = $this->getMock('\OC_Group_Database');
+		$backend1->expects($this->once())
+			->method('groupExists')
+			->with('group1')
+			->will($this->returnValue(false));
+
+		/**
+		 * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend2
+		 */
+		$backend2 = $this->getMock('\OC_Group_Database');
+		$backend2->expects($this->once())
+			->method('groupExists')
+			->with('group1')
+			->will($this->returnValue(true));
+
+		/**
+		 * @var \OC\User\Manager $userManager
+		 */
+		$userManager = $this->getMock('\OC\User\Manager');
+		$manager = new \OC\Group\Manager($userManager);
+		$manager->addBackend($backend1);
+		$manager->addBackend($backend2);
+
+		$group = $manager->get('group1');
+		$this->assertNotNull($group);
+		$this->assertEquals('group1', $group->getGID());
+	}
+
+	public function testCreate() {
+		/**
+		 * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend
+		 */
+		$backend = $this->getMock('\OC_Group_Database');
+		$backend->expects($this->once())
+			->method('groupExists')
+			->with('group1')
+			->will($this->returnValue(false));
+		$backend->expects($this->once())
+			->method('implementsActions')
+			->will($this->returnValue(true));
+		$backend->expects($this->once())
+			->method('createGroup');
+
+		/**
+		 * @var \OC\User\Manager $userManager
+		 */
+		$userManager = $this->getMock('\OC\User\Manager');
+		$manager = new \OC\Group\Manager($userManager);
+		$manager->addBackend($backend);
+
+		$group = $manager->create('group1');
+		$this->assertEquals('group1', $group->getGID());
+	}
+
+	public function testCreateExists() {
+		/**
+		 * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend
+		 */
+		$backend = $this->getMock('\OC_Group_Database');
+		$backend->expects($this->once())
+			->method('groupExists')
+			->with('group1')
+			->will($this->returnValue(true));
+		$backend->expects($this->never())
+			->method('createGroup');
+
+		/**
+		 * @var \OC\User\Manager $userManager
+		 */
+		$userManager = $this->getMock('\OC\User\Manager');
+		$manager = new \OC\Group\Manager($userManager);
+		$manager->addBackend($backend);
+
+		$group = $manager->create('group1');
+		$this->assertEquals('group1', $group->getGID());
+	}
+
+	public function testSearch() {
+		/**
+		 * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend
+		 */
+		$backend = $this->getMock('\OC_Group_Database');
+		$backend->expects($this->once())
+			->method('getGroups')
+			->with('1')
+			->will($this->returnValue(array('group1')));
+
+		/**
+		 * @var \OC\User\Manager $userManager
+		 */
+		$userManager = $this->getMock('\OC\User\Manager');
+		$manager = new \OC\Group\Manager($userManager);
+		$manager->addBackend($backend);
+
+		$groups = $manager->search('1');
+		$this->assertEquals(1, count($groups));
+		$group1 = $groups[0];
+		$this->assertEquals('group1', $group1->getGID());
+	}
+
+	public function testSearchMultipleBackends() {
+		/**
+		 * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend1
+		 */
+		$backend1 = $this->getMock('\OC_Group_Database');
+		$backend1->expects($this->once())
+			->method('getGroups')
+			->with('1')
+			->will($this->returnValue(array('group1')));
+
+		/**
+		 * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend2
+		 */
+		$backend2 = $this->getMock('\OC_Group_Database');
+		$backend2->expects($this->once())
+			->method('getGroups')
+			->with('1')
+			->will($this->returnValue(array('group12', 'group1')));
+
+		/**
+		 * @var \OC\User\Manager $userManager
+		 */
+		$userManager = $this->getMock('\OC\User\Manager');
+		$manager = new \OC\Group\Manager($userManager);
+		$manager->addBackend($backend1);
+		$manager->addBackend($backend2);
+
+		$groups = $manager->search('1');
+		$this->assertEquals(2, count($groups));
+		$group1 = $groups[0];
+		$group12 = $groups[1];
+		$this->assertEquals('group1', $group1->getGID());
+		$this->assertEquals('group12', $group12->getGID());
+	}
+
+	public function testSearchMultipleBackendsLimitAndOffset() {
+		/**
+		 * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend1
+		 */
+		$backend1 = $this->getMock('\OC_Group_Database');
+		$backend1->expects($this->once())
+			->method('getGroups')
+			->with('1', 2, 1)
+			->will($this->returnValue(array('group1')));
+
+		/**
+		 * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend2
+		 */
+		$backend2 = $this->getMock('\OC_Group_Database');
+		$backend2->expects($this->once())
+			->method('getGroups')
+			->with('1', 1, 0)
+			->will($this->returnValue(array('group12')));
+
+		/**
+		 * @var \OC\User\Manager $userManager
+		 */
+		$userManager = $this->getMock('\OC\User\Manager');
+		$manager = new \OC\Group\Manager($userManager);
+		$manager->addBackend($backend1);
+		$manager->addBackend($backend2);
+
+		$groups = $manager->search('1', 2, 1);
+		$this->assertEquals(2, count($groups));
+		$group1 = $groups[0];
+		$group12 = $groups[1];
+		$this->assertEquals('group1', $group1->getGID());
+		$this->assertEquals('group12', $group12->getGID());
+	}
+
+	public function testGetUserGroups() {
+		/**
+		 * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend
+		 */
+		$backend = $this->getMock('\OC_Group_Database');
+		$backend->expects($this->once())
+			->method('getUserGroups')
+			->with('user1')
+			->will($this->returnValue(array('group1')));
+
+		/**
+		 * @var \OC\User\Manager $userManager
+		 */
+		$userManager = $this->getMock('\OC\User\Manager');
+		$manager = new \OC\Group\Manager($userManager);
+		$manager->addBackend($backend);
+
+		$groups = $manager->getUserGroups(new User('user1', null));
+		$this->assertEquals(1, count($groups));
+		$group1 = $groups[0];
+		$this->assertEquals('group1', $group1->getGID());
+	}
+
+	public function testGetUserGroupsMultipleBackends() {
+		/**
+		 * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend1
+		 */
+		$backend1 = $this->getMock('\OC_Group_Database');
+		$backend1->expects($this->once())
+			->method('getUserGroups')
+			->with('user1')
+			->will($this->returnValue(array('group1')));
+		/**
+		 * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend2
+		 */
+		$backend2 = $this->getMock('\OC_Group_Database');
+		$backend2->expects($this->once())
+			->method('getUserGroups')
+			->with('user1')
+			->will($this->returnValue(array('group1', 'group2')));
+
+		/**
+		 * @var \OC\User\Manager $userManager
+		 */
+		$userManager = $this->getMock('\OC\User\Manager');
+		$manager = new \OC\Group\Manager($userManager);
+		$manager->addBackend($backend1);
+		$manager->addBackend($backend2);
+
+		$groups = $manager->getUserGroups(new User('user1', null));
+		$this->assertEquals(2, count($groups));
+		$group1 = $groups[0];
+		$group2 = $groups[1];
+		$this->assertEquals('group1', $group1->getGID());
+		$this->assertEquals('group2', $group2->getGID());
+	}
+}