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.process.AllProcessesCommands;
34 import org.sonar.process.ProcessId;
36 import static org.assertj.core.api.Assertions.assertThat;
37 import static org.assertj.core.data.MapEntry.entry;
38 import static org.mockito.Mockito.RETURNS_MOCKS;
39 import static org.mockito.Mockito.mock;
40 import static org.mockito.Mockito.when;
42 public class ProcessLauncherImplTest {
45 public TemporaryFolder temp = new TemporaryFolder();
47 public ExpectedException expectedException = ExpectedException.none();
49 private AllProcessesCommands commands = mock(AllProcessesCommands.class, RETURNS_MOCKS);
52 public void launch_forks_a_new_process() throws Exception {
53 File tempDir = temp.newFolder();
54 TestProcessBuilder processBuilder = new TestProcessBuilder();
55 ProcessLauncher underTest = new ProcessLauncherImpl(tempDir, commands, () -> processBuilder);
56 JavaCommand command = new JavaCommand(ProcessId.ELASTICSEARCH);
57 command.addClasspath("lib/*.class");
58 command.addClasspath("lib/*.jar");
59 command.setArgument("foo", "bar");
60 command.setClassName("org.sonarqube.Main");
61 command.setEnvVariable("VAR1", "valueOfVar1");
62 command.setWorkDir(temp.newFolder());
64 ProcessMonitor monitor = underTest.launch(command);
66 assertThat(monitor).isNotNull();
67 assertThat(processBuilder.started).isTrue();
68 assertThat(processBuilder.commands.get(0)).endsWith("java");
69 assertThat(processBuilder.commands).containsSequence(
70 "-Djava.io.tmpdir=" + tempDir.getAbsolutePath(),
72 "lib/*.class" + System.getProperty("path.separator") + "lib/*.jar",
73 "org.sonarqube.Main");
74 assertThat(processBuilder.dir).isEqualTo(command.getWorkDir());
75 assertThat(processBuilder.redirectErrorStream).isTrue();
76 assertThat(processBuilder.environment)
77 .contains(entry("VAR1", "valueOfVar1"))
78 .containsAllEntriesOf(command.getEnvVariables());
82 public void properties_are_passed_to_command_via_a_temporary_properties_file() throws Exception {
83 File tempDir = temp.newFolder();
84 TestProcessBuilder processBuilder = new TestProcessBuilder();
85 ProcessLauncher underTest = new ProcessLauncherImpl(tempDir, commands, () -> processBuilder);
86 JavaCommand command = new JavaCommand(ProcessId.ELASTICSEARCH);
87 command.setArgument("foo", "bar");
88 command.setArgument("baz", "woo");
90 underTest.launch(command);
92 String propsFilePath = processBuilder.commands.get(processBuilder.commands.size() - 1);
93 File file = new File(propsFilePath);
94 assertThat(file).exists().isFile();
95 try (FileReader reader = new FileReader(file)) {
96 Properties props = new Properties();
98 assertThat(props).containsOnly(
101 entry("process.terminationTimeout", "60000"),
102 entry("process.key", ProcessId.ELASTICSEARCH.getKey()),
103 entry("process.index", String.valueOf(ProcessId.ELASTICSEARCH.getIpcIndex())),
104 entry("process.sharedDir", tempDir.getAbsolutePath()));
109 public void throw_ISE_if_command_fails() throws IOException {
110 File tempDir = temp.newFolder();
111 ProcessLauncherImpl.ProcessBuilder processBuilder = mock(ProcessLauncherImpl.ProcessBuilder.class, RETURNS_MOCKS);
112 when(processBuilder.start()).thenThrow(new IOException("error"));
113 ProcessLauncher underTest = new ProcessLauncherImpl(tempDir, commands, () -> processBuilder);
115 expectedException.expect(IllegalStateException.class);
116 expectedException.expectMessage("Fail to launch process [es]");
118 underTest.launch(new JavaCommand(ProcessId.ELASTICSEARCH));
121 private static class TestProcessBuilder implements ProcessLauncherImpl.ProcessBuilder {
122 private List<String> commands = null;
123 private File dir = null;
124 private Boolean redirectErrorStream = null;
125 private final Map<String, String> environment = new HashMap<>();
126 private boolean started = false;
129 public List<String> command() {
134 public TestProcessBuilder command(List<String> commands) {
135 this.commands = commands;
140 public TestProcessBuilder directory(File dir) {
146 public Map<String, String> environment() {
151 public TestProcessBuilder redirectErrorStream(boolean b) {
152 this.redirectErrorStream = b;
157 public Process start() throws IOException {
159 return mock(Process.class);