/** * Assert a collection of {@link Account}s exist in the {@link AccountService}. * @param accounts The collection of {@link Account}s to assert their existence. * @param expectedAccountCount The expected number of {@link Account}s in the {@link AccountService}. * @param accountService The {@link AccountService} to assert {@link Account}s existence. */ static void assertAccountsInAccountService(Collection<Account> accounts, int expectedAccountCount, AccountService accountService) { assertEquals("Wrong number of accounts in accountService", expectedAccountCount, accountService.getAllAccounts().size()); for (Account account : accounts) { assertAccountInAccountService(account, accountService); } }
/** * Tests starting up a {@link HelixAccountService}, when the corresponding {@code ZooKeeper} has account metadata * already stored on it. * @throws Exception Any unexpected exception. */ @Test public void testStartUpWithMetadataExists() throws Exception { // pre-populate account metadata in ZK. writeAccountsToHelixPropertyStore(idToRefAccountMap.values(), false); // When start, the helixAccountService should get the account metadata. accountService = mockHelixAccountServiceFactory.getAccountService(); assertAccountsInAccountService(idToRefAccountMap.values(), NUM_REF_ACCOUNT, accountService); }
refAccount = new AccountBuilder(refAccountId, refAccountName, refAccountStatus).addOrUpdateContainer(refContainer).build(); generateRefAccounts(idToRefAccountMap, idToRefContainerMap, accountIdSet, NUM_REF_ACCOUNT, NUM_CONTAINER_PER_ACCOUNT);
/** * Asserts that an {@link Account} exists in the {@link AccountService}. * @param account The {@link Account} to assert existence. * @param accountService The {@link AccountService} to assert {@link Account} existence. */ static void assertAccountInAccountService(Account account, AccountService accountService) { Account accountFoundById = accountService.getAccountById(account.getId()); Account accountFoundByName = accountService.getAccountByName(account.getName()); assertEquals("Account got by name from accountService does not match account to assert.", account, accountFoundByName); assertEquals("Account got by id from accountService does not match the account to assert", account, accountFoundById); assertEquals("The number of containers in the account is wrong.", accountFoundById.getAllContainers().size(), account.getAllContainers().size()); for (Container container : account.getAllContainers()) { assertContainerInAccountService(container, accountService); } }
/** * Tests creating a number of new {@link Account} through {@link HelixAccountService}, where there is no {@link ZNRecord} * exists on the {@code ZooKeeper}. */ @Test public void testCreateAccount() { accountService = mockHelixAccountServiceFactory.getAccountService(); assertEquals("The number of account in HelixAccountService is incorrect", 0, accountService.getAllAccounts().size()); boolean res = accountService.updateAccounts(idToRefAccountMap.values()); assertTrue("Failed to update accounts", res); assertAccountsInAccountService(idToRefAccountMap.values(), NUM_REF_ACCOUNT, accountService); }
/** * Does several operations: * 1. Writes a {@link ZNRecord} to {@link HelixPropertyStore} without notifying listeners; * 2. Starts up a {@link HelixAccountService} that should fetch the {@link ZNRecord}; * 3. Updates (creates) one more {@link Account} through the {@link HelixAccountService}; * 4. Writes the same {@link ZNRecord} to {@link HelixPropertyStore} and publishes a message for {@link Account} update; * * If the {@link ZNRecord} is good, it should not affect updating operation. * @param zNRecord A {@link ZNRecord} to write to {@link HelixPropertyStore}. * @param isGoodZNRecord {code true} to indicate the {@link ZNRecord} is good, which should not affect updating * operation; {@code false} otherwise. * @throws Exception Any unexpected exception. */ private void updateAndWriteZNRecord(ZNRecord zNRecord, boolean isGoodZNRecord) throws Exception { writeZNRecordToHelixPropertyStore(zNRecord, false); accountService = mockHelixAccountServiceFactory.getAccountService(); assertEquals("Number of account is wrong", 0, accountService.getAllAccounts().size()); updateAccountsAndAssertAccountExistence(Collections.singletonList(refAccount), isGoodZNRecord ? 1 : 0, isGoodZNRecord); writeZNRecordToHelixPropertyStore(zNRecord, true); if (isGoodZNRecord) { assertAccountInAccountService(refAccount, accountService); } else { assertEquals("Number of accounts is wrong.", 0, accountService.getAllAccounts().size()); } }
/** * Updates a collection of {@link Account}s through {@link HelixAccountService}, and verifies that the * {@link Account}s have been successfully updated, so they can be queried through {@link HelixAccountService}. * @param accounts A collection of {@link Account}s to update through {@link HelixAccountService}. */ private void updateAccountsAndAssertAccountExistence(Collection<Account> accounts, int expectedAccountCount, boolean shouldUpdateSucceed) throws Exception { Collection<Account> expectedOldState = accountService.getAllAccounts(); boolean hasUpdateAccountSucceed = accountService.updateAccounts(accounts); assertEquals("Wrong update return status", shouldUpdateSucceed, hasUpdateAccountSucceed); if (shouldUpdateSucceed) { assertAccountsInAccountService(accounts, expectedAccountCount, accountService); if (helixConfigProps.containsKey(HelixAccountServiceConfig.BACKUP_DIRECTORY_KEY)) { Path oldStateBackup = Files.list(accountBackupDir) .filter(path -> path.getFileName().toString().endsWith(OLD_STATE_SUFFIX)) .max(Comparator.naturalOrder()) .get(); checkBackupFile(expectedOldState, oldStateBackup); String newStateFilename = oldStateBackup.getFileName().toString().replace(OLD_STATE_SUFFIX, NEW_STATE_SUFFIX); Path newStateBackup = oldStateBackup.getParent().resolve(newStateFilename); checkBackupFile(accountService.getAllAccounts(), newStateBackup); } else { assertEquals("No backup files should exist.", 0, Files.list(accountBackupDir).count()); } } else { assertEquals("Wrong number of accounts in accountService", expectedAccountCount, accountService.getAllAccounts().size()); } }
/** * Tests a series of operations. * 1. PrePopulates account (1, "a"); * 2. Starts up a {@link HelixAccountService}; * 3. Remote copy adds a new account (2, "b"), and the update has not been propagated to the {@link HelixAccountService}; * 4. The {@link HelixAccountService} attempts to update an account (3, "b"), which should fail because it will eventually * conflict with the remote copy; * @throws Exception Any unexpected exception. */ @Test public void testReadConflictAccountDataFromHelixPropertyStoreCase3() throws Exception { Account account1 = new AccountBuilder((short) 1, "a", AccountStatus.INACTIVE).build(); List<Account> accounts = Collections.singletonList(account1); writeAccountsToHelixPropertyStore(accounts, false); accountService = mockHelixAccountServiceFactory.getAccountService(); assertAccountInAccountService(account1, accountService); Account account2 = new AccountBuilder((short) 2, "b", AccountStatus.INACTIVE).build(); accounts = Collections.singletonList(account2); writeAccountsToHelixPropertyStore(accounts, false); Account conflictingAccount = new AccountBuilder((short) 3, "b", AccountStatus.INACTIVE).build(); accounts = Collections.singletonList(conflictingAccount); assertFalse(accountService.updateAccounts(accounts)); assertEquals("Number of account is wrong.", 1, accountService.getAllAccounts().size()); assertAccountInAccountService(account1, accountService); }
assertAccountsInAccountService(idToRefAccountMap.values(), NUM_REF_ACCOUNT, accountService);
assertAccountsInAccountService(idToRefAccountMap.values(), NUM_REF_ACCOUNT, accountService);