/** * Copyright (c) 2014 Richard Warburton (richard.warburton@gmail.com) * <p> * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * <p> * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * <p> * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **/ package com.insightfullogic.honest_profiler.system_tests; import com.insightfullogic.honest_profiler.core.MachineListener; import com.insightfullogic.honest_profiler.core.Monitor; import com.insightfullogic.honest_profiler.core.profiles.Profile; import com.insightfullogic.honest_profiler.core.sources.VirtualMachine; import com.insightfullogic.honest_profiler.ports.sources.FileLogSource; import com.insightfullogic.honest_profiler.ports.sources.LocalMachineSource; import com.insightfullogic.honest_profiler.testing_utilities.AgentRunner; import com.insightfullogic.honest_profiler.testing_utilities.NonInteractiveAgentRunner; import com.insightfullogic.lambdabehave.JunitSuiteRunner; import com.insightfullogic.lambdabehave.expectations.Expect; import org.hamcrest.Matcher; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.atomic.AtomicReference; import static com.insightfullogic.lambdabehave.Suite.describe; import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.locks.LockSupport.parkNanos; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; @RunWith(JunitSuiteRunner.class) public class AgentIntegrationTest { private static Logger logger = LoggerFactory.getLogger(AgentIntegrationTest.class); private AtomicReference<FileLogSource> file = new AtomicReference<>(); { describe("Agent Integration", it -> { it.isConcludedWith(() -> { final FileLogSource source = file.get(); if (source != null) { source.getFile().delete(); } }); it.should("should result in a monitorable JVM", expect -> { AgentRunner.run("InfiniteExample", AgentRunner.DEFAULT_AGENT_INTERVAL, runner -> { int seenTraceCount = 0; AtomicReference<Profile> lastProfile = discoverVirtualMachines(); seenTraceCount = expectIncreasingTraceCount(expect, seenTraceCount, lastProfile); seenTraceCount = expectIncreasingTraceCount(expect, seenTraceCount, lastProfile); seenTraceCount = expectIncreasingTraceCount(expect, seenTraceCount, lastProfile); }); }); it.should("should be able to start/stop the JVM", expect -> { AgentRunner.run("InfiniteExample", new String[] { "start=0", AgentRunner.DEFAULT_AGENT_INTERVAL }, runner -> { int seenTraceCount = 0; AtomicReference<Profile> lastProfile = discoverVirtualMachines(); seenTraceCount = expectNonIncreasingTraceCount(expect, seenTraceCount, lastProfile); runner.startProfiler(); seenTraceCount = expectIncreasingTraceCount(expect, seenTraceCount, lastProfile); runner.stopProfiler(); seenTraceCount = expectIncreasingTraceCount(expect, seenTraceCount, lastProfile); seenTraceCount = expectNonIncreasingTraceCount(expect, seenTraceCount, lastProfile); }); }); it.should("should be able to change agent settings", expect -> { NonInteractiveAgentRunner.run("AgentApiExample", "start=0", runner -> { expect.that(runner.isSuccessful()).is(equalTo(true)); if (!runner.isSuccessful()) logger.debug("Errors in agent profiled process {}", runner.getErrorMessages()); }); }); }); } private AtomicReference<Profile> discoverVirtualMachines() { AtomicReference<Profile> lastProfile = new AtomicReference<>(); parkNanos(SECONDS.toNanos(1)); new LocalMachineSource(logger, new MachineListener() { @Override public void onNewMachine(final VirtualMachine machine) { if (machine.isAgentLoaded()) { final FileLogSource logSource = (FileLogSource) machine.getLogSource(); file.set(logSource); Monitor.pipeFile(logSource, lastProfile::set); } } @Override public void onClosedMachine(final VirtualMachine machine) { } }).discoverVirtualMachines(); return lastProfile; } private int expectIncreasingTraceCount(Expect expect, int seenTraceCount, AtomicReference<Profile> lastProfile) { return expectTraceCount(expect, seenTraceCount, greaterThan(seenTraceCount), lastProfile); } private int expectNonIncreasingTraceCount(Expect expect, int seenTraceCount, AtomicReference<Profile> lastProfile) { return expectTraceCount(expect, seenTraceCount, equalTo(seenTraceCount), lastProfile); } private int expectTraceCount(final Expect expect, final int seenTraceCount, final Matcher<Integer> matcher, final AtomicReference<Profile> lastProfile) { logger.debug("Last seen trace count is {}", seenTraceCount); parkNanos(SECONDS.toNanos(1)); Profile profile = lastProfile.get(); int currentTraceCount = profile == null ? 0 : profile.getTraceCount(); expect.that(currentTraceCount).is(matcher); return currentTraceCount; } }