Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.metron.indexing.dao.metaalert.lucene; import static org.apache.metron.indexing.dao.metaalert.MetaAlertConstants.ALERT_FIELD; import static org.apache.metron.indexing.dao.metaalert.MetaAlertConstants.GROUPS_FIELD; import static org.apache.metron.indexing.dao.metaalert.MetaAlertConstants.METAALERT_FIELD; import static org.apache.metron.indexing.dao.metaalert.MetaAlertConstants.METAALERT_TYPE; import static org.apache.metron.indexing.dao.metaalert.MetaAlertConstants.STATUS_FIELD; import static org.apache.metron.indexing.dao.metaalert.MetaAlertConstants.THREAT_FIELD_DEFAULT; import static org.apache.metron.indexing.dao.metaalert.MetaAlertConstants.THREAT_SORT_DEFAULT; import static org.apache.metron.indexing.dao.metaalert.MetaAlertStatus.ACTIVE; import static org.apache.metron.indexing.dao.metaalert.MetaAlertStatus.INACTIVE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.UUID; import com.google.common.collect.ImmutableMap; import org.adrianwalker.multilinestring.Multiline; import org.apache.commons.math.util.MathUtils; import org.apache.metron.common.Constants; import org.apache.metron.common.Constants.Fields; import org.apache.metron.indexing.dao.IndexDao; import org.apache.metron.indexing.dao.RetrieveLatestDao; import org.apache.metron.indexing.dao.metaalert.MetaAlertConfig; import org.apache.metron.indexing.dao.metaalert.MetaAlertConstants; import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateRequest; import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateResponse; import org.apache.metron.indexing.dao.metaalert.MetaAlertRetrieveLatestDao; import org.apache.metron.indexing.dao.metaalert.MetaAlertStatus; import org.apache.metron.indexing.dao.metaalert.MetaScores; import org.apache.metron.indexing.dao.search.GetRequest; import org.apache.metron.indexing.dao.search.InvalidSearchException; import org.apache.metron.indexing.dao.update.CommentAddRemoveRequest; import org.apache.metron.indexing.dao.update.Document; import org.apache.metron.indexing.dao.update.PatchRequest; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class AbstractLuceneMetaAlertUpdateDaoTest { @Mock IndexDao indexDao; @Before public void setup() { dao = new TestLuceneMetaAlertUpdateDao(); } private static final double EPS = 0.00001; private static final String METAALERT_INDEX = "metaalert_index"; private static final String METAALERT_GUID = "meta_0"; private static final String DEFAULT_PREFIX = "child_"; private static final MetaAlertConfig TEST_CONFIG = new MetaAlertConfig(METAALERT_INDEX, THREAT_SORT_DEFAULT, () -> ImmutableMap.of(Constants.SENSOR_TYPE_FIELD_PROPERTY, Constants.SENSOR_TYPE, Constants.THREAT_SCORE_FIELD_PROPERTY, THREAT_FIELD_DEFAULT)) { @Override protected String getDefaultThreatTriageField() { return THREAT_FIELD_DEFAULT.replace(':', '.'); } @Override protected String getDefaultSourceTypeField() { return Constants.SENSOR_TYPE; } }; private static Map<String, Document> documents = new HashMap<>(); static { Document active = new Document(new HashMap<>(), ACTIVE.getStatusString(), METAALERT_TYPE, 0L); documents.put(ACTIVE.getStatusString(), active); Document inactive = new Document(new HashMap<>(), INACTIVE.getStatusString(), METAALERT_TYPE, 0L); inactive.getDocument().put(STATUS_FIELD, INACTIVE.getStatusString()); documents.put(INACTIVE.getStatusString(), inactive); } TestMetaAlertRetrieveLatestDao retrieveLatestDao = new TestMetaAlertRetrieveLatestDao(); private class TestMetaAlertRetrieveLatestDao implements MetaAlertRetrieveLatestDao { @Override public Document getLatest(String guid, String sensorType) { return documents.get(guid); } @Override public Iterable<Document> getAllLatest(List<GetRequest> getRequests) { return null; } } TestLuceneMetaAlertUpdateDao dao = new TestLuceneMetaAlertUpdateDao(); private class TestLuceneMetaAlertUpdateDao extends AbstractLuceneMetaAlertUpdateDao { TestLuceneMetaAlertUpdateDao() { super(indexDao, retrieveLatestDao, TEST_CONFIG); } @Override public void update(Document update, Optional<String> index) { } @Override public void addCommentToAlert(CommentAddRemoveRequest request) { } @Override public void removeCommentFromAlert(CommentAddRemoveRequest request) { } @Override public void addCommentToAlert(CommentAddRemoveRequest request, Document latest) { } @Override public void removeCommentFromAlert(CommentAddRemoveRequest request, Document latest) { } @Override public void patch(RetrieveLatestDao retrieveLatestDao, PatchRequest request, Optional<Long> timestamp) { } @Override public MetaAlertCreateResponse createMetaAlert(MetaAlertCreateRequest request) { return null; } @Override public boolean addAlertsToMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests) { return false; } @Override public boolean updateMetaAlertStatus(String metaAlertGuid, MetaAlertStatus status) { return false; } } /** { "guid": "meta_alert", "index": "metaalert_index", "patch": [ { "op": "add", "path": "/metron_alert", "value": [] } ], "sensorType": "metaalert" } */ @Multiline public static String alertPatchRequest; /** { "guid": "meta_alert", "index": "metaalert_index", "patch": [ { "op": "add", "path": "/status", "value": [] } ], "sensorType": "metaalert" } */ @Multiline public static String statusPatchRequest; /** { "guid": "meta_alert", "index": "metaalert_index", "patch": [ { "op": "add", "path": "/name", "value": [] } ], "sensorType": "metaalert" } */ @Multiline public static String namePatchRequest; @Rule public ExpectedException thrown = ExpectedException.none(); @Test(expected = UnsupportedOperationException.class) public void testBatchUpdateThrowsException() { dao.batchUpdate(null); } @Test @SuppressWarnings("unchecked") public void testPatchNotAllowedAlert() throws ParseException { PatchRequest pr = new PatchRequest(); Map<String, Object> patch = (JSONObject) new JSONParser().parse(alertPatchRequest); pr.setPatch(Collections.singletonList((JSONObject) ((JSONArray) patch.get("patch")).get(0))); assertFalse(dao.isPatchAllowed(pr)); } @Test @SuppressWarnings("unchecked") public void testPatchNotAllowedStatus() throws ParseException { PatchRequest pr = new PatchRequest(); Map<String, Object> patch = (JSONObject) new JSONParser().parse(statusPatchRequest); pr.setPatch(Collections.singletonList((JSONObject) ((JSONArray) patch.get("patch")).get(0))); assertFalse(dao.isPatchAllowed(pr)); } @Test @SuppressWarnings("unchecked") public void testPatchAllowedName() throws ParseException { PatchRequest pr = new PatchRequest(); Map<String, Object> patch = (JSONObject) new JSONParser().parse(namePatchRequest); pr.setPatch(Collections.singletonList((JSONObject) ((JSONArray) patch.get("patch")).get(0))); assertTrue(dao.isPatchAllowed(pr)); } @Test public void testUpdateSingle() throws IOException { Map<Document, Optional<String>> updates = new HashMap<>(); Document document = new Document(new HashMap<>(), "guid", "sensor", 0L); updates.put(document, Optional.empty()); dao.update(updates); verify(indexDao, times(1)).update(document, Optional.empty()); } @Test public void testUpdateMultiple() throws IOException { Map<Document, Optional<String>> updates = new HashMap<>(); Document documentOne = new Document(new HashMap<>(), "guid", "sensor", 0L); updates.put(documentOne, Optional.empty()); Document documentTwo = new Document(new HashMap<>(), "guid2", "sensor", 0L); updates.put(documentTwo, Optional.empty()); dao.update(updates); verify(indexDao, times(1)).batchUpdate(updates); } @Test public void testBuildAddAlertToMetaAlertUpdatesEmpty() { Document metaDoc = new Document(new HashMap<>(), METAALERT_GUID, METAALERT_TYPE, 0L); metaDoc.getDocument().put(ALERT_FIELD, getRawMaps(buildChildAlerts(1, METAALERT_GUID, null))); Map<Document, Optional<String>> actual = dao.buildAddAlertToMetaAlertUpdates(metaDoc, new ArrayList<>()); assertEquals(0, actual.size()); } @Test public void testBuildAddAlertToMetaAlertUpdates() { List<Document> alerts = buildChildAlerts(1, METAALERT_GUID, null); Document metaDoc = buildMetaAlert(alerts); List<Document> newAlerts = buildChildAlerts(2, null, "new_"); Map<Document, Optional<String>> actual = dao.buildAddAlertToMetaAlertUpdates(metaDoc, newAlerts); assertEquals(3, actual.size()); HashMap<String, Object> expectedExistingAlert = new HashMap<>(); expectedExistingAlert.put(Constants.GUID, "child_0"); expectedExistingAlert.put(METAALERT_FIELD, Collections.singletonList(METAALERT_GUID)); expectedExistingAlert.put(THREAT_FIELD_DEFAULT, 0.0f); List<Map<String, Object>> expectedAlerts = new ArrayList<>(); expectedAlerts.add(expectedExistingAlert); expectedAlerts.addAll(getRawMaps(newAlerts)); List<Double> scores = new ArrayList<>(); scores.add(0.0d); scores.add(0.0d); scores.add(0.0d); Map<String, Object> expectedMetaAlertMap = new HashMap<>(); expectedMetaAlertMap.put(Constants.GUID, METAALERT_GUID); expectedMetaAlertMap.put(ALERT_FIELD, expectedAlerts); expectedMetaAlertMap.put(THREAT_FIELD_DEFAULT, 0.0f); expectedMetaAlertMap.putAll(new MetaScores(scores).getMetaScores()); Document expectedMetaAlertDoc = new Document(expectedMetaAlertMap, METAALERT_GUID, METAALERT_TYPE, 0L); Map<Document, Optional<String>> expected = new HashMap<>(); expected.put(expectedMetaAlertDoc, Optional.of(METAALERT_INDEX)); expected.put(newAlerts.get(0), Optional.empty()); expected.put(newAlerts.get(1), Optional.empty()); assertTrue(updatesMapEquals(expected, actual)); } @Test public void testRemoveAlertsFromMetaAlert() throws IOException { List<Document> alerts = buildChildAlerts(3, METAALERT_GUID, null); Document metaDoc = buildMetaAlert(alerts); List<Document> deletedAlerts = new ArrayList<>(); deletedAlerts.add(alerts.get(0)); deletedAlerts.add(alerts.get(2)); Map<Document, Optional<String>> actual = dao.buildRemoveAlertsFromMetaAlert(metaDoc, deletedAlerts); assertEquals(3, actual.size()); Map<String, Object> expectedDeletedAlert = new HashMap<>(); expectedDeletedAlert.put(Constants.GUID, "child_0"); expectedDeletedAlert.put(THREAT_FIELD_DEFAULT, 0.0f); expectedDeletedAlert.put(MetaAlertConstants.METAALERT_FIELD, new ArrayList<>()); Document expectedDeletedDocument = new Document(expectedDeletedAlert, "child_0", "test", 0L); Map<String, Object> expectedDeletedAlert3 = new HashMap<>(); expectedDeletedAlert3.put(Constants.GUID, "child_2"); expectedDeletedAlert3.put(THREAT_FIELD_DEFAULT, 0.0f); expectedDeletedAlert3.put(MetaAlertConstants.METAALERT_FIELD, new ArrayList<>()); Document expectedDeletedDocument2 = new Document(expectedDeletedAlert3, "child_2", "test", 0L); List<Map<String, Object>> expectedAlerts = new ArrayList<>(); expectedAlerts.add(alerts.get(1).getDocument()); Map<String, Object> expectedMetaAlertMap = new HashMap<>(); expectedMetaAlertMap.put(Constants.GUID, METAALERT_GUID); expectedMetaAlertMap.put(ALERT_FIELD, expectedAlerts); expectedMetaAlertMap.put(THREAT_FIELD_DEFAULT, 0.0f); expectedMetaAlertMap.putAll(new MetaScores(Collections.singletonList(0.0d)).getMetaScores()); Document expectedMetaAlertDoc = new Document(expectedMetaAlertMap, METAALERT_GUID, METAALERT_TYPE, 0L); Map<Document, Optional<String>> expected = new HashMap<>(); expected.put(expectedDeletedDocument, Optional.empty()); expected.put(expectedDeletedDocument2, Optional.empty()); expected.put(expectedMetaAlertDoc, Optional.of(METAALERT_INDEX)); assertTrue(updatesMapEquals(expected, actual)); } @Test public void testBuildRemoveAlertsFromMetaAlertThrowsException() throws Exception { thrown.expect(IllegalStateException.class); thrown.expectMessage( "Removing these alerts will result in an empty meta alert. Empty meta alerts are not allowed."); List<Document> alerts = buildChildAlerts(1, METAALERT_GUID, null); Document metaDoc = buildMetaAlert(alerts); dao.buildRemoveAlertsFromMetaAlert(metaDoc, alerts); } @Test public void testRemoveAlertsFromMetaAlertNoChildAlerts() { Document empty = new Document(new HashMap<>(), "empty", METAALERT_TYPE, 0L); boolean actual = dao.removeAlertsFromMetaAlert(empty, Collections.singletonList("child")); assertFalse(actual); } @Test public void testRemoveAlertsFromMetaAlertEmptyRemoveList() { Document metaDoc = new Document(new HashMap<>(), METAALERT_GUID, METAALERT_TYPE, 0L); metaDoc.getDocument().put(STATUS_FIELD, ACTIVE.getStatusString()); metaDoc.getDocument().put(ALERT_FIELD, new HashMap<String, Object>() { { put(Constants.GUID, "child_0"); } }); boolean actual = dao.removeAlertsFromMetaAlert(metaDoc, new ArrayList<>()); assertFalse(actual); } @Test public void testRemoveAlertsFromMetaAlertEmptyRemoveSingle() { Document metaDoc = new Document(new HashMap<>(), METAALERT_GUID, METAALERT_TYPE, 0L); metaDoc.getDocument().put(STATUS_FIELD, ACTIVE.getStatusString()); List<Map<String, Object>> alerts = new ArrayList<>(); alerts.add(new HashMap<String, Object>() { { put(Constants.GUID, "child_0"); } }); metaDoc.getDocument().put(ALERT_FIELD, alerts); boolean actual = dao.removeAlertsFromMetaAlert(metaDoc, Collections.singletonList("child_0")); Document expected = new Document(new HashMap<>(), METAALERT_GUID, METAALERT_TYPE, 0L); expected.getDocument().put(STATUS_FIELD, ACTIVE.getStatusString()); expected.getDocument().put(ALERT_FIELD, new ArrayList<>()); assertTrue(actual); assertEquals(expected, metaDoc); } @Test public void testBuildStatusChangeUpdatesToInactive() { List<Document> alerts = buildChildAlerts(2, METAALERT_GUID, null); Map<String, Object> metaAlertMap = new HashMap<>(); metaAlertMap.put(ALERT_FIELD, getRawMaps(alerts)); metaAlertMap.put(Constants.GUID, METAALERT_GUID); metaAlertMap.put(STATUS_FIELD, MetaAlertStatus.ACTIVE.getStatusString()); Document metaDoc = new Document(metaAlertMap, METAALERT_GUID, METAALERT_TYPE, 0L); Map<Document, Optional<String>> actual = dao.buildStatusChangeUpdates(metaDoc, alerts, MetaAlertStatus.INACTIVE); assertEquals(3, actual.size()); List<Document> expectedDeletedAlerts = buildChildAlerts(2, null, null); List<Map<String, Object>> expectedAlerts = new ArrayList<>(); expectedAlerts.add(alerts.get(0).getDocument()); expectedAlerts.add(alerts.get(1).getDocument()); Map<String, Object> expectedMetaAlertMap = new HashMap<>(); expectedMetaAlertMap.put(Constants.GUID, METAALERT_GUID); expectedMetaAlertMap.put(ALERT_FIELD, expectedAlerts); expectedMetaAlertMap.put(STATUS_FIELD, MetaAlertStatus.INACTIVE.getStatusString()); Document expectedMetaAlertDoc = new Document(expectedMetaAlertMap, METAALERT_GUID, METAALERT_TYPE, 0L); Map<Document, Optional<String>> expected = new HashMap<>(); expected.put(expectedMetaAlertDoc, Optional.of(METAALERT_INDEX)); expected.put(expectedDeletedAlerts.get(0), Optional.empty()); expected.put(expectedDeletedAlerts.get(1), Optional.empty()); assertTrue(updatesMapEquals(expected, actual)); } @Test public void testBuildStatusChangeUpdatesToActive() { List<Document> alerts = buildChildAlerts(2, METAALERT_GUID, null); Map<String, Object> metaAlertMap = new HashMap<>(); metaAlertMap.put(ALERT_FIELD, getRawMaps(alerts)); metaAlertMap.put(Constants.GUID, METAALERT_GUID); metaAlertMap.put(STATUS_FIELD, MetaAlertStatus.INACTIVE.getStatusString()); Document metaDoc = new Document(metaAlertMap, METAALERT_GUID, METAALERT_TYPE, 0L); Map<Document, Optional<String>> actual = dao.buildStatusChangeUpdates(metaDoc, alerts, MetaAlertStatus.ACTIVE); List<Map<String, Object>> expectedAlerts = new ArrayList<>(); expectedAlerts.add(alerts.get(0).getDocument()); expectedAlerts.add(alerts.get(1).getDocument()); Map<String, Object> expectedMetaAlertMap = new HashMap<>(); expectedMetaAlertMap.put(ALERT_FIELD, expectedAlerts); expectedMetaAlertMap.put(Constants.GUID, METAALERT_GUID); expectedMetaAlertMap.put(STATUS_FIELD, MetaAlertStatus.ACTIVE.getStatusString()); Document expectedMetaAlertDoc = new Document(expectedMetaAlertMap, METAALERT_GUID, METAALERT_TYPE, 0L); Map<Document, Optional<String>> expected = new HashMap<>(); expected.put(expectedMetaAlertDoc, Optional.of(METAALERT_INDEX)); assertTrue(updatesMapEquals(expected, actual)); } @Test public void testRemoveAlertsFromMetaAlertEmptyRemoveMultiple() { Document metDoc = new Document(new HashMap<>(), METAALERT_GUID, METAALERT_TYPE, 0L); metDoc.getDocument().put(STATUS_FIELD, ACTIVE.getStatusString()); List<Document> alerts = buildChildAlerts(3, null, null); metDoc.getDocument().put(ALERT_FIELD, getRawMaps(alerts)); List<String> removeGuids = new ArrayList<>(); removeGuids.add("child_0"); removeGuids.add("child_2"); removeGuids.add("child_doesn't_exist"); boolean actual = dao.removeAlertsFromMetaAlert(metDoc, removeGuids); // Build the expected metaalert Document expected = new Document(new HashMap<>(), METAALERT_GUID, METAALERT_TYPE, 0L); expected.getDocument().put(STATUS_FIELD, ACTIVE.getStatusString()); List<Map<String, Object>> alertsExpected = new ArrayList<>(); alertsExpected.add(new HashMap<String, Object>() { { put(METAALERT_FIELD, new ArrayList<>()); put(Constants.GUID, "child_1"); put(THREAT_FIELD_DEFAULT, 0.0f); } }); expected.getDocument().put(ALERT_FIELD, alertsExpected); assertEquals(expected, metDoc); assertTrue(actual); } @Test(expected = IllegalStateException.class) public void testRemoveAlertsFromMetaAlertInactive() throws IOException { dao.removeAlertsFromMetaAlert(INACTIVE.getStatusString(), null); } @Test public void testRemoveMetaAlertFromAlertSuccess() { List<String> metaAlertGuids = new ArrayList<>(); metaAlertGuids.add("metaalert1"); metaAlertGuids.add("metaalert2"); Map<String, Object> alertFields = new HashMap<>(); alertFields.put(METAALERT_FIELD, metaAlertGuids); Document alert = new Document(alertFields, "alert", "test", 0L); Document expected = new Document(new HashMap<>(), "alert", "test", 0L); List<String> expectedMetaAlertGuids = new ArrayList<>(); expectedMetaAlertGuids.add("metaalert2"); expected.getDocument().put(METAALERT_FIELD, expectedMetaAlertGuids); boolean actual = dao.removeMetaAlertFromAlert("metaalert1", alert); assertTrue(actual); assertEquals(expected, alert); } @Test public void testRemoveMetaAlertFromAlertMissing() { List<String> metaAlertGuids = new ArrayList<>(); metaAlertGuids.add("metaalert1"); metaAlertGuids.add("metaalert2"); Map<String, Object> alertFields = new HashMap<>(); alertFields.put(METAALERT_FIELD, metaAlertGuids); Document alert = new Document(alertFields, "alert", "test", 0L); boolean actual = dao.removeMetaAlertFromAlert("metaalert3", alert); assertFalse(actual); } @Test public void testAddMetaAlertToAlertEmpty() { Map<String, Object> alertFields = new HashMap<>(); alertFields.put(METAALERT_FIELD, new ArrayList<>()); Document alert = new Document(alertFields, "alert", "test", 0L); Document expected = new Document(new HashMap<>(), "alert", "test", 0L); List<String> expectedMetaAlertGuids = new ArrayList<>(); expectedMetaAlertGuids.add("metaalert1"); expected.getDocument().put(METAALERT_FIELD, expectedMetaAlertGuids); boolean actual = dao.addMetaAlertToAlert("metaalert1", alert); assertTrue(actual); assertEquals(expected, alert); } @Test public void testAddMetaAlertToAlertNonEmpty() { List<String> metaAlertGuids = new ArrayList<>(); metaAlertGuids.add("metaalert1"); Map<String, Object> alertFields = new HashMap<>(); alertFields.put(METAALERT_FIELD, metaAlertGuids); Document alert = new Document(alertFields, "alert", "test", 0L); Document expected = new Document(new HashMap<>(), "alert", "test", 0L); List<String> expectedMetaAlertGuids = new ArrayList<>(); expectedMetaAlertGuids.add("metaalert1"); expectedMetaAlertGuids.add("metaalert2"); expected.getDocument().put(METAALERT_FIELD, expectedMetaAlertGuids); boolean actual = dao.addMetaAlertToAlert("metaalert2", alert); assertTrue(actual); assertEquals(expected, alert); } @Test public void testAddMetaAlertToAlertDuplicate() { List<String> metaAlertGuids = new ArrayList<>(); metaAlertGuids.add("metaalert1"); Map<String, Object> alertFields = new HashMap<>(); alertFields.put(METAALERT_FIELD, metaAlertGuids); Document alert = new Document(alertFields, "alert", "test", 0L); boolean actual = dao.addMetaAlertToAlert("metaalert1", alert); assertFalse(actual); } @Test public void testBuildCreateDocumentSingleAlert() { List<String> groups = new ArrayList<>(); groups.add("group_one"); groups.add("group_two"); // Build the first response from the multiget Map<String, Object> alertOne = new HashMap<>(); alertOne.put(Constants.GUID, "alert_one"); alertOne.put(THREAT_FIELD_DEFAULT, 10.0d); List<Document> alerts = new ArrayList<Document>() { { add(new Document(alertOne, "", "", 0L)); } }; // Actually build the doc Document actual = dao.buildCreateDocument(alerts, groups, ALERT_FIELD); ArrayList<Map<String, Object>> alertList = new ArrayList<>(); alertList.add(alertOne); Map<String, Object> actualDocument = actual.getDocument(); assertEquals(MetaAlertStatus.ACTIVE.getStatusString(), actualDocument.get(STATUS_FIELD)); assertEquals(alertList, actualDocument.get(ALERT_FIELD)); assertEquals(groups, actualDocument.get(GROUPS_FIELD)); // Don't care about the result, just that it's a UUID. Exception will be thrown if not. UUID.fromString((String) actualDocument.get(Constants.GUID)); } @Test public void testBuildCreateDocumentMultipleAlerts() { List<String> groups = new ArrayList<>(); groups.add("group_one"); groups.add("group_two"); // Build the first response from the multiget Map<String, Object> alertOne = new HashMap<>(); alertOne.put(Constants.GUID, "alert_one"); alertOne.put(THREAT_FIELD_DEFAULT, 10.0d); // Build the second response from the multiget Map<String, Object> alertTwo = new HashMap<>(); alertTwo.put(Constants.GUID, "alert_one"); alertTwo.put(THREAT_FIELD_DEFAULT, 5.0d); List<Document> alerts = new ArrayList<>(); alerts.add(new Document(alertOne, "", "", 0L)); alerts.add(new Document(alertTwo, "", "", 0L)); // Actually build the doc Document actual = dao.buildCreateDocument(alerts, groups, ALERT_FIELD); ArrayList<Map<String, Object>> alertList = new ArrayList<>(); alertList.add(alertOne); alertList.add(alertTwo); Map<String, Object> actualDocument = actual.getDocument(); assertNotNull(actualDocument.get(Fields.TIMESTAMP.getName())); assertEquals(alertList, actualDocument.get(ALERT_FIELD)); assertEquals(groups, actualDocument.get(GROUPS_FIELD)); // Don't care about the result, just that it's a UUID. Exception will be thrown if not. UUID.fromString((String) actualDocument.get(Constants.GUID)); } // Utility method to manage comparing update maps protected boolean updatesMapEquals(Map<Document, Optional<String>> expected, Map<Document, Optional<String>> actual) { Entry<Document, Optional<String>> expectedMetaEntry; Entry<Document, Optional<String>> actualMetaEntry; expectedMetaEntry = findMetaEntry(expected); actualMetaEntry = findMetaEntry(actual); // Compare the metaalerts directly: they can mess with comparison because of float scores. if (!metaAlertDocumentEquals(expectedMetaEntry.getKey(), actualMetaEntry.getKey())) { return false; } else { // Remove the potentially problematic metaalert comparison. return removeMetaEntry(expected).equals(removeMetaEntry(actual)); } } protected Entry<Document, Optional<String>> findMetaEntry(Map<Document, Optional<String>> expected) { for (Entry<Document, Optional<String>> entry : expected.entrySet()) { if (entry.getKey().getSensorType().equals(METAALERT_TYPE)) { return entry; } } return null; } // Unfortunately, the floating point comparison problem prevents direct remove call. protected Map<Document, Optional<String>> removeMetaEntry(Map<Document, Optional<String>> updates) { Map<Document, Optional<String>> filteredUpdates = new HashMap<>(); for (Entry<Document, Optional<String>> entry : updates.entrySet()) { if (!(entry.getKey().getSensorType().equals(METAALERT_TYPE))) { filteredUpdates.put(entry.getKey(), entry.getValue()); } } return filteredUpdates; } // Utility method to ensure that the floating point values contained in a metaalert don't get // incorrectly evaluated as not equal. private boolean metaAlertDocumentEquals(Document expected, Document actual) { if (!expected.getGuid().equals(actual.getGuid())) { return false; } if (!expected.getSensorType().equals(actual.getSensorType())) { return false; } if (!expected.getTimestamp().equals(actual.getTimestamp())) { return false; } // The underlying documents have to be compared more thoroughly since it has floating point Map<String, Object> expectedDocument = expected.getDocument(); Map<String, Object> actualDocument = actual.getDocument(); if (expectedDocument.size() != actualDocument.size()) { return false; } for (Entry<String, Object> entry : expectedDocument.entrySet()) { Object value = entry.getValue(); Object actualValue = actual.getDocument().get(entry.getKey()); if (value instanceof Float) { if (!MathUtils.equals((Float) value, (Float) actualValue, EPS)) { return false; } } else if (value instanceof Double) { if (!MathUtils.equals((Double) value, (Double) actualValue, EPS)) { return false; } } else { if (!value.equals(actual.getDocument().get(entry.getKey()))) { return false; } } } return true; } // Generate some child alerts. protected List<Document> buildChildAlerts(int num, String parent, String guidPrefix) { String prefix = guidPrefix != null ? guidPrefix : DEFAULT_PREFIX; List<Document> alerts = new ArrayList<>(); for (int i = 0; i < num; i++) { HashMap<String, Object> fields = new HashMap<>(); fields.put(Constants.GUID, prefix + i); fields.put(THREAT_FIELD_DEFAULT, 0.0f); if (parent != null) { fields.put(METAALERT_FIELD, Collections.singletonList(parent)); } else { fields.put(METAALERT_FIELD, new ArrayList<>()); } alerts.add(new Document(fields, prefix + i, "test", 0L)); } return alerts; } protected List<Map<String, Object>> getRawMaps(List<Document> documents) { List<Map<String, Object>> rawMaps = new ArrayList<>(); for (Document document : documents) { rawMaps.add(document.getDocument()); } return rawMaps; } protected Document buildMetaAlert(List<Document> alerts) { Map<String, Object> metaAlertMap = new HashMap<>(); metaAlertMap.put(ALERT_FIELD, getRawMaps(alerts)); metaAlertMap.put(Constants.GUID, METAALERT_GUID); return new Document(metaAlertMap, METAALERT_GUID, METAALERT_TYPE, 0L); } }