/* * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and others. * * 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. * * Contributors: * Thierry Delprat */ package org.nuxeo.elasticsearch.test.commands; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.event.DocumentEventTypes; import org.nuxeo.ecm.core.api.impl.DocumentModelImpl; import org.nuxeo.elasticsearch.commands.IndexingCommand; import org.nuxeo.elasticsearch.commands.IndexingCommand.Type; import org.nuxeo.elasticsearch.commands.IndexingCommands; import org.nuxeo.elasticsearch.commands.IndexingCommandsStacker; /** * Test that the logic for transforming CoreEvents in ElasticSearch commands * * @author <a href="mailto:tdelprat@nuxeo.com">Tiry</a> */ public class TestIndexingCommandsStacker extends IndexingCommandsStacker { protected Map<String, IndexingCommands> commands = new HashMap<String, IndexingCommands>(); protected List<IndexingCommand> flushedSyncCommands; protected List<IndexingCommand> flushedAsyncCommands; @Override protected Map<String, IndexingCommands> getAllCommands() { return commands; } @Override protected boolean isSyncIndexingByDefault() { return false; } @Before public void reset() { flushedSyncCommands = new ArrayList<>(); flushedAsyncCommands = new ArrayList<>(); } protected void fireSyncIndexing(List<IndexingCommand> syncCommands) { flushedSyncCommands.addAll(syncCommands); } protected void fireAsyncIndexing(List<IndexingCommand> asyncCommands) { flushedAsyncCommands.addAll(asyncCommands); } protected void flushCommands() { Map<String, IndexingCommands> allCmds = getAllCommands(); List<IndexingCommand> syncCommands = new ArrayList<>(); List<IndexingCommand> asyncCommands = new ArrayList<>(); for (IndexingCommands cmds : allCmds.values()) { for (IndexingCommand cmd : cmds.getCommands()) { if (cmd.isSync()) { syncCommands.add(cmd); } else { asyncCommands.add(cmd); } } } getAllCommands().clear(); if (syncCommands.size() > 0) { fireSyncIndexing(syncCommands); } if (asyncCommands.size() > 0) { fireAsyncIndexing(asyncCommands); } } public final class MockDocumentModel extends DocumentModelImpl { private static final long serialVersionUID = 1L; protected String uid; protected boolean folder = false; public MockDocumentModel(String uid) { this(uid, false); } public MockDocumentModel(String uid, boolean folder) { super(); this.uid = uid; this.folder = folder; } @Override public String getId() { return uid; } @Override public boolean isFolder() { return folder; } } @Test public void shouldRemoveDuplicatedEvents() throws Exception { DocumentModel doc1 = new MockDocumentModel("1"); DocumentModel doc2 = new MockDocumentModel("2"); DocumentModel doc3 = new MockDocumentModel("3"); stackCommand(doc1, DocumentEventTypes.DOCUMENT_CREATED, false); stackCommand(doc1, DocumentEventTypes.BEFORE_DOC_UPDATE, false); stackCommand(doc2, DocumentEventTypes.BEFORE_DOC_UPDATE, false); stackCommand(doc2, DocumentEventTypes.BEFORE_DOC_UPDATE, false); stackCommand(doc2, DocumentEventTypes.BEFORE_DOC_UPDATE, false); stackCommand(doc3, DocumentEventTypes.DOCUMENT_CREATED, false); stackCommand(doc3, DocumentEventTypes.BEFORE_DOC_UPDATE, false); stackCommand(doc3, DocumentEventTypes.DOCUMENT_REMOVED, false); Assert.assertEquals(3, commands.size()); IndexingCommands ic1 = getCommands(doc1); Assert.assertEquals(1, ic1.getCommands().size()); Assert.assertTrue(ic1.contains(Type.INSERT)); Assert.assertEquals(Type.INSERT, ic1.getCommands().get(0).getType()); IndexingCommands ic2 = getCommands(doc2); Assert.assertEquals(1, ic2.getCommands().size()); Assert.assertTrue(ic2.contains(Type.UPDATE)); Assert.assertEquals(Type.UPDATE, ic2.getCommands().get(0).getType()); IndexingCommands ic3 = getCommands(doc3); Assert.assertEquals(0, ic3.getCommands().size()); flushCommands(); Assert.assertEquals(0, flushedSyncCommands.size()); Assert.assertEquals(2, flushedAsyncCommands.size()); } @Test public void shouldMergeDuplicatedEventsAndSwitchToSync() throws Exception { DocumentModel doc1 = new MockDocumentModel("1"); DocumentModel doc2 = new MockDocumentModel("2"); stackCommand(doc1, DocumentEventTypes.BEFORE_DOC_UPDATE, false); stackCommand(doc1, DocumentEventTypes.BEFORE_DOC_UPDATE, true); stackCommand(doc2, DocumentEventTypes.DOCUMENT_CREATED, false); stackCommand(doc2, DocumentEventTypes.BEFORE_DOC_UPDATE, false); stackCommand(doc2, DocumentEventTypes.BEFORE_DOC_UPDATE, true); Assert.assertEquals(2, commands.size()); IndexingCommands ic1 = getCommands(doc1); Assert.assertEquals(1, ic1.getCommands().size()); Assert.assertTrue(ic1.contains(Type.UPDATE)); Assert.assertEquals(Type.UPDATE, ic1.getCommands().get(0).getType()); Assert.assertTrue(ic1.getCommands().get(0).isSync()); IndexingCommands ic2 = getCommands(doc2); Assert.assertEquals(1, ic2.getCommands().size()); Assert.assertTrue(ic2.contains(Type.INSERT)); Assert.assertEquals(Type.INSERT, ic2.getCommands().get(0).getType()); Assert.assertTrue(ic2.getCommands().get(0).isSync()); flushCommands(); Assert.assertEquals(2, flushedSyncCommands.size()); Assert.assertEquals(0, flushedAsyncCommands.size()); } @Test public void shouldRecurseReindex() throws Exception { DocumentModel doc1 = new MockDocumentModel("1", true); DocumentModel doc2 = new MockDocumentModel("2", true); stackCommand(doc1, DocumentEventTypes.DOCUMENT_MOVED, false); stackCommand(doc2, DocumentEventTypes.DOCUMENT_SECURITY_UPDATED, false); IndexingCommands ic1 = getCommands(doc1); Assert.assertEquals(1, ic1.getCommands().size()); Assert.assertTrue(ic1.contains(Type.UPDATE)); Assert.assertEquals(Type.UPDATE, ic1.getCommands().get(0).getType()); Assert.assertTrue(ic1.getCommands().get(0).isRecurse()); IndexingCommands ic2 = getCommands(doc2); Assert.assertEquals(1, ic2.getCommands().size()); Assert.assertTrue(ic2.contains(Type.UPDATE_SECURITY)); Assert.assertEquals(Type.UPDATE_SECURITY, ic2.getCommands().get(0).getType()); Assert.assertTrue(ic2.getCommands().get(0).isRecurse()); flushCommands(); Assert.assertEquals(0, flushedSyncCommands.size()); Assert.assertEquals(2, flushedAsyncCommands.size()); } @Test public void shouldRecurseReindexInSync() throws Exception { DocumentModel doc1 = new MockDocumentModel("1", true); DocumentModel doc2 = new MockDocumentModel("2", true); stackCommand(doc1, DocumentEventTypes.DOCUMENT_MOVED, true); IndexingCommands ic1 = getCommands(doc1); // We should have 2 commands 1 sync + 1 async and recursive Assert.assertEquals(2, ic1.getCommands().size()); Assert.assertTrue(ic1.contains(Type.UPDATE)); Assert.assertEquals(Type.UPDATE, ic1.getCommands().get(0).getType()); Assert.assertFalse(ic1.getCommands().get(0).isRecurse()); Assert.assertTrue(ic1.getCommands().get(1).isRecurse()); flushCommands(); Assert.assertEquals(1, flushedSyncCommands.size()); Assert.assertEquals(1, flushedAsyncCommands.size()); } }