Prober circular list (#218)

* Fixed changes suggested by CydeWeys

* Fixed Javadoc and comments for ActionHandler

* Fixed comments and JavaDoc on other files

* EOL added

* Removed Unnecessary Files

* fixed .gradle files styles

* Removed outbound message from ActionHandler's fields and renamed Marker Interfaces

* Fixed javadoc for Marker Interfaced

* Modified Comments on ActionHandler

* Removed LocalAddress from Protocol

* Fixed Travis Build Issues

* Rebased to Master and added in modified Handlers and ProbingAction

* Added missing license headers and JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor Style Fix

* Full WebWhoIs Sequence Added

* fixed build issues

* Refactored by responses suggested by jianglai.

* Minor Style Fixes

* Updated build.gradle file

* Modified license header dates

* Updated WebWhois tests.

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* SpotlessApply run to fix style issues

* Added license header and newline where appropriate.

* Javadoc style fix in tests and removed unused methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Initial Commit.

* Initial Commit.

* Deleted unfinished features. Added ActionHandler and its Unit Tests.

* Included prober subproject in settings.gradle

* Added Protocol Class and its Basic Unit Tests

* Added Protocol Class and its Basic Unit Tests

* Added Changes Suggested by jianglai

* Fixed Gitignore to take out AutoValue generated code

* Fixed Gitignore to take out AutoValue generated code

* Removed AutoValue java files

* Added gitignore within prober

* Removed all generated java

* Final Changes in .gitignore

* Final Changes in .gitignore

* Added Ssl and WebWhois Action Handlers and their unit tests in addition to the ProbingAction class

* Fixed build.gradle changes requested

* Removed Files irrelevant to current pull request

* Fixed changes suggested by CydeWeys

* Fixed changes suggested by CydeWeys

* Fixed changes suggested by CydeWeys

* Fixed changes suggested by CydeWeys

* Minor fixes to ActionHandler, as responded in comments, removed package-info, and updated settings.gradle

* Minor fixes to ActionHandler, as responded in comments, removed package-info, and updated settings.gradle

* Fully Updated ActionHandler (missing updated JavaDoc)

* Added changed Protocol and both Inbound and Outbound Markers

* Removed AutoVaue ignore clause from .gitignore

* Removed AutoVaue ignore clause from .gitignore

* removed unneccessary dependencies in build.gradle

* Fixed Javadoc and comments for ActionHandler

* Fixed comments and JavaDoc on other files

* EOL added

* Removed Unnecessary Files

* fixed .gradle files styles

* Removed outbound message from ActionHandler's fields and renamed Marker Interfaces

* Fixed javadoc for Marker Interfaced

* Modified Comments on ActionHandler

* Removed LocalAddress from Protocol

* Fixed Travis Build Issues

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Added missing license headers and JavaDoc

* Added missing license headers and JavaDoc

* Added missing license headers and JavaDoc

* Added missing license headers and JavaDoc

* Added missing license headers and JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor Style Fix

* Minor Style Fix

* Minor Style Fix

* Minor Style Fix

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* fixed build issues

* fixed build issues

* fixed build issues

* fixed build issues

* fixed build issues

* Refactored by responses suggested by jianglai.

* Refactored by responses suggested by jianglai.

* Refactored by responses suggested by jianglai.

* Refactored by responses suggested by jianglai.

* Refactored by responses suggested by jianglai.

* Refactored by responses suggested by jianglai.

* Minor Style Fixes

* Minor Style Fixes

* Minor Style Fixes

* Minor Style Fixes

* Minor Style Fixes

* Updated build.gradle file

* Updated build.gradle file

* Updated build.gradle file

* Updated build.gradle file

* Modified license header dates

* Modified license header dates

* Modified license header dates

* Modified license header dates

* Modified license header dates

* Updated WebWhois tests.

* Updated WebWhois tests.

* Updated WebWhois tests.

* Updated WebWhois tests.

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* SpotlessApply run to fix style issues

* SpotlessApply run to fix style issues

* SpotlessApply run to fix style issues

* SpotlessApply run to fix style issues

* SpotlessApply run to fix style issues

* Added license header and newline where appropriate.

* Added license header and newline where appropriate.

* Added license header and newline where appropriate.

* Added license header and newline where appropriate.

* Added license header and newline where appropriate.

* Javadoc style fix in tests and removed unused methods

* Javadoc style fix in tests and removed unused methods

* Javadoc style fix in tests and removed unused methods

* Javadoc style fix in tests and removed unused methods

* Javadoc style fix in tests and removed unused methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Modified tests for WebWhois according to changes suggested by laijiang.

* Modified tests for WebWhois according to changes suggested by laijiang.

* Modified tests for WebWhois according to changes suggested by laijiang.

* Modified tests for WebWhois according to changes suggested by laijiang.

* Modified tests for WebWhois according to changes suggested by laijiang.

* Removed TestProvider from TestUtils.

* Removed TestProvider from TestUtils.

* Removed TestProvider from TestUtils.

* Removed TestProvider from TestUtils.

* Removed TestProvider from TestUtils.

* Rebased to master

* Rebased to master

* Updated issues in rebasing

* Updated issues in rebasing

* Minor style change on prober/build.gradle

* Minor style change on prober/build.gradle

* Fixed warnings for java compilation

* Fixed warnings for java compilation

* Fixed files to pass all style tests

* Fixed files to pass all style tests

* Fixed files to pass all style tests

* Minor syle fixes after succesful rebase onto master

* Fixed changes suggested by CydeWeys

* Fixed changes suggested by CydeWeys

* Fixed changes suggested by CydeWeys

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Added missing license headers and JavaDoc

* Added missing license headers and JavaDoc

* Added missing license headers and JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor Style Fix

* Minor Style Fix

* Minor Style Fix

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* fixed build issues

* fixed build issues

* fixed build issues

* Refactored by responses suggested by jianglai.

* Refactored by responses suggested by jianglai.

* Refactored by responses suggested by jianglai.

* Minor Style Fixes

* Minor Style Fixes

* Updated build.gradle file

* Updated build.gradle file

* Updated build.gradle file

* Modified license header dates

* Modified license header dates

* Modified license header dates

* Updated WebWhois tests.

* Updated WebWhois tests.

* Updated WebWhois tests.

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* SpotlessApply run to fix style issues

* Added circular linked list to utils

* Added circular linked list to utils

* Added circular linked list to utils

* Added circular linked list to utils

* Added circular linked list to utils

* License Header added

* License Header added

* License Header added

* License Header added

* License Header added

* Added license header and newline where appropriate.

* Added license header and newline where appropriate.

* Refactored probing sequence to be circular linked list iterator

* Refactored probing sequence to be circular linked list iterator

* Refactored probing sequence to be circular linked list iterator

* Refactored probing sequence to be circular linked list iterator

* Javadoc style fix in tests and removed unused methods

* Javadoc style fix in tests and removed unused methods

* Javadoc style fix in tests and removed unused methods

* Modified ProbingStep tests to reflect new ProbingStep structure.

* Modified ProbingStep tests to reflect new ProbingStep structure.

* Refactored ProbingAction to minimize number of unnecessary methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Modified tests for WebWhois according to changes suggested by laijiang.

* Modified tests for WebWhois according to changes suggested by laijiang.

* Modified tests for WebWhois according to changes suggested by laijiang.

* Removed TestProvider from TestUtils.

* Removed TestProvider from TestUtils.

* Rebased to master

* ProbingStepTest modified to have fewer unnecessary helper methods

* ProbingStepTest modified to have fewer unnecessary helper methods

* Updated issues in rebasing

* Updated issues in rebasing

* Added missing license header to DefaultCircularLinkedListIterator

* Fixed max column length to be 100

* Fixed max column length to be 100

* Minor changes to pass style tests

* Successful rebase onto finished web-whois branch

* Removed need for TestTokens with Mockito mocks of Tokens

* Fixed style issues in DefaultCircularLinkedListIterator and AbstractCircularLinkedListIterator

* Modified CircularList according to changes suggested by jianglai.

* Merge branch 'master' into prober-circular-list

* Modified ProbingSequenceTest to not expect unnecessary NullPointerException

* ProbingSequence and tests modified to reflect addition of UnrecoverableStateException and restarts on failures

* Modified ProbingSequence and its tests to reflect action generation and calling being put in the same try catch block
This commit is contained in:
Aman Sanger 2019-08-12 18:41:50 -04:00 committed by GitHub
parent 89a44f176c
commit df5f450435
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 697 additions and 281 deletions

View file

@ -17,76 +17,304 @@ package google.registry.monitoring.blackbox;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import google.registry.monitoring.blackbox.exceptions.FailureException;
import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException;
import google.registry.monitoring.blackbox.exceptions.UnrecoverableStateException;
import google.registry.monitoring.blackbox.tokens.Token;
import io.netty.channel.Channel;
import io.netty.channel.ChannelPromise;
import io.netty.channel.embedded.EmbeddedChannel;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mockito;
/**
* Unit Tests on {@link ProbingSequence}
*
* <p>First tests the construction of sequences and ensures the ordering is exactly how
* we expect it to be.</p>
*
* <p>Then tests the execution of each step, by ensuring the methods treatment of any kind
* of response from the {@link ProbingStep}s or {@link ProbingAction}s is what is expected.</p>
*
* <p>On every test that runs the sequence, in order for the sequence to stop, we throw an
* {@link UnrecoverableStateException}, using mocks of the steps or actions, as the sequences
* are run using the main thread (with {@link EmbeddedChannel}).</p>
*/
@RunWith(JUnit4.class)
public class ProbingSequenceTest {
private ProbingStep firstStep;
private ProbingStep secondStep;
private ProbingStep thirdStep;
/**
* Default mock {@link ProbingAction} returned when generating an action with a mockStep.
*/
private ProbingAction mockAction = Mockito.mock(ProbingAction.class);
private Token testToken;
/**
* Default mock {@link ProbingStep} that will usually return a {@code mockAction} on call to
* generate action.
*/
private ProbingStep mockStep = Mockito.mock(ProbingStep.class);
private ProbingStep setupMockStep() {
ProbingStep mock = Mockito.mock(ProbingStep.class);
doCallRealMethod().when(mock).nextStep(any(ProbingStep.class));
doCallRealMethod().when(mock).nextStep();
return mock;
}
/**
* Default mock {@link Token} that is passed into each {@link ProbingSequence} tested.
*/
private Token mockToken = Mockito.mock(Token.class);
/**
* Default mock {@link Protocol} returned {@code mockStep} and occasionally, other mock {@link
* ProbingStep}s.
*/
private Protocol mockProtocol = Mockito.mock(Protocol.class);
/**
* {@link EmbeddedChannel} used to create new {@link ChannelPromise} objects returned by mock
* {@link ProbingAction}s on their {@code call} methods.
*/
private EmbeddedChannel channel = new EmbeddedChannel();
@Before
public void setup() {
firstStep = setupMockStep();
secondStep = setupMockStep();
thirdStep = setupMockStep();
// To avoid a NullPointerException, we must have a protocol return persistent connection as
// false.
doReturn(true).when(mockProtocol).persistentConnection();
testToken = Mockito.mock(Token.class);
// In order to avoid a NullPointerException, we must have the protocol returned that stores
// persistent connection as false.
doReturn(mockProtocol).when(mockStep).protocol();
// Allows for test if channel is accurately set.
doCallRealMethod().when(mockToken).setChannel(any(Channel.class));
doCallRealMethod().when(mockToken).channel();
// Allows call to mockAction to retrieve mocked channel.
doReturn(channel).when(mockAction).channel();
}
@Test
public void testSequenceBasicConstruction_Success() {
ProbingStep firstStep = Mockito.mock(ProbingStep.class);
ProbingStep secondStep = Mockito.mock(ProbingStep.class);
ProbingStep thirdStep = Mockito.mock(ProbingStep.class);
ProbingSequence sequence = new ProbingSequence.Builder(testToken)
.addStep(firstStep)
.addStep(secondStep)
.addStep(thirdStep)
ProbingSequence sequence = new ProbingSequence.Builder(mockToken)
.add(firstStep)
.add(secondStep)
.add(thirdStep)
.build();
assertThat(firstStep.nextStep()).isEqualTo(secondStep);
assertThat(secondStep.nextStep()).isEqualTo(thirdStep);
assertThat(thirdStep.nextStep()).isEqualTo(firstStep);
assertThat(sequence.get()).isEqualTo(firstStep);
sequence = sequence.next();
sequence.start();
assertThat(sequence.get()).isEqualTo(secondStep);
sequence = sequence.next();
verify(firstStep, times(1)).accept(testToken);
assertThat(sequence.get()).isEqualTo(thirdStep);
sequence = sequence.next();
assertThat(sequence.get()).isEqualTo(firstStep);
}
@Test
public void testSequenceAdvancedConstruction_Success() {
ProbingStep firstStep = Mockito.mock(ProbingStep.class);
ProbingStep secondStep = Mockito.mock(ProbingStep.class);
ProbingStep thirdStep = Mockito.mock(ProbingStep.class);
ProbingSequence sequence = new ProbingSequence.Builder(testToken)
.addStep(thirdStep)
.addStep(secondStep)
ProbingSequence sequence = new ProbingSequence.Builder(mockToken)
.add(thirdStep)
.add(secondStep)
.markFirstRepeated()
.addStep(firstStep)
.add(firstStep)
.build();
assertThat(firstStep.nextStep()).isEqualTo(secondStep);
assertThat(secondStep.nextStep()).isEqualTo(firstStep);
assertThat(thirdStep.nextStep()).isEqualTo(secondStep);
assertThat(sequence.get()).isEqualTo(thirdStep);
sequence = sequence.next();
assertThat(sequence.get()).isEqualTo(secondStep);
sequence = sequence.next();
assertThat(sequence.get()).isEqualTo(firstStep);
sequence = sequence.next();
assertThat(sequence.get()).isEqualTo(secondStep);
}
@Test
public void testRunStep_Success() throws UndeterminedStateException {
//Always returns a succeeded future on call to mockAction.
doReturn(channel.newSucceededFuture()).when(mockAction).call();
// Has mockStep always return mockAction on call to generateAction
doReturn(mockAction).when(mockStep).generateAction(any(Token.class));
//Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on.
ProbingStep secondStep = Mockito.mock(ProbingStep.class);
ProbingAction secondAction = Mockito.mock(ProbingAction.class);
doReturn(channel.newFailedFuture(new UnrecoverableStateException(""))).when(secondAction)
.call();
doReturn(secondAction).when(secondStep).generateAction(mockToken);
//Build testable sequence from mocked components.
ProbingSequence sequence = new ProbingSequence.Builder(mockToken)
.add(mockStep)
.add(secondStep)
.build();
sequence.start();
verify(thirdStep, times(1)).accept(testToken);
// We expect to have only generated actions from mockStep once, and we expect to have called
// this generated action only once, as when we move on to secondStep, it terminates the
// sequence.
verify(mockStep).generateAction(any(Token.class));
verify(mockStep).generateAction(mockToken);
verify(mockAction).call();
// Similarly, we expect to generate actions and call the action from the secondStep once, as
// after calling it, the sequence should be terminated
verify(secondStep).generateAction(any(Token.class));
verify(secondStep).generateAction(mockToken);
verify(secondAction).call();
//We should have modified the token's channel after the first, succeeded step.
assertThat(mockToken.channel()).isEqualTo(channel);
}
@Test
public void testRunLoop_Success() throws UndeterminedStateException {
// Always returns a succeeded future on call to mockAction.
doReturn(channel.newSucceededFuture()).when(mockAction).call();
// Has mockStep always return mockAction on call to generateAction
doReturn(mockAction).when(mockStep).generateAction(mockToken);
// Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on.
ProbingStep secondStep = Mockito.mock(ProbingStep.class);
ProbingAction secondAction = Mockito.mock(ProbingAction.class);
// Necessary for success of ProbingSequence runStep method as it calls get().protocol()
doReturn(mockProtocol).when(secondStep).protocol();
// We ensure that secondStep has necessary attributes to be successful step to pass on to
// mockStep once more.
doReturn(channel.newSucceededFuture()).when(secondAction).call();
doReturn(secondAction).when(secondStep).generateAction(mockToken);
// We get a secondToken that is returned when we are on our second loop in the sequence. This
// will inform mockStep on when to generate a different ProbingAction.
Token secondToken = Mockito.mock(Token.class);
doReturn(secondToken).when(mockToken).next();
// The thirdAction we use is made so that when it is called, it will halt the ProbingSequence
// by returning an UnrecoverableStateException.
ProbingAction thirdAction = Mockito.mock(ProbingAction.class);
doReturn(channel.newFailedFuture(new UnrecoverableStateException(""))).when(thirdAction).call();
doReturn(thirdAction).when(mockStep).generateAction(secondToken);
//Build testable sequence from mocked components.
ProbingSequence sequence = new ProbingSequence.Builder(mockToken)
.add(mockStep)
.add(secondStep)
.build();
sequence.start();
// We expect to have generated actions from mockStep twice (once for mockToken and once for
// secondToken), and we expectto have called each generated action only once, as when we move
// on to mockStep the second time, it will terminate the sequence after calling thirdAction.
verify(mockStep, times(2)).generateAction(any(Token.class));
verify(mockStep).generateAction(mockToken);
verify(mockStep).generateAction(secondToken);
verify(mockAction).call();
verify(thirdAction).call();
// Similarly, we expect to generate actions and call the action from the secondStep once, as
// after calling it, we move on to mockStep again, which terminates the sequence.
verify(secondStep).generateAction(any(Token.class));
verify(secondStep).generateAction(mockToken);
verify(secondAction).call();
//We should have modified the token's channel after the first, succeeded step.
assertThat(mockToken.channel()).isEqualTo(channel);
}
/**
* Test for when we expect Failure within try catch block of generating and calling a
* {@link ProbingAction}.
*
* @throws UndeterminedStateException - necessary for having mock return anything on a call to
* {@code generateAction}.
*/
private void testActionFailure() throws UndeterminedStateException {
//Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on.
ProbingStep secondStep = Mockito.mock(ProbingStep.class);
// We create a second token that when used to generate an action throws an
// UnrecoverableStateException to terminate the sequence
Token secondToken = Mockito.mock(Token.class);
doReturn(secondToken).when(mockToken).next();
doThrow(new UnrecoverableStateException("")).when(mockStep).generateAction(secondToken);
//Build testable sequence from mocked components.
ProbingSequence sequence = new ProbingSequence.Builder(mockToken)
.add(mockStep)
.add(secondStep)
.build();
sequence.start();
// We expect that we have generated actions twice. First, when we actually test generateAction
// with an actual call using mockToken, and second when we throw an
// UnrecoverableStateException with secondToken.
verify(mockStep, times(2)).generateAction(any(Token.class));
verify(mockStep).generateAction(mockToken);
verify(mockStep).generateAction(secondToken);
// We should never reach the step where we modify the channel, as it should have failed by then
assertThat(mockToken.channel()).isNull();
assertThat(secondToken.channel()).isNull();
// We should never reach the second step, since we fail on the first step, then terminate on
// the first step after retrying.
verify(secondStep, times(0)).generateAction(any(Token.class));
}
@Test
public void testRunStep_FailureRunning() throws UndeterminedStateException {
// Returns a failed future when calling the generated mock action.
doReturn(channel.newFailedFuture(new FailureException(""))).when(mockAction).call();
// Returns mock action on call to generate action for ProbingStep.
doReturn(mockAction).when(mockStep).generateAction(mockToken);
//Tests generic behavior we expect when we fail in generating or calling an action.
testActionFailure();
// We only expect to have called this action once, as we only get it from one generateAction
// call.
verify(mockAction).call();
}
@Test
public void testRunStep_FailureGenerating() throws UndeterminedStateException {
// Create a mock first step that returns the dummy action when called to generate an action.
doThrow(UndeterminedStateException.class).when(mockStep).generateAction(mockToken);
testActionFailure();
// We expect to have never called this action, as we fail each time whenever generating actions.
verify(mockAction, times(0)).call();
}
}

View file

@ -16,13 +16,9 @@ package google.registry.monitoring.blackbox;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY;
import static java.nio.charset.StandardCharsets.US_ASCII;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import com.google.common.collect.ImmutableList;
import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException;
@ -34,8 +30,7 @@ import google.registry.monitoring.blackbox.messages.OutboundMessageType;
import google.registry.monitoring.blackbox.messages.TestMessage;
import google.registry.monitoring.blackbox.tokens.Token;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.embedded.EmbeddedChannel;
@ -43,7 +38,6 @@ import io.netty.channel.local.LocalAddress;
import io.netty.channel.local.LocalChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import org.joda.time.Duration;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mockito;
@ -62,14 +56,11 @@ public class ProbingStepTest {
private static final int PROTOCOL_PORT = 0;
private static final String TEST_MESSAGE = "TEST_MESSAGE";
private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE";
private static final LocalAddress ADDRESS = new LocalAddress(ADDRESS_NAME);
private static final LocalAddress address = new LocalAddress(ADDRESS_NAME);
private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1);
private final Bootstrap bootstrap = new Bootstrap()
.group(eventLoopGroup)
.channel(LocalChannel.class);
/**
* Used for testing how well probing step can create connection to blackbox server
*/
@ -91,13 +82,53 @@ public class ProbingStepTest {
private Token testToken(String host) throws UndeterminedStateException {
Token token = Mockito.mock(Token.class);
doReturn(host).when(token).host();
doAnswer(answer -> answer.getArgument(0)).when(token)
doAnswer(answer -> ((OutboundMessageType) answer.getArgument(0)).modifyMessage(host))
.when(token)
.modifyMessage(any(OutboundMessageType.class));
return token;
}
@Test
public void testNewChannel() throws Exception {
public void testProbingActionGenerate_embeddedChannel() throws UndeterminedStateException {
// Sets up Protocol to represent existing channel connection.
Protocol testProtocol = Protocol.builder()
.setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler))
.setName(PROTOCOL_NAME)
.setPort(PROTOCOL_PORT)
.setPersistentConnection(true)
.build();
// Sets up an embedded channel to contain the two handlers we created already.
EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler);
channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture());
// Sets up testToken to return arbitrary value, and the embedded channel. Used for when the
// ProbingStep generates an ExistingChannelAction.
Token testToken = testToken(SECONDARY_TEST_MESSAGE);
doReturn(channel).when(testToken).channel();
// Sets up generic {@link ProbingStep} that we are testing.
ProbingStep testStep = ProbingStep.builder()
.setMessageTemplate(new TestMessage(TEST_MESSAGE))
.setBootstrap(bootstrap)
.setDuration(Duration.ZERO)
.setProtocol(testProtocol)
.build();
ProbingAction testAction = testStep.generateAction(testToken);
assertThat(testAction.channel()).isEqualTo(channel);
assertThat(testAction.delay()).isEqualTo(Duration.ZERO);
assertThat(testAction.outboundMessage().toString()).isEqualTo(SECONDARY_TEST_MESSAGE);
assertThat(testAction.host()).isEqualTo(SECONDARY_TEST_MESSAGE);
assertThat(testAction.protocol()).isEqualTo(testProtocol);
}
@Test
public void testProbingActionGenerate_newChannel() throws UndeterminedStateException {
// Sets up Protocol for when we create a new channel.
Protocol testProtocol = Protocol.builder()
.setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler))
@ -106,97 +137,32 @@ public class ProbingStepTest {
.setPersistentConnection(false)
.build();
// Sets up our main step (firstStep) and throwaway step (dummyStep).
ProbingStep firstStep = ProbingStep.builder()
// Sets up generic ProbingStep that we are testing.
ProbingStep testStep = ProbingStep.builder()
.setMessageTemplate(new TestMessage(TEST_MESSAGE))
.setBootstrap(bootstrap)
.setDuration(Duration.ZERO)
.setMessageTemplate(new TestMessage(TEST_MESSAGE))
.setProtocol(testProtocol)
.build();
//Sets up mock dummy step that returns succeeded promise when we successfully reach it.
ProbingStep dummyStep = Mockito.mock(ProbingStep.class);
firstStep.nextStep(dummyStep);
// Sets up testToken to return arbitrary values, and no channel. Used when we create a new
// channel.
Token testToken = testToken(ADDRESS_NAME);
//Set up blackbox server that receives our messages then echoes them back to us
nettyRule.setUpServer(ADDRESS);
// Sets up server listening at LocalAddress so generated action can have successful connection.
nettyRule.setUpServer(address);
//checks that the ProbingSteps are appropriately pointing to each other
assertThat(firstStep.nextStep()).isEqualTo(dummyStep);
ProbingAction testAction = testStep.generateAction(testToken);
//Call accept on the first step, which should send our message to the server, which will then be
//echoed back to us, causing us to move to the next step
firstStep.accept(testToken);
ChannelFuture connectionFuture = testAction.channel().attr(CONNECTION_FUTURE_KEY).get();
connectionFuture = connectionFuture.syncUninterruptibly();
//checks that we have appropriately sent the write message to server
nettyRule.assertReceivedMessage(TEST_MESSAGE);
assertThat(connectionFuture.isSuccess()).isTrue();
assertThat(testAction.delay()).isEqualTo(Duration.ZERO);
assertThat(testAction.outboundMessage().toString()).isEqualTo(ADDRESS_NAME);
assertThat(testAction.host()).isEqualTo(ADDRESS_NAME);
assertThat(testAction.protocol()).isEqualTo(testProtocol);
//checks that when the future is successful, we pass down the requisite token
verify(dummyStep, times(1)).accept(any(Token.class));
}
//TODO - Currently, this test fails to receive outbound messages from the embedded channel, which
// we will fix in a later release.
@Ignore
@Test
public void testWithSequence_ExistingChannel() throws Exception {
// Sets up Protocol for when a channel already exists.
Protocol testProtocol = Protocol.builder()
.setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler))
.setName(PROTOCOL_NAME)
.setPort(PROTOCOL_PORT)
.setPersistentConnection(true)
.build();
// Sets up our main step (firstStep) and throwaway step (dummyStep).
ProbingStep firstStep = ProbingStep.builder()
.setBootstrap(bootstrap)
.setDuration(Duration.ZERO)
.setMessageTemplate(new TestMessage(TEST_MESSAGE))
.setProtocol(testProtocol)
.build();
//Sets up mock dummy step that returns succeeded promise when we successfully reach it.
ProbingStep dummyStep = Mockito.mock(ProbingStep.class);
firstStep.nextStep(dummyStep);
// Sets up an embedded channel to contain the two handlers we created already.
EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler);
//Assures that the channel has a succeeded connectionFuture.
channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture());
// Sets up testToken to return arbitrary value, and the embedded channel. Used for when the
// ProbingStep generates an ExistingChannelAction.
Token testToken = testToken("");
doReturn(channel).when(testToken).channel();
//checks that the ProbingSteps are appropriately pointing to each other
assertThat(firstStep.nextStep()).isEqualTo(dummyStep);
//Call accept on the first step, which should send our message through the EmbeddedChannel
// pipeline
firstStep.accept(testToken);
Object msg = channel.readOutbound();
while (msg == null) {
msg = channel.readOutbound();
}
//Ensures the accurate message is sent down the pipeline
assertThat(((ByteBuf) channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE);
//Write response to our message down EmbeddedChannel pipeline
channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII)));
//At this point, we should have received the message, so the future obtained should be marked
// as a success
verify(dummyStep, times(1)).accept(any(Token.class));
}
}

