@Override public void grant(final EntityId entity, final String user) { aclsTx.get().executeUnchecked(new TransactionExecutor.Procedure<ACLDataset>() { @Override public void apply(ACLDataset acls) throws Exception { acls.add(entity, user, Action.ALL); } }, acls.get()); }
@Test public void testPersistFailure() throws TransactionFailureException, InterruptedException { ds1.failCommitTxOnce = InduceFailure.ThrowException; // execute: add a change to ds1 and ds2 try { getExecutor().execute(testFunction, 10); Assert.fail("persist failed - exception should be thrown"); } catch (TransactionFailureException e) { Assert.assertEquals("persist failure", e.getCause().getMessage()); } // verify both are rolled back and tx is aborted Assert.assertTrue(ds1.started); Assert.assertTrue(ds2.started); Assert.assertTrue(ds1.checked); Assert.assertTrue(ds2.checked); Assert.assertTrue(ds1.committed); Assert.assertFalse(ds2.committed); Assert.assertFalse(ds1.postCommitted); Assert.assertFalse(ds2.postCommitted); Assert.assertTrue(ds1.rolledBack); Assert.assertTrue(ds2.rolledBack); Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Aborted); }
@Test public void testFunctionAndRollbackFailure() throws TransactionFailureException, InterruptedException { ds1.failRollbackTxOnce = InduceFailure.ReturnFalse; // execute: add a change to ds1 and ds2 try { getExecutor().execute(testFunction, null); Assert.fail("function failed - exception should be thrown"); } catch (TransactionFailureException e) { Assert.assertEquals("function failed", e.getCause().getMessage()); } // verify both are rolled back and tx is invalidated Assert.assertTrue(ds1.started); Assert.assertTrue(ds2.started); Assert.assertFalse(ds1.checked); Assert.assertFalse(ds2.checked); Assert.assertFalse(ds1.committed); Assert.assertFalse(ds2.committed); Assert.assertFalse(ds1.postCommitted); Assert.assertFalse(ds2.postCommitted); Assert.assertTrue(ds1.rolledBack); Assert.assertTrue(ds2.rolledBack); Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Invalidated); }
@Test public void testPostCommitFailure() throws TransactionFailureException, InterruptedException { ds1.failPostCommitTxOnce = InduceFailure.ThrowException; // execute: add a change to ds1 and ds2 try { getExecutor().execute(testFunction, 10); Assert.fail("post commit failed - exception should be thrown"); } catch (TransactionFailureException e) { Assert.assertEquals("post failure", e.getCause().getMessage()); } // verify both are committed and post-committed Assert.assertTrue(ds1.started); Assert.assertTrue(ds2.started); Assert.assertTrue(ds1.checked); Assert.assertTrue(ds2.checked); Assert.assertTrue(ds1.committed); Assert.assertTrue(ds2.committed); Assert.assertTrue(ds1.postCommitted); Assert.assertTrue(ds2.postCommitted); Assert.assertFalse(ds1.rolledBack); Assert.assertFalse(ds2.rolledBack); Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Committed); }
@Override public void revoke(final EntityId entity, final String user, final Set<Action> actions) { aclsTx.get().executeUnchecked(new TransactionExecutor.Procedure<ACLDataset>() { @Override public void apply(ACLDataset acls) throws Exception { for (Action action : actions) { acls.remove(entity, user, action); } } }, acls.get()); }
@Test public void testStartAndRollbackFailure() throws TransactionFailureException, InterruptedException { ds1.failStartTxOnce = InduceFailure.ThrowException; // execute: add a change to ds1 and ds2 try { getExecutor().execute(testFunction, 10); Assert.fail("start failed - exception should be thrown"); } catch (TransactionFailureException e) { Assert.assertEquals("start failure", e.getCause().getMessage()); } // verify both are not rolled back and tx is aborted Assert.assertTrue(ds1.started); Assert.assertFalse(ds2.started); Assert.assertFalse(ds1.checked); Assert.assertFalse(ds2.checked); Assert.assertFalse(ds1.committed); Assert.assertFalse(ds2.committed); Assert.assertFalse(ds1.postCommitted); Assert.assertFalse(ds2.postCommitted); Assert.assertFalse(ds1.rolledBack); Assert.assertFalse(ds2.rolledBack); Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Aborted); }
@Override public void grant(final EntityId entity, final String user, final Set<Action> actions) { aclsTx.get().executeUnchecked(new TransactionExecutor.Procedure<ACLDataset>() { @Override public void apply(ACLDataset acls) throws Exception { for (Action action : actions) { acls.add(entity, user, action); } } }, acls.get()); }
@Test public void testPersistAndRollbackFailure() throws TransactionFailureException, InterruptedException { ds1.failCommitTxOnce = InduceFailure.ThrowException; ds1.failRollbackTxOnce = InduceFailure.ThrowException; // execute: add a change to ds1 and ds2 try { getExecutor().execute(testFunction, 10); Assert.fail("persist failed - exception should be thrown"); } catch (TransactionFailureException e) { Assert.assertEquals("persist failure", e.getCause().getMessage()); } // verify both are rolled back and tx is invalidated Assert.assertTrue(ds1.started); Assert.assertTrue(ds2.started); Assert.assertTrue(ds1.checked); Assert.assertTrue(ds2.checked); Assert.assertTrue(ds1.committed); Assert.assertFalse(ds2.committed); Assert.assertFalse(ds1.postCommitted); Assert.assertFalse(ds2.postCommitted); Assert.assertTrue(ds1.rolledBack); Assert.assertTrue(ds2.rolledBack); Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Invalidated); }
@Override public void revoke(final EntityId entity, final String user) { aclsTx.get().executeUnchecked(new TransactionExecutor.Procedure<ACLDataset>() { @Override public void apply(ACLDataset acls) throws Exception { acls.remove(entity, user); } }, acls.get()); }
@Test public void testChangesAndRollbackFailure() throws TransactionFailureException, InterruptedException { ds1.failChangesTxOnce = InduceFailure.ThrowException; ds1.failRollbackTxOnce = InduceFailure.ThrowException; // execute: add a change to ds1 and ds2 try { getExecutor().execute(testFunction, 10); Assert.fail("get changes failed - exception should be thrown"); } catch (TransactionFailureException e) { Assert.assertEquals("changes failure", e.getCause().getMessage()); } // verify both are rolled back and tx is invalidated Assert.assertTrue(ds1.started); Assert.assertTrue(ds2.started); Assert.assertTrue(ds1.checked); Assert.assertFalse(ds2.checked); Assert.assertFalse(ds1.committed); Assert.assertFalse(ds2.committed); Assert.assertFalse(ds1.postCommitted); Assert.assertFalse(ds2.postCommitted); Assert.assertTrue(ds1.rolledBack); Assert.assertTrue(ds2.rolledBack); Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Invalidated); }
@Override public void revoke(final EntityId entity) { aclsTx.get().executeUnchecked(new TransactionExecutor.Procedure<ACLDataset>() { @Override public void apply(ACLDataset acls) throws Exception { acls.remove(entity); } }, acls.get()); } }
@Test public void testSuccessful() throws TransactionFailureException, InterruptedException { // execute: add a change to ds1 and ds2 Integer result = getExecutor().execute(testFunction, 10); // verify both are committed and post-committed Assert.assertTrue(ds1.started); Assert.assertTrue(ds2.started); Assert.assertTrue(ds1.checked); Assert.assertTrue(ds2.checked); Assert.assertTrue(ds1.committed); Assert.assertTrue(ds2.committed); Assert.assertTrue(ds1.postCommitted); Assert.assertTrue(ds2.postCommitted); Assert.assertFalse(ds1.rolledBack); Assert.assertFalse(ds2.rolledBack); Assert.assertTrue(100 == result); Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Committed); }
@Override public boolean authorized(final EntityId entity, final String user, final Set<Action> actions) { return aclsTx.get().executeUnchecked(new TransactionExecutor.Function<ACLDataset, Boolean>() { @Override public Boolean apply(ACLDataset acls) throws Exception { Set<Action> unfulfilledActions = new HashSet<>(actions); for (EntityId current : entity.getHierarchy()) { Set<Action> allowedActions = acls.search(current, user); if (allowedActions.contains(Action.ALL)) { return true; } unfulfilledActions.removeAll(allowedActions); if (unfulfilledActions.isEmpty()) { return true; } } return unfulfilledActions.isEmpty(); } }, acls.get()); }
@Test public void testRetryByDefault() throws TransactionFailureException, InterruptedException { // we want retry by default, so that engineers don't miss it txClient.failCommits = 2; // execute: add a change to ds1 and ds2 getExecutor().execute(testFunction, 10); // should not fail, but continue // verify both are committed Assert.assertTrue(ds1.started); Assert.assertTrue(ds2.started); Assert.assertTrue(ds1.checked); Assert.assertTrue(ds2.checked); Assert.assertTrue(ds1.committed); Assert.assertTrue(ds2.committed); Assert.assertTrue(ds1.postCommitted); Assert.assertTrue(ds2.postCommitted); Assert.assertFalse(ds1.rolledBack); Assert.assertFalse(ds2.rolledBack); Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Committed); }
@Test public void testPersistFalse() throws TransactionFailureException, InterruptedException { ds1.failCommitTxOnce = InduceFailure.ReturnFalse; // execute: add a change to ds1 and ds2 try { getExecutor().execute(testFunction, 10); Assert.fail("persist failed - exception should be thrown"); } catch (TransactionFailureException e) { Assert.assertNull(e.getCause()); // in this case, the ds simply returned false } // verify both are rolled back and tx is aborted Assert.assertTrue(ds1.started); Assert.assertTrue(ds2.started); Assert.assertTrue(ds1.checked); Assert.assertTrue(ds2.checked); Assert.assertTrue(ds1.committed); Assert.assertFalse(ds2.committed); Assert.assertFalse(ds1.postCommitted); Assert.assertFalse(ds2.postCommitted); Assert.assertTrue(ds1.rolledBack); Assert.assertTrue(ds2.rolledBack); Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Aborted); }
@Test public void testCommitFalse() throws TransactionFailureException, InterruptedException { txClient.failCommits = 1; // execute: add a change to ds1 and ds2 try { getExecutorWithNoRetry().execute(testFunction, 10); Assert.fail("commit failed - exception should be thrown"); } catch (TransactionConflictException e) { Assert.assertNull(e.getCause()); } // verify both are rolled back and tx is aborted Assert.assertTrue(ds1.started); Assert.assertTrue(ds2.started); Assert.assertTrue(ds1.checked); Assert.assertTrue(ds2.checked); Assert.assertTrue(ds1.committed); Assert.assertTrue(ds2.committed); Assert.assertFalse(ds1.postCommitted); Assert.assertFalse(ds2.postCommitted); Assert.assertTrue(ds1.rolledBack); Assert.assertTrue(ds2.rolledBack); Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Aborted); }
@Test public void testCanCommitFalse() throws TransactionFailureException, InterruptedException { txClient.failCanCommitOnce = true; // execute: add a change to ds1 and ds2 try { getExecutorWithNoRetry().execute(testFunction, 10); Assert.fail("commit failed - exception should be thrown"); } catch (TransactionConflictException e) { Assert.assertNull(e.getCause()); } // verify both are rolled back and tx is aborted Assert.assertTrue(ds1.started); Assert.assertTrue(ds2.started); Assert.assertTrue(ds1.checked); Assert.assertTrue(ds2.checked); Assert.assertFalse(ds1.committed); Assert.assertFalse(ds2.committed); Assert.assertFalse(ds1.postCommitted); Assert.assertFalse(ds2.postCommitted); Assert.assertTrue(ds1.rolledBack); Assert.assertTrue(ds2.rolledBack); Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Aborted); }
@Test public void testPersistAndRollbackFalse() throws TransactionFailureException, InterruptedException { ds1.failCommitTxOnce = InduceFailure.ReturnFalse; ds1.failRollbackTxOnce = InduceFailure.ReturnFalse; // execute: add a change to ds1 and ds2 try { getExecutor().execute(testFunction, 10); Assert.fail("persist failed - exception should be thrown"); } catch (TransactionFailureException e) { Assert.assertNull(e.getCause()); // in this case, the ds simply returned false } // verify both are rolled back and tx is invalidated Assert.assertTrue(ds1.started); Assert.assertTrue(ds2.started); Assert.assertTrue(ds1.checked); Assert.assertTrue(ds2.checked); Assert.assertTrue(ds1.committed); Assert.assertFalse(ds2.committed); Assert.assertFalse(ds1.postCommitted); Assert.assertFalse(ds2.postCommitted); Assert.assertTrue(ds1.rolledBack); Assert.assertTrue(ds2.rolledBack); Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Invalidated); }
@Test public void testNoIndefiniteRetryByDefault() throws TransactionFailureException, InterruptedException { // we want retry by default, so that engineers don't miss it txClient.failCommits = 1000; try { // execute: add a change to ds1 and ds2 getExecutor().execute(testFunction, 10); Assert.fail("commit failed too many times to retry - exception should be thrown"); } catch (TransactionConflictException e) { Assert.assertNull(e.getCause()); } txClient.failCommits = 0; // verify both are rolled back and tx is aborted Assert.assertTrue(ds1.started); Assert.assertTrue(ds2.started); Assert.assertTrue(ds1.checked); Assert.assertTrue(ds2.checked); Assert.assertTrue(ds1.committed); Assert.assertTrue(ds2.committed); Assert.assertFalse(ds1.postCommitted); Assert.assertFalse(ds2.postCommitted); Assert.assertTrue(ds1.rolledBack); Assert.assertTrue(ds2.rolledBack); Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Aborted); }