/** * Pre-populates two {@link Account}s: (id=1, name="a") and (id=2, name="b") in * {@link org.apache.helix.store.HelixPropertyStore}. * @throws Exception Any unexpected exception. */ private void writeAccountsForConflictTest() throws Exception { List<Account> existingAccounts = new ArrayList<>(); existingAccounts.add(new AccountBuilder((short) 1, "a", AccountStatus.INACTIVE).build()); existingAccounts.add(new AccountBuilder((short) 2, "b", AccountStatus.INACTIVE).build()); updateAccountsAndAssertAccountExistence(existingAccounts, 2, true); }
/** * Tests reading conflicting {@link Account} metadata from {@link org.apache.helix.store.HelixPropertyStore}. * @throws Exception Any unexpected exception. */ @Test public void testReadConflictAccountDataFromHelixPropertyStoreCase2() throws Exception { List<Account> conflictAccounts = new ArrayList<>(); Account account1 = new AccountBuilder((short) 1, "a", AccountStatus.INACTIVE).build(); Account account2 = new AccountBuilder((short) 2, "a", AccountStatus.INACTIVE).build(); Account account3 = new AccountBuilder((short) 2, "b", AccountStatus.INACTIVE).build(); Account account4 = new AccountBuilder((short) 3, "b", AccountStatus.INACTIVE).build(); conflictAccounts.add(account1); conflictAccounts.add(account2); conflictAccounts.add(account3); conflictAccounts.add(account4); readAndUpdateBadRecord(conflictAccounts); }
/** * Tests reading conflicting {@link Account} metadata from {@link HelixPropertyStore}. Two {@link Account}s have * different accountIds but the same accountNames. This is a BAD record that should impact fetching or updating * {@link Account}s. * @throws Exception Any unexpected exception. */ @Test public void testReadConflictAccountDataFromHelixPropertyStoreCase1() throws Exception { List<Account> conflictAccounts = new ArrayList<>(); Account account1 = new AccountBuilder((short) 1, "a", AccountStatus.INACTIVE).build(); Account account2 = new AccountBuilder((short) 2, "a", AccountStatus.INACTIVE).build(); conflictAccounts.add(account1); conflictAccounts.add(account2); readAndUpdateBadRecord(conflictAccounts); }
/** * Tests updating a collection of {@link Account}s, where there are duplicate {@link Account}s in id and name. * @throws Exception Any unexpected exception. */ @Test public void testUpdateDuplicateAccounts() throws Exception { accountService = mockHelixAccountServiceFactory.getAccountService(); List<Account> conflictAccounts = new ArrayList<>(); conflictAccounts.add(new AccountBuilder((short) 1, "a", AccountStatus.INACTIVE).build()); conflictAccounts.add(new AccountBuilder((short) 1, "a", AccountStatus.INACTIVE).build()); assertFalse("Wrong return value from update operation.", accountService.updateAccounts(conflictAccounts)); }
/** * Tests updating a collection of {@link Account}s, where the {@link Account}s are conflicting among themselves * in name. * @throws Exception Any unexpected exception. */ @Test public void testUpdateNameConflictingAccounts() throws Exception { accountService = mockHelixAccountServiceFactory.getAccountService(); List<Account> conflictAccounts = new ArrayList<>(); conflictAccounts.add(new AccountBuilder((short) 1, "a", AccountStatus.INACTIVE).build()); conflictAccounts.add(new AccountBuilder((short) 2, "a", AccountStatus.INACTIVE).build()); assertFalse("Wrong return value from update operation.", accountService.updateAccounts(conflictAccounts)); }
/** * Tests updating a collection of {@link Account}s, where the {@link Account}s are conflicting among themselves * in id. * @throws Exception Any unexpected exception. */ @Test public void testUpdateIdConflictingAccounts() throws Exception { accountService = mockHelixAccountServiceFactory.getAccountService(); List<Account> conflictAccounts = new ArrayList<>(); conflictAccounts.add(new AccountBuilder((short) 1, "a", AccountStatus.INACTIVE).build()); conflictAccounts.add(new AccountBuilder((short) 1, "b", AccountStatus.INACTIVE).build()); assertFalse("Wrong return value from update operation.", accountService.updateAccounts(conflictAccounts)); }
/** * Tests adding/removing {@link Consumer}. */ @Test public void testAddRemoveConsumer() { List<Collection<Account>> updatedAccountsReceivedByConsumers = new ArrayList<>(); // add consumers Consumer<Collection<Account>> accountUpdateConsumer = updatedAccounts -> { updatedAccountsReceivedByConsumers.add(updatedAccounts); }; accountService.addAccountUpdateConsumer(accountUpdateConsumer); Account updatedAccount = new AccountBuilder(InMemoryUnknownAccountService.UNKNOWN_ACCOUNT).name("newName").build(); accountService.updateAccounts(Collections.singletonList(updatedAccount)); assertEquals("Wrong number of updated accounts received by consumer.", 0, updatedAccountsReceivedByConsumers.size()); Account newAccount = new AccountBuilder((short) 1, "newAccount", Account.AccountStatus.ACTIVE).build(); accountService.updateAccounts(Collections.singletonList(newAccount)); assertEquals("Wrong number of updated accounts received by consumer.", 0, updatedAccountsReceivedByConsumers.size()); accountService.removeAccountUpdateConsumer(accountUpdateConsumer); } }
/** * Tests updating a {@link Account}, which has a new id and name different from any of the existing record. The * new record will replace the existing record. This test corresponds to case C specified in the JavaDoc of * {@link AccountService}. * @throws Exception Any unexpected exception. */ @Test public void testNonConflictingUpdateCaseC() throws Exception { accountService = mockHelixAccountServiceFactory.getAccountService(); // write two accounts (1, "a") and (2, "b") writeAccountsForConflictTest(); Collection<Account> nonConflictAccounts = Collections.singleton((new AccountBuilder((short) 3, "c", AccountStatus.ACTIVE).build())); updateAccountsAndAssertAccountExistence(nonConflictAccounts, 3, true); }
idToContainers.put(containerId, container); Account account = new AccountBuilder(accountId, accountName, accountStatus).containers(containers).build(); assertEquals("Wrong number of generated containers for the account", containerCountPerAccount, account.getAllContainers().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); }
.build(); refAccount = new AccountBuilder(refAccountId, refAccountName, refAccountStatus).addOrUpdateContainer(refContainer).build(); generateRefAccounts(idToRefAccountMap, idToRefContainerMap, accountIdSet, NUM_REF_ACCOUNT, NUM_CONTAINER_PER_ACCOUNT);
Account newAccount = new AccountBuilder(refAccountId, refAccountName, refAccountStatus).build(); Set<Account> accountsToUpdate = Collections.singleton(newAccount); updateAccountsAndAssertAccountExistence(accountsToUpdate, 1 + NUM_REF_ACCOUNT, true); AccountBuilder accountBuilder = new AccountBuilder(account); accountBuilder.name(account.getName() + "-extra"); accountsToUpdate.add(accountBuilder.build()); Account updatedAccount = new AccountBuilder(account).name(account.getName() + "-extra").build(); accountsToUpdate = new HashSet<>(Collections.singleton(updatedAccount)); updateAccountsAndAssertAccountExistence(accountsToUpdate, 1 + NUM_REF_ACCOUNT, true);
/** * Tests updating a {@link Account}, which has the same id and name as an existing record, and will replace the * existing record. This test corresponds to case A specified in the JavaDoc of {@link AccountService}. * @throws Exception Any unexpected exception. */ @Test public void testNonConflictingUpdateCaseA() throws Exception { accountService = mockHelixAccountServiceFactory.getAccountService(); // write two accounts (1, "a") and (2, "b") writeAccountsForConflictTest(); Account accountToUpdate = accountService.getAccountById((short) 1); Collection<Account> nonConflictAccounts = Collections.singleton(new AccountBuilder(accountToUpdate).status(AccountStatus.ACTIVE).build()); updateAccountsAndAssertAccountExistence(nonConflictAccounts, 2, true); }
/** * Tests updating a {@link Account}, which has the same id as an existing record and a non-conflicting name with any * of the existing record. The new record will replace the existing record. This test corresponds to case B specified * in the JavaDoc of {@link AccountService}. * @throws Exception Any unexpected exception. */ @Test public void testNonConflictingUpdateCaseB() throws Exception { accountService = mockHelixAccountServiceFactory.getAccountService(); // write two accounts (1, "a") and (2, "b") writeAccountsForConflictTest(); Account accountToUpdate = accountService.getAccountById((short) 1); Collection<Account> nonConflictAccounts = Collections.singleton((new AccountBuilder(accountToUpdate).status(AccountStatus.ACTIVE).build())); updateAccountsAndAssertAccountExistence(nonConflictAccounts, 2, true); }
/** * Tests updating a {@link Account}, which has a new id but a name conflicting with an existing record. The update * operation will fail. This test corresponds to case D specified in the JavaDoc of {@link AccountService}. * @throws Exception Any unexpected exception. */ @Test public void testConflictingUpdateCaseD() throws Exception { accountService = mockHelixAccountServiceFactory.getAccountService(); // write two accounts (1, "a") and (2, "b") writeAccountsForConflictTest(); Collection<Account> conflictAccounts = Collections.singleton((new AccountBuilder((short) 3, "a", AccountStatus.INACTIVE).build())); assertFalse("Wrong return value from update operation.", accountService.updateAccounts(conflictAccounts)); assertEquals("Wrong account number in HelixAccountService", 2, accountService.getAllAccounts().size()); assertNull("Wrong account got from HelixAccountService", accountService.getAccountById((short) 3)); }
/** * Tests updating a {@link Account}, which has the same id as an existing record, but the name conflicting with * another existing record. The update operation will fail. This test corresponds to case E specified in the JavaDoc * of {@link AccountService}. * @throws Exception Any unexpected exception. */ @Test public void testConflictingUpdateCaseE() throws Exception { accountService = mockHelixAccountServiceFactory.getAccountService(); // write two accounts (1, "a") and (2, "b") writeAccountsForConflictTest(); Collection<Account> conflictAccounts = Collections.singleton((new AccountBuilder((short) 1, "b", AccountStatus.INACTIVE).build())); assertFalse("Wrong return value from update operation.", accountService.updateAccounts(conflictAccounts)); assertEquals("Wrong account number in HelixAccountService", 2, accountService.getAllAccounts().size()); assertEquals("Wrong account name got from HelixAccountService", "a", accountService.getAccountById((short) 1).getName()); }
/** * Test updating an account with a conflicting expected snapshot version. */ @Test public void testConflictingSnapshotVersionUpdate() throws Exception { accountService = mockHelixAccountServiceFactory.getAccountService(); // write two accounts (1, "a") and (2, "b") writeAccountsForConflictTest(); Account expectedAccount = accountService.getAccountById((short) 1); int currentSnapshotVersion = expectedAccount.getSnapshotVersion(); for (int snapshotVersionOffset : new int[]{-2, -1, 1}) { int snapshotVersionToUse = currentSnapshotVersion + snapshotVersionOffset; Collection<Account> conflictAccounts = Collections.singleton( new AccountBuilder((short) 1, "c", AccountStatus.INACTIVE).snapshotVersion(snapshotVersionToUse).build()); assertFalse("Wrong return value from update operation.", accountService.updateAccounts(conflictAccounts)); assertEquals("Wrong account number in HelixAccountService", 2, accountService.getAllAccounts().size()); Account account = accountService.getAccountById((short) 1); assertEquals("Account should not have been updated", expectedAccount, account); assertEquals("Snapshot version should not have been updated", currentSnapshotVersion, account.getSnapshotVersion()); } Collection<Account> validAccounts = Collections.singleton( new AccountBuilder((short) 1, "c", AccountStatus.INACTIVE).snapshotVersion(currentSnapshotVersion).build()); updateAccountsAndAssertAccountExistence(validAccounts, 2, true); }
@Test public void testAllMethods() throws Exception { assertEquals("Wrong account", null, accountService.getAccountById(Utils.getRandomShort(random))); assertEquals("Wrong account", InMemoryUnknownAccountService.UNKNOWN_ACCOUNT, accountService.getAccountById((short) -1)); assertEquals("Wrong account", InMemoryUnknownAccountService.UNKNOWN_ACCOUNT, accountService.getAccountByName(UtilsTest.getRandomString(10))); assertEquals("Wrong size of account collection", 1, accountService.getAllAccounts().size()); // updating the InMemoryUnknownAccountService should fail. Account account = new AccountBuilder((short) 1, "a", Account.AccountStatus.INACTIVE).build(); assertFalse("Wrong return value from an unsuccessful update operation", accountService.updateAccounts(Collections.singletonList(account))); assertEquals("Wrong size of account collection", 1, accountService.getAllAccounts().size()); try { accountService.getAllAccounts().add(account); fail("Should have thrown."); } catch (UnsupportedOperationException e) { // expected } accountService.close(); }
Account newAccountWithoutContainer = new AccountBuilder(refAccountId, refAccountName, refAccountStatus).build(); List<Account> accountsToUpdate = Collections.singletonList(newAccountWithoutContainer); updateAccountsAndAssertAccountExistence(accountsToUpdate, 1 + NUM_REF_ACCOUNT, true); accountBuilder.status( account.getStatus().equals(AccountStatus.ACTIVE) ? AccountStatus.INACTIVE : AccountStatus.ACTIVE); accountsToUpdate.add(accountBuilder.build()); accountsToUpdate = Collections.singletonList(accountBuilder.addOrUpdateContainer(refContainer).build()); updateAccountsAndAssertAccountExistence(accountsToUpdate, 1 + NUM_REF_ACCOUNT, true); accountBuilder.addOrUpdateContainer(containerBuilder.build()); accountsToUpdate.add(accountBuilder.build());