package org.ei.drishti.common; import org.ei.drishti.common.audit.AuditMessage; import org.ei.drishti.common.audit.Auditor; import org.ei.drishti.common.audit.ForbiddenFieldInAuditMessage; import org.hamcrest.Matcher; import org.joda.time.DateTime; import org.junit.Test; import org.motechproject.testing.utils.BaseUnitTest; import java.util.ArrayList; import java.util.List; import static org.ei.drishti.common.audit.AuditMessageType.NORMAL; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; public class AuditorTest extends BaseUnitTest { @Test public void shouldHaveOnlyAsManyMessagesAsTheSizeOfTheAuditorLog() { Auditor auditor = new Auditor(2); audit(auditor, "Message 1"); audit(auditor, "Message 2"); audit(auditor, "Message 3"); assertThat(auditor.messagesSince(0).size(), is(2)); } @Test public void shouldKeepOnlyTheNewestMessagesWhenRemovingMessagesWhichOverflow() { Auditor auditor = new Auditor(2); audit(auditor, "Message 1"); audit(auditor, "Message 2"); audit(auditor, "Message 3"); List<AuditMessage> messages = auditor.messagesSince(0); assertData(messages.get(0), is("Message 2")); assertData(messages.get(1), is("Message 3")); } @Test public void shouldGiveAllMessageWhenMessageIndexBeingSearchedForIsZeroOrNegative() { Auditor auditor = new Auditor(3); audit(auditor, "Message 1"); audit(auditor, "Message 2"); audit(auditor, "Message 3"); audit(auditor, "Message 4"); audit(auditor, "Message 5"); List<AuditMessage> messages = auditor.messagesSince(0); assertThat(messages.size(), is(3)); assertData(messages.get(0), is("Message 3")); assertData(messages.get(1), is("Message 4")); assertData(messages.get(2), is("Message 5")); messages = auditor.messagesSince(-10); assertThat(messages.size(), is(3)); assertData(messages.get(0), is("Message 3")); assertData(messages.get(1), is("Message 4")); assertData(messages.get(2), is("Message 5")); } @Test public void shouldBeAbleToFindMessagesSubmittedSinceAGivenIndex() throws Exception { Auditor auditor = new Auditor(3); audit(auditor, "Message 1"); audit(auditor, "Message 2"); audit(auditor, "Message 3"); long messageIndexOfLastMessage = auditor.messagesSince(0).get(2).index(); audit(auditor, "Message 4"); audit(auditor, "Message 5"); List<AuditMessage> newMessages = auditor.messagesSince(messageIndexOfLastMessage); assertThat(newMessages.size(), is(2)); assertData(newMessages.get(0), is("Message 4")); assertData(newMessages.get(1), is("Message 5")); } @Test public void shouldBeAbleToSearchForMessagesByIndexEvenIfThereHaveBeenManyMessagesInBetween() { Auditor auditor = new Auditor(3); audit(auditor, "Message 1"); long messageIndexOfLastMessage = auditor.messagesSince(0).get(0).index(); audit(auditor, "Message 2"); audit(auditor, "Message 3"); audit(auditor, "Message 4"); audit(auditor, "Message 5"); audit(auditor, "Message 6"); audit(auditor, "Message 7"); List<AuditMessage> messages = auditor.messagesSince(messageIndexOfLastMessage); assertThat(messages.size(), is(3)); assertData(messages.get(0), is("Message 5")); assertData(messages.get(1), is("Message 6")); assertData(messages.get(2), is("Message 7")); } @Test public void shouldNotFindAnyMessagesIfAllMessagesHaveAlreadyBeenSeen() { Auditor auditor = new Auditor(3); audit(auditor, "Message 1"); audit(auditor, "Message 2"); audit(auditor, "Message 3"); long messageIndexOfLastMessage = auditor.messagesSince(0).get(2).index(); List<AuditMessage> newMessages = auditor.messagesSince(messageIndexOfLastMessage); assertThat(newMessages.size(), is(0)); } @Test public void shouldNotFindAnyMessagesWhenAWrongMessageIndexIfProvided() { Auditor auditor = new Auditor(3); audit(auditor, "Message 1"); audit(auditor, "Message 2"); audit(auditor, "Message 3"); long messageIndexOfLastMessage = auditor.messagesSince(0).get(2).index(); List<AuditMessage> newMessages = auditor.messagesSince(messageIndexOfLastMessage + 10); assertThat(newMessages.size(), is(0)); } @Test public void shouldNotAllowTwoMessagesToHaveTheSameIndexEvenIfTheyAreAddedInTheSameMillisecond() { DateTime timeNow = DateTime.now(); Auditor auditor = new Auditor(3); mockCurrentDate(timeNow); audit(auditor, "Message 1 - Same timestamp as Messages 2 and 3"); audit(auditor, "Message 2 - Same timestamp as Messages 1 and 3"); audit(auditor, "Message 3 - Same timestamp as Messages 1 and 2"); resetDateTimeSource(); long messageIndexOfLastMessage = auditor.messagesSince(0).get(2).index(); List<AuditMessage> newMessages = auditor.messagesSince(messageIndexOfLastMessage); assertThat(newMessages.size(), is(0)); } @Test(expected = ForbiddenFieldInAuditMessage.class) public void shouldNotAllowAddingOfFieldsWhichAreNotSupportedByTheAuditMessageTypeUsed() { Auditor auditor = new Auditor(3); auditor.audit(NORMAL).with("SOMETHING_OTHER_THAN_data", "Message 1").done(); } @Test public void shouldCaptureAllAuditMessagesEvenIfCalledFromMultipleThreads() throws Exception { final Auditor auditor = new Auditor(10000); List<Thread> threads = new ArrayList<Thread>(); for (int i = 0; i < 10; i++) { Thread thread = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 1000; i++) { auditor.audit(NORMAL).with("data", "abc + " + i + " " + Thread.currentThread().getId()).done(); } } }); threads.add(thread); } for (int i = 0; i < 10; i++) { threads.get(i).start(); } for (int i = 0; i < 10; i++) { threads.get(i).join(); } assertEquals(10000, auditor.messagesSince(0).size()); } private void assertData(AuditMessage message, Matcher<String> expectedDataMatcher) { assertThat(message.data().get("data"), expectedDataMatcher); } private void audit(Auditor auditor, String value) { auditor.audit(NORMAL).with("data", value).done(); } }