/*
* Copyright 2016 ThoughtWorks, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.thoughtworks.go.util;
import com.jezhumble.javasysmon.JavaSysMon;
import com.jezhumble.javasysmon.OsProcess;
import com.jezhumble.javasysmon.ProcessInfo;
import com.jezhumble.javasysmon.ProcessVisitor;
import static com.thoughtworks.go.util.LogFixture.logFixtureFor;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNot.not;
import org.apache.log4j.Level;
import org.junit.After;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class SubprocessLoggerTest {
private SubprocessLogger logger;
@After
public void tearDown() {
Runtime.getRuntime().removeShutdownHook(logger.exitHook());
}
@Test
public void shouldNotLogAnythingWhenNoChildProcessesFound() {
JavaSysMon sysMon = mock(JavaSysMon.class);
logger = new SubprocessLogger(sysMon);
try (LogFixture log = logFixtureFor(SubprocessLogger.class, Level.ALL)) {
logger.run();
assertThat(log.allLogs(), is(""));
}
}
@Test
public void shouldLogDefaultMessageWhenNoMessageGiven() {
logger = new SubprocessLogger(stubSysMon());
String allLogs;
try (LogFixture log = logFixtureFor(SubprocessLogger.class, Level.ALL)) {
logger.run();
allLogs = log.allLogs();
}
assertThat(allLogs, containsString("Logged all subprocesses."));
}
@Test
public void shouldLogAllTheRunningChildProcesses() {
logger = new SubprocessLogger(stubSysMon());
String allLogs;
try (LogFixture log = logFixtureFor(SubprocessLogger.class, Level.ALL)) {
logger.registerAsExitHook("foo bar baz");
logger.run();
allLogs = log.allLogs();
}
assertThat(allLogs, containsString("foo bar baz\n\tPID: 101\tname: name-1\towner: owner-1\tcommand: command-1\n\tPID: 103\tname: name-1a\towner: owner-1\tcommand: command-1a"));
assertThat(allLogs, not(containsString("PID: 102")));
}
private JavaSysMon stubSysMon() {
final OsProcess process1 = mock(OsProcess.class);
when(process1.processInfo()).thenReturn(new ProcessInfo(101, 100, "command-1", "name-1", "owner-1", 100, 200, 400, 800));
final OsProcess process1a = mock(OsProcess.class);
when(process1a.processInfo()).thenReturn(new ProcessInfo(103, 100, "command-1a", "name-1a", "owner-1", 160, 260, 460, 860));
final OsProcess process2 = mock(OsProcess.class);
when(process2.processInfo()).thenReturn(new ProcessInfo(102, 101, "command-2", "name-2", "owner-1", 150, 250, 450, 850));
JavaSysMon sysMon = new JavaSysMon() {
@Override
public void visitProcessTree(int pid, ProcessVisitor processVisitor) {
processVisitor.visit(process2, 2);
processVisitor.visit(process1, 1);
processVisitor.visit(process1a, 1);
}
@Override
public int currentPid() {
return 100;
}
};
return sysMon;
}
@Test
public void shouldRegisterItselfAsExitHook() {
logger = new SubprocessLogger(new JavaSysMon());
logger.registerAsExitHook("foo");
try {
Runtime.getRuntime().addShutdownHook(logger.exitHook());
} catch (IllegalArgumentException e) {
assertThat(e.getMessage(), is("Hook previously registered"));
}
}
}