Skip to content

Commit 8f3cd11

Browse files
authored
Merge pull request #816 from rabbitmq/rabbitmq-perf-test-813
Add test for queue sequence to / from specified via JSON
2 parents eff8ad5 + 702950f commit 8f3cd11

File tree

7 files changed

+199
-21
lines changed

7 files changed

+199
-21
lines changed

src/main/java/com/rabbitmq/perf/MulticastParams.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,18 @@ Map<String, Object> getQueueArguments() {
371371
return queueArguments;
372372
}
373373

374+
String getQueuePattern() {
375+
return queuePattern;
376+
}
377+
378+
int getQueueSequenceFrom() {
379+
return queueSequenceFrom;
380+
}
381+
382+
int getQueueSequenceTo() {
383+
return queueSequenceTo;
384+
}
385+
374386
public void setBodyContentType(String bodyContentType) {
375387
this.bodyContentType = bodyContentType;
376388
}

src/main/java/com/rabbitmq/perf/PerfTest.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1591,6 +1591,14 @@ public PerfTestOptions setConsoleErr(PrintStream consoleErr) {
15911591
this.consoleErr = consoleErr;
15921592
return this;
15931593
}
1594+
1595+
SystemExiter systemExiter() {
1596+
return systemExiter;
1597+
}
1598+
1599+
PrintStream consoleOut() {
1600+
return consoleOut;
1601+
}
15941602
}
15951603

