package org.ff4j.test.audit;
import static org.ff4j.audit.EventConstants.ACTION_CHECK_OFF;
/*
* #%L
* ff4j-core
* %%
* Copyright (C) 2013 - 2016 FF4J
* %%
* 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.
* #L%
*/
import static org.ff4j.audit.EventConstants.ACTION_CHECK_OK;
import static org.ff4j.audit.EventConstants.ACTION_CREATE;
import static org.ff4j.audit.EventConstants.SOURCE_JAVA;
import static org.ff4j.audit.EventConstants.SOURCE_WEB;
import static org.ff4j.audit.EventConstants.SOURCE_WEBAPI;
import static org.ff4j.audit.EventConstants.TARGET_FEATURE;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.ff4j.audit.Event;
import org.ff4j.audit.EventConstants;
import org.ff4j.audit.EventPublisher;
import org.ff4j.audit.EventQueryDefinition;
import org.ff4j.audit.EventSeries;
import org.ff4j.audit.MutableHitCount;
import org.ff4j.audit.chart.BarChart;
import org.ff4j.audit.chart.TimeSeriesChart;
import org.ff4j.audit.repository.EventRepository;
import org.ff4j.core.Feature;
import org.ff4j.store.InMemoryFeatureStore;
import org.ff4j.utils.Util;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* Superclass to test {@link EventRepository}.
*
* @author Cedrick Lunven (@clunven)
*/
public abstract class AbstractEventRepositoryTest {
/** Feature List. */
protected ArrayList<Feature> features;
/** Target {@link EventRepository}. */
protected EventRepository repo;
/** Target publisher. */
protected EventPublisher publisher;
/** {@inheritDoc} */
@Before
public void setUp() throws Exception {
repo = initRepository();
publisher = new EventPublisher(repo);
features = new ArrayList<Feature>(new InMemoryFeatureStore("ff4j.xml").readAll().values());
}
// Utility to generate event
protected Event generateFeatureUsageEvent(String uid) {
return new Event(SOURCE_JAVA, TARGET_FEATURE, uid, ACTION_CHECK_OK);
}
// Generate a random event during the period
protected Event generateFeatureUsageEvent(String uid, long timestamp) {
Event event = generateFeatureUsageEvent(uid);
event.setTimestamp(timestamp);
return event;
}
// Generate a random event during the period
protected Event generateFeatureUsageEvent(String uid, long from, long to) {
return generateFeatureUsageEvent(uid, from + (long) (Math.random() * (to-from)));
}
// Generate a random event during the period
protected Event generateRandomFeatureUsageEvent(long from, long to) {
return generateFeatureUsageEvent(Util.getRandomElement(features).getUid(), from , to);
}
// Populate repository for test
protected void populateRepository(long from, long to, int totalEvent) throws InterruptedException {
for (int i = 0; i < totalEvent; i++) {
repo.saveEvent(generateRandomFeatureUsageEvent(from, to));
}
}
/**
* Any store test will declare its store through this callback.
*
* @return working feature store
* @throws Exception
* error during building feature store
*/
protected abstract EventRepository initRepository();
@Test
public void testSaveEventUnit() throws InterruptedException {
long start = System.currentTimeMillis();
Assert.assertEquals(0, repo.getFeatureUsageTotalHitCount(new EventQueryDefinition(start, System.currentTimeMillis())));
repo.saveEvent(generateFeatureUsageEvent("f1"));
Thread.sleep(100);
Assert.assertEquals(1, repo.getFeatureUsageTotalHitCount(new EventQueryDefinition(start-20, System.currentTimeMillis())));
}
@Test(expected = IllegalArgumentException.class)
public void testSaveEventNull() {
Assert.assertFalse(repo.saveEvent(null));
}
@Test
public void testSaveAuditTrail() throws InterruptedException {
long start = System.currentTimeMillis();
Event evt1 = new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", EventConstants.ACTION_CREATE);
Assert.assertTrue(repo.saveEvent(evt1));
Thread.sleep(200);
Assert.assertEquals(1, repo.getAuditTrail(new EventQueryDefinition(start-10, System.currentTimeMillis())).size());
}
@Test
public void testPieChart() throws InterruptedException {
long start = System.currentTimeMillis();
Event evt1 = new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", EventConstants.ACTION_CREATE);
Assert.assertTrue(repo.saveEvent(evt1));
Thread.sleep(200);
EventQueryDefinition eqd = new EventQueryDefinition(start-10, System.currentTimeMillis());
Assert.assertNotNull(repo.getFeatureUsagePieChart(eqd));
Assert.assertNotNull(repo.getHostPieChart(eqd));
Assert.assertNotNull(repo.getSourcePieChart(eqd));
Assert.assertNotNull(repo.getUserPieChart(eqd));
Assert.assertNotNull(repo.getHostBarChart(eqd));
Assert.assertNotNull(repo.getSourceBarChart(eqd));
Assert.assertNotNull(repo.getUserBarChart(eqd));
}
@Test
public void testFeatureUsageBarCharts() throws InterruptedException {
long start = System.currentTimeMillis();
// Create Event
repo.saveEvent(new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", EventConstants.ACTION_CREATE));
for(int i = 0;i<8;i++) {
Thread.sleep(100);
repo.saveEvent(new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", ACTION_CHECK_OK));
repo.saveEvent(new Event(SOURCE_WEB, TARGET_FEATURE, "f2", ACTION_CHECK_OK));
}
// Assert bar chart (2 bars with 8 and 8)
EventQueryDefinition testQuery = new EventQueryDefinition(start-10, System.currentTimeMillis()+10);
BarChart bChart = repo.getFeatureUsageBarChart(testQuery);
Assert.assertEquals(2, bChart.getChartBars().size());
Assert.assertEquals(new Integer(8), bChart.getChartBars().get(0).getValue());
Assert.assertEquals(new Integer(8), bChart.getChartBars().get(1).getValue());
Assert.assertNotNull(bChart.getChartBars().get(0).getColor());
Assert.assertNotNull(bChart.getChartBars().get(1).getColor());
}
@Test
public void testFeatureUsageHitCount() throws InterruptedException {
long start = System.currentTimeMillis();
// Create Event
repo.saveEvent(new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", EventConstants.ACTION_CREATE));
for(int i = 0;i<8;i++) {
Thread.sleep(100);
repo.saveEvent(new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", EventConstants.ACTION_CHECK_OK));
repo.saveEvent(new Event(SOURCE_WEB, TARGET_FEATURE, "f2", EventConstants.ACTION_CHECK_OK));
}
Thread.sleep(100);
// Assert bar chart (2 bars with 8 and 8)
EventQueryDefinition testQuery = new EventQueryDefinition(start, System.currentTimeMillis());
// Assert Pie Chart (2 sectors with 8 and 8)
Map < String, MutableHitCount > mapOfHit = repo.getFeatureUsageHitCount(testQuery);
Assert.assertEquals(2, mapOfHit.size());
Assert.assertTrue(mapOfHit.containsKey("f1"));
Assert.assertTrue(mapOfHit.containsKey("f2"));
Assert.assertEquals(8, mapOfHit.get("f1").get());
}
@Test
public void testSearchFeatureUsageEvents() throws InterruptedException {
long start = System.currentTimeMillis();
repo.saveEvent(new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", ACTION_CREATE));
for(int i = 0;i<8;i++) {
Thread.sleep(100);
repo.saveEvent(new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", ACTION_CHECK_OK));
repo.saveEvent(new Event(SOURCE_WEB, TARGET_FEATURE, "f2", ACTION_CHECK_OK));
}
Thread.sleep(100);
// Then
EventQueryDefinition testQuery = new EventQueryDefinition(start-20, System.currentTimeMillis());
EventSeries es = repo.searchFeatureUsageEvents(testQuery);
Assert.assertEquals(16, es.size());
// Then
}
@Test
public void testGetFeatureUsageHistory() throws InterruptedException {
long start = System.currentTimeMillis();
repo.saveEvent(new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", ACTION_CREATE));
for(int i = 0;i<8;i++) {
Thread.sleep(100);
repo.saveEvent(new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", ACTION_CHECK_OK));
repo.saveEvent(new Event(SOURCE_WEB, TARGET_FEATURE, "f2", ACTION_CHECK_OK));
}
Thread.sleep(100);
// Then
EventQueryDefinition testQuery = new EventQueryDefinition(start-20, System.currentTimeMillis());
TimeSeriesChart tsc = repo.getFeatureUsageHistory(testQuery, TimeUnit.HOURS);
Assert.assertEquals(1, tsc.getTimeSlots().size());
}
/** TDD. */
@Test
public void testSourceHitCount() throws InterruptedException {
long start = System.currentTimeMillis();
// When
for(int i = 0;i<8;i++) {
Thread.sleep(100);
repo.saveEvent(new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", ACTION_CHECK_OK));
repo.saveEvent(new Event(SOURCE_WEB, TARGET_FEATURE, "f2", ACTION_CHECK_OK));
}
Thread.sleep(200);
repo.saveEvent(new Event(SOURCE_WEBAPI, TARGET_FEATURE, "f1", ACTION_CHECK_OK));
Thread.sleep(200);
// Then
EventQueryDefinition testQuery = new EventQueryDefinition(start-20, System.currentTimeMillis());
Map < String, MutableHitCount > mapOfHit = repo.getSourceHitCount(testQuery);
Assert.assertEquals(3, mapOfHit.size());
Assert.assertTrue(mapOfHit.containsKey(SOURCE_JAVA));
Assert.assertTrue(mapOfHit.containsKey(SOURCE_WEB));
Assert.assertEquals(1, mapOfHit.get(SOURCE_WEBAPI).get());
}
/** TDD. */
@Test
public void testUserHitCount() throws InterruptedException {
long start = System.currentTimeMillis();
// When
for(int i = 0;i<8;i++) {
Event e1 = new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", ACTION_CHECK_OK);
e1.setUser("JOHN");
repo.saveEvent(e1);
Thread.sleep(100);
Event e2 = new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", ACTION_CHECK_OK);
e2.setUser("BOB");
repo.saveEvent(e2);
Thread.sleep(100);
}
Thread.sleep(200);
// Then
EventQueryDefinition testQuery = new EventQueryDefinition(start-20, System.currentTimeMillis());
Map < String, MutableHitCount > mapOfHit = repo.getUserHitCount(testQuery);
Assert.assertEquals(2, mapOfHit.size());
Assert.assertTrue(mapOfHit.containsKey("JOHN"));
Assert.assertTrue(mapOfHit.containsKey("BOB"));
Assert.assertEquals(8, mapOfHit.get("BOB").get());
}
/** TDD. */
@Test
public void testHostHitCount() throws InterruptedException {
long start = System.currentTimeMillis();
// When
for(int i = 0;i<8;i++) {
Thread.sleep(100);
repo.saveEvent(new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", ACTION_CHECK_OK));
}
Thread.sleep(200);
// Then
EventQueryDefinition testQuery = new EventQueryDefinition(start, System.currentTimeMillis());
Map < String, MutableHitCount > mapOfHit = repo.getHostHitCount(testQuery);
Assert.assertEquals(1, mapOfHit.size());
Assert.assertEquals(1, mapOfHit.values().size());
}
/** TDD. */
@Test
public void testSaveCheckOff() throws InterruptedException {
long start = System.currentTimeMillis();
// Given
Event evt1 = new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", ACTION_CHECK_OFF);
// When
Assert.assertTrue(repo.saveEvent(evt1));
Thread.sleep(100);
// Then
Assert.assertEquals(0, repo.getFeatureUsageTotalHitCount(new EventQueryDefinition(start, System.currentTimeMillis())));
Assert.assertEquals(0, repo.getAuditTrail(new EventQueryDefinition(start, System.currentTimeMillis())).size());
}
/** TDD. */
@Test
public void testLimitEventSeries() throws InterruptedException {
EventSeries es = new EventSeries(5);
for(int i=0;i<10;i++) {
Thread.sleep(10);
es.add(new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", ACTION_CREATE));
}
Assert.assertEquals(5, es.size());
}
/** TDD. */
@Test
public void testGetEventByUID() throws InterruptedException {
// Given
String dummyId = "1234-5678-9012-3456";
Event evt1 = new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", ACTION_CREATE);
evt1.setUuid(dummyId);
// When
repo.saveEvent(evt1);
// Let the store to be updated
Thread.sleep(100);
// Then
Event evt = repo.getEventByUUID(dummyId, System.currentTimeMillis());
Assert.assertNotNull(evt);
}
/** TDD. */
@Test
public void testGetEventByUID2() throws InterruptedException {
// Given
String dummyId = "1234-5678-9012-3456";
Event evt1 = new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", ACTION_CREATE);
evt1.setUuid(dummyId);
// When
repo.saveEvent(evt1);
// Let the store to be updated
Thread.sleep(100);
// Then
Event evt = repo.getEventByUUID(dummyId, null);
Assert.assertNotNull(evt);
}
/** TDD. */
@Test
public void testPurgeEvents() throws InterruptedException {
// Given, 2 events in the repo
long topStart = System.currentTimeMillis();
Event evtAudit = new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", ACTION_CREATE);
evtAudit.setUuid("1234-5678-9012-3456");
Event evtFeatureUsage = new Event(SOURCE_JAVA, TARGET_FEATURE, "f2", ACTION_CHECK_OK);
evtFeatureUsage.setUuid("1234-5678-9012-3457");
repo.saveEvent(evtAudit);
repo.saveEvent(evtFeatureUsage);
Thread.sleep(100);
Assert.assertNotNull(repo.getEventByUUID(evtAudit.getUuid(), System.currentTimeMillis()));
Assert.assertNotNull(repo.getEventByUUID(evtFeatureUsage.getUuid(), System.currentTimeMillis()));
// When
EventQueryDefinition testQuery = new EventQueryDefinition(topStart-100, System.currentTimeMillis());
repo.purgeFeatureUsage(testQuery);
Assert.assertNull(repo.getEventByUUID(evtFeatureUsage.getUuid(), System.currentTimeMillis()));
Assert.assertTrue(repo.searchFeatureUsageEvents(testQuery).isEmpty());
// Then
EventQueryDefinition testQuery2 = new EventQueryDefinition(topStart-100, System.currentTimeMillis());
repo.purgeAuditTrail(testQuery2);
Assert.assertNull(repo.getEventByUUID(evtAudit.getUuid(), System.currentTimeMillis()));
}
}