package org.ff4j.test.audit; import static org.ff4j.audit.EventConstants.ACTION_CHECK_OFF; 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; /* * #%L * ff4j-test * %% * 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 org.ff4j.FF4j; 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.property.store.InMemoryPropertyStore; import org.ff4j.store.InMemoryFeatureStore; import org.ff4j.utils.Util; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * Event Repository test support. * * @author Cedrick LUNVEN (@clunven) */ public abstract class EventRepositoryTestSupport { /** Initialize */ protected FF4j ff4j = null; /** Feature List. */ protected ArrayList<Feature> features; /** Target {@link EventRepository}. */ protected EventRepository repo; /** Target publisher. */ protected EventPublisher publisher; /** {@inheritDoc} */ @Before public void setUp() throws Exception { ff4j = new FF4j(); ff4j.setFeatureStore(new InMemoryFeatureStore("test-ff4j-features.xml")); ff4j.setPropertiesStore(new InMemoryPropertyStore("test-ff4j-features.xml")); ff4j.setEventRepository(initRepository()); repo = ff4j.getEventRepository(); } /** * Event generation. * * @param uid * target unique identifier * @return unique event */ protected Event generateFeatureUsageEvent(String uid) { return new Event(SOURCE_JAVA, TARGET_FEATURE, uid, ACTION_CHECK_OK); } /** * Event generation. * * @param uid * target unique identifier * @param timestamp * current event time * @return */ protected Event generateFeatureUsageEvent(String uid, long timestamp) { Event event = generateFeatureUsageEvent(uid); event.setTimestamp(timestamp); return event; } /** * Generate random event. * * @param uid * event uid * @param from * time slot in * @param to * time slot to * @return target event */ protected Event generateRandomFeatureUsageEvent(String uid, long from, long to) { return generateFeatureUsageEvent(uid, from + (long) (Math.random() * (to - from))); } /** * Generate random event. * * @param uid * event uid * @param from * time slot in * @param to * time slot to * @return target event */ protected Event generateRandomFeatureUsageEvent(long from, long to) { return generateRandomFeatureUsageEvent(Util.getRandomElement(features).getUid(), from, to); } /** * Generate random events for. */ 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(); /** TDD. */ @Test public void testSaveEventUnit() throws InterruptedException { long start = System.currentTimeMillis(); // Given EventQueryDefinition eqd = new EventQueryDefinition(start, System.currentTimeMillis()); Assert.assertEquals(0, repo.getFeatureUsageTotalHitCount(eqd)); // When repo.saveEvent(generateFeatureUsageEvent("f1")); // Wait for the event to be effectively store Thread.sleep(100); // Then EventQueryDefinition eqd2 = new EventQueryDefinition(start - 20, System.currentTimeMillis()); Assert.assertEquals(1, repo.getFeatureUsageTotalHitCount(eqd2)); } /** TDD. */ @Test(expected = IllegalArgumentException.class) public void testSaveEventNull() { Assert.assertFalse(repo.saveEvent(null)); } /** TDD. */ @Test public void testSaveAuditTrail() throws InterruptedException { long start = System.currentTimeMillis(); // Given Event evt1 = new Event(SOURCE_JAVA, TARGET_FEATURE, "f1", EventConstants.ACTION_CREATE); // When repo.saveEvent(evt1); // Wait for the event to be effectively store Thread.sleep(200); EventQueryDefinition eqd2 = new EventQueryDefinition(start - 200, System.currentTimeMillis()); Assert.assertEquals(1, repo.getAuditTrail(eqd2).size()); } /** TDD. */ @Test public void testFeatureUsageBarCharts() throws InterruptedException { long start = System.currentTimeMillis(); // Given empty event repository // When 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)); } // Then : 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()); } /** TDD. */ @Test public void testFeatureUsageHitCount() throws InterruptedException { long start = System.currentTimeMillis(); // Given empty event repository // When 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, 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_CHECK_OFF); 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 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.purgeAuditTrail(testQuery); // Then Assert.assertNull(repo.getEventByUUID(evtAudit.getUuid(), System.currentTimeMillis())); repo.purgeFeatureUsage(testQuery); Thread.sleep(100); Assert.assertNull(repo.getEventByUUID(evtFeatureUsage.getUuid(), System.currentTimeMillis())); } }