15961604
/**
@@ -1607,7 +1615,7 @@ public interface SystemExiter {
16071615
void exit(int status);
16081616
}
16091617

1610-
private static class JvmSystemExiter implements SystemExiter {
1618+
static class JvmSystemExiter implements SystemExiter {
16111619

16121620
@Override
16131621
public void exit(int status) {

src/main/java/com/rabbitmq/perf/PerfTestMulti.java

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.io.FileWriter;
2424
import java.io.IOException;
2525
import java.io.InputStreamReader;
26+
import java.io.PrintStream;
2627
import java.io.PrintWriter;
2728
import java.io.Reader;
2829
import java.util.HashMap;
@@ -39,40 +40,50 @@ public class PerfTestMulti {
3940

4041
private static final Map<String, Object> results = new HashMap<>();
4142

42-
@SuppressWarnings("unchecked")
43-
public static void main(String[] args) throws Exception {
43+
public static void main(String[] args, PerfTest.PerfTestOptions perfTestOptions)
44+
throws Exception {
45+
PrintStream consoleOut = perfTestOptions.consoleOut();
46+
PerfTest.SystemExiter systemExiter = perfTestOptions.systemExiter();
4447
if (args.length != 2) {
45-
System.out.println("Usage: PerfTestMulti input-json-file output-json-file");
46-
System.exit(1);
48+
consoleOut.println("Usage: PerfTestMulti input-json-file output-json-file");
49+
systemExiter.exit(1);
4750
}
48-
Log.configureLog();
4951
String inJSON = args[0];
5052
String outJSON = args[1];
5153

5254
String json = null;
5355
try {
5456
json = readFile(inJSON);
5557
} catch (FileNotFoundException e) {
56-
System.out.println("Input json file " + inJSON + " could not be found");
57-
System.exit(1);
58+
consoleOut.println("Input json file " + inJSON + " could not be found");
59+
systemExiter.exit(1);
5860
}
59-
Scenario[] scenarios = scenarios(json, status -> System.exit(status));
61+
Scenario[] scenarios = scenarios(json, systemExiter, consoleOut);
6062
try {
61-
runStaticBrokerTests(scenarios);
63+
runStaticBrokerTests(scenarios, consoleOut);
6264
writeJSON(outJSON);
63-
System.exit(0);
65+
systemExiter.exit(0);
6466
} catch (Exception e) {
6567
LOGGER.error("Error during test execution", e);
66-
System.exit(1);
68+
systemExiter.exit(1);
6769
}
6870
}
6971

7072
@SuppressWarnings("unchecked")
71-
static Scenario[] scenarios(String json, PerfTest.SystemExiter systemExiter) {
73+
public static void main(String[] args) throws Exception {
74+
Log.configureLog();
75+
PerfTest.PerfTestOptions perfTestOptions = new PerfTest.PerfTestOptions();
76+
main(
77+
args,
78+
perfTestOptions.setSystemExiter(new PerfTest.JvmSystemExiter()).setConsoleOut(System.out));
79+
}
80+
81+
@SuppressWarnings("unchecked")
82+
static Scenario[] scenarios(String json, PerfTest.SystemExiter systemExiter, PrintStream out) {
7283
Gson gson = new Gson();
7384
List<Map> scenariosJSON = gson.fromJson(json, List.class);
7485
if (scenariosJSON == null) {
75-
System.out.println("Input json file could not be parsed");
86+
out.println("Input json file could not be parsed");
7687
systemExiter.exit(1);
7788
}
7889
Scenario[] scenarios = new Scenario[scenariosJSON.size()];
@@ -109,15 +120,15 @@ static String toJson(Object object) {
109120
return gson.toJson(object);
110121
}
111122

112-
private static void runStaticBrokerTests(Scenario[] scenarios) throws Exception {
113-
runTests(scenarios);
123+
private static void runStaticBrokerTests(Scenario[] scenarios, PrintStream out) throws Exception {
124+
runTests(scenarios, out);
114125
}
115126

116-
private static void runTests(Scenario[] scenarios) throws Exception {
127+
private static void runTests(Scenario[] scenarios, PrintStream out) throws Exception {
117128
for (Scenario scenario : scenarios) {
118-
System.out.print("Running scenario '" + scenario.getName() + "' ");
129+
out.print("Running scenario '" + scenario.getName() + "' ");
119130
scenario.run();
120-
System.out.println();
131+
out.println();
121132
results.put(scenario.getName(), scenario.getStats().results());
122133
}
123134
}

src/test/java/com/rabbitmq/perf/PerfTestMultiTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public void scenarios() {
3737
+ " 'params': [{'time-limit': 30}], "
3838
+ " 'variables': [{'name':'min-msg-size', 'values': [0, 100, 200, 500, 1000, 2000, 5000]}]}"
3939
+ "]";
40-
Scenario[] scenarios = PerfTestMulti.scenarios(json, status -> {});
40+
Scenario[] scenarios = PerfTestMulti.scenarios(json, status -> {}, System.out);
4141
assertThat(scenarios).hasSize(3);
4242
assertThat(scenarios[0]).isInstanceOf(SimpleScenario.class);
4343
SimpleScenario simpleScenario = (SimpleScenario) scenarios[0];

src/test/java/com/rabbitmq/perf/ScenarioFactoryTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ public void paramsFromJSON() {
3333
+ " 'rate': 10, 'exclusive': true, "
3434
+ " 'confirm': 10, "
3535
+ " 'queue-arguments': 'x-max-length=10,x-dead-letter-exchange=some.exchange.name,x-single-active-consumer=true', "
36+
+ " 'queue-pattern': 'gh-813-%d', "
37+
+ " 'queue-sequence-from': 0, "
38+
+ " 'queue-sequence-to': 3, "
3639
+ " 'flags': 'persistent,mandatory', "
3740
+ " 'auto-delete': 'false', "
3841
+ " 'body': ['file1.json','file2.json'], 'body-content-type' : 'application/json'}]}]";
@@ -54,6 +57,9 @@ public void paramsFromJSON() {
5457
.containsEntry("x-max-length", 10L)
5558
.containsEntry("x-dead-letter-exchange", "some.exchange.name")
5659
.containsEntry("x-single-active-consumer", true);
60+
assertThat(params.getQueuePattern()).isEqualTo("gh-813-%d");
61+
assertThat(params.getQueueSequenceFrom()).isEqualTo(0);
62+
assertThat(params.getQueueSequenceTo()).isEqualTo(3);
5763
assertThat(params.getFlags()).hasSize(2).containsExactly("persistent", "mandatory");
5864
assertThat(params.isAutoDelete()).isFalse();
5965
}

src/test/java/com/rabbitmq/perf/TestUtils.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,18 @@
1515
1616
package com.rabbitmq.perf;
1717

18+
import static java.lang.String.format;
1819
import static org.junit.jupiter.api.Assertions.fail;
1920

21+
import com.rabbitmq.client.ConnectionFactory;
2022
import java.io.ByteArrayInputStream;
2123
import java.io.IOException;
2224
import java.lang.annotation.*;
25+
import java.lang.reflect.Method;
2326
import java.net.ServerSocket;
2427
import java.nio.charset.StandardCharsets;
2528
import java.util.Locale;
29+
import java.util.UUID;
2630
import java.util.concurrent.ThreadFactory;
2731
import java.util.function.BooleanSupplier;
2832
import java.util.function.Supplier;
@@ -35,7 +39,13 @@
3539
import org.junit.jupiter.api.extension.ExtensionContext;
3640

3741
/** */
38-
public abstract class TestUtils {
42+
public final class TestUtils {
43+
44+
private TestUtils() {}
45+
46+
public static ConnectionFactory connectionFactory() {
47+
return new ConnectionFactory();
48+
}
3949

4050
static int randomNetworkPort() throws IOException {
4151
ServerSocket socket = new ServerSocket();
@@ -83,6 +93,17 @@ public static String name(TestInfo info) {
8393
return info.getTestMethod().get().getName() + "-" + info.getDisplayName() + "-";
8494
}
8595

96+
public static String randomName(TestInfo info) {
97+
return name(info.getTestClass().get(), info.getTestMethod().get());
98+
}
99+
100+
private static String name(Class<?> testClass, Method testMethod) {
101+
String uuid = UUID.randomUUID().toString();
102+
return format(
103+
"%s_%s%s",
104+
testClass.getSimpleName(), testMethod.getName(), uuid.substring(uuid.length() / 2));
105+
}
106+
86107
static Condition<String> validXml() {
87108
return new Condition<>(
88109
xml -> {
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Copyright (c) 2025 Broadcom. All Rights Reserved.
2+
// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
3+
//
4+
// This software, the RabbitMQ Java client library, is triple-licensed under the
5+
// Mozilla Public License 2.0 ("MPL"), the GNU General Public License version 2
6+
// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see
7+
// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL,
8+
// please see LICENSE-APACHE2.
9+
//
10+
// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND,
11+
// either express or implied. See the LICENSE file for specific language governing
12+
// rights and limitations of this software.
13+
//
14+
// If you have any questions regarding licensing, please contact us at
15+
16+
package com.rabbitmq.perf.it;
17+
18+
import static java.nio.charset.StandardCharsets.UTF_8;
19+
import static org.assertj.core.api.Assertions.assertThat;
20+
import static org.assertj.core.api.Assertions.fail;
21+
22+
import com.google.gson.Gson;
23+
import com.google.gson.reflect.TypeToken;
24+
import com.rabbitmq.client.Channel;
25+
import com.rabbitmq.client.Connection;
26+
import com.rabbitmq.perf.PerfTest;
27+
import com.rabbitmq.perf.PerfTestMulti;
28+
import com.rabbitmq.perf.TestUtils;
29+
import java.io.ByteArrayOutputStream;
30+
import java.io.IOException;
31+
import java.io.PrintStream;
32+
import java.lang.reflect.Type;
33+
import java.nio.charset.StandardCharsets;
34+
import java.nio.file.Files;
35+
import java.nio.file.Path;
36+
import java.nio.file.StandardOpenOption;
37+
import java.util.List;
38+
import java.util.Map;
39+
import org.junit.jupiter.api.BeforeEach;
40+
import org.junit.jupiter.api.Test;
41+
import org.junit.jupiter.api.TestInfo;
42+
import org.junit.jupiter.api.io.TempDir;
43+
44+
public class PerfTestMultiIT {
45+
46+
private static final Gson GSON = new Gson();
47+
48+
Path specFile, resultFile;
49+
50+
@BeforeEach
51+
void setUp(@TempDir Path directory) throws Exception {
52+
specFile = directory.resolve("spec.json");
53+
resultFile = directory.resolve("result.json");
54+
}
55+
56+
@Test
57+
void simpleScenario() throws Exception {
58+
String spec =
59+
"[{'name': 'simple', 'type': 'simple', 'params':\n"
60+
+ "[{'time-limit': 2, 'producer-count': 1, 'consumer-count': 1}]}]";
61+
writeSpec(spec);
62+
run();
63+
assertReceiveRatePositive();
64+
}
65+
66+
@Test
67+
void queuePattern(TestInfo info) throws Exception {
68+
String prefix = TestUtils.randomName(info);
69+
int queueCount = 3;
70+
String spec =
71+
String.format(
72+
"[{'name': 'simple', 'type': 'simple', 'params':\n"
73+
+ "[{"
74+
+ "'time-limit': 2, 'producer-count': 6, 'consumer-count': 3,"
75+
+ "'flags': 'persistent', 'auto-delete': false,"
76+
+ "'queue-pattern': '%s', 'queue-sequence-from': 1, 'queue-sequence-to': %d"
77+
+ "}]}]",
78+
prefix + "-%d", queueCount);
79+
writeSpec(spec);
80+
run();
81+
assertReceiveRatePositive();
82+
try (Connection c = TestUtils.connectionFactory().newConnection()) {
83+
Channel ch = c.createChannel();
84+
for (int i = 1; i <= queueCount; i++) {
85+
String queueName = String.format("%s-%d", prefix, i);
86+
ch.queueDeclarePassive(queueName);
87+
ch.queueDelete(queueName);
88+
}
89+
}
90+
}
91+
92+
@SuppressWarnings("unchecked")
93+
private void assertReceiveRatePositive() throws IOException {
94+
String result = new String(Files.readAllBytes(resultFile), StandardCharsets.UTF_8);
95+
Type type = new TypeToken<Map<String, Object>>() {}.getType();
96+
Map<String, Object> results = GSON.fromJson(result, type);
97+
Map<String, Object> scenario = (Map<String, Object>) results.values().iterator().next();
98+
List<Map<String, Object>> samples = (List<Map<String, Object>>) scenario.get("samples");
99+
assertThat(samples).isNotEmpty();
100+
for (Map<String, Object> sample : samples) {
101+
if (((Number) sample.get("recv-msg-rate")).intValue() > 0) {
102+
return;
103+
}
104+
}
105+
fail("The receive rate is not positive");
106+
}
107+
108+
private void run() throws Exception {
109+
String[] args = {specFile.toAbsolutePath().toString(), resultFile.toAbsolutePath().toString()};
110+
PerfTest.PerfTestOptions options = new PerfTest.PerfTestOptions();
111+
options
112+
.setSystemExiter(status -> {})
113+
.setConsoleOut(new PrintStream(new ByteArrayOutputStream()));
114+
PerfTestMulti.main(args, options);
115+
}
116+
117+
private void writeSpec(String spec) throws IOException {
118+
Files.write(specFile, spec.getBytes(UTF_8), StandardOpenOption.CREATE_NEW);
119+
}
120+
}

0 commit comments

Comments
 (0)