/*
* Copyright (c) 2015 Dell Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.tsdr.datastorage.test;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import com.google.common.collect.ImmutableMap;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.opendaylight.tsdr.datastorage.TSDRMetricsMap;
import org.opendaylight.tsdr.datastorage.TSDRStorageServiceImpl;
import org.opendaylight.tsdr.spi.model.TSDRConstants;
import org.opendaylight.tsdr.spi.persistence.TSDRLogPersistenceService;
import org.opendaylight.tsdr.spi.persistence.TSDRMetricPersistenceService;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.log.data.rev160325.GetTSDRLogRecordsInputBuilder;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.log.data.rev160325.StoreTSDRLogRecordInputBuilder;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.log.data.rev160325.storetsdrlogrecord.input.TSDRLogRecord;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.log.data.rev160325.storetsdrlogrecord.input.TSDRLogRecordBuilder;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.metric.data.rev160325.AggregationType;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.metric.data.rev160325.GetTSDRAggregatedMetricsInputBuilder;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.metric.data.rev160325.GetTSDRAggregatedMetricsOutput;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.metric.data.rev160325.GetTSDRMetricsInputBuilder;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.metric.data.rev160325.StoreTSDRMetricRecordInputBuilder;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.metric.data.rev160325.gettsdraggregatedmetrics.output.AggregatedMetrics;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.metric.data.rev160325.storetsdrmetricrecord.input.TSDRMetricRecord;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.metric.data.rev160325.storetsdrmetricrecord.input.TSDRMetricRecordBuilder;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.rev150219.DataCategory;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.rev150219.PurgeAllTSDRRecordInputBuilder;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.rev150219.PurgeTSDRRecordInputBuilder;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.rev150219.TSDRRecord;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.rev150219.tsdrrecord.RecordKeys;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.rev150219.tsdrrecord.RecordKeysBuilder;
import org.opendaylight.yangtools.yang.common.RpcResult;
/**
* Unit Test for TSDR Data Storage Service.
* * @author <a href="mailto:hariharan_sethuraman@dell.com">Hariharan Sethuraman</a>
*
* Created: Apr 27, 2015
*/
public class TSDRStorageServiceImplTest {
public TSDRStorageServiceImpl storageService;
public TSDRMetricPersistenceService metricPersistenceService;
public TSDRLogPersistenceService logPersistenceService;
public TSDRMetricsMap MetricsMap;
private static Map<String, List<TSDRRecord>> tableRecordMap;
@Before
public void setup() {
metricPersistenceService = mock(TSDRMetricPersistenceService.class);
logPersistenceService = mock(TSDRLogPersistenceService.class);
storageService = new TSDRStorageServiceImpl(metricPersistenceService,logPersistenceService);
MetricsMap = new TSDRMetricsMap();
tableRecordMap = new HashMap<String, List<TSDRRecord>>();
Answer answerStore = new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] arguments = invocation.getArguments();
String tableName = null;
if (arguments != null && arguments.length > 0 && arguments[0] != null) {
List<TSDRRecord> recordCol = (List<TSDRRecord>)arguments[0];
for(TSDRRecord record: recordCol){
tableName = getTableNameFrom(record.getTSDRDataCategory());
if(!tableRecordMap.containsKey(tableName)){
tableRecordMap.put(tableName, new ArrayList<TSDRRecord>());
}
List<TSDRRecord> existingRecordCol = tableRecordMap.get(tableName);
System.out.println("Creating record " + record + " under table " + tableName);
existingRecordCol.add(record);
}
}
return null;
}
};
doAnswer(answerStore).when(metricPersistenceService).storeMetric(any(List.class));
doAnswer(answerStore).when(logPersistenceService).storeLog(any(List.class));
Mockito.doNothing().when(metricPersistenceService).purge(any(DataCategory.class),any(long.class));
Mockito.doNothing().when(logPersistenceService).purge(any(DataCategory.class),any(long.class));
Mockito.doNothing().when(metricPersistenceService).purge(any(long.class));
Mockito.doNothing().when(logPersistenceService).purge(any(long.class));
Answer answerGetMetrics = new Answer() {
@Override
public List<?> answer(InvocationOnMock invocation) throws Throwable {
Object[] arguments = invocation.getArguments();
List<TSDRRecord> recordCol = new ArrayList<TSDRRecord>();
if (arguments != null && arguments.length > 0 && arguments[0] != null) {
String tableName = (String)arguments[0];
System.out.println("Retrieving metrics from table name " + tableName + " records:"+tableRecordMap);
List<TSDRRecord> allRecordCol = tableRecordMap.get(tableName);
System.out.println(allRecordCol);
for(TSDRRecord record: allRecordCol){
recordCol.add(record);
}
}
System.out.println("Get metrics of size " + recordCol.size() + ", records:" + recordCol);
return recordCol;
}
};
doAnswer(answerGetMetrics).when(metricPersistenceService).getTSDRMetricRecords(any(String.class),any(long.class),any(long.class));
doAnswer(answerGetMetrics).when(logPersistenceService).getTSDRLogRecords(any(String.class),any(long.class),any(long.class));
}
@Test
public void testpurgeAllTSDRRecord(){
String timeStamp = (new Long((new Date()).getTime())).toString();
storageService.purgeAllTSDRRecord(new PurgeAllTSDRRecordInputBuilder().setRetentionTime(new Long(timeStamp)).build());
storageService.purgeAllTSDRRecord(new PurgeAllTSDRRecordInputBuilder().setRetentionTime(null).build());
}
@Test
public void teststoreTSDRLogRecord() {
List<TSDRLogRecord> metricCol = new ArrayList<TSDRLogRecord>();
String timeStamp = (new Long((new Date()).getTime())).toString();
List<RecordKeys> recordKeys = new ArrayList<RecordKeys>();
RecordKeys recordKey1 = new RecordKeysBuilder()
.setKeyName(DataCategory.SYSLOG.name())
.setKeyValue("log1").build();
recordKeys.add(recordKey1);
TSDRLogRecordBuilder builder1 = new TSDRLogRecordBuilder();
metricCol.add(builder1.setIndex(1)
.setRecordFullText("su root failed for lonvick")
.setNodeID("node1.example.com")
.setRecordKeys(recordKeys)
.setTSDRDataCategory(DataCategory.SYSLOG)
.setTimeStamp(new Long(timeStamp)).build());
storageService.storeTSDRLogRecord(new StoreTSDRLogRecordInputBuilder().setTSDRLogRecord(metricCol).build());
storageService.storeTSDRLogRecord(new StoreTSDRLogRecordInputBuilder().setTSDRLogRecord(null).build());
}
@Test
public void testgetTSDRLogRecord() {
Date startDate = new Date();
List<TSDRLogRecord> metricCol = new ArrayList<TSDRLogRecord>();
String timeStamp = (new Long((new Date()).getTime())).toString();
List<RecordKeys> recordKeys = new ArrayList<RecordKeys>();
RecordKeys recordKey1 = new RecordKeysBuilder()
.setKeyName(DataCategory.SYSLOG.name())
.setKeyValue("log1").build();
recordKeys.add(recordKey1);
TSDRLogRecordBuilder builder1 = new TSDRLogRecordBuilder();
metricCol.add(builder1.setIndex(1)
.setRecordFullText("su root failed for lonvick")
.setNodeID("node1.example.com")
.setRecordKeys(recordKeys)
.setTSDRDataCategory(DataCategory.SYSLOG)
.setTimeStamp(new Long(timeStamp)).build());
Date endDate = new Date();
storageService.storeTSDRLogRecord(new StoreTSDRLogRecordInputBuilder().setTSDRLogRecord(metricCol).build());
storageService.storeTSDRLogRecord(new StoreTSDRLogRecordInputBuilder().setTSDRLogRecord(null).build());
storageService.getTSDRLogRecords(new GetTSDRLogRecordsInputBuilder()
.setStartTime(startDate.getTime())
.setEndTime(endDate.getTime())
.setTSDRDataCategory(SYS_LOG_TABLE_NAME).build());
}
@Test
public void testpurgeTSDRRecord(){
String timeStamp = (new Long((new Date()).getTime())).toString();
storageService.purgeTSDRRecord(new PurgeTSDRRecordInputBuilder()
.setTSDRDataCategory(DataCategory.SYSLOG)
.setRetentionTime(new Long(timeStamp)).build());
storageService.purgeTSDRRecord(new PurgeTSDRRecordInputBuilder()
.setRetentionTime(null).build());
}
@Test
public void teststoreTSDRMetricRecord(){
List<TSDRMetricRecord> metricCol = new ArrayList<TSDRMetricRecord>();
String timeStamp = (new Long((new Date()).getTime())).toString();
List<RecordKeys> recordKeys = new ArrayList<RecordKeys>();
RecordKeys recordKey1 = new RecordKeysBuilder()
.setKeyName(TSDRConstants.GROUP_KEY_NAME)
.setKeyValue("group1").build();
recordKeys.add(recordKey1);
TSDRMetricRecordBuilder builder1 = new TSDRMetricRecordBuilder();
metricCol.add(builder1.setMetricName("PacketCount")
.setMetricValue(new BigDecimal(Double.parseDouble(new Long(40).toString())))
.setNodeID("node1")
.setRecordKeys(recordKeys)
.setTSDRDataCategory(DataCategory.FLOWGROUPSTATS)
.setTimeStamp(new Long(timeStamp)).build());
storageService.storeTSDRMetricRecord(new StoreTSDRMetricRecordInputBuilder().setTSDRMetricRecord(metricCol).build());
storageService.storeTSDRMetricRecord(new StoreTSDRMetricRecordInputBuilder().setTSDRMetricRecord(null).build());
}
@Test
public void testgetTSDRMetricRecord(){
Date startDate = new Date();
List<TSDRMetricRecord> metricCol = new ArrayList<TSDRMetricRecord>();
String timeStamp = (new Long((new Date()).getTime())).toString();
List<RecordKeys> recordKeys = new ArrayList<RecordKeys>();
RecordKeys recordKey1 = new RecordKeysBuilder()
.setKeyName(TSDRConstants.GROUP_KEY_NAME)
.setKeyValue("group1").build();
recordKeys.add(recordKey1);
TSDRMetricRecordBuilder builder1 = new TSDRMetricRecordBuilder();
metricCol.add(builder1.setMetricName("PacketCount")
.setMetricValue(new BigDecimal(Double.parseDouble(new Long(40).toString())))
.setNodeID("node1")
.setRecordKeys(recordKeys)
.setTSDRDataCategory(DataCategory.FLOWGROUPSTATS)
.setTimeStamp(new Long(timeStamp)).build());
Date endDate = new Date();
storageService.storeTSDRMetricRecord(new StoreTSDRMetricRecordInputBuilder().setTSDRMetricRecord(metricCol).build());
storageService.storeTSDRMetricRecord(new StoreTSDRMetricRecordInputBuilder().setTSDRMetricRecord(null).build());
storageService.getTSDRMetrics(new GetTSDRMetricsInputBuilder()
.setStartTime(startDate.getTime())
.setEndTime(endDate.getTime())
.setTSDRDataCategory(GROUP_METRICS_TABLE_NAME).build());
}
@Test
public void testGetTSDRAggregatedMetrics() throws InterruptedException, ExecutionException{
// Generate and store metrics
final ImmutableMap<Long, Double> valuesByTimestamps =
new ImmutableMap.Builder<Long, Double>()
.put(0L, 100d)
.put(1L, 130d)
.put(2L, 100d)
.put(3L, 99d)
.put(4L, 101d)
.put(5L, 108d)
.build();
for (Entry<Long, Double> valueAtTimestamp : valuesByTimestamps.entrySet()) {
List<TSDRMetricRecord> metricCol = new ArrayList<TSDRMetricRecord>();
List<RecordKeys> recordKeys = new ArrayList<RecordKeys>();
RecordKeys recordKey1 = new RecordKeysBuilder()
.setKeyName(TSDRConstants.GROUP_KEY_NAME)
.setKeyValue("group1").build();
recordKeys.add(recordKey1);
TSDRMetricRecordBuilder builder1 = new TSDRMetricRecordBuilder();
metricCol.add(builder1.setMetricName("PacketCount")
.setMetricValue(BigDecimal.valueOf(valueAtTimestamp.getValue()))
.setNodeID("node1")
.setRecordKeys(recordKeys)
.setTSDRDataCategory(DataCategory.FLOWGROUPSTATS)
.setTimeStamp(valueAtTimestamp.getKey()).build());
storageService.storeTSDRMetricRecord(new StoreTSDRMetricRecordInputBuilder().setTSDRMetricRecord(metricCol).build());
}
// Issue the RPC call to gather the aggregated results
Future<RpcResult<GetTSDRAggregatedMetricsOutput>> future = storageService.getTSDRAggregatedMetrics(new GetTSDRAggregatedMetricsInputBuilder()
.setTSDRDataCategory(GROUP_METRICS_TABLE_NAME)
.setStartTime(0L)
.setEndTime(6L)
.setAggregation(AggregationType.MEAN)
.setInterval(2L)
.build());
List<AggregatedMetrics> metrics = future.get().getResult().getAggregatedMetrics();
// Verify
double delta = 0.00001;
assertEquals(4, metrics.size());
assertEquals(115, metrics.get(0).getMetricValue().doubleValue(), delta);
assertEquals(99.5, metrics.get(1).getMetricValue().doubleValue(),delta);
assertEquals(104.5, metrics.get(2).getMetricValue().doubleValue(), delta);
assertEquals(null, metrics.get(3).getMetricValue());
}
@Test
public void testGetTSDRAggregatedMetricsNoMean() throws InterruptedException, ExecutionException{
// Generate and store metrics
final ImmutableMap<Long, Double> valuesByTimestamps =
new ImmutableMap.Builder<Long, Double>()
.put(0L, 100d)
.put(1L, 130d)
.put(2L, 100d)
.put(3L, 99d)
.put(4L, 101d)
.put(5L, 108d)
.build();
for (Entry<Long, Double> valueAtTimestamp : valuesByTimestamps.entrySet()) {
List<TSDRMetricRecord> metricCol = new ArrayList<TSDRMetricRecord>();
List<RecordKeys> recordKeys = new ArrayList<RecordKeys>();
RecordKeys recordKey1 = new RecordKeysBuilder()
.setKeyName(TSDRConstants.GROUP_KEY_NAME)
.setKeyValue("group1").build();
recordKeys.add(recordKey1);
TSDRMetricRecordBuilder builder1 = new TSDRMetricRecordBuilder();
metricCol.add(builder1.setMetricName("PacketCount")
.setMetricValue(BigDecimal.valueOf(valueAtTimestamp.getValue()))
.setNodeID("node1")
.setRecordKeys(recordKeys)
.setTSDRDataCategory(DataCategory.FLOWGROUPSTATS)
.setTimeStamp(valueAtTimestamp.getKey()).build());
storageService.storeTSDRMetricRecord(new StoreTSDRMetricRecordInputBuilder().setTSDRMetricRecord(metricCol).build());
}
// Issue the RPC call to gather the aggregated results
Future<RpcResult<GetTSDRAggregatedMetricsOutput>> future = storageService.getTSDRAggregatedMetrics(new GetTSDRAggregatedMetricsInputBuilder()
.setTSDRDataCategory(GROUP_METRICS_TABLE_NAME)
.setStartTime(0L)
.setEndTime(20L)
.setAggregation(AggregationType.MEAN)
.setInterval(1L)
.build());
List<AggregatedMetrics> metrics = future.get().getResult().getAggregatedMetrics();
// Verify
//output should be exactly as the input above as the Mean was not applied
double delta = 0.00001;
assertEquals(6, metrics.size());
assertEquals(100, metrics.get(0).getMetricValue().doubleValue(), delta);
assertEquals(130, metrics.get(1).getMetricValue().doubleValue(),delta);
assertEquals(100, metrics.get(2).getMetricValue().doubleValue(),delta);
assertEquals(99, metrics.get(3).getMetricValue().doubleValue(), delta);
assertEquals(101, metrics.get(4).getMetricValue().doubleValue(), delta);
assertEquals(108, metrics.get(5).getMetricValue().doubleValue(), delta);
}
private static final String GROUP_METRICS_TABLE_NAME = "GroupMetrics";
private static final String SYS_LOG_TABLE_NAME = "SYSLOG";
private static String getTableNameFrom(DataCategory datacategory){
if ( datacategory == DataCategory.FLOWGROUPSTATS){
return GROUP_METRICS_TABLE_NAME;
}else if (datacategory == DataCategory.SYSLOG){
return SYS_LOG_TABLE_NAME;
}
return "";
}
@After
public void teardown() {
try {
storageService.close();
}catch(Exception ee){}
storageService = null;
metricPersistenceService = null;
logPersistenceService = null;
tableRecordMap.clear();
}
}