Skip to content

Commit ad01d4c

Browse files
authored
add methods to generate random port within given range (#1651)
1 parent e412160 commit ad01d4c

2 files changed

Lines changed: 83 additions & 10 deletions

File tree

src/main/java/net/datafaker/providers/base/Internet.java

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@
2121
public class Internet extends AbstractProvider<BaseProviders> {
2222
private static final Pattern COLON = Pattern.compile(":");
2323
private static final List<String> HTTP_SCHEMES = List.of("http://", "https://");
24+
private static final int MIN_PORT_NUMBER = 0;
25+
private static final int MAX_PORT_NUMBER = 65535;
2426

2527
protected Internet(BaseProviders faker) {
2628
super(faker);
2729
}
2830

29-
3031
/**
3132
* A lowercase username composed of the first_name and last_name joined with a '.'. Some examples are:
3233
* <ul>
@@ -128,11 +129,11 @@ private String stripAccents(String input) {
128129
/**
129130
* Converts a name to a local part (the part before the '@') of an email
130131
* address.
131-
*
132+
*
132133
* Will use the first and last names of the provided name, ignoring middle
133134
* names, and will remove any prefixes or suffixes that are defined in the
134135
* faker's configuration.
135-
*
136+
*
136137
* @param name The name ({@link Name}) to be converted to a local part.
137138
* @return A String representing the local part of an email address.
138139
* @since 2.4.5
@@ -211,7 +212,7 @@ public String url() {
211212
* @since 2.0.0
212213
*/
213214
public String url(boolean schemeChoice, boolean portChoice, boolean pathChoice, boolean fileChoice, boolean paramsChoice, boolean anchorChoice) {
214-
String scheme = schemeChoice ? HTTP_SCHEMES.get(faker.random().nextInt(0, 1)) : "https://";
215+
String scheme = schemeChoice ? faker.options().nextElement(HTTP_SCHEMES) : "https://";
215216
String port = portChoice ? (":" + port()) : "";
216217
String path = pathChoice ? ("/" + slug(faker.lorem().words(2), "/")) : "/";
217218
String file = fileChoice ? faker.lorem().words(1).get(0) : "";
@@ -314,7 +315,32 @@ public String password(int minimumLength, int maximumLength, boolean includeUppe
314315
* @return a port number
315316
*/
316317
public int port() {
317-
return faker.random().nextInt(0, 65535);
318+
return port(MIN_PORT_NUMBER, MAX_PORT_NUMBER);
319+
}
320+
321+
/**
322+
* Returns a port number within given range
323+
*
324+
* @param range either Well-Known Ports (0-1023), Registered Ports (1024-49151) or Dynamic/Private Ports (49152-65535)
325+
* @return a port number
326+
*/
327+
public int port(PortRange range) {
328+
return port(range.from, range.to);
329+
}
330+
331+
/**
332+
* Returns a port number between {@code from} and {@code to} (inclusive)
333+
*
334+
* @param from minimum port number (must not be less than 0)
335+
* @param to maximum port number (must not be greater than 65535)
336+
* @return a port number within given range
337+
*/
338+
public int port(int from, int to) {
339+
if (from < MIN_PORT_NUMBER)
340+
throw new IllegalArgumentException("Port number %s cannot be less than %s".formatted(from, MIN_PORT_NUMBER));
341+
if (to > MAX_PORT_NUMBER)
342+
throw new IllegalArgumentException("Port number %s cannot be greater than %s".formatted(to, MAX_PORT_NUMBER));
343+
return faker.random().nextInt(from, to);
318344
}
319345

320346
/**
@@ -653,4 +679,18 @@ private static InetAddress inet6Address(String host) {
653679
throw new RuntimeException("Failed to create Inet6Address from host '%s'".formatted(host), e);
654680
}
655681
}
682+
683+
public enum PortRange {
684+
WellKnownPorts(0, 1023),
685+
RegisteredPorts(1024, 49151),
686+
DynamicPrivatePorts(49152, 65535);
687+
688+
private final int from;
689+
private final int to;
690+
691+
PortRange(int from, int to) {
692+
this.from = from;
693+
this.to = to;
694+
}
695+
}
656696
}

src/test/java/net/datafaker/providers/base/InternetTest.java

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package net.datafaker.providers.base;
22

33
import net.datafaker.Faker;
4+
import net.datafaker.providers.base.Internet.PortRange;
45
import net.datafaker.service.FakeValuesService;
5-
66
import org.apache.commons.validator.routines.EmailValidator;
77
import org.assertj.core.api.Condition;
88
import org.junit.jupiter.api.RepeatedTest;
@@ -18,8 +18,11 @@
1818
import java.util.stream.Collectors;
1919

2020
import static java.lang.Integer.parseInt;
21+
import static net.datafaker.providers.base.Internet.PortRange.RegisteredPorts;
22+
import static net.datafaker.providers.base.Internet.PortRange.WellKnownPorts;
2123
import static org.assertj.core.api.Assertions.anyOf;
2224
import static org.assertj.core.api.Assertions.assertThat;
25+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
2326
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
2427
import static org.mockito.Mockito.doReturn;
2528
import static org.mockito.Mockito.mock;
@@ -31,7 +34,7 @@ class InternetTest {
3134
public static final Pattern IPV6_HOST_ADDRESS = Pattern.compile("[0-9a-fA-F]{1,4}(:([0-9a-fA-F]{1,4})){1,7}");
3235
private final Faker faker = new Faker();
3336

34-
@RepeatedTest(100)
37+
@RepeatedTest(10)
3538
@SuppressWarnings("removal")
3639
void testUsername() {
3740
assertThat(faker.internet().username()).matches("^(\\w+)\\.(\\w+)$");
@@ -182,7 +185,7 @@ void testWebdomain() {
182185
assertThat(faker.internet().webdomain()).matches("www\\.[\\w-]+\\.\\w+");
183186
}
184187

185-
@RepeatedTest(100)
188+
@RepeatedTest(10)
186189
void testUrl() {
187190
// This test assumes that java.net.URL has better validation than we can come up with in
188191
// regex.
@@ -263,11 +266,41 @@ void testPasswordMinLengthMaxLengthIncludeUpperCaseIncludeSpecial() {
263266
assertThat(faker.internet().password(10, 25, true, true)).matches("[a-zA-Z\\d!@#$%^&*]{10,25}");
264267
}
265268

266-
@RepeatedTest(100)
269+
@RepeatedTest(10)
267270
void testPort() {
268271
assertThat(faker.internet().port()).isBetween(0, 65535);
269272
}
270273

274+
@RepeatedTest(10)
275+
void portWithinGivenBounds() {
276+
assertThat(faker.internet().port(0, 1)).isBetween(0, 1);
277+
assertThat(faker.internet().port(100, 200)).isBetween(100, 200);
278+
assertThat(faker.internet().port(1000, 1000)).isEqualTo(1000);
279+
assertThat(faker.internet().port(65535, 65535)).isEqualTo(65535);
280+
}
281+
282+
@RepeatedTest(10)
283+
void portWithinGivenRange() {
284+
assertThat(faker.internet().port(WellKnownPorts)).isBetween(0, 1023);
285+
assertThat(faker.internet().port(RegisteredPorts)).isBetween(1024, 49151);
286+
assertThat(faker.internet().port(PortRange.DynamicPrivatePorts)).isBetween(49152, 65535);
287+
}
288+
289+
@Test
290+
void portWithinGivenRange_validation() {
291+
assertThatThrownBy(() -> faker.internet().port(-1, 100))
292+
.isInstanceOf(IllegalArgumentException.class)
293+
.hasMessage("Port number -1 cannot be less than 0");
294+
295+
assertThatThrownBy(() -> faker.internet().port(100, 99))
296+
.isInstanceOf(IllegalArgumentException.class)
297+
.hasMessage("Min (100) > Max (99)");
298+
299+
assertThatThrownBy(() -> faker.internet().port(65535, 65536))
300+
.isInstanceOf(IllegalArgumentException.class)
301+
.hasMessage("Port number 65536 cannot be greater than 65535");
302+
}
303+
271304
@Test
272305
@SuppressWarnings("removal")
273306
void shouldGenerateAPasswordWithMinAndMaxLength() {
@@ -463,7 +496,7 @@ void testUuidv7() {
463496
assertThat(faker.internet().uuidv7()).matches("^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$");
464497
}
465498

466-
@RepeatedTest(100)
499+
@RepeatedTest(10)
467500
void testFarsiIDNs() {
468501
// in this case, we're just making sure Farsi doesn't blow up.
469502
// there have been issues with Farsi not being produced.

0 commit comments

Comments
 (0)