View file

@ -16,9 +16,9 @@ package google.registry.monitoring.blackbox.tokens;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.collect.ImmutableList;
import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException;
import google.registry.monitoring.blackbox.messages.HttpRequestMessage;
import google.registry.util.CircularList;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@ -29,15 +29,17 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class WebWhoisTokenTest {
private static String PREFIX = "whois.nic.";
private static String HOST = "starter";
private static String FIRST_TLD = "first_test";
private static String SECOND_TLD = "second_test";
private static String THIRD_TLD = "third_test";
private static ImmutableList<String> TEST_DOMAINS = ImmutableList.of(FIRST_TLD, SECOND_TLD,
THIRD_TLD);
private static final String PREFIX = "whois.nic.";
private static final String HOST = "starter";
private static final String FIRST_TLD = "first_test";
private static final String SECOND_TLD = "second_test";
private static final String THIRD_TLD = "third_test";
private final CircularList<String> testDomains =
new CircularList.Builder<String>()
.add(FIRST_TLD, SECOND_TLD, THIRD_TLD)
.build();
public Token webToken = new WebWhoisToken(TEST_DOMAINS);
public Token webToken = new WebWhoisToken(testDomains);
@Test
public void testMessageModification() throws UndeterminedStateException {
@ -47,7 +49,7 @@ public class WebWhoisTokenTest {
//attempts to use Token's method for modifying the method based on its stored host
HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message);
assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX + TEST_DOMAINS.get(0));
assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX + FIRST_TLD);
}
/**
@ -63,6 +65,9 @@ public class WebWhoisTokenTest {
webToken = webToken.next();
assertThat(webToken.host()).isEqualTo(PREFIX + THIRD_TLD);
webToken = webToken.next();
assertThat(webToken.host()).isEqualTo(PREFIX + FIRST_TLD);
}
}