Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FreePort resource to create ServerSocket #733

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/docs-nav.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,5 @@
url: /docs/simple-arguments-aggregator/
- title: "Vintage @Test"
url: /docs/vintage-test/
- title: "Free port"
url: /docs/free-port/
23 changes: 23 additions & 0 deletions docs/free-port.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
:page-title: Free Port
:page-description: Extends JUnit Jupiter with `@FreePort` to get a free port.
:xp-demo-dir: ../src/demo/java
:demo: {xp-demo-dir}/org/junitpioneer/jupiter/resource/FreePortDemo.java

== Introduction

Sometimes we want a free port in our tests so that we can either start a server on it or
to test a failure scenario when there is no service at given port.

It's a JUnit Jupiter extension which provides a free port for above-mentioned use cases.
Also, there is no guarantee that the port will still be available by the time you use it.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe highlight this (port might be not free when used) as a note / warning?


NOTE: You can retry the test in such cases based on `FreePort.isFreeNow`

== Usage

To get the `FreePort` as an argument on a test just add the annotation to your test suite as shown in the following example:

[source,java]
----
include::{demo}[tag=basic_free_port_example]
----
29 changes: 29 additions & 0 deletions src/demo/java/org/junitpioneer/jupiter/resource/FreePortDemo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2016-2023 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v20.html
*/

package org.junitpioneer.jupiter.resource;

import static org.assertj.core.api.Assertions.assertThat;

import java.net.ServerSocket;

import org.junit.jupiter.api.Test;

public class FreePortDemo {

// tag::basic_free_port_example[]
@Test
void testFreePort(@NewPort ServerSocket port) {
assertThat(port).isNotNull();
assertThat(port.isClosed()).isFalse();
}
// end::basic_free_port_example[]

}
1 change: 1 addition & 0 deletions src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
exports org.junitpioneer.jupiter.cartesian;
exports org.junitpioneer.jupiter.params;
exports org.junitpioneer.jupiter.json;
exports org.junitpioneer.jupiter.resource;
exports org.junitpioneer.jupiter.converter;

opens org.junitpioneer.vintage to org.junit.platform.commons;
Expand Down
48 changes: 48 additions & 0 deletions src/main/java/org/junitpioneer/jupiter/resource/FreePort.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2016-2022 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v20.html
*/

package org.junitpioneer.jupiter.resource;

import java.io.IOException;
import java.net.ServerSocket;
import java.util.List;

public final class FreePort implements ResourceFactory<ServerSocket> {
Michael1993 marked this conversation as resolved.
Show resolved Hide resolved

public FreePort() {
// recreate default constructor to prevent compiler warning
}

@Override
public Resource<ServerSocket> create(List<String> arguments) throws Exception {
return new FreePortResource();
}

private static final class FreePortResource implements Resource<ServerSocket> {

private final ServerSocket serverSocket;

FreePortResource() throws IOException {
this.serverSocket = new ServerSocket(0);
}

@Override
public ServerSocket get() {
return serverSocket;
}

@Override
public void close() throws IOException {
this.serverSocket.close();
}

}

}
22 changes: 22 additions & 0 deletions src/main/java/org/junitpioneer/jupiter/resource/NewPort.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright 2016-2023 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v20.html
*/

package org.junitpioneer.jupiter.resource;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@New(FreePort.class)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it means that a new instance of the FreePort class is created, but I would like to double check as I know @New only as a deprecated CDI annotation (and I'm not getting any other proper search result from google 🆘). This would mean that the user always get a Socket on port zero - which is hardly what they want I guess.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again - NewPort was removed. The @New annotation is part of our resources abstract extension.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for updating.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface NewPort {
Michael1993 marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
*/
public final class TemporaryDirectory implements ResourceFactory<Path> {

public TemporaryDirectory() {
// recreate default constructor to prevent compiler warning
}

@Override
public Resource<Path> create(List<String> arguments) throws Exception {
if (arguments.size() >= 2) {
Expand Down
3 changes: 2 additions & 1 deletion src/test/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@
exports org.junitpioneer.jupiter.params;
exports org.junitpioneer.jupiter.json;
exports org.junitpioneer.jupiter.converter;
exports org.junitpioneer.jupiter.resource;

opens org.junitpioneer.vintage to org.junit.platform.commons;
opens org.junitpioneer.jupiter to org.junit.platform.commons, nl.jqno.equalsverifier;
opens org.junitpioneer.jupiter.cartesian to org.junit.platform.commons;
opens org.junitpioneer.jupiter.issue to org.junit.platform.commons;
opens org.junitpioneer.jupiter.params to org.junit.platform.commons;
opens org.junitpioneer.jupiter.resource to org.junit.platform.commons;
opens org.junitpioneer.jupiter.resource to nl.jqno.equalsverifier, org.junit.platform.commons;
opens org.junitpioneer.jupiter.json to org.junit.platform.commons, com.fasterxml.jackson.databind;
opens org.junitpioneer.jupiter.converter to org.junit.platform.commons;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2016-2022 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v20.html
*/

package org.junitpioneer.jupiter.resource;

import static org.junitpioneer.testkit.PioneerTestKit.executeTestClass;
import static org.junitpioneer.testkit.assertion.PioneerAssert.assertThat;

import java.net.ServerSocket;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junitpioneer.testkit.ExecutionResults;

@DisplayName("Free port extension")
public class FreePortExtensionTests {

@Test
@DisplayName("resolve FreePort parameter successfully")
void testFreePortParameterResolution() {
ExecutionResults results = executeTestClass(FreePortTestCase.class);
assertThat(results).hasSingleSucceededTest();
}

static class FreePortTestCase {

@Test
void testFreePortParameterResolution(@NewPort ServerSocket port) {
Assertions.assertThat(port).isNotNull();
}

}

}