3 * Copyright (C) 2009-2017 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.application.process;
23 import java.io.FileReader;
24 import java.io.IOException;
25 import java.util.HashMap;
26 import java.util.List;
28 import java.util.Properties;
29 import org.junit.Rule;
30 import org.junit.Test;
31 import org.junit.rules.ExpectedException;
32 import org.junit.rules.TemporaryFolder;
33 import org.sonar.application.process.JavaCommand;
34 import org.sonar.application.process.JavaProcessLauncher;
35 import org.sonar.application.process.JavaProcessLauncherImpl;
36 import org.sonar.application.process.ProcessMonitor;
37 import org.sonar.process.AllProcessesCommands;
38 import org.sonar.process.ProcessId;
40 import static org.assertj.core.api.Java6Assertions.assertThat;
41 import static org.assertj.core.data.MapEntry.entry;
42 import static org.mockito.Mockito.RETURNS_MOCKS;
43 import static org.mockito.Mockito.mock;
44 import static org.mockito.Mockito.when;
46 public class JavaProcessLauncherImplTest {
49 public TemporaryFolder temp = new TemporaryFolder();
51 public ExpectedException expectedException = ExpectedException.none();
53 private AllProcessesCommands commands = mock(AllProcessesCommands.class, RETURNS_MOCKS);
56 public void launch_forks_a_new_process() throws Exception {
57 File tempDir = temp.newFolder();
58 TestProcessBuilder processBuilder = new TestProcessBuilder();
59 JavaProcessLauncher underTest = new JavaProcessLauncherImpl(tempDir, commands, () -> processBuilder);
60 JavaCommand command = new JavaCommand(ProcessId.ELASTICSEARCH);
61 command.addClasspath("lib/*.class");
62 command.addClasspath("lib/*.jar");
63 command.setArgument("foo", "bar");
64 command.setClassName("org.sonarqube.Main");
65 command.setEnvVariable("VAR1", "valueOfVar1");
66 command.setWorkDir(temp.newFolder());
68 ProcessMonitor monitor = underTest.launch(command);
70 assertThat(monitor).isNotNull();
71 assertThat(processBuilder.started).isTrue();
72 assertThat(processBuilder.commands.get(0)).endsWith("java");
73 assertThat(processBuilder.commands).containsSequence(
74 "-Djava.io.tmpdir=" + tempDir.getAbsolutePath(),
76 "lib/*.class" + System.getProperty("path.separator") + "lib/*.jar",
77 "org.sonarqube.Main");
78 assertThat(processBuilder.dir).isEqualTo(command.getWorkDir());
79 assertThat(processBuilder.redirectErrorStream).isTrue();
80 assertThat(processBuilder.environment)
81 .contains(entry("VAR1", "valueOfVar1"))
82 .containsAllEntriesOf(command.getEnvVariables());
86 public void properties_are_passed_to_command_via_a_temporary_properties_file() throws Exception {
87 File tempDir = temp.newFolder();
88 TestProcessBuilder processBuilder = new TestProcessBuilder();
89 JavaProcessLauncher underTest = new JavaProcessLauncherImpl(tempDir, commands, () -> processBuilder);
90 JavaCommand command = new JavaCommand(ProcessId.ELASTICSEARCH);
91 command.setArgument("foo", "bar");
92 command.setArgument("baz", "woo");
94 underTest.launch(command);
96 String propsFilePath = processBuilder.commands.get(processBuilder.commands.size() - 1);
97 File file = new File(propsFilePath);
98 assertThat(file).exists().isFile();
99 try (FileReader reader = new FileReader(file)) {
100 Properties props = new Properties();
102 assertThat(props).containsOnly(
105 entry("process.terminationTimeout", "60000"),
106 entry("process.key", ProcessId.ELASTICSEARCH.getKey()),
107 entry("process.index", String.valueOf(ProcessId.ELASTICSEARCH.getIpcIndex())),
108 entry("process.sharedDir", tempDir.getAbsolutePath()));
113 public void throw_ISE_if_command_fails() throws IOException {
114 File tempDir = temp.newFolder();
115 JavaProcessLauncher.SystemProcessBuilder processBuilder = mock(JavaProcessLauncher.SystemProcessBuilder.class, RETURNS_MOCKS);
116 when(processBuilder.start()).thenThrow(new IOException("error"));
117 JavaProcessLauncher underTest = new JavaProcessLauncherImpl(tempDir, commands, () -> processBuilder);
119 expectedException.expect(IllegalStateException.class);
120 expectedException.expectMessage("Fail to launch process [es]");
122 underTest.launch(new JavaCommand(ProcessId.ELASTICSEARCH));
125 private static class TestProcessBuilder extends JavaProcessLauncher.SystemProcessBuilder {
126 private List<String> commands = null;
127 private File dir = null;
128 private Boolean redirectErrorStream = null;
129 private final Map<String, String> environment = new HashMap<>();
130 private boolean started = false;
133 public List<String> command() {
138 public TestProcessBuilder command(List<String> commands) {
139 this.commands = commands;
144 public TestProcessBuilder directory(File dir) {
150 public Map<String, String> environment() {
155 public TestProcessBuilder redirectErrorStream(boolean b) {
156 this.redirectErrorStream = b;
161 public Process start() throws IOException {
163 return mock(Process.class);