helper = $this->createMock(Helper::class); $this->ldapWrapper = $this->createMock(LDAP::class); $this->userManager = $this->createMock(Manager::class); $this->mapper = $this->createMock(UserMapping::class); $this->config = $this->createMock(IConfig::class); $this->avatarManager = $this->createMock(IAvatarManager::class); $this->dbc = $this->createMock(IDBConnection::class); $this->ncUserManager = $this->createMock(IUserManager::class); $this->notificationManager = $this->createMock(IManager::class); $this->connectionFactory = $this->createMock(ConnectionFactory::class); $this->accessFactory = $this->createMock(AccessFactory::class); $this->sync = new Sync( Server::get(ITimeFactory::class), Server::get(IEventDispatcher::class), $this->config, $this->dbc, $this->avatarManager, $this->ncUserManager, Server::get(LoggerInterface::class), $this->notificationManager, $this->mapper, $this->helper, $this->connectionFactory, $this->accessFactory, ); $this->sync->overwritePropertiesForTest($this->ldapWrapper); } public function intervalDataProvider(): array { return [ [ 0, 1000, 750 ], [ 22, 0, 50 ], [ 500, 500, 500 ], [ 1357, 0, 0 ], [ 421337, 2000, 3000 ] ]; } /** * @dataProvider intervalDataProvider */ public function testUpdateInterval(int $userCount, int $pagingSize1, int $pagingSize2): void { $this->config->expects($this->once()) ->method('setAppValue') ->with('user_ldap', 'background_sync_interval', $this->anything()) ->willReturnCallback(function ($a, $k, $interval) { $this->assertTrue($interval >= SYNC::MIN_INTERVAL); $this->assertTrue($interval <= SYNC::MAX_INTERVAL); return true; }); $this->config->expects($this->atLeastOnce()) ->method('getAppKeys') ->willReturn([ 'blabla', 'ldap_paging_size', 's07blabla', 'installed', 's07ldap_paging_size' ]); $this->config->expects($this->exactly(2)) ->method('getAppValue') ->willReturnOnConsecutiveCalls($pagingSize1, $pagingSize2); $this->mapper->expects($this->atLeastOnce()) ->method('count') ->willReturn($userCount); $this->sync->setArgument($this->arguments); $this->sync->updateInterval(); } public function moreResultsProvider() { return [ [ 3, 3, true ], [ 3, 5, true ], [ 3, 2, false], [ 0, 4, false], [ null, 4, false] ]; } /** * @dataProvider moreResultsProvider */ public function testMoreResults($pagingSize, $results, $expected): void { $connection = $this->createMock(Connection::class); $this->connectionFactory->expects($this->any()) ->method('get') ->willReturn($connection); $connection->expects($this->any()) ->method('__get') ->willReturnCallback(function ($key) use ($pagingSize) { if ($key === 'ldapPagingSize') { return $pagingSize; } return null; }); /** @var Access|MockObject $access */ $access = $this->createMock(Access::class); $this->accessFactory->expects($this->any()) ->method('get') ->with($connection) ->willReturn($access); $this->userManager->expects($this->any()) ->method('getAttributes') ->willReturn(['dn', 'uid', 'mail', 'displayname']); $access->expects($this->once()) ->method('fetchListOfUsers') ->willReturn(array_pad([], $results, 'someUser')); $access->expects($this->any()) ->method('combineFilterWithAnd') ->willReturn('pseudo=filter'); $access->connection = $connection; $access->userManager = $this->userManager; $this->sync->setArgument($this->arguments); $hasMoreResults = $this->sync->runCycle(['prefix' => 's01', 'offset' => 100]); $this->assertSame($expected, $hasMoreResults); } public function cycleDataProvider() { $lastCycle = ['prefix' => 's01', 'offset' => 1000]; $lastCycle2 = ['prefix' => '', 'offset' => 1000]; return [ [ null, ['s01'], ['prefix' => 's01', 'offset' => 0] ], [ null, [''], ['prefix' => '', 'offset' => 0] ], [ $lastCycle, ['s01', 's02'], ['prefix' => 's02', 'offset' => 0] ], [ $lastCycle, [''], ['prefix' => '', 'offset' => 0] ], [ $lastCycle2, ['', 's01'], ['prefix' => 's01', 'offset' => 0] ], [ $lastCycle, [], null ], ]; } /** * @dataProvider cycleDataProvider */ public function testDetermineNextCycle($cycleData, $prefixes, $expectedCycle): void { $this->helper->expects($this->any()) ->method('getServerConfigurationPrefixes') ->with(true) ->willReturn($prefixes); if (is_array($expectedCycle)) { $this->config->expects($this->exactly(2)) ->method('setAppValue') ->withConsecutive( ['user_ldap', 'background_sync_prefix', $expectedCycle['prefix']], ['user_ldap', 'background_sync_offset', $expectedCycle['offset']] ); } else { $this->config->expects($this->never()) ->method('setAppValue'); } $this->sync->setArgument($this->arguments); $nextCycle = $this->sync->determineNextCycle($cycleData); if ($expectedCycle === null) { $this->assertNull($nextCycle); } else { $this->assertSame($expectedCycle['prefix'], $nextCycle['prefix']); $this->assertSame($expectedCycle['offset'], $nextCycle['offset']); } } public function testQualifiesToRun(): void { $cycleData = ['prefix' => 's01']; $this->config->expects($this->exactly(2)) ->method('getAppValue') ->willReturnOnConsecutiveCalls(time() - 60 * 40, time() - 60 * 20); $this->sync->setArgument($this->arguments); $this->assertTrue($this->sync->qualifiesToRun($cycleData)); $this->assertFalse($this->sync->qualifiesToRun($cycleData)); } public function runDataProvider(): array { return [ #0 - one LDAP server, reset [[ 'prefixes' => [''], 'scheduledCycle' => ['prefix' => '', 'offset' => '4500'], 'pagingSize' => 500, 'usersThisCycle' => 0, 'expectedNextCycle' => ['prefix' => '', 'offset' => '0'], 'mappedUsers' => 123, ]], #1 - 2 LDAP servers, next prefix [[ 'prefixes' => ['', 's01'], 'scheduledCycle' => ['prefix' => '', 'offset' => '4500'], 'pagingSize' => 500, 'usersThisCycle' => 0, 'expectedNextCycle' => ['prefix' => 's01', 'offset' => '0'], 'mappedUsers' => 123, ]], #2 - 2 LDAP servers, rotate prefix [[ 'prefixes' => ['', 's01'], 'scheduledCycle' => ['prefix' => 's01', 'offset' => '4500'], 'pagingSize' => 500, 'usersThisCycle' => 0, 'expectedNextCycle' => ['prefix' => '', 'offset' => '0'], 'mappedUsers' => 123, ]], ]; } /** * @dataProvider runDataProvider */ public function testRun($runData): void { $this->config->expects($this->any()) ->method('getAppValue') ->willReturnCallback(function ($app, $key, $default) use ($runData) { if ($app === 'core' && $key === 'backgroundjobs_mode') { return 'cron'; } if ($app = 'user_ldap') { // for getCycle() if ($key === 'background_sync_prefix') { return $runData['scheduledCycle']['prefix']; } if ($key === 'background_sync_offset') { return $runData['scheduledCycle']['offset']; } // for qualifiesToRun() if ($key === $runData['scheduledCycle']['prefix'] . '_lastChange') { return time() - 60 * 40; } // for getMinPagingSize if ($key === $runData['scheduledCycle']['prefix'] . 'ldap_paging_size') { return $runData['pagingSize']; } } return $default; }); $this->config->expects($this->exactly(3)) ->method('setAppValue') ->withConsecutive( ['user_ldap', 'background_sync_prefix', $runData['expectedNextCycle']['prefix']], ['user_ldap', 'background_sync_offset', $runData['expectedNextCycle']['offset']], ['user_ldap', 'background_sync_interval', $this->anything()] ); $this->config->expects($this->any()) ->method('getAppKeys') ->with('user_ldap') ->willReturn([$runData['scheduledCycle']['prefix'] . 'ldap_paging_size']); $this->helper->expects($this->any()) ->method('getServerConfigurationPrefixes') ->with(true) ->willReturn($runData['prefixes']); $connection = $this->createMock(Connection::class); $this->connectionFactory->expects($this->any()) ->method('get') ->willReturn($connection); $connection->expects($this->any()) ->method('__get') ->willReturnCallback(function ($key) use ($runData) { if ($key === 'ldapPagingSize') { return $runData['pagingSize']; } return null; }); /** @var Access|MockObject $access */ $access = $this->createMock(Access::class); $this->accessFactory->expects($this->any()) ->method('get') ->with($connection) ->willReturn($access); $this->userManager->expects($this->any()) ->method('getAttributes') ->willReturn(['dn', 'uid', 'mail', 'displayname']); $access->expects($this->once()) ->method('fetchListOfUsers') ->willReturn(array_pad([], $runData['usersThisCycle'], 'someUser')); $access->expects($this->any()) ->method('combineFilterWithAnd') ->willReturn('pseudo=filter'); $access->connection = $connection; $access->userManager = $this->userManager; $this->mapper->expects($this->any()) ->method('count') ->willReturn($runData['mappedUsers']); $this->sync->run($this->arguments); } }