/**
* 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.elastic;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.googlecode.jmxtrans.exceptions.LifecycleException;
import com.googlecode.jmxtrans.model.Result;
import com.googlecode.jmxtrans.model.Server;
import io.searchbox.action.Action;
import io.searchbox.client.JestClient;
import io.searchbox.client.JestResult;
import io.searchbox.core.DocumentResult;
import io.searchbox.core.Index;
import io.searchbox.indices.IndicesExists;
import io.searchbox.indices.mapping.PutMapping;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static com.googlecode.jmxtrans.model.QueryFixtures.dummyQuery;
import static com.googlecode.jmxtrans.model.ServerFixtures.DEFAULT_HOST;
import static com.googlecode.jmxtrans.model.ServerFixtures.DEFAULT_PORT;
import static com.googlecode.jmxtrans.model.ServerFixtures.SERVER_ALIAS;
import static com.googlecode.jmxtrans.model.ServerFixtures.dummyServer;
import static com.googlecode.jmxtrans.model.ServerFixtures.serverWithAliasAndNoQuery;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class ElasticWriterTests {
private static final String PREFIX = "rootPrefix";
@Mock(name = "jestClient")
private JestClient mockClient;
@Mock
private DocumentResult jestResultTrue;
@Mock
private JestResult jestResultFalse;
@InjectMocks
private ElasticWriter writer = createElasticWriter();
private Result result;
@Before
public void initializeMocks() throws IOException {
when(jestResultFalse.isSucceeded()).thenReturn(Boolean.FALSE);
when(jestResultTrue.isSucceeded()).thenReturn(Boolean.TRUE);
result = new Result(1, "attributeName", "className", "objDomain", "classNameAlias", "typeName", ImmutableMap.of("key", (Object)1));
}
@Test
public void sendMessageToElastic() throws Exception {
// return for call, does index exist
when(mockClient.execute(isA(IndicesExists.class))).thenReturn(jestResultFalse);
// return for call, is index created
when(mockClient.execute(isA(PutMapping.class))).thenReturn(jestResultTrue);
// return for call, add index entry
when(mockClient.execute(isA(Index.class))).thenReturn(jestResultTrue);
// creates the index if needed
writer.start();
writer.doWrite(dummyServer(), dummyQuery(), ImmutableList.of(result));
writer.close();
Mockito.verify(mockClient, times(4)).execute(Matchers.<Action<JestResult>>any());
}
@Test
public void sendNonNumericMessageToElastic() throws Exception {
Result resultWithNonNumericValue = new Result(1, "attributeName", "className", "objDomain", "classNameAlias", "typeName", ImmutableMap.of("key", (Object)"abc"));
writer.doWrite(dummyServer(), dummyQuery(), ImmutableList.of(resultWithNonNumericValue));
// only one call is expected: the index check. No write is being made with non-numeric values.
Mockito.verify(mockClient, times(0)).execute(Matchers.<Action<JestResult>>any());
}
@Test(expected = IOException.class)
public void sendMessageToElasticWriteThrowsException() throws Exception {
// return for call, is index created
when(mockClient.execute(isA(Action.class))).thenThrow(new IOException("Failed to add index entry to elastic."));
writer.doWrite(dummyServer(), dummyQuery(), ImmutableList.of(result));
// only one call is expected: the insert index entry. No write is being made with non-numeric values.
Mockito.verify(mockClient, times(1)).execute(Matchers.<Action<JestResult>>any());
}
@Test(expected = ElasticWriterException.class)
public void sendMessageToElasticWriteResultNotSucceeded() throws Exception {
// return for call, is index created
when(mockClient.execute(isA(Action.class))).thenReturn(jestResultFalse);
when(jestResultFalse.getErrorMessage()).thenReturn("Failed to add index entry to elastic.");
writer.doWrite(dummyServer(), dummyQuery(), ImmutableList.of(result));
// only one call is expected: the insert index entry.
Mockito.verify(mockClient, times(1)).execute(Matchers.<Action<JestResult>>any());
}
@Test
public void sendMessageToElasticAndVerify() throws Exception {
Server serverWithKnownValues = serverWithAliasAndNoQuery();
int epoch = 1123455;
String attributeName = "attributeName123";
String className = "className123";
String objDomain = "objDomain123";
String classNameAlias = "classNameAlias123";
String typeName = "typeName123";
String key = "myKey";
int value = 1122;
Result resultWithKnownValues = new Result(epoch, attributeName, className, objDomain, classNameAlias, typeName, ImmutableMap.of(key, (Object) value));
ArgumentCaptor<Index> argument = ArgumentCaptor.forClass(Index.class);
// return for call, add index entry
when(mockClient.execute(isA(Index.class))).thenReturn(jestResultTrue);
writer.doWrite(serverWithKnownValues, dummyQuery(), ImmutableList.of(resultWithKnownValues));
verify(mockClient).execute(argument.capture());
assertEquals(PREFIX + "_jmx-entries", argument.getValue().getIndex());
Gson gson = new Gson();
String data = argument.getValue().getData(gson);
assertTrue("Contains host", data.contains(DEFAULT_HOST));
assertTrue("Contains port", data.contains(DEFAULT_PORT));
assertTrue("Contains attribute name", data.contains(attributeName));
assertTrue("Contains class name", data.contains(className));
assertTrue("Contains object domain", data.contains(objDomain));
assertTrue("Contains classNameAlias", data.contains(classNameAlias));
assertTrue("Contains type name", data.contains(typeName));
assertTrue("Contains timestamp", data.contains(String.valueOf(epoch)));
assertTrue("Contains key", data.contains(key));
assertTrue("Contains value", data.contains(String.valueOf(value)));
assertTrue("Contains serverAlias", data.contains(SERVER_ALIAS));
}
@Test(expected = LifecycleException.class)
public void indexCreateFailure() throws Exception {
// return for call, does index exist
when(mockClient.execute(isA(IndicesExists.class))).thenReturn(jestResultFalse);
// return for call, is index created; return false
when(mockClient.execute(isA(PutMapping.class))).thenReturn(jestResultFalse);
// return error message
when(jestResultFalse.getErrorMessage()).thenReturn("Unknown error creating index in elastic");
// expected to throw an exception
writer.start();
}
private ElasticWriter createElasticWriter() {
ImmutableList<String> typenames = ImmutableList.of();
Map<String,Object> settings = new HashMap<String,Object>();
String connectionUrl = "http://localhost";
ElasticWriter writer;
try {
writer = new ElasticWriter(typenames, true, PREFIX, true, connectionUrl, settings);
} catch (IOException e) {
throw new RuntimeException("Unexpected failure to creare elastic writer for test", e);
}
return writer;
}
@Test
public void checkToString() throws Exception {
assertTrue(writer.toString().contains("ElasticWriter"));
}
@Test
public void testValidateSetup() throws Exception {
writer.validateSetup(dummyServer(), dummyQuery());
// no exception expected
}
}