Skip to content

Commit 6acb7d0

Browse files
authored
fix MercurialRepositoryTest.testBuildTagListOneMore failure with Mercurial 7.1.1 on macOS (#4850)
this avoids interactive mode and errors due to no user being set fixes #4849
1 parent fe7a26c commit 6acb7d0

File tree

3 files changed

+108
-42
lines changed

3 files changed

+108
-42
lines changed

opengrok-indexer/src/main/java/org/opengrok/indexer/util/Executor.java

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.io.Reader;
3434
import java.lang.Thread.UncaughtExceptionHandler;
3535
import java.util.Arrays;
36+
import java.util.HashMap;
3637
import java.util.List;
3738
import java.util.Map;
3839
import java.util.Optional;
@@ -67,6 +68,7 @@ public class Executor {
6768
private byte[] stdout;
6869
private byte[] stderr;
6970
private int timeout; // in milliseconds, 0 means no timeout
71+
private final Map<String, String> environ;
7072

7173
/**
7274
* Create a new instance of the Executor.
@@ -88,47 +90,65 @@ public Executor(List<String> cmdList) {
8890
* Create a new instance of the Executor with default command timeout value.
8991
* The timeout value will be based on the running context (indexer or web application).
9092
* @param cmdList A list containing the command to execute
91-
* @param workingDirectory The directory the process should have as the
92-
* working directory
93+
* @param workingDirectory The directory the process should have as the working directory
9394
*/
94-
public Executor(List<String> cmdList, File workingDirectory) {
95-
RuntimeEnvironment env = RuntimeEnvironment.getInstance();
96-
int timeoutSec = env.isIndexer() ? env.getIndexerCommandTimeout() : env.getInteractiveCommandTimeout();
97-
98-
this.cmdList = cmdList;
99-
this.workingDirectory = workingDirectory;
100-
this.timeout = timeoutSec * 1000;
95+
public Executor(List<String> cmdList, @Nullable File workingDirectory) {
96+
this(cmdList, workingDirectory, new HashMap<>());
10197
}
10298

10399
/**
104100
* Create a new instance of the Executor with specific timeout value.
105101
* @param cmdList A list containing the command to execute
106-
* @param workingDirectory The directory the process should have as the
107-
* working directory
102+
* @param workingDirectory The directory the process should have as the working directory
108103
* @param timeout If the command runs longer than the timeout (seconds),
109104
* it will be terminated. If the value is 0, no timer
110105
* will be set up.
111106
*/
112-
public Executor(List<String> cmdList, File workingDirectory, int timeout) {
107+
public Executor(List<String> cmdList, @Nullable File workingDirectory, int timeout) {
108+
this(cmdList, workingDirectory, new HashMap<>());
109+
110+
this.timeout = timeout * 1000;
111+
}
112+
113+
/**
114+
* Create a new instance of the Executor with default command timeout value and environment.
115+
* The timeout value will be based on the running context (indexer or web application).
116+
* @param cmdList A list containing the command to execute
117+
* @param workingDirectory The directory the process should have as the working directory
118+
* @param environ map of environment variables to be added/overridden
119+
*/
120+
public Executor(List<String> cmdList, @Nullable File workingDirectory, Map<String, String> environ) {
113121
this.cmdList = cmdList;
114122
this.workingDirectory = workingDirectory;
115-
this.timeout = timeout * 1000;
123+
this.environ = environ;
124+
125+
setDefaultTimeout();
116126
}
117127

118128
/**
119129
* Create a new instance of the Executor with or without timeout.
120130
* @param cmdList A list containing the command to execute
121-
* @param workingDirectory The directory the process should have as the
122-
* working directory
131+
* @param workingDirectory The directory the process should have as the working directory
123132
* @param useTimeout terminate the process after default timeout or not
124133
*/
125-
public Executor(List<String> cmdList, File workingDirectory, boolean useTimeout) {
134+
public Executor(List<String> cmdList, @Nullable File workingDirectory, boolean useTimeout) {
126135
this(cmdList, workingDirectory);
127136
if (!useTimeout) {
128137
this.timeout = 0;
129138
}
130139
}
131140

141+
private void setDefaultTimeout() {
142+
RuntimeEnvironment env = RuntimeEnvironment.getInstance();
143+
int timeoutSec = env.isIndexer() ? env.getIndexerCommandTimeout() : env.getInteractiveCommandTimeout();
144+
145+
this.timeout = timeoutSec * 1000;
146+
}
147+
148+
int getTimeout() {
149+
return timeout / 1000;
150+
}
151+
132152
/**
133153
* Execute the command and collect the output. All exceptions will be
134154
* logged.
@@ -180,6 +200,8 @@ public int exec(final boolean reportExceptions, StreamHandler handler) {
180200
.map(File::toString)
181201
.orElseGet(() -> System.getProperty("user.dir"));
182202

203+
processBuilder.environment().putAll(environ);
204+
183205
String envStr = "";
184206
if (LOGGER.isLoggable(Level.FINER)) {
185207
Map<String, String> envMap = processBuilder.environment();
@@ -222,7 +244,7 @@ public int exec(final boolean reportExceptions, StreamHandler handler) {
222244
@Override public void run() {
223245
LOGGER.log(Level.WARNING,
224246
String.format("Terminating process of command [%s] in directory '%s' " +
225-
"due to timeout %d seconds", cmd_str, dir_str, timeout / 1000));
247+
"due to timeout %d seconds", cmd_str, dir_str, getTimeout()));
226248
proc.destroy();
227249
}
228250
}, timeout);

opengrok-indexer/src/test/java/org/opengrok/indexer/history/MercurialRepositoryTest.java

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@
5050
import java.util.ArrayList;
5151
import java.util.Arrays;
5252
import java.util.Collections;
53+
import java.util.HashMap;
5354
import java.util.List;
55+
import java.util.Map;
5456
import java.util.Objects;
5557
import java.util.Set;
5658
import java.util.TreeSet;
@@ -187,15 +189,18 @@ void testGetHistoryPartial() throws Exception {
187189
* @param args {@code hg} command arguments
188190
*/
189191
public static void runHgCommand(File reposRoot, String... args) {
190-
List<String> cmdargs = new ArrayList<>();
192+
List<String> commandWithArgs = new ArrayList<>();
191193
MercurialRepository repo = new MercurialRepository();
192194

193-
cmdargs.add(repo.getRepoCommand());
194-
cmdargs.addAll(Arrays.asList(args));
195+
commandWithArgs.add(repo.getRepoCommand());
196+
commandWithArgs.addAll(Arrays.asList(args));
195197

196-
Executor exec = new Executor(cmdargs, reposRoot);
198+
final Map<String, String> env = new HashMap<>();
199+
// Set the user to record commits in order to prevent hg commands entering interactive mode.
200+
env.put("HGUSER", "Snufkin <[email protected]>");
201+
Executor exec = new Executor(commandWithArgs, reposRoot, env);
197202
int exitCode = exec.exec();
198-
assertEquals(0, exitCode, "hg command '" + cmdargs + "' failed."
203+
assertEquals(0, exitCode, "command '" + commandWithArgs + "' failed."
199204
+ "\nexit code: " + exitCode
200205
+ "\nstdout:\n" + exec.getOutputString()
201206
+ "\nstderr:\n" + exec.getErrorString());
@@ -299,10 +304,7 @@ void testGetHistoryGetRenamed() throws Exception {
299304
String exp_str = "This is totally plaintext file.\n";
300305
byte[] buffer = new byte[1024];
301306

302-
/*
303-
* In our test repository the file was renamed twice since
304-
* revision 3.
305-
*/
307+
// In our test repository the file was renamed twice since revision 3.
306308
InputStream input = mr.getHistoryGet(repositoryRoot.getCanonicalPath(),
307309
"novel.txt", "3");
308310
assertNotNull(input);
@@ -350,8 +352,7 @@ void testGetHistorySinceTillNullRev() throws Exception {
350352
assertNotNull(history);
351353
assertNotNull(history.getHistoryEntries());
352354
assertEquals(6, history.getHistoryEntries().size());
353-
List<String> revisions = history.getHistoryEntries().stream().map(HistoryEntry::getRevision).
354-
collect(Collectors.toList());
355+
List<String> revisions = history.getHistoryEntries().stream().map(HistoryEntry::getRevision).toList();
355356
assertEquals(List.of(Arrays.copyOfRange(REVISIONS, 4, REVISIONS.length)), revisions);
356357
}
357358

@@ -362,8 +363,7 @@ void testGetHistorySinceTillRevNull() throws Exception {
362363
assertNotNull(history);
363364
assertNotNull(history.getHistoryEntries());
364365
assertEquals(3, history.getHistoryEntries().size());
365-
List<String> revisions = history.getHistoryEntries().stream().map(HistoryEntry::getRevision).
366-
collect(Collectors.toList());
366+
List<String> revisions = history.getHistoryEntries().stream().map(HistoryEntry::getRevision).toList();
367367
assertEquals(List.of(Arrays.copyOfRange(REVISIONS, 0, 3)), revisions);
368368
}
369369

@@ -374,8 +374,7 @@ void testGetHistorySinceTillRevRev() throws Exception {
374374
assertNotNull(history);
375375
assertNotNull(history.getHistoryEntries());
376376
assertEquals(5, history.getHistoryEntries().size());
377-
List<String> revisions = history.getHistoryEntries().stream().map(HistoryEntry::getRevision).
378-
collect(Collectors.toList());
377+
List<String> revisions = history.getHistoryEntries().stream().map(HistoryEntry::getRevision).toList();
379378
assertEquals(List.of(Arrays.copyOfRange(REVISIONS, 2, 7)), revisions);
380379
}
381380

@@ -389,8 +388,7 @@ void testGetHistoryRenamedFileTillRev() throws Exception {
389388
assertNotNull(history);
390389
assertNotNull(history.getHistoryEntries());
391390
assertEquals(5, history.getHistoryEntries().size());
392-
List<String> revisions = history.getHistoryEntries().stream().map(HistoryEntry::getRevision).
393-
collect(Collectors.toList());
391+
List<String> revisions = history.getHistoryEntries().stream().map(HistoryEntry::getRevision).toList();
394392
assertEquals(List.of(Arrays.copyOfRange(REVISIONS, 2, 7)), revisions);
395393
}
396394

@@ -443,8 +441,10 @@ void testAnnotationNegative() throws Exception {
443441
}
444442

445443
private static Stream<Triple<String, List<String>, List<String>>> provideParametersForPositiveAnnotationTest() {
446-
return Stream.of(Triple.of("8:6a8c423f5624", List.of("7", "8"), List.of("8:6a8c423f5624", "7:db1394c05268")),
447-
Triple.of("7:db1394c05268", List.of("7"), List.of("7:db1394c05268")));
444+
return Stream.of(
445+
Triple.of("8:6a8c423f5624", List.of("7", "8"), List.of("8:6a8c423f5624", "7:db1394c05268")),
446+
Triple.of("7:db1394c05268", List.of("7"), List.of("7:db1394c05268"))
447+
);
448448
}
449449

450450
@ParameterizedTest
@@ -579,7 +579,7 @@ void testBuildTagListOneMore() throws Exception {
579579
assertNotNull(tags);
580580
assertEquals(3, tags.size());
581581
expectedTags = List.of("start_of_novel", newTagName, branchTagName);
582-
assertEquals(expectedTags, tags.stream().map(TagEntry::getTags).collect(Collectors.toList()));
582+
assertEquals(expectedTags, tags.stream().map(TagEntry::getTags).toList());
583583

584584
// cleanup
585585
IOUtils.removeRecursive(repositoryRootPath);

opengrok-indexer/src/test/java/org/opengrok/indexer/util/ExecutorTest.java

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919

2020
/*
21-
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
21+
* Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
2222
* Portions Copyright (c) 2019, Chris Fraire <[email protected]>.
2323
*/
2424
package org.opengrok.indexer.util;
@@ -30,9 +30,12 @@
3030
import java.io.File;
3131
import java.io.IOException;
3232
import java.io.InputStream;
33+
import java.io.Reader;
3334
import java.util.ArrayList;
3435
import java.util.Arrays;
36+
import java.util.HashMap;
3537
import java.util.List;
38+
import java.util.Map;
3639

3740
import static org.junit.jupiter.api.Assertions.assertEquals;
3841
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -45,6 +48,13 @@
4548
*/
4649
class ExecutorTest {
4750

51+
@Test
52+
void testConstructorWithTimeout() {
53+
int timeout = 42;
54+
Executor executor = new Executor(List.of("foo"), null, timeout);
55+
assertEquals(timeout, executor.getTimeout());
56+
}
57+
4858
@Test
4959
void testString() {
5060
List<String> cmdList = new ArrayList<>();
@@ -64,10 +74,14 @@ void testReader() throws IOException {
6474
cmdList.add("testing org.opengrok.indexer.util.Executor");
6575
Executor instance = new Executor(cmdList);
6676
assertEquals(0, instance.exec());
67-
BufferedReader in = new BufferedReader(instance.getOutputReader());
77+
Reader outputReader = instance.getOutputReader();
78+
assertNotNull(outputReader);
79+
BufferedReader in = new BufferedReader(outputReader);
6880
assertEquals("testing org.opengrok.indexer.util.Executor", in.readLine());
6981
in.close();
70-
in = new BufferedReader(instance.getErrorReader());
82+
Reader errorReader = instance.getErrorReader();
83+
assertNotNull(errorReader);
84+
in = new BufferedReader(errorReader);
7185
assertNull(in.readLine());
7286
in.close();
7387
}
@@ -81,14 +95,44 @@ void testStream() throws IOException {
8195
assertEquals(0, instance.exec());
8296
assertNotNull(instance.getOutputStream());
8397
assertNotNull(instance.getErrorStream());
84-
BufferedReader in = new BufferedReader(instance.getOutputReader());
98+
Reader outputReader = instance.getOutputReader();
99+
assertNotNull(outputReader);
100+
BufferedReader in = new BufferedReader(outputReader);
85101
assertEquals("testing org.opengrok.indexer.util.Executor", in.readLine());
86102
in.close();
87-
in = new BufferedReader(instance.getErrorReader());
103+
Reader errorReader = instance.getErrorReader();
104+
assertNotNull(errorReader);
105+
in = new BufferedReader(errorReader);
88106
assertNull(in.readLine());
89107
in.close();
90108
}
91109

110+
/**
111+
* Test setting environment variable. Assumes the {@code env} program exists
112+
* and reports list of environment variables along with their values.
113+
*/
114+
@Test
115+
void testEnv() throws IOException {
116+
List<String> cmdList = List.of("env");
117+
final Map<String, String> env = new HashMap<>();
118+
env.put("foo", "bar");
119+
Executor instance = new Executor(cmdList, null, env);
120+
assertEquals(0, instance.exec());
121+
Reader outputReader = instance.getOutputReader();
122+
assertNotNull(outputReader);
123+
BufferedReader in = new BufferedReader(outputReader);
124+
String line;
125+
boolean found = false;
126+
while ((line = in.readLine()) != null) {
127+
if (line.equals("foo=bar")) {
128+
found = true;
129+
break;
130+
}
131+
}
132+
assertTrue(found);
133+
in.close();
134+
}
135+
92136
/**
93137
* {@link Executor.StreamHandler} implementation that always fails with {@link IOException}.
94138
*/

0 commit comments

Comments
 (0)