/**
* Copyright (c) 2009 - 2012 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package org.candlepin.policy.js.entitlement;
import static org.hamcrest.Matchers.hasItems;
import static org.junit.Assert.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import org.candlepin.config.ConfigProperties;
import org.candlepin.controller.PoolManager;
import org.candlepin.model.ConsumerType;
import org.candlepin.model.ConsumerType.ConsumerTypeEnum;
import org.candlepin.model.Entitlement;
import org.candlepin.model.Owner;
import org.candlepin.model.Pool;
import org.candlepin.model.Product;
import org.candlepin.model.PoolQuantity;
import org.candlepin.model.dto.Subscription;
import org.candlepin.test.TestUtil;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* HostedVirtLimitEntitlementRulesTest: Complex tests around the hosted virt limit
* bonus pool functionality.
*/
public class HostedVirtLimitEntitlementRulesTest extends EntitlementRulesTestFixture {
@Test
public void hostedParentConsumerPostCreatesNoPool() {
Pool pool = setupVirtLimitPool();
List<Pool> pools = new ArrayList<Pool>();
pools.add(pool);
Map<String, Entitlement> entitlements = new HashMap<String, Entitlement>();
entitlements.put(pool.getId(), new Entitlement(pool, consumer, 1));
Map<String, PoolQuantity> poolQuantityMap = new HashMap<String, PoolQuantity>();
poolQuantityMap.put(pool.getId(), new PoolQuantity(pool, 1));
PoolManager poolManager = mock(PoolManager.class);
when(config.getBoolean(ConfigProperties.STANDALONE)).thenReturn(false);
enforcer.postEntitlement(poolManager, consumer, entitlements, null, false, poolQuantityMap);
verify(poolManager, never()).createPools(any(List.class));
}
@Test
@SuppressWarnings("unchecked")
public void hostedVirtLimitAltersBonusPoolQuantity() {
when(config.getBoolean(ConfigProperties.STANDALONE)).thenReturn(false);
Subscription s = createVirtLimitSub("virtLimitProduct", 10, "10");
consumer.setType(new ConsumerType(ConsumerTypeEnum.CANDLEPIN));
List<Pool> pools = poolRules.createAndEnrichPools(TestUtil.copyFromSub(s), new LinkedList<Pool>());
assertEquals(2, pools.size());
Pool physicalPool = pools.get(0);
physicalPool.setId("physical");
Pool virtBonusPool = pools.get(1);
virtBonusPool.setId("virt");
assertEquals(new Long(10), physicalPool.getQuantity());
assertEquals(0, physicalPool.getAttributes().size());
// Quantity on bonus pool should be virt limit * sub quantity:
assertEquals(new Long(100), virtBonusPool.getQuantity());
assertEquals("true", virtBonusPool.getAttributeValue(Product.Attributes.VIRT_ONLY));
assertEquals("10", virtBonusPool.getProduct().getAttributeValue(Product.Attributes.VIRT_LIMIT));
Entitlement e = new Entitlement(physicalPool, consumer, 1);
List<Pool> poolList = new ArrayList<Pool>();
poolList.add(virtBonusPool);
ArgumentCaptor<Set> captor = ArgumentCaptor.forClass(Set.class);
ArgumentCaptor<Owner> ownerCaptor = ArgumentCaptor.forClass(Owner.class);
when(poolManagerMock.lookupBySubscriptionIds(ownerCaptor.capture(), captor.capture()))
.thenReturn(poolList);
when(poolManagerMock.lookupBySubscriptionId(eq(physicalPool.getOwner()),
eq(physicalPool.getSubscriptionId())))
.thenReturn(poolList);
Map<String, Entitlement> entitlements = new HashMap<String, Entitlement>();
entitlements.put(physicalPool.getId(), e);
Map<String, PoolQuantity> poolQuantityMap = new HashMap<String, PoolQuantity>();
poolQuantityMap.put(physicalPool.getId(), new PoolQuantity(physicalPool, 1));
List<Pool> physicalPools = new ArrayList<Pool>();
physicalPools.add(physicalPool);
enforcer.postEntitlement(poolManagerMock, consumer, entitlements, null, false, poolQuantityMap);
Set<String> subscriptionIds = captor.getValue();
assertEquals(1, subscriptionIds.size());
assertEquals("subId", subscriptionIds.iterator().next());
verify(poolManagerMock).updatePoolQuantity(eq(virtBonusPool), eq(-10L));
enforcer.postUnbind(consumer, poolManagerMock, e);
verify(poolManagerMock).updatePoolQuantity(eq(virtBonusPool), eq(10L));
}
@Test
public void batchHostedVirtLimitAltersBonusPoolQuantity() {
when(config.getBoolean(ConfigProperties.STANDALONE)).thenReturn(false);
consumer.setType(new ConsumerType(ConsumerTypeEnum.CANDLEPIN));
Subscription s = createVirtLimitSub("virtLimitProduct", 10, "10");
List<Pool> pools = poolRules.createAndEnrichPools(TestUtil.copyFromSub(s), new LinkedList<Pool>());
assertEquals(2, pools.size());
Pool physicalPool = pools.get(0);
physicalPool.setId("physical");
Pool virtBonusPool = pools.get(1);
virtBonusPool.setId("virt");
assertEquals(new Long(10), physicalPool.getQuantity());
assertEquals(0, physicalPool.getAttributes().size());
// Quantity on bonus pool should be virt limit * sub quantity:
assertEquals(new Long(100), virtBonusPool.getQuantity());
assertEquals("true", virtBonusPool.getAttributeValue(Product.Attributes.VIRT_ONLY));
assertEquals("10", virtBonusPool.getProduct().getAttributeValue(Product.Attributes.VIRT_LIMIT));
Entitlement e = new Entitlement(physicalPool, consumer, 1);
Subscription s2 = createVirtLimitSub("virtLimitProduct2", 10, "10");
s2.setId("subId2");
List<Pool> pools2 = poolRules.createAndEnrichPools(TestUtil.copyFromSub(s2), new LinkedList<Pool>());
assertEquals(2, pools.size());
Pool physicalPool2 = pools2.get(0);
physicalPool2.setId("physical2");
Pool virtBonusPool2 = pools2.get(1);
virtBonusPool2.setId("virt2");
assertEquals(new Long(10), physicalPool2.getQuantity());
assertEquals(0, physicalPool2.getAttributes().size());
// Quantity on bonus pool should be virt limit * sub quantity:
assertEquals(new Long(100), virtBonusPool2.getQuantity());
assertEquals("true", virtBonusPool2.getAttributeValue(Product.Attributes.VIRT_ONLY));
assertEquals("10", virtBonusPool2.getProduct().getAttributeValue(Product.Attributes.VIRT_LIMIT));
Entitlement e2 = new Entitlement(physicalPool2, consumer, 1);
List<Pool> poolList = new ArrayList<Pool>();
poolList.add(virtBonusPool);
List<Pool> poolList2 = new ArrayList<Pool>();
poolList.add(virtBonusPool2);
ArgumentCaptor<Set> captor = ArgumentCaptor.forClass(Set.class);
ArgumentCaptor<Owner> ownerCaptor = ArgumentCaptor.forClass(Owner.class);
when(poolManagerMock.lookupBySubscriptionIds(ownerCaptor.capture(), captor.capture()))
.thenReturn(poolList);
when(poolManagerMock.lookupBySubscriptionId(eq(physicalPool.getOwner()),
eq(physicalPool.getSubscriptionId())))
.thenReturn(poolList);
when(poolManagerMock.lookupBySubscriptionId(eq(physicalPool.getOwner()),
eq(physicalPool2.getSubscriptionId())))
.thenReturn(poolList2);
Map<String, Entitlement> entitlements = new HashMap<String, Entitlement>();
entitlements.put(physicalPool.getId(), e);
entitlements.put(physicalPool2.getId(), e2);
Map<String, PoolQuantity> poolQuantityMap = new HashMap<String, PoolQuantity>();
poolQuantityMap.put(physicalPool.getId(), new PoolQuantity(physicalPool, 1));
poolQuantityMap.put(physicalPool2.getId(), new PoolQuantity(physicalPool2, 1));
enforcer.postEntitlement(poolManagerMock, consumer, entitlements, null, false, poolQuantityMap);
@SuppressWarnings("unchecked")
Set<String> subscriptionIds = captor.getValue();
assertEquals(2, subscriptionIds.size());
assertThat(subscriptionIds, hasItems("subId", "subId2"));
verify(poolManagerMock).updatePoolQuantity(eq(virtBonusPool), eq(-10L));
verify(poolManagerMock).updatePoolQuantity(eq(virtBonusPool2), eq(-10L));
enforcer.postUnbind(consumer, poolManagerMock, e);
verify(poolManagerMock).updatePoolQuantity(eq(virtBonusPool), eq(10L));
enforcer.postUnbind(consumer, poolManagerMock, e2);
verify(poolManagerMock).updatePoolQuantity(eq(virtBonusPool2), eq(10L));
}
/*
* Bonus pools in hosted mode for products with the host_limited attribute
* are created during binding.
*/
@Test
public void hostedVirtLimitWithHostLimitedCreatesBonusPoolsOnBind() {
when(config.getBoolean(ConfigProperties.STANDALONE)).thenReturn(false);
Subscription s = createVirtLimitSub("virtLimitProduct", 10, "unlimited");
s.getProduct().setAttribute(Product.Attributes.HOST_LIMITED, "true");
List<Pool> pools = poolRules.createAndEnrichPools(TestUtil.copyFromSub(s), new LinkedList<Pool>());
assertEquals(2, pools.size());
Pool physicalPool = pools.get(0);
physicalPool.setId("physical");
assertEquals(new Long(10), physicalPool.getQuantity());
assertEquals(0, physicalPool.getAttributes().size());
Entitlement e = new Entitlement(physicalPool, consumer, 1);
Map<String, Entitlement> entitlements = new HashMap<String, Entitlement>();
entitlements.put(physicalPool.getId(), e);
Map<String, PoolQuantity> poolQuantityMap = new HashMap<String, PoolQuantity>();
poolQuantityMap.put(physicalPool.getId(), new PoolQuantity(physicalPool, 1));
enforcer.postEntitlement(poolManagerMock, consumer, entitlements, null, false, poolQuantityMap);
verify(poolManagerMock).createPools(any(List.class));
}
@Test
public void hostedVirtLimitUnlimitedBonusPoolQuantity() {
when(config.getBoolean(ConfigProperties.STANDALONE)).thenReturn(false);
Subscription s = createVirtLimitSub("virtLimitProduct", 10, "unlimited");
List<Pool> pools = poolRules.createAndEnrichPools(TestUtil.copyFromSub(s), new LinkedList<Pool>());
assertEquals(2, pools.size());
Pool physicalPool = pools.get(0);
physicalPool.setId("physical");
Pool virtBonusPool = pools.get(1);
virtBonusPool.setId("virt");
assertEquals(new Long(10), physicalPool.getQuantity());
assertEquals(0, physicalPool.getAttributes().size());
// Quantity on bonus pool should be -1:
assertEquals(new Long(-1), virtBonusPool.getQuantity());
assertEquals("true", virtBonusPool.getAttributeValue(Product.Attributes.VIRT_ONLY));
assertEquals("unlimited",
virtBonusPool.getProduct().getAttributeValue(Product.Attributes.VIRT_LIMIT));
Entitlement e = new Entitlement(physicalPool, consumer, 1);
List<Pool> poolList = new ArrayList<Pool>();
poolList.add(virtBonusPool);
when(poolManagerMock.lookupBySubscriptionId(eq(physicalPool.getOwner()),
eq(physicalPool.getSubscriptionId())))
.thenReturn(poolList);
Map<String, Entitlement> entitlements = new HashMap<String, Entitlement>();
entitlements.put(physicalPool.getId(), e);
Map<String, PoolQuantity> poolQuantityMap = new HashMap<String, PoolQuantity>();
poolQuantityMap.put(physicalPool.getId(), new PoolQuantity(physicalPool, 1));
enforcer.postEntitlement(poolManagerMock, consumer, entitlements, null, false, poolQuantityMap);
verify(poolManagerMock, never()).updatePoolQuantity(any(Pool.class), anyInt());
enforcer.postUnbind(consumer, poolManagerMock, e);
verify(poolManagerMock, never()).updatePoolQuantity(any(Pool.class), anyInt());
}
/*
* Bonus pools should not be created when we are in a hosted scenario without
* distributor binds.
*/
@Test
public void noBonusPoolsForHostedNonDistributorBinds() {
when(config.getBoolean(ConfigProperties.STANDALONE)).thenReturn(false);
Subscription s = createVirtLimitSub("virtLimitProduct", 10, "unlimited");
List<Pool> pools = poolRules.createAndEnrichPools(TestUtil.copyFromSub(s), new LinkedList<Pool>());
assertEquals(2, pools.size());
Pool physicalPool = pools.get(0);
physicalPool.setId("physical");
Pool virtBonusPool = pools.get(1);
virtBonusPool.setId("virt");
assertEquals(new Long(10), physicalPool.getQuantity());
assertEquals(0, physicalPool.getAttributes().size());
// Quantity on bonus pool should be -1:
assertEquals(new Long(-1), virtBonusPool.getQuantity());
assertEquals("true", virtBonusPool.getAttributeValue(Product.Attributes.VIRT_ONLY));
assertEquals("unlimited",
virtBonusPool.getProduct().getAttributeValue(Product.Attributes.VIRT_LIMIT));
Entitlement e = new Entitlement(physicalPool, consumer, 1);
Map<String, Entitlement> entitlements = new HashMap<String, Entitlement>();
entitlements.put(physicalPool.getId(), e);
Map<String, PoolQuantity> poolQuantityMap = new HashMap<String, PoolQuantity>();
poolQuantityMap.put(physicalPool.getId(), new PoolQuantity(physicalPool, 1));
enforcer.postEntitlement(poolManagerMock, consumer, entitlements, null, false, poolQuantityMap);
verify(poolManagerMock, never()).createPool(any(Pool.class));
verify(poolManagerMock, never()).updatePoolQuantity(any(Pool.class), anyInt());
enforcer.postUnbind(consumer, poolManagerMock, e);
verify(poolManagerMock, never()).updatePoolQuantity(any(Pool.class), anyInt());
verify(poolManagerMock, never()).setPoolQuantity(any(Pool.class), anyLong());
}
@Test
public void exportAllPhysicalZeroBonusPoolQuantity() {
when(config.getBoolean(ConfigProperties.STANDALONE)).thenReturn(false);
consumer.setType(new ConsumerType(ConsumerTypeEnum.CANDLEPIN));
Subscription s = createVirtLimitSub("virtLimitProduct", 10, "unlimited");
List<Pool> pools = poolRules.createAndEnrichPools(TestUtil.copyFromSub(s), new LinkedList<Pool>());
assertEquals(2, pools.size());
Pool physicalPool = pools.get(0);
physicalPool.setId("physical");
Pool virtBonusPool = pools.get(1);
virtBonusPool.setId("virt");
assertEquals(new Long(10), physicalPool.getQuantity());
assertEquals(0, physicalPool.getAttributes().size());
// Quantity on bonus pool should be -1:
assertEquals(new Long(-1), virtBonusPool.getQuantity());
assertEquals("true", virtBonusPool.getAttributeValue(Product.Attributes.VIRT_ONLY));
assertEquals("unlimited",
virtBonusPool.getProduct().getAttributeValue(Product.Attributes.VIRT_LIMIT));
Entitlement e = new Entitlement(physicalPool, consumer, 10);
physicalPool.setConsumed(10L);
physicalPool.setExported(10L);
List<Pool> poolList = new ArrayList<Pool>();
poolList.add(virtBonusPool);
ArgumentCaptor<Set> captor = ArgumentCaptor.forClass(Set.class);
ArgumentCaptor<Owner> ownerCaptor = ArgumentCaptor.forClass(Owner.class);
when(poolManagerMock.lookupBySubscriptionIds(ownerCaptor.capture(), captor.capture()))
.thenReturn(poolList);
when(poolManagerMock.lookupBySubscriptionId(eq(physicalPool.getOwner()), eq("subId")))
.thenReturn(poolList);
Map<String, Entitlement> entitlements = new HashMap<String, Entitlement>();
entitlements.put(physicalPool.getId(), e);
Map<String, PoolQuantity> poolQuantityMap = new HashMap<String, PoolQuantity>();
poolQuantityMap.put(physicalPool.getId(), new PoolQuantity(physicalPool, 10));
enforcer.postEntitlement(poolManagerMock, consumer, entitlements, null, false, poolQuantityMap);
@SuppressWarnings("unchecked")
Set<String> subscriptionIds = captor.getValue();
assertEquals(1, subscriptionIds.size());
assertEquals("subId", subscriptionIds.iterator().next());
verify(poolManagerMock).setPoolQuantity(eq(virtBonusPool), eq(0L));
virtBonusPool.setQuantity(0L);
enforcer.postUnbind(consumer, poolManagerMock, e);
verify(poolManagerMock).setPoolQuantity(eq(virtBonusPool), eq(-1L));
}
@Test
public void hostedVirtLimitDoesNotAlterQuantitiesForHostLimited() {
when(config.getBoolean(ConfigProperties.STANDALONE)).thenReturn(false);
consumer.setType(new ConsumerType(ConsumerTypeEnum.CANDLEPIN));
Pool virtBonusPool = setupVirtLimitPool();
virtBonusPool.setQuantity(100L);
virtBonusPool.setAttribute(Product.Attributes.HOST_LIMITED, "true");
virtBonusPool.setAttribute(Product.Attributes.VIRT_ONLY, "true");
virtBonusPool.setAttribute(Product.Attributes.VIRT_LIMIT, "10");
virtBonusPool.setAttribute(Pool.Attributes.DERIVED_POOL, "true");
Entitlement e = new Entitlement(virtBonusPool, consumer, 1);
List<Pool> poolList = new ArrayList<Pool>();
poolList.add(virtBonusPool);
when(poolManagerMock.lookupBySubscriptionId(eq(virtBonusPool.getOwner()),
eq(virtBonusPool.getSubscriptionId())))
.thenReturn(poolList);
Map<String, Entitlement> entitlements = new HashMap<String, Entitlement>();
entitlements.put(virtBonusPool.getId(), e);
Map<String, PoolQuantity> poolQuantityMap = new HashMap<String, PoolQuantity>();
poolQuantityMap.put(virtBonusPool.getId(), new PoolQuantity(virtBonusPool, 1));
enforcer.postEntitlement(poolManagerMock, consumer, entitlements, null, false, poolQuantityMap);
verify(poolManagerMock, never()).updatePoolQuantity(eq(virtBonusPool), eq(-10L));
enforcer.postUnbind(consumer, poolManagerMock, e);
verify(poolManagerMock, never()).updatePoolQuantity(eq(virtBonusPool), eq(10L));
}
}