smengcl commented on code in PR #8805:
URL: https://github.com/apache/hadoop/pull/8805#discussion_r4351846548
##########
hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/TestDelegationToken.java:
##########
@@ -425,6 +430,86 @@ public Object run() throws Exception {
}
}
+ /**
+ * Returns a secret manager that runs onFail on every incrementCurrentKeyId()
+ * call after the first. The first call comes from startThreads(); the next
+ * one comes from rollMasterKey() in the remover thread.
+ */
+ private static TestDelegationTokenSecretManager failingAfterFirstKeyId(
+ Runnable onFail) {
+ AtomicInteger keyIdCalls = new AtomicInteger();
+ return new TestDelegationTokenSecretManager(3600000, 3600000, 3600000,
+ 3600000) {
+ @Override
+ protected int incrementCurrentKeyId() {
+ if (keyIdCalls.incrementAndGet() > 1) {
+ onFail.run();
+ }
+ return super.incrementCurrentKeyId();
+ }
+ };
+ }
+
+ /**
+ * An unexpected exception in the expired token remover thread must go
+ * through ExitUtil so that tests can intercept it.
+ */
+ @Test
+ @Timeout(value = 30)
+ public void testExpiredTokenRemoverFailureTerminates() throws Exception {
+ ExitUtil.disableSystemExit();
+ TestDelegationTokenSecretManager dtSecretManager =
+ failingAfterFirstKeyId(() -> {
+ throw new RuntimeException("injected key id failure");
+ });
+ try {
+ dtSecretManager.startThreads();
+ GenericTestUtils.waitFor(ExitUtil::terminateCalled, 100, 10000);
+ ExitUtil.ExitException ee = ExitUtil.getFirstExitException();
+ assertEquals(-1, ee.getExitCode());
+ assertThat(ee.getCause()).hasMessage("injected key id failure");
+ } finally {
+ dtSecretManager.stopThreads();
+ ExitUtil.enableSystemExit();
+ ExitUtil.resetFirstExitException();
+ }
+ }
+
+ /**
+ * An exception raised because stopThreads() interrupted the expired token
+ * remover thread must not terminate the process.
+ */
+ @Test
+ @Timeout(value = 30)
+ public void testExpiredTokenRemoverFailureWhileStoppingDoesNotTerminate()
+ throws Exception {
+ ExitUtil.disableSystemExit();
+ CountDownLatch blocked = new CountDownLatch(1);
+ TestDelegationTokenSecretManager dtSecretManager =
+ failingAfterFirstKeyId(() -> {
+ // Block in the remover thread until stopThreads() interrupts it,
+ // as a backing store call would.
+ blocked.countDown();
+ try {
+ new CountDownLatch(1).await();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("interrupted", e);
+ }
+ });
+ boolean terminated;
+ try {
+ dtSecretManager.startThreads();
+ assertTrue(blocked.await(10, TimeUnit.SECONDS));
+ } finally {
+ // stopThreads() joins the remover thread, so its outcome is final here.
+ dtSecretManager.stopThreads();
+ terminated = ExitUtil.terminateCalled();
+ ExitUtil.enableSystemExit();
+ ExitUtil.resetFirstExitException();
+ }
+ assertFalse(terminated, "terminate should not be called while stopping");
Review Comment:
nit: capturing the exception instead of a boolean would show what triggered
the exit if this ever fails:
```java
ExitUtil.ExitException ee;
...
ee = ExitUtil.getFirstExitException();
...
assertThat(ee).as("terminate should not be called while stopping").isNull();
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]