/**
* Copyright (c) Codice Foundation
* <p>
* This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. A copy of the GNU Lesser General Public License
* is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
*/
package org.codice.ddf.registry.api.impl;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Collections;
import java.util.Date;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import org.codice.ddf.registry.api.internal.RegistryStore;
import org.codice.ddf.registry.common.RegistryConstants;
import org.codice.ddf.registry.common.metacard.RegistryObjectMetacardType;
import org.codice.ddf.registry.federationadmin.service.internal.FederationAdminService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceReference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventConstants;
import ddf.catalog.data.Metacard;
import ddf.catalog.data.impl.AttributeImpl;
import ddf.catalog.data.impl.MetacardImpl;
@RunWith(MockitoJUnitRunner.class)
public class RegistryStoreCleanupHandlerTest {
@Mock
private ExecutorService executorService;
@Mock
private FederationAdminService federationAdmin;
@Mock
private BundleContext context;
@Mock
private RegistryStore store;
private MetacardImpl mcard;
private Event event;
private Dictionary<String, Object> eventProperties;
private RegistryStoreCleanupHandler cleanupHandler;
@Before
public void setup() {
cleanupHandler = new RegistryStoreCleanupHandler() {
@Override
BundleContext getBundleContext() {
return context;
}
};
cleanupHandler.setExecutor(executorService);
cleanupHandler.setFederationAdminService(federationAdmin);
setupSerialExecutor();
when(context.getService(any(ServiceReference.class))).thenReturn(store);
when(store.getRegistryId()).thenReturn("registryId");
mcard = new MetacardImpl();
mcard.setId("id");
mcard.setModifiedDate(new Date());
mcard.setAttribute(Metacard.TAGS, RegistryConstants.REGISTRY_TAG_INTERNAL);
mcard.setAttribute(new AttributeImpl(RegistryObjectMetacardType.REGISTRY_ID, "registryId"));
eventProperties = new Hashtable<>();
}
@Test
public void testBindRegistryStoreNullReference() throws Exception {
ServiceReference ref = getServiceReference("servicePid");
handleEvent(null,
ref,
ServiceEvent.UNREGISTERING,
"registryId",
Collections.singletonList(mcard));
verify(federationAdmin,
never()).deleteRegistryEntriesByMetacardIds(Collections.singletonList(mcard.getId()));
}
@Test
public void testUnregisterEvent() throws Exception {
ServiceReference ref = getServiceReference("servicePid");
handleEvent(ref,
ref,
ServiceEvent.UNREGISTERING,
"registryId",
Collections.singletonList(mcard));
verify(federationAdmin).deleteRegistryEntriesByMetacardIds(Collections.singletonList(mcard.getId()));
}
@Test
public void testUnregisterEventCleanupDisabled() throws Exception {
cleanupHandler.setCleanupRelatedMetacards(false);
ServiceReference ref = getServiceReference("servicePid");
handleEvent(ref,
ref,
ServiceEvent.UNREGISTERING,
"registryId",
Collections.singletonList(mcard));
verify(federationAdmin,
never()).deleteRegistryEntriesByMetacardIds(Collections.singletonList(mcard.getId()));
}
@Test
public void testUnregisterEventWrongServiceEvent() throws Exception {
ServiceReference ref = getServiceReference("servicePid");
handleEvent(ref,
ref,
ServiceEvent.REGISTERED,
"registryId",
Collections.singletonList(mcard));
verify(federationAdmin,
never()).deleteRegistryEntriesByMetacardIds(Collections.singletonList(mcard.getId()));
}
@Test
public void testUnregisterEventUnrelatedService() throws Exception {
ServiceReference ref1 = getServiceReference("servicePid");
ServiceReference ref2 = getServiceReference("differentServicePid");
handleEvent(ref1,
ref2,
ServiceEvent.UNREGISTERING,
"registryId",
Collections.singletonList(mcard));
verify(federationAdmin,
never()).deleteRegistryEntriesByMetacardIds(Collections.singletonList(mcard.getId()));
}
@Test
public void testUnregisterEventNoRelatedMetacards() throws Exception {
ServiceReference ref = getServiceReference("servicePid");
handleEvent(ref, ref, ServiceEvent.UNREGISTERING, "registryId", Collections.emptyList());
verify(federationAdmin,
never()).deleteRegistryEntriesByMetacardIds(Collections.singletonList(mcard.getId()));
}
@Test
public void testDestroy() throws Exception {
when(executorService.awaitTermination(anyLong(), any(TimeUnit.class))).thenReturn(true);
cleanupHandler.destroy();
verify(executorService, times(1)).awaitTermination(60L, TimeUnit.SECONDS);
verify(executorService, times(0)).shutdownNow();
}
@Test
public void testDestroyTerminateTasks() throws Exception {
when(executorService.awaitTermination(anyLong(), any(TimeUnit.class))).thenReturn(false);
cleanupHandler.destroy();
verify(executorService, times(2)).awaitTermination(anyLong(), any(TimeUnit.class));
verify(executorService, times(1)).shutdownNow();
}
@Test
public void testDestroyInterupt() throws Exception {
when(executorService.awaitTermination(anyLong(),
any(TimeUnit.class))).thenThrow(new InterruptedException("interrupt"));
cleanupHandler.destroy();
verify(executorService, times(1)).awaitTermination(anyLong(), any(TimeUnit.class));
verify(executorService, times(1)).shutdownNow();
}
private void handleEvent(ServiceReference bindRef, ServiceReference eventRef,
int serviceEventType, String searchRegId, List<Metacard> metacards) throws Exception {
cleanupHandler.bindRegistryStore(bindRef);
ServiceEvent serviceEvent = mock(ServiceEvent.class);
when(serviceEvent.getType()).thenReturn(serviceEventType);
when(serviceEvent.getServiceReference()).thenReturn(eventRef);
eventProperties.put(EventConstants.EVENT, serviceEvent);
when(federationAdmin.getInternalRegistryMetacardsByRegistryId(searchRegId)).thenReturn(
metacards);
event = new Event("myevent", eventProperties);
cleanupHandler.handleEvent(event);
}
private ServiceReference getServiceReference(String pid) {
ServiceReference reference = mock(ServiceReference.class);
when(reference.getProperty(Constants.SERVICE_PID)).thenReturn(pid);
return reference;
}
private void setupSerialExecutor() {
doAnswer((args) -> {
((Runnable) args.getArguments()[0]).run();
return null;
}).when(executorService)
.execute(any());
}
}