• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nats-io / java-nats-server-runner / #15

11 Nov 2023 05:13PM UTC coverage: 87.993% (+1.3%) from 86.693%
#15

push

github

web-flow
Mapped ports, better (#30)

61 of 63 new or added lines in 3 files covered. (96.83%)

2 existing lines in 1 file now uncovered.

491 of 558 relevant lines covered (87.99%)

0.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.37
/src/main/java/nats/io/NatsRunnerUtils.java
1
// Copyright 2020-2023 The NATS Authors
2
// Licensed under the Apache License, Version 2.0 (the "License");
3
// you may not use this file except in compliance with the License.
4
// You may obtain a copy of the License at:
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software
9
// distributed under the License is distributed on an "AS IS" BASIS,
10
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
// See the License for the specific language governing permissions and
12
// limitations under the License.
13

14
package nats.io;
15

16
import java.io.BufferedReader;
17
import java.io.File;
18
import java.io.IOException;
19
import java.io.InputStreamReader;
20
import java.net.ServerSocket;
21
import java.nio.file.Path;
22
import java.nio.file.Paths;
23
import java.util.ArrayList;
24
import java.util.List;
25

26
public abstract class NatsRunnerUtils {
27
    public static final String NATS_SERVER_PATH_ENV = "nats_server_path";
28
    public static final String DEFAULT_NATS_SERVER = "nats-server";
29

30
    public static final String CONFIG_FILE_OPTION_NAME = "--config";
31
    public static final String VERSION_OPTION = "--version";
32
    public static final String JETSTREAM_OPTION = "-js";
33

34
    public static final String CONF_FILE_PREFIX = "nats_java_test";
35
    public static final String CONF_FILE_EXT = ".conf";
36
    public static final String PORT_REGEX = "port: (\\d+)";
37
    public static final String PORT_MAPPED_REGEX = "port: <(\\w+)>";
38
    public static final String PORT_PROPERTY = "port: ";
39
    public static final String CONFIG_PORT_KEY = "config_port";
40
    public static final String USER_PORT_KEY = "user_port";
41
    public static final String NATS_PORT_KEY = "nats_port";
42
    public static final String NON_NATS_PORT_KEY = "non_nats_port";
43
    public static final int DEFAULT_CLUSTER_COUNT = 3;
44
    public static final String DEFAULT_CLUSTER_NAME = "cluster";
45
    public static final String DEFAULT_SERVER_NAME_PREFIX = "server";
46
    public static final String NATS = "nats";
47
    public static final String LOCALHOST = "localhost";
48

49
    public static String DEFAULT_HOST = "127.0.0.1";
1✔
50
    public static int DEFAULT_PORT_START = 4220;
1✔
51
    public static int DEFAULT_LISTEN_START = 4230;
1✔
52
    public static int DEFAULT_MONITOR_START = 4280;
1✔
53

54
    private NatsRunnerUtils() {}
55

56
    /**
57
     * Build a standard nats://localhost:port uri
58
     * @param port the port
59
     * @return the uri
60
     * @deprecated Use {@link #getNatsLocalhostUri(int)} instead.
61
     */
62
    @Deprecated
63
    public static String getURIForPort(int port) {
64
        return getUri(NATS, LOCALHOST, port);
1✔
65
    }
66

67
    /**
68
     * Build a nats://localhost:port uri
69
     * @param port the port
70
     * @return the uri
71
     */
72
    public static String getNatsLocalhostUri(int port) {
73
        return getUri(NATS, LOCALHOST, port);
1✔
74
    }
75

76
    /**
77
     * Build a nats://host:port uri
78
     * @param host the host
79
     * @param port the port
80
     * @return the uri
81
     */
82
    public static String getNatsUri(String host, int port) {
NEW
83
        return getUri(NATS, host, port);
×
84
    }
85

86
    /**
87
     * Build a schema://localhost:port uri
88
     * @param schema the schema
89
     * @param port the port
90
     * @return the uri
91
     */
92
    public static String getLocalhostUri(String schema, int port) {
NEW
93
        return getUri(schema, LOCALHOST, port);
×
94
    }
95

96
    /**
97
     * Build a schema://host:port uri
98
     * @param schema the schema
99
     * @param host the host
100
     * @param port the port
101
     * @return the uri
102
     */
103
    public static String getUri(String schema, String host, int port) {
104
        return schema + "://" + host + ":" + port;
1✔
105
    }
106

107
    /**
108
     * Set the path for the server. Will be used if {@value #NATS_SERVER_PATH_ENV} environment variable is not set.
109
     * @deprecated Use {@link NatsServerRunner#setPreferredServerPath} instead
110
     * @param serverPath the fully qualified path of the server
111
     */
112
    @Deprecated
113
    public static void setServerPath(String serverPath) {
114
        NatsServerRunner.setPreferredServerPath(serverPath);
1✔
115
    }
1✔
116

117
    /**
118
     * Clear the default path for the server.
119
     * @deprecated Use {@link NatsServerRunner#clearPreferredServerPath} instead
120
     */
121
    @Deprecated
122
    public static void clearServerPath() {
123
        NatsServerRunner.clearPreferredServerPath();
1✔
124
    }
1✔
125

126
    /**
127
     * Resolves the server executable path in this order:
128
     * <ol>
129
     * <li>Checking the {@value #NATS_SERVER_PATH_ENV} environment variable</li>
130
     * <li>Checking the value set via {@link NatsServerRunner#setPreferredServerPath} method</li>
131
     * <li>{@value #DEFAULT_NATS_SERVER}</li>
132
     * </ol>
133
     * @return the resolved path
134
     */
135
    public static String getResolvedServerPath() {
136
        String serverPath = NatsServerRunner.getPreferredServerPath();
1✔
137
        if (serverPath == null) {
1✔
138
            serverPath = System.getenv(NATS_SERVER_PATH_ENV);
1✔
139
            if (serverPath == null) {
1✔
140
                serverPath = DEFAULT_NATS_SERVER;
1✔
141
            }
142
        }
143
        return serverPath;
1✔
144
    }
145

146
    /**
147
     * Get a port number automatically allocated by the system, typically from an ephemeral port range.
148
     * @return the port number
149
     * @throws IOException if there is a problem getting a port
150
     */
151
    public static int nextPort() throws IOException {
152
        try (ServerSocket socket = new ServerSocket(0)) {
1✔
153
            while ( !socket.isBound() ) {
1✔
154
                //noinspection BusyWait
155
                Thread.sleep(50);
×
156
            }
157
            return socket.getLocalPort();
1✔
158
        } catch (InterruptedException e) {
×
159
            Thread.currentThread().interrupt();
×
160
            throw new IOException("Thread interrupted", e);
×
161
        }
162
    }
163

164
    /**
165
     * Get the version string from the nats server i.e. nats-server: v2.2.2
166
     * Using the server resolved by {@link #getResolvedServerPath}
167
     * @return the version string
168
     */
169
    public static String getNatsServerVersionString() {
170
        return getNatsServerVersionString(getResolvedServerPath());
1✔
171
    }
172

173

174
    /**
175
     * Get the version string from the nats server i.e. nats-server: v2.2.2
176
     * @param serverPath the specific server path to check
177
     * @return the version string
178
     */
179
    public static String getNatsServerVersionString(String serverPath) {
180
        ArrayList<String> cmd = new ArrayList<String>();
1✔
181

182
        // order of precedence is environment, value set statically, default
183

184
        cmd.add(serverPath);
1✔
185
        cmd.add(VERSION_OPTION);
1✔
186

187
        try {
188
            ProcessBuilder pb = new ProcessBuilder(cmd);
1✔
189
            Process process = pb.start();
1✔
190
            if (0 != process.waitFor()) {
1✔
191
                throw new IllegalStateException(String.format("Process %s failed", pb.command()));
×
192
            }
193
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
1✔
194
            ArrayList<String> lines = new ArrayList<>();
1✔
195
            String line = "";
1✔
196
            while ((line = reader.readLine())!= null) {
1✔
197
                lines.add(line);
1✔
198
            }
199

200
            if (lines.size() > 0) {
1✔
201
                return lines.get(0);
1✔
202
            }
203

204
            return null;
×
205
        }
206
        catch (Exception exp) {
×
207
            return null;
×
208
        }
209
    }
210

211
    public static List<ClusterInsert> createClusterInserts() throws IOException {
212
        return createClusterInserts(DEFAULT_CLUSTER_COUNT, DEFAULT_CLUSTER_NAME, DEFAULT_SERVER_NAME_PREFIX, false, null);
1✔
213
    }
214

215
    public static List<ClusterInsert> createClusterInserts(Path jsStoreDirBase) throws IOException {
216
        return createClusterInserts(DEFAULT_CLUSTER_COUNT, DEFAULT_CLUSTER_NAME, DEFAULT_SERVER_NAME_PREFIX, false, jsStoreDirBase);
×
217
    }
218

219
    public static List<ClusterInsert> createClusterInserts(int count) throws IOException {
220
        return createClusterInserts(count, DEFAULT_CLUSTER_NAME, DEFAULT_SERVER_NAME_PREFIX, false, null);
1✔
221
    }
222

223
    public static List<ClusterInsert> createClusterInserts(int count, Path jsStoreDirBase) throws IOException {
224
        return createClusterInserts(count, DEFAULT_CLUSTER_NAME, DEFAULT_SERVER_NAME_PREFIX, false, jsStoreDirBase);
×
225
    }
226

227
    public static List<ClusterInsert> createClusterInserts(int count, String clusterName, String serverNamePrefix) throws IOException {
228
        return createClusterInserts(createNodes(count, clusterName, serverNamePrefix, false, null));
×
229
    }
230

231
    public static List<ClusterInsert> createClusterInserts(int count, String clusterName, String serverNamePrefix, Path jsStoreDirBase) throws IOException {
232
        return createClusterInserts(createNodes(count, clusterName, serverNamePrefix, false, jsStoreDirBase));
×
233
    }
234

235
    public static List<ClusterInsert> createClusterInserts(int count, String clusterName, String serverNamePrefix, boolean monitor) throws IOException {
236
        return createClusterInserts(createNodes(count, clusterName, serverNamePrefix, monitor, null));
×
237
    }
238

239
    public static List<ClusterInsert> createClusterInserts(int count, String clusterName, String serverNamePrefix, boolean monitor, Path jsStoreDirBase) throws IOException {
240
        return createClusterInserts(createNodes(count, clusterName, serverNamePrefix, monitor, jsStoreDirBase));
1✔
241
    }
242

243
    public static void defaultHost(String defaultHost) {
244
        DEFAULT_HOST = defaultHost;
×
245
    }
×
246

247
    public static void defaultPortStart(int defaultPortStart) {
248
        DEFAULT_PORT_START = defaultPortStart;
×
249
    }
×
250

251
    public static void defaultListenStart(int defaultListenStart) {
252
        DEFAULT_LISTEN_START = defaultListenStart;
×
253
    }
×
254

255
    public static void defaultMonitorStart(int defaultMonitorStart) {
256
        DEFAULT_MONITOR_START = defaultMonitorStart;
×
257
    }
×
258

259
    public static List<ClusterNode> createNodes(int count, String clusterName, String serverNamePrefix, boolean monitor, Path jsStoreDirBase) {
260
        return createNodes(count, clusterName, serverNamePrefix, jsStoreDirBase,
1✔
261
            DEFAULT_HOST, DEFAULT_PORT_START, DEFAULT_LISTEN_START,
262
            monitor ? DEFAULT_MONITOR_START : null);
1✔
263
    }
264

265
    public static List<ClusterNode> createNodes(int count, String clusterName, String serverNamePrefix, Path jsStoreDirBase,
266
                                                String host, int portStart, int listenStart, Integer monitorStart) {
267
        List<ClusterNode> nodes = new ArrayList<>();
1✔
268
        for (int x = 0; x < count; x++) {
1✔
269
            int port = portStart + x;
1✔
270
            int listen = listenStart + x;
1✔
271
            Integer monitor = monitorStart == null ? null : monitorStart + x;
1✔
272
            Path jsStoreDir = jsStoreDirBase == null ? null : Paths.get(jsStoreDirBase.toString(), "" + port);
1✔
273
            nodes.add( new ClusterNode(clusterName, serverNamePrefix + x, host, port, listen, monitor, jsStoreDir));
1✔
274
        }
275
        return nodes;
1✔
276
    }
277

278
    public static List<ClusterInsert> createClusterInserts(List<ClusterNode> nodes) {
279
        List<ClusterInsert> inserts = new ArrayList<>();
1✔
280
        for (ClusterNode node : nodes) {
1✔
281
            List<String> lines = new ArrayList<>();
1✔
282
            lines.add("port:" + node.port);
1✔
283
            if (node.monitor != null) {
1✔
284
                lines.add("http:" + node.monitor);
×
285
            }
286
            if (node.jsStoreDir != null) {
1✔
287
                String dir = node.jsStoreDir.toString();
×
288
                if (File.separatorChar == '\\') {
×
289
                    dir = dir.replace("\\", "\\\\").replace("/", "\\\\");
×
290
                }
291
                else {
292
                    dir = dir.replace("\\", "/");
×
293
                }
294
                lines.add("jetstream {");
×
295
                lines.add("    store_dir=" + dir);
×
296
                lines.add("}");
×
297
            }
298
            lines.add("server_name=" + node.serverName);
1✔
299
            lines.add("cluster {");
1✔
300
            lines.add("  name: " + node.clusterName);
1✔
301
            lines.add("  listen: " + node.host + ":" + node.listen);
1✔
302
            lines.add("  routes: [");
1✔
303
            for (ClusterNode routeNode : nodes) {
1✔
304
                if (!routeNode.serverName.equals(node.serverName)) {
1✔
305
                    lines.add("    nats-route://" + node.host + ":" + routeNode.listen);
1✔
306
                }
307
            }
1✔
308
            lines.add("  ]");
1✔
309
            lines.add("}");
1✔
310
            inserts.add(new ClusterInsert(node, lines.toArray(new String[0])));
1✔
311
        }
1✔
312
        return inserts;
1✔
313

314
    }
315
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc