/**
* The MIT License
* Copyright © 2010 JmxTrans team
*
* 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:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* 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.googlecode.jmxtrans.model.output;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.googlecode.jmxtrans.exceptions.LifecycleException;
import com.googlecode.jmxtrans.model.Query;
import com.googlecode.jmxtrans.model.Result;
import com.googlecode.jmxtrans.model.Server;
import com.googlecode.jmxtrans.model.ServerFixtures;
import org.assertj.core.api.Assertions;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static com.google.common.collect.Maps.newHashMap;
/**
* Tests for {@link OpenTSDBGenericWriter}.
*/
public class OpenTSDBGenericWriterTests {
protected Query mockQuery;
protected Result mockResult;
// Interactions with the custom, test subclass of OpenTSDBGenericWriter.
protected boolean tvAddHostnameTagDefault;
protected boolean prepareSenderCalled;
protected boolean shutdownSenderCalled;
protected boolean startOutputCalled;
protected boolean finishOutputCalled;
protected List<String> tvMetricLinesSent;
@Before
public void setupTest() {
this.mockQuery = Mockito.mock(Query.class);
this.mockResult = Mockito.mock(Result.class);
// Setup test data
tvAddHostnameTagDefault = true;
prepareSenderCalled = false;
shutdownSenderCalled = false;
startOutputCalled = false;
finishOutputCalled = false;
tvMetricLinesSent = new LinkedList<String>();
// Setup common mock interactions.
Mockito.when(this.mockResult.getValues()).thenReturn(ImmutableMap.of("x-att1-x", (Object) "120021"));
Mockito.when(this.mockResult.getAttributeName()).thenReturn("X-ATT-X");
Mockito.when(this.mockResult.getClassName()).thenReturn("X-DOMAIN.PKG.CLASS-X");
Mockito.when(this.mockResult.getTypeName()).
thenReturn("Type=x-type-x,Group=x-group-x,Other=x-other-x,Name=x-name-x");
}
@Test
public void testEmptyTagSetting() throws Exception {
Map<String, String> tagMap = newHashMap();
Map<String, Object> settings = newHashMap();
settings.put("tags", tagMap);
OpenTSDBGenericWriter writer = new TestOpenTSDBGenericWriter(
ImmutableList.<String>of(),
false,
settings);
Mockito.when(this.mockResult.getValues()).thenReturn(ImmutableMap.of("X-ATT-X", (Object) "120021"));
// Verify empty tag map.
Assertions.assertThat(writer.getTypeNames()).isEmpty();
writer.start();
writer.doWrite(ServerFixtures.dummyServer(), this.mockQuery, ImmutableList.of(this.mockResult));
writer.close();
Assert.assertTrue(
this.tvMetricLinesSent.get(0).matches("^X-DOMAIN.PKG.CLASS-X\\.X-ATT-X 0 120021 host=[^ ]*$"));
}
@Test
public void testTagSetting() throws Exception {
Map<String, String> tagMap;
// Verify tag map with multiple values.
tagMap = newHashMap();
tagMap.put("x-tag1-x", "x-tag1val-x");
tagMap.put("x-tag2-x", "x-tag2val-x");
tagMap.put("x-tag3-x", "x-tag3val-x");
OpenTSDBGenericWriter writer = createWriter("tags", tagMap);
writer.start();
writer.doWrite(ServerFixtures.dummyServer(), this.mockQuery, ImmutableList.of(this.mockResult));
writer.close();
Assert.assertTrue(this.tvMetricLinesSent.get(0).matches("^X-DOMAIN.PKG.CLASS-X\\.X-ATT-X 0 120021.*"));
Assert.assertTrue(this.tvMetricLinesSent.get(0).matches(".*\\bhost=.*"));
Assert.assertTrue(this.tvMetricLinesSent.get(0).matches(".*\\bx-tag1-x=x-tag1val-x\\b.*"));
Assert.assertTrue(this.tvMetricLinesSent.get(0).matches(".*\\bx-tag2-x=x-tag2val-x\\b.*"));
Assert.assertTrue(this.tvMetricLinesSent.get(0).matches(".*\\bx-tag3-x=x-tag3val-x\\b.*"));
}
@Test
public void testValidateValidHostPort() throws Exception {
OpenTSDBGenericWriter writer = createWriter(ImmutableMap.of(
"host", (Object) "localhost",
"port", 4242));
writer.start();
writer.validateSetup(null, this.mockQuery);
}
@Test
public void testPortNumberAsString() throws Exception {
OpenTSDBGenericWriter writer = createWriter(ImmutableMap.of("host", (Object) "localhost", "port", "4242"));
writer.start();
writer.validateSetup(null, this.mockQuery);
}
@Test
public void testHooksCalled() throws Exception {
OpenTSDBGenericWriter writer = createWriter();
writer.start();
Assert.assertTrue(prepareSenderCalled);
Assert.assertFalse(shutdownSenderCalled);
Assert.assertFalse(startOutputCalled);
Assert.assertFalse(finishOutputCalled);
writer.doWrite(ServerFixtures.dummyServer(), this.mockQuery, ImmutableList.of(this.mockResult));
Assert.assertTrue(prepareSenderCalled);
Assert.assertFalse(shutdownSenderCalled);
Assert.assertTrue(startOutputCalled);
Assert.assertTrue(finishOutputCalled);
writer.close();
Assert.assertTrue(prepareSenderCalled);
Assert.assertTrue(shutdownSenderCalled);
Assert.assertTrue(startOutputCalled);
Assert.assertTrue(finishOutputCalled);
}
@Test
public void testDebugEnabled() throws Exception {
OpenTSDBGenericWriter writer = createWriter(ImmutableMap.of("host", (Object) "localhost", "port", 4242, "debug", true));
writer.start();
writer.validateSetup(null, this.mockQuery);
writer.doWrite(ServerFixtures.dummyServer(), this.mockQuery, ImmutableList.of(this.mockResult));
}
@Test
@Ignore("issue with classloader used by powermockito and the securityManager which use ClassLoader.getResource")
public void testLocalhostUnknownHostException() throws Exception {
UnknownHostException unknownHostException = new UnknownHostException("X-TEST-UHE-X");
try {
PowerMockito.mockStatic(InetAddress.class);
PowerMockito.when(InetAddress.getLocalHost()).thenThrow(unknownHostException);
createWriter();
Assert.fail("LifecycleException missing");
} catch (UnknownHostException ex) {
// Verify.
Assert.assertSame(unknownHostException, ex);
}
}
/**
* Confirm operation when the host tag is enabled, but the local hostname is not known.
*/
@Test
@Ignore("issue with classloader used by powermockito and the securityManager which use ClassLoader.getResource")
public void testNullHostTagname() throws Exception {
// Prepare.
InetAddress mockInetAddress = Mockito.mock(InetAddress.class);
PowerMockito.mockStatic(InetAddress.class);
PowerMockito.when(InetAddress.getLocalHost()).thenReturn(mockInetAddress);
Mockito.when(mockInetAddress.getHostName()).thenReturn(null);
OpenTSDBGenericWriter writer = createWriter("addHostnameTag", true);
// Execute.
writer.start();
writer.doWrite(null, this.mockQuery, ImmutableList.of(this.mockResult));
// Validate.
Assert.assertFalse(this.tvMetricLinesSent.get(0).matches(".*\\bhost=.*")); // Ensure host tag is excluded
}
protected OpenTSDBGenericWriter createWriter() throws LifecycleException, UnknownHostException {
return createWriter(Collections.<String, Object>emptyMap());
}
protected OpenTSDBGenericWriter createWriter(String additionalSettingKey, Object additionalSettingValue) throws LifecycleException, UnknownHostException {
return createWriter(ImmutableMap.of(additionalSettingKey, additionalSettingValue));
}
protected OpenTSDBGenericWriter createWriter(Map<String, Object> additionalSettings) throws LifecycleException, UnknownHostException {
Map<String, Object> settings = newHashMap();
settings.put("host", "localhost");
settings.put("port", 4242);
settings.putAll(additionalSettings);
OpenTSDBGenericWriter writer = new TestOpenTSDBGenericWriter(
ImmutableList.of("Type", "Group", "Name", "Missing"),
false,
settings);
return writer;
}
private class TestOpenTSDBGenericWriter extends OpenTSDBGenericWriter {
public TestOpenTSDBGenericWriter(
@JsonProperty("typeNames") ImmutableList<String> typeNames,
@JsonProperty("debug") Boolean debugEnabled,
@JsonProperty("settings") Map<String, Object> settings) throws LifecycleException {
super(typeNames, false, debugEnabled, "localhost", 1234, null, null, null, null, true, settings);
}
protected void prepareSender() throws LifecycleException {
OpenTSDBGenericWriterTests.this.prepareSenderCalled = true;
}
protected void shutdownSender() throws LifecycleException {
OpenTSDBGenericWriterTests.this.shutdownSenderCalled = true;
}
protected void startOutput() throws IOException {
OpenTSDBGenericWriterTests.this.startOutputCalled = true;
}
protected void finishOutput() throws IOException {
OpenTSDBGenericWriterTests.this.finishOutputCalled = true;
}
protected boolean getAddHostnameTagDefault() {
return tvAddHostnameTagDefault;
}
protected void sendOutput(String metricLine) {
OpenTSDBGenericWriterTests.this.tvMetricLinesSent.add(metricLine);
}
}
}