/**
* 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.resourcemanagement.usage;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.Serializable;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SimpleSession;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DelegatingSubject;
import org.codice.ddf.persistence.PersistenceException;
import org.codice.ddf.persistence.attributes.AttributesStore;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import ddf.catalog.Constants;
import ddf.catalog.data.Metacard;
import ddf.catalog.operation.ResourceRequest;
import ddf.catalog.operation.ResourceResponse;
import ddf.catalog.plugin.PluginExecutionException;
import ddf.catalog.plugin.StopProcessingException;
import ddf.catalog.resource.DataUsageLimitExceededException;
import ddf.security.SecurityConstants;
import ddf.security.Subject;
public class TestResourceUsagePlugin {
private ResourceUsagePlugin plugin;
private AttributesStore attributeStore;
private static final String TEST_USER = "testuser";
private static final String RESOURCE_SIZE = "100";
private static final String RESOURCE_SIZE_LARGE = "200";
private static final long DATA_LIMIT = 200L;
private Subject subject;
@Before
public void setUp() throws PersistenceException {
attributeStore = mock(AttributesStore.class);
doReturn(DATA_LIMIT).when(attributeStore)
.getDataLimitByUser(anyString());
plugin = new ResourceUsagePlugin(attributeStore);
plugin.setMonitorLocalSources(true);
}
@Test
public void getMonitorLocalSources() {
assertThat(plugin.getMonitorLocalSources(), is(true));
}
@Test
public void testNullInput() throws StopProcessingException, PluginExecutionException {
assertThat(plugin.process((ResourceRequest) null), is(nullValue()));
assertThat(plugin.process((ResourceResponse) null), is(nullValue()));
}
@Test
public void testPreResourceValidSize()
throws StopProcessingException, PluginExecutionException, PersistenceException {
ArgumentCaptor<String> usernameArg = ArgumentCaptor.forClass(String.class);
ResourceRequest originalRequest = getMockLocalResourceRequest(RESOURCE_SIZE, TEST_USER);
ResourceRequest request = plugin.process(originalRequest);
assertThat(request, notNullValue());
assertThat(request, is(originalRequest));
verify(attributeStore).getDataLimitByUser(usernameArg.capture());
assertThat(usernameArg.getValue(), is(TEST_USER));
}
@Test(expected = DataUsageLimitExceededException.class)
public void testPreResourceSizeExceedsDataLimit()
throws StopProcessingException, PluginExecutionException, PersistenceException {
doReturn(DATA_LIMIT).when(attributeStore)
.getCurrentDataUsageByUser(anyString());
ResourceRequest originalRequest = getMockLocalResourceRequest(RESOURCE_SIZE_LARGE, TEST_USER);
plugin.process(originalRequest);
}
@Test
public void testPreResourceLocalSourceSizeNotFound()
throws PersistenceException, PluginExecutionException, StopProcessingException {
ResourceRequest originalRequest = getMockLocalResourceRequest(null, TEST_USER);
ResourceRequest request = plugin.process(originalRequest);
assertThat(request, is(notNullValue()));
assertThat(request, is(originalRequest));
verify(attributeStore, never()).getDataLimitByUser(anyString());
verify(attributeStore, never()).getCurrentDataUsageByUser(anyString());
}
@Test
public void testPreResourceLocalSourceInvalidSize()
throws StopProcessingException, PluginExecutionException, PersistenceException {
ResourceRequest originalRequest = getMockLocalResourceRequest("47 bytes", TEST_USER);
ResourceRequest request = plugin.process(originalRequest);
assertThat(request, is(notNullValue()));
assertThat(request, is(originalRequest));
verify(attributeStore, never()).getDataLimitByUser(anyString());
verify(attributeStore, never()).getCurrentDataUsageByUser(anyString());
}
@Test
public void testPreResourceLocalSourceNoLocalMonitoring()
throws StopProcessingException, PluginExecutionException, PersistenceException {
plugin.setMonitorLocalSources(false);
ResourceRequest originalRequest = getMockLocalResourceRequest(RESOURCE_SIZE, TEST_USER);
ResourceRequest request = plugin.process(originalRequest);
assertThat(request, is(notNullValue()));
assertThat(request, is(originalRequest));
verify(attributeStore, never()).getDataLimitByUser(anyString());
verify(attributeStore, never()).getCurrentDataUsageByUser(anyString());
}
@Test
public void testPostResourceLocalSourceNoLocalMonitoring()
throws StopProcessingException, PluginExecutionException, PersistenceException {
plugin.setMonitorLocalSources(false);
ResourceResponse originalResponse = getMockLocalResourceResponse(RESOURCE_SIZE, TEST_USER);
ResourceResponse response = plugin.process(originalResponse);
assertThat(response, is(notNullValue()));
assertThat(response, is(originalResponse));
verify(attributeStore, never()).getDataLimitByUser(anyString());
verify(attributeStore, never()).getCurrentDataUsageByUser(anyString());
}
@Test
public void testPostResourceRemoteSourceNoRemoteDestinationKey() throws Exception {
plugin.setMonitorLocalSources(false);
ResourceResponse originalResponse= getMockRemoteResourceResponseNoRemoteDestinationKey(
RESOURCE_SIZE,
TEST_USER);
ResourceResponse response = plugin.process(originalResponse);
assertThat(response, is(notNullValue()));
assertThat(response, is(originalResponse));
verify(attributeStore, never()).getDataLimitByUser(anyString());
verify(attributeStore, never()).getCurrentDataUsageByUser(anyString());
}
@Test
public void testPostResourceRemoteSourceFalseRemoteDestinationKey() throws Exception {
plugin.setMonitorLocalSources(false);
ResourceResponse originalResponse = getMockRemoteResourceResponseFalseRemoteDestinationKey(
RESOURCE_SIZE,
TEST_USER);
ResourceResponse response = plugin.process(originalResponse);
assertThat(response, is(notNullValue()));
assertThat(response, is(originalResponse));
verify(attributeStore, never()).getDataLimitByUser(anyString());
verify(attributeStore, never()).getCurrentDataUsageByUser(anyString());
}
@Test
public void testPreResourcePersistenceException()
throws StopProcessingException, PluginExecutionException, PersistenceException {
doThrow(PersistenceException.class).when(attributeStore)
.getCurrentDataUsageByUser(anyString());
ResourceRequest originalRequest = getMockLocalResourceRequest(RESOURCE_SIZE, TEST_USER);
ResourceRequest request = plugin.process(originalRequest);
assertThat(request, notNullValue());
assertThat(request, is(originalRequest));
}
@Test
public void testPostResourcePersistenceException()
throws StopProcessingException, PluginExecutionException, PersistenceException {
doThrow(PersistenceException.class).when(attributeStore).updateUserDataUsage(anyString(),
anyLong());
ResourceResponse resourceResponse = getMockLocalResourceResponse(RESOURCE_SIZE, TEST_USER);
ResourceResponse response = plugin.process(resourceResponse);
assertThat(response, notNullValue());
assertThat(response, is(resourceResponse));
}
@Test
public void testPreResourceNoSubject()
throws StopProcessingException, PluginExecutionException, PersistenceException {
ResourceRequest originalRequest = getMockResourceRequestNoSubject(RESOURCE_SIZE);
ResourceRequest request = plugin.process(originalRequest);
assertThat(request, is(notNullValue()));
assertThat(request, is(originalRequest));
verify(attributeStore, never()).getDataLimitByUser(anyString());
verify(attributeStore, never()).getCurrentDataUsageByUser(anyString());
}
@Test
public void testPostResourceNoSubject()
throws StopProcessingException, PluginExecutionException, PersistenceException {
ResourceResponse originalResponse = getMockResourceResponseNoSubject(RESOURCE_SIZE);
ResourceResponse response = plugin.process(originalResponse);
assertThat(response, is(notNullValue()));
assertThat(response, is(originalResponse));
verify(attributeStore, never()).updateUserDataUsage(anyString(), anyLong());
}
@Test
public void testPostResourceLocalSourceValidSize()
throws StopProcessingException, PluginExecutionException, PersistenceException {
ArgumentCaptor<String> usernameArg = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<Long> dataUsage = ArgumentCaptor.forClass(Long.class);
ResourceResponse originalResponse = getMockLocalResourceResponse(RESOURCE_SIZE, TEST_USER);
ResourceResponse response = plugin.process(originalResponse);
assertThat(response, notNullValue());
assertThat(response, is(originalResponse));
verify(attributeStore).updateUserDataUsage(usernameArg.capture(), dataUsage.capture());
assertThat(usernameArg.getValue(), is(TEST_USER));
assertThat(dataUsage.getValue(), is(Long.valueOf(RESOURCE_SIZE)));
}
@Test
public void testPostResourceLocalSourceSizeNotFound()
throws PersistenceException, PluginExecutionException, StopProcessingException {
ResourceResponse resourceResponse = getMockLocalResourceResponse(null, TEST_USER);
ResourceResponse request = plugin.process(resourceResponse);
assertThat(request, is(notNullValue()));
assertThat(request, is(resourceResponse));
verify(attributeStore, never()).updateUserDataUsage(anyString(), anyLong());
}
@Test
public void testPostResourceInvalidSize()
throws StopProcessingException, PluginExecutionException, PersistenceException {
ResourceResponse originalResponse = getMockLocalResourceResponse("47 bytes", TEST_USER);
ResourceResponse response = plugin.process(originalResponse);
assertThat(response, is(notNullValue()));
assertThat(response, is(originalResponse));
verify(attributeStore, never()).updateUserDataUsage(anyString(), anyLong());
}
@Test
public void testPreResourceRemoteSourceValidSize() throws Exception {
plugin.setMonitorLocalSources(false);
ArgumentCaptor<String> usernameArg = ArgumentCaptor.forClass(String.class);
ResourceRequest originalRequest = getMockRemoteResourceRequest(RESOURCE_SIZE, TEST_USER);
ResourceRequest request = plugin.process(originalRequest);
assertThat(request, notNullValue());
assertThat(request, is(originalRequest));
verify(attributeStore).getDataLimitByUser(usernameArg.capture());
assertThat(usernameArg.getValue(), is(TEST_USER));
}
@Test
public void testPostResourceRemoteSourceValidSize() throws Exception {
plugin.setMonitorLocalSources(false);
ArgumentCaptor<String> usernameArg = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<Long> dataUsage = ArgumentCaptor.forClass(Long.class);
ResourceResponse originalResponse = getMockRemoteResourceResponse(RESOURCE_SIZE, TEST_USER);
ResourceResponse response = plugin.process(originalResponse);
assertThat(response, notNullValue());
assertThat(response, is(originalResponse));
verify(attributeStore).updateUserDataUsage(usernameArg.capture(), dataUsage.capture());
assertThat(usernameArg.getValue(), is(TEST_USER));
assertThat(dataUsage.getValue(), is(Long.valueOf(RESOURCE_SIZE)));
}
private ResourceResponse getMockResourceResponse(String resourceSize, String expectedUsername) {
setSubject(expectedUsername);
ResourceResponse resourceResponse = mock(ResourceResponse.class);
Map<String, Serializable> responseProperties = new HashMap<>();
responseProperties.put(SecurityConstants.SECURITY_SUBJECT, subject);
responseProperties.put(Metacard.RESOURCE_SIZE, resourceSize);
when(resourceResponse.getPropertyNames()).thenReturn(responseProperties.keySet());
when(resourceResponse.getPropertyValue(SecurityConstants.SECURITY_SUBJECT)).thenReturn(
subject);
when(resourceResponse.getPropertyValue(Metacard.RESOURCE_SIZE)).thenReturn(resourceSize);
return resourceResponse;
}
private ResourceRequest getMockResourceRequest(String resourceSize,
String expectedUsername) {
setSubject(expectedUsername);
ResourceRequest resourceRequest = mock(ResourceRequest.class);
Map<String, Serializable> requestProperties = new HashMap<>();
requestProperties.put(SecurityConstants.SECURITY_SUBJECT, subject);
requestProperties.put(Metacard.RESOURCE_SIZE, resourceSize);
when(resourceRequest.getPropertyNames()).thenReturn(requestProperties.keySet());
when(resourceRequest.getPropertyValue(SecurityConstants.SECURITY_SUBJECT)).thenReturn(
subject);
when(resourceRequest.getPropertyValue(Metacard.RESOURCE_SIZE)).thenReturn(resourceSize);
return resourceRequest;
}
private ResourceResponse getMockLocalResourceResponse(String resourceSize,
String expectedUsername) {
setSubject(expectedUsername);
return getMockResourceResponse(resourceSize, expectedUsername);
}
private ResourceRequest getMockLocalResourceRequest(String resourceSize,
String expectedUsername) {
setSubject(expectedUsername);
return getMockResourceRequest(resourceSize, expectedUsername);
}
private ResourceRequest getMockRemoteResourceRequest(String resourceSize,
String expectedUsername) {
setSubject(expectedUsername);
ResourceRequest resourceRequest =getMockResourceRequest(resourceSize, expectedUsername);
when(resourceRequest.getPropertyValue(Constants.REMOTE_DESTINATION_KEY)).thenReturn(true);
when(resourceRequest.hasProperties()).thenReturn(true);
return resourceRequest;
}
private ResourceResponse getMockRemoteResourceResponse(String resourceSize,
String expectedUsername) {
setSubject(expectedUsername);
ResourceResponse resourceResponse = getMockResourceResponse(resourceSize, expectedUsername);
when(resourceResponse.getPropertyValue(Constants.REMOTE_DESTINATION_KEY)).thenReturn(true);
when(resourceResponse.hasProperties()).thenReturn(true);
return resourceResponse;
}
private ResourceResponse getMockRemoteResourceResponseNoRemoteDestinationKey(
String resourceSize, String expectedUsername) {
setSubject(expectedUsername);
ResourceResponse resourceResponse = getMockResourceResponse(resourceSize, expectedUsername);
when(resourceResponse.hasProperties()).thenReturn(true);
return resourceResponse;
}
private ResourceResponse getMockRemoteResourceResponseFalseRemoteDestinationKey(
String resourceSize, String expectedUsername) {
setSubject(expectedUsername);
ResourceResponse resourceResponse = getMockResourceResponse(resourceSize, expectedUsername);
when(resourceResponse.getPropertyValue(Constants.REMOTE_DESTINATION_KEY)).thenReturn(false);
when(resourceResponse.hasProperties()).thenReturn(true);
return resourceResponse;
}
private ResourceRequest getMockResourceRequestNoSubject(String resourceSize) {
ResourceRequest resourceRequest =getMockResourceRequest(resourceSize, null);
when(resourceRequest.getPropertyValue(SecurityConstants.SECURITY_SUBJECT)).thenReturn(
null);
return resourceRequest;
}
private ResourceResponse getMockResourceResponseNoSubject(String resourceSize) {
ResourceResponse resourceResponse = getMockResourceResponse(resourceSize, null);
when(resourceResponse.getPropertyValue(SecurityConstants.SECURITY_SUBJECT)).thenReturn(null);
return resourceResponse;
}
private void setSubject(String expectedUsername) {
AuthorizingRealm realm = mock(AuthorizingRealm.class);
when(realm.getName()).thenReturn("mockRealm");
when(realm.isPermitted(any(PrincipalCollection.class), any(Permission.class))).thenReturn(
true);
Collection<Realm> realms = new ArrayList<>();
realms.add(realm);
DefaultSecurityManager manager = new DefaultSecurityManager();
manager.setRealms(realms);
SimplePrincipalCollection principalCollection =
new SimplePrincipalCollection(new Principal() {
@Override
public String getName() {
return expectedUsername;
}
@Override
public String toString() {
return expectedUsername;
}
}, realm.getName());
subject = new MockSubject(manager, principalCollection);
}
private class MockSubject extends DelegatingSubject implements Subject {
public MockSubject(SecurityManager manager, PrincipalCollection principals) {
super(principals, true, null, new SimpleSession(UUID.randomUUID()
.toString()), manager);
}
@Override
public boolean isGuest() {
return false;
}
}
}