### Question:
Replicator implements ThreadId.OnError { @SuppressWarnings("unused") static boolean onInstallSnapshotReturned(final ThreadId id, final Replicator r, final Status status, final InstallSnapshotRequest request, final InstallSnapshotResponse response) { boolean success = true; r.releaseReader(); do { final StringBuilder sb = new StringBuilder("Node "). append(r.options.getGroupId()).append(":").append(r.options.getServerId()). append(" received InstallSnapshotResponse from ").append(r.options.getPeerId()). append(" lastIncludedIndex=").append(request.getMeta().getLastIncludedIndex()). append(" lastIncludedTerm=").append(request.getMeta().getLastIncludedTerm()); if (!status.isOk()) { sb.append(" error:").append(status); LOG.info(sb.toString()); notifyReplicatorStatusListener(r, ReplicatorEvent.ERROR, status); if (++r.consecutiveErrorTimes % 10 == 0) { LOG.warn("Fail to install snapshot at peer={}, error={}", r.options.getPeerId(), status); } success = false; break; } if (!response.getSuccess()) { sb.append(" success=false"); LOG.info(sb.toString()); success = false; break; } r.nextIndex = request.getMeta().getLastIncludedIndex() + 1; sb.append(" success=true"); LOG.info(sb.toString()); } while (false); if (!success) { r.resetInflights(); r.state = State.Probe; r.block(Utils.nowMs(), status.getCode()); return false; } r.hasSucceeded = true; r.notifyOnCaughtUp(RaftError.SUCCESS.getNumber(), false); if (r.timeoutNowIndex > 0 && r.timeoutNowIndex < r.nextIndex) { r.sendTimeoutNow(false, false); } r.state = State.Replicate; return true; } Replicator(final ReplicatorOptions replicatorOptions, final RaftOptions raftOptions); @OnlyForTest PriorityQueue<RpcResponse> getPendingResponses(); static ThreadId start(final ReplicatorOptions opts, final RaftOptions raftOptions); static void waitForCaughtUp(final ThreadId id, final long maxMargin, final long dueTime,
                                       final CatchUpClosure done); @Override String toString(); @Override void onError(final ThreadId id, final Object data, final int errorCode); static void sendHeartbeat(final ThreadId id, final RpcResponseClosure<AppendEntriesResponse> closure); static boolean stop(final ThreadId id); static boolean join(final ThreadId id); static long getLastRpcSendTimestamp(final ThreadId id); static boolean transferLeadership(final ThreadId id, final long logIndex); static boolean stopTransferLeadership(final ThreadId id); static boolean sendTimeoutNowAndStop(final ThreadId id, final int timeoutMs); static long getNextIndex(final ThreadId id);  }### Answer:
@Test public void testOnInstallSnapshotReturned() { final Replicator r = getReplicator(); this.id.unlock(); assertNull(r.getBlockTimer()); final RpcRequests.InstallSnapshotRequest request = createInstallSnapshotRequest(); final RpcRequests.InstallSnapshotResponse response = RpcRequests.InstallSnapshotResponse.newBuilder() .setSuccess(true).setTerm(1).build(); assertEquals(-1, r.getWaitId()); Mockito.when(this.logManager.getTerm(11)).thenReturn(1L); Replicator.onRpcReturned(this.id, Replicator.RequestType.Snapshot, Status.OK(), request, response, 0, 0, -1); assertNull(r.getBlockTimer()); assertEquals(0, r.getWaitId()); }