-
Notifications
You must be signed in to change notification settings - Fork 864
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enable BlockHound for integration tests and stability tests (#2863)
* Enable BlockHound for integration tests and stability tests This PR enables [BlockHound](https://github.com/reactor/BlockHound) for the SDK integration test and stability tests. BlockHound can be used to detect blocking behavior in threads that must be treated as non-blocking, like Netty's EventLoop threads. If BlockHound detects an illegal blocking operation being performed, it will throw a BlockingOperationError. Doing so in an integration test would typically fail the integration test and allow us to investigate the behavior. This PR enables BlockHound by leveraging BlockHound's provided [BlockHoundTestExecutionListener](https://github .com/reactor/BlockHound/blob/2071ca8dbb06eba9ffa65596f327e3182d3b9730 /junit-platform/src/main/java/reactor/blockhound/junit/platform /BlockHoundTestExecutionListener.java), which uses @autoservice to automatically register with JUnit 5's ServiceLoader support: https://junit.org/junit5/docs/current/user-guide/#launcher-api-listeners-custom
- Loading branch information
1 parent
ee3d583
commit a5f7a2e
Showing
8 changed files
with
194 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
131 changes: 131 additions & 0 deletions
131
services/s3/src/it/java/software/amazon/awssdk/services/BlockHoundInstalledTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). | ||
* You may not use this file except in compliance with the License. | ||
* A copy of the License is located at | ||
* | ||
* http://aws.amazon.com/apache2.0 | ||
* | ||
* or in the "license" file accompanying this file. This file is distributed | ||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | ||
* express or implied. See the License for the specific language governing | ||
* permissions and limitations under the License. | ||
*/ | ||
|
||
package software.amazon.awssdk.services; | ||
|
||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
import io.netty.bootstrap.ServerBootstrap; | ||
import io.netty.channel.Channel; | ||
import io.netty.channel.ChannelDuplexHandler; | ||
import io.netty.channel.ChannelHandlerContext; | ||
import io.netty.channel.EventLoop; | ||
import io.netty.channel.EventLoopGroup; | ||
import io.netty.channel.nio.NioEventLoopGroup; | ||
import io.netty.channel.socket.nio.NioServerSocketChannel; | ||
import java.io.IOException; | ||
import java.net.ServerSocket; | ||
import java.net.Socket; | ||
import java.util.concurrent.CountDownLatch; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.concurrent.atomic.AtomicReference; | ||
import org.junit.jupiter.api.AfterEach; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
import reactor.blockhound.BlockHound; | ||
import reactor.blockhound.BlockingOperationError; | ||
import reactor.blockhound.integration.BlockHoundIntegration; | ||
import reactor.blockhound.junit.platform.BlockHoundTestExecutionListener; | ||
import software.amazon.awssdk.testutils.service.AwsIntegrationTestBase; | ||
import software.amazon.awssdk.testutils.service.AwsTestBase; | ||
import software.amazon.awssdk.utils.Logger; | ||
|
||
/** | ||
* This test ensures that BlockHound is correctly installed for integration tests. The test is somewhat arbitrarily placed in the | ||
* {@code s3} module in order to assert against the configuration of all service integration tests. | ||
* <p> | ||
* BlockHound is installed in one of two ways: | ||
* <ol> | ||
* <li>Using BlockHound's provided {@link BlockHoundTestExecutionListener}, which will be automatically detected by the | ||
* JUnit 5 platform upon initialization.</li> | ||
* <li>Manually calling {@link BlockHound#install(BlockHoundIntegration...)}. This is done as part of static initialization in | ||
* {@link AwsIntegrationTestBase} and {@link AwsTestBase}, which most integration/stability tests extend. | ||
* </ol> | ||
* <p> | ||
* This test ensures BlockHound is correctly installed by intentionally performing a blocking operation on the Netty | ||
* {@link EventLoop} and asserting that a {@link BlockingOperationError} is thrown to forbid it. | ||
*/ | ||
class BlockHoundInstalledTest { | ||
private static final Logger log = Logger.loggerFor(BlockHoundInstalledTest.class); | ||
|
||
AtomicReference<Throwable> throwableReference; | ||
CountDownLatch latch; | ||
EventLoopGroup bossGroup; | ||
EventLoopGroup workerGroup; | ||
Socket clientSocket; | ||
Channel serverChannel; | ||
|
||
@BeforeEach | ||
public void setup() { | ||
throwableReference = new AtomicReference<>(); | ||
latch = new CountDownLatch(1); | ||
bossGroup = new NioEventLoopGroup(); | ||
workerGroup = new NioEventLoopGroup(); | ||
} | ||
|
||
@AfterEach | ||
public void teardown() throws Exception { | ||
if (clientSocket != null) { | ||
clientSocket.close(); | ||
} | ||
if (serverChannel != null) { | ||
serverChannel.close(); | ||
} | ||
workerGroup.shutdownGracefully(); | ||
bossGroup.shutdownGracefully(); | ||
} | ||
|
||
@Test | ||
void testBlockHoundInstalled() throws Exception { | ||
ServerBootstrap bootstrap = new ServerBootstrap(); | ||
bootstrap.group(bossGroup, workerGroup) | ||
.channel(NioServerSocketChannel.class) | ||
.childHandler(new ChannelDuplexHandler() { | ||
@Override | ||
public void channelActive(ChannelHandlerContext ctx) { | ||
log.info(() -> "Preparing to sleep on the EventLoop to test if BlockHound is installed"); | ||
try { | ||
Thread.sleep(1000); | ||
log.info(() -> "BlockHound does not appear to be successfully installed"); | ||
} catch (Throwable t) { | ||
log.info(() -> "BlockHound is successfully installed", t); | ||
throwableReference.set(t); | ||
} | ||
latch.countDown(); | ||
ctx.fireChannelActive(); | ||
} | ||
}); | ||
|
||
int port = getUnusedPort(); | ||
serverChannel = bootstrap.bind(port).sync().channel(); | ||
clientSocket = new Socket("localhost", port); | ||
|
||
latch.await(5, TimeUnit.SECONDS); | ||
assertThat(throwableReference.get()) | ||
.withFailMessage("BlockHound does not appear to be successfully installed. Ensure that either BlockHound.install() " | ||
+ "is called prior to all test executions or that BlockHoundTestExecutionListener is available on " | ||
+ "the class path and correctly detected by JUnit: " | ||
+ "https://github.com/reactor/BlockHound/blob/master/docs/supported_testing_frameworks.md") | ||
.isInstanceOf(BlockingOperationError.class); | ||
} | ||
|
||
private static int getUnusedPort() throws IOException { | ||
try (ServerSocket socket = new ServerSocket(0)) { | ||
socket.setReuseAddress(true); | ||
return socket.getLocalPort(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters