/**
* 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.controller;
import static org.junit.Assert.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import static org.mockito.AdditionalAnswers.*;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.candlepin.model.Content;
import org.candlepin.model.Owner;
import org.candlepin.model.Pool;
import org.candlepin.model.Product;
import org.candlepin.model.ProductContent;
import org.candlepin.model.dto.ProductData;
import org.candlepin.test.DatabaseTestFixture;
import org.candlepin.test.TestUtil;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Arrays;
import java.util.Date;
/**
* ProductManagerTest
*/
@RunWith(JUnitParamsRunner.class)
public class ProductManagerTest extends DatabaseTestFixture {
private EntitlementCertificateGenerator mockEntCertGenerator;
private ProductManager productManager;
@Before
public void setup() throws Exception {
this.mockEntCertGenerator = mock(EntitlementCertificateGenerator.class);
this.productManager = new ProductManager(
this.mockEntCertGenerator, this.ownerContentCurator, this.ownerProductCurator, this.productCurator
);
}
@Test
public void testCreateProduct() {
Owner owner = this.createOwner("test-owner", "Test Owner");
ProductData dto = TestUtil.createProductDTO("p1", "prod1");
assertNull(this.ownerProductCurator.getProductById(owner, "p1"));
Product output = this.productManager.createProduct(dto, owner);
assertEquals(output, this.ownerProductCurator.getProductById(owner, "p1"));
}
@Test(expected = IllegalStateException.class)
public void testCreateProductThatAlreadyExists() {
Owner owner = this.createOwner("test-owner", "Test Owner");
ProductData dto = TestUtil.createProductDTO("p1", "prod1");
Product output = this.productManager.createProduct(dto, owner);
assertNotNull(output);
assertEquals(output, this.ownerProductCurator.getProductById(owner, dto.getId()));
this.productManager.createProduct(dto, owner);
}
@Test
public void testCreateProductMergeWithExisting() {
Owner owner1 = this.createOwner("test-owner-1", "Test Owner 1");
Owner owner2 = this.createOwner("test-owner-2", "Test Owner 2");
Product product1 = TestUtil.createProduct("p1", "prod1");
Product product2 = this.createProduct("p1", "prod1", owner2);
Product output = this.productManager.createProduct(product1.toDTO(), owner1);
assertEquals(output.getUuid(), product2.getUuid());
assertEquals(output, product2);
assertTrue(this.ownerProductCurator.isProductMappedToOwner(output, owner1));
assertTrue(this.ownerProductCurator.isProductMappedToOwner(output, owner2));
}
@Test
public void testUpdateProductNoChange() {
Owner owner = this.createOwner("test-owner", "Test Owner");
Product product = this.createProduct("p1", "prod1", owner);
Product output = this.productManager.updateProduct(product.toDTO(), owner, true);
assertEquals(output.getUuid(), product.getUuid());
assertEquals(output, product);
verifyZeroInteractions(this.mockEntCertGenerator);
}
@Test
@Parameters({"false", "true"})
public void testUpdateProduct(boolean regenCerts) {
Owner owner = this.createOwner("test-owner", "Test Owner");
Product product = this.createProduct("p1", "prod1", owner);
ProductData update = TestUtil.createProductDTO("p1", "new product name");
Product output = this.productManager.updateProduct(update, owner, regenCerts);
assertNotEquals(output.getUuid(), product.getUuid());
assertEquals(output.getName(), update.getName());
// We expect the original to be kept around as an orphan until the orphan removal job
// gets around to removing them
assertNotNull(this.productCurator.find(product.getUuid()));
assertEquals(0, this.ownerProductCurator.getOwnerCount(product));
assertNotNull(this.ownerProductCurator.getProductById(owner, product.getId()));
if (regenCerts) {
// TODO: Is there a better way to do this? We won't know the exact product instance,
// we just know that a product should be refreshed as a result of this operation.
verify(this.mockEntCertGenerator, times(1)).regenerateCertificatesOf(
eq(Arrays.asList(owner)), anyCollectionOf(Product.class), anyBoolean()
);
}
else {
verifyZeroInteractions(this.mockEntCertGenerator);
}
}
@Test
@Parameters({"false", "true"})
public void testUpdateProductConvergeWithExisting(boolean regenCerts) {
Owner owner1 = this.createOwner("test-owner-1", "Test Owner 1");
Owner owner2 = this.createOwner("test-owner-2", "Test Owner 2");
Product product1 = this.createProduct("p1", "prod1", owner1);
Product product2 = this.createProduct("p1", "updated product", owner2);
ProductData update = TestUtil.createProductDTO("p1", "updated product");
assertTrue(this.ownerProductCurator.isProductMappedToOwner(product1, owner1));
assertFalse(this.ownerProductCurator.isProductMappedToOwner(product2, owner1));
assertFalse(this.ownerProductCurator.isProductMappedToOwner(product1, owner2));
assertTrue(this.ownerProductCurator.isProductMappedToOwner(product2, owner2));
Product output = this.productManager.updateProduct(update, owner1, regenCerts);
assertEquals(output.getUuid(), product2.getUuid());
assertFalse(this.ownerProductCurator.isProductMappedToOwner(product1, owner1));
assertTrue(this.ownerProductCurator.isProductMappedToOwner(product2, owner1));
assertFalse(this.ownerProductCurator.isProductMappedToOwner(product1, owner2));
assertTrue(this.ownerProductCurator.isProductMappedToOwner(product2, owner2));
if (regenCerts) {
verify(this.mockEntCertGenerator, times(1)).regenerateCertificatesOf(
eq(Arrays.asList(owner1)), anyCollectionOf(Product.class), anyBoolean()
);
}
else {
verifyZeroInteractions(this.mockEntCertGenerator);
}
}
@Test
@Parameters({"false", "true"})
public void testUpdateProductDivergeFromExisting(boolean regenCerts) {
Owner owner1 = this.createOwner("test-owner-1", "Test Owner 1");
Owner owner2 = this.createOwner("test-owner-2", "Test Owner 2");
Product product = this.createProduct("p1", "prod1", owner1, owner2);
ProductData update = TestUtil.createProductDTO("p1", "updated product");
assertTrue(this.ownerProductCurator.isProductMappedToOwner(product, owner1));
assertTrue(this.ownerProductCurator.isProductMappedToOwner(product, owner2));
Product output = this.productManager.updateProduct(update, owner1, regenCerts);
assertNotEquals(output.getUuid(), product.getUuid());
assertTrue(this.ownerProductCurator.isProductMappedToOwner(output, owner1));
assertFalse(this.ownerProductCurator.isProductMappedToOwner(output, owner2));
assertFalse(this.ownerProductCurator.isProductMappedToOwner(product, owner1));
assertTrue(this.ownerProductCurator.isProductMappedToOwner(product, owner2));
if (regenCerts) {
verify(this.mockEntCertGenerator, times(1)).regenerateCertificatesOf(
eq(Arrays.asList(owner1)), anyCollectionOf(Product.class), anyBoolean()
);
}
else {
verifyZeroInteractions(this.mockEntCertGenerator);
}
}
@Test(expected = IllegalStateException.class)
public void testUpdateProductThatDoesntExist() {
Owner owner = this.createOwner("test-owner", "Test Owner");
Product product = TestUtil.createProduct("p1", "new_name");
ProductData update = TestUtil.createProductDTO("p1", "new_name");
assertFalse(this.ownerProductCurator.isProductMappedToOwner(product, owner));
this.productManager.updateProduct(update, owner, false);
}
@Test
public void testRemoveProduct() {
Owner owner = this.createOwner("test-owner-1", "Test Owner 1");
Product product = this.createProduct("p1", "prod1", owner);
assertTrue(this.ownerProductCurator.isProductMappedToOwner(product, owner));
this.productManager.removeProduct(owner, product);
// The product will be orphaned, but should still exist
assertFalse(this.ownerProductCurator.isProductMappedToOwner(product, owner));
assertNotNull(this.productCurator.find(product.getUuid()));
assertEquals(0, this.ownerProductCurator.getOwnerCount(product));
verifyZeroInteractions(this.mockEntCertGenerator);
}
@Test
public void testRemoveProductDivergeFromExisting() {
Owner owner1 = this.createOwner("test-owner-1", "Test Owner 1");
Owner owner2 = this.createOwner("test-owner-2", "Test Owner 2");
Product product = this.createProduct("p1", "prod1", owner1, owner2);
assertTrue(this.ownerProductCurator.isProductMappedToOwner(product, owner1));
assertTrue(this.ownerProductCurator.isProductMappedToOwner(product, owner2));
this.productManager.removeProduct(owner1, product);
assertFalse(this.ownerProductCurator.isProductMappedToOwner(product, owner1));
assertTrue(this.ownerProductCurator.isProductMappedToOwner(product, owner2));
assertNotNull(this.productCurator.find(product.getUuid()));
assertEquals(1, this.ownerProductCurator.getOwnerCount(product));
verifyZeroInteractions(this.mockEntCertGenerator);
}
@Test(expected = IllegalStateException.class)
public void testRemoveProductThatDoesntExist() {
Owner owner = this.createOwner("test-owner", "Test Owner");
Product product = TestUtil.createProduct("p1", "prod1");
assertFalse(this.ownerProductCurator.isProductMappedToOwner(product, owner));
this.productManager.removeProduct(owner, product);
}
@Test(expected = IllegalStateException.class)
public void testRemoveProductWithSubscriptions() {
long now = System.currentTimeMillis();
Owner owner = this.createOwner("test-owner", "Test Owner");
Product product = this.createProduct("p1", "prod1", owner);
Pool pool = this.createPool(owner, product, 1L, new Date(now - 86400), new Date(now + 86400));
this.productManager.removeProduct(owner, product);
}
@Test
@Parameters({"false", "true"})
public void testRemoveProductContent(boolean regenCerts) {
Owner owner = this.createOwner("test-owner", "Test Owner");
Product product = TestUtil.createProduct("p1", "prod1");
Content content = TestUtil.createContent("c1");
product.addContent(content, true);
this.contentCurator.create(content);
this.productCurator.create(product);
this.ownerProductCurator.mapProductToOwners(product, owner);
this.ownerContentCurator.mapContentToOwner(content, owner);
Product output = this.productManager.removeProductContent(
product, Arrays.asList(content), owner, regenCerts
);
assertFalse(output.hasContent(content.getId()));
// When we change the content associated with a product, we're making a net change to the
// product itself, which should trigger the creation of a new product object (since reuse
// is currently disabled). The old product will still, temporarily, exist as an orphan
// until the orphan cleanup job has a chance to run and remove them.
assertNotNull(this.productCurator.find(product.getUuid()));
assertEquals(0, this.ownerProductCurator.getOwnerCount(product));
assertNotNull(this.ownerProductCurator.getProductById(owner, product.getId()));
assertNotNull(this.contentCurator.find(content.getUuid()));
if (regenCerts) {
verify(this.mockEntCertGenerator, times(1)).regenerateCertificatesOf(
eq(Arrays.asList(owner)), anyCollectionOf(Product.class), anyBoolean()
);
}
else {
verifyZeroInteractions(this.mockEntCertGenerator);
}
}
@Test
@Parameters({"false", "true"})
public void testRemoveContentFromSharedProduct(boolean regenCerts) {
Owner owner1 = this.createOwner("test-owner-1", "Test Owner 1");
Owner owner2 = this.createOwner("test-owner-2", "Test Owner 2");
Product product = TestUtil.createProduct("p1", "prod1");
Content content = TestUtil.createContent("c1");
product.addContent(content, true);
content = this.contentCurator.create(content);
product = this.productCurator.create(product);
this.ownerProductCurator.mapProductToOwners(product, owner1, owner2);
this.ownerContentCurator.mapContentToOwner(content, owner1);
Product output = this.productManager.removeProductContent(
product, Arrays.asList(content), owner1, regenCerts
);
assertNotEquals(product, output);
assertFalse(output.hasContent(content.getId()));
assertTrue(product.hasContent(content.getId()));
assertFalse(this.ownerProductCurator.isProductMappedToOwner(product, owner1));
assertTrue(this.ownerProductCurator.isProductMappedToOwner(product, owner2));
assertTrue(this.ownerProductCurator.isProductMappedToOwner(output, owner1));
assertFalse(this.ownerProductCurator.isProductMappedToOwner(output, owner2));
if (regenCerts) {
verify(this.mockEntCertGenerator, times(1)).regenerateCertificatesOf(
eq(Arrays.asList(owner1)), anyCollectionOf(Product.class), anyBoolean()
);
}
else {
verifyZeroInteractions(this.mockEntCertGenerator);
}
}
@Test
public void testRemoveContentFromProductForBadOwner() {
Owner owner = this.createOwner("test-owner", "Test Owner");
Owner owner2 = this.createOwner("test-owner-2", "Test Owner");
Product product = TestUtil.createProduct("p1", "prod1");
Content content = TestUtil.createContent("c1");
product.addContent(content, true);
this.contentCurator.create(content);
this.productCurator.create(product);
this.ownerProductCurator.mapProductToOwner(product, owner);
this.ownerContentCurator.mapContentToOwner(content, owner);
Product output = this.productManager.removeProductContent(
product, Arrays.asList(content), owner2, false
);
assertTrue(output == product);
assertTrue(product.hasContent(content.getId()));
}
@Test
public void testAddContentToProduct() {
Owner owner = this.createOwner("test-owner-1", "Test Owner 1");
Product product = this.createProduct("p1", "prod1");
Content content = this.createContent("c1", "content1", owner);
this.ownerProductCurator.mapProductToOwners(product, owner);
Product output = this.productManager.addContentToProduct(
product, Arrays.asList(new ProductContent(null, content, true)), owner, false
);
assertNotEquals(product, output);
assertTrue(output.hasContent(content.getId()));
verifyZeroInteractions(this.mockEntCertGenerator);
}
@Test
@Parameters({"false", "true"})
public void testAddContentToSharedProduct(boolean regenCerts) {
Owner owner1 = this.createOwner("test-owner-1", "Test Owner 1");
Owner owner2 = this.createOwner("test-owner-2", "Test Owner 2");
Product product = this.createProduct("p1", "prod1", owner1);
Content content = this.createContent("c1", "content1", owner1);
this.ownerProductCurator.mapProductToOwners(product, owner1, owner2);
Product output = this.productManager.addContentToProduct(
product, Arrays.asList(new ProductContent(null, content, true)), owner1, regenCerts
);
assertNotEquals(product, output);
assertFalse(product.hasContent(content.getId()));
assertTrue(output.hasContent(content.getId()));
assertFalse(this.ownerProductCurator.isProductMappedToOwner(product, owner1));
assertTrue(this.ownerProductCurator.isProductMappedToOwner(product, owner2));
assertTrue(this.ownerProductCurator.isProductMappedToOwner(output, owner1));
assertFalse(this.ownerProductCurator.isProductMappedToOwner(output, owner2));
if (regenCerts) {
verify(this.mockEntCertGenerator, times(1)).regenerateCertificatesOf(
eq(Arrays.asList(owner1)), anyCollectionOf(Product.class), anyBoolean()
);
}
else {
verifyZeroInteractions(this.mockEntCertGenerator);
}
}
// Move this to ContentManagerTest
@Test
public void testUpdateProductContentOnSharedProduct() {
Owner owner1 = this.createOwner("test-owner-1", "Test Owner 1");
Owner owner2 = this.createOwner("test-owner-2", "Test Owner 2");
Product product = this.createProduct("p1", "prod1", owner1);
Content content = this.createContent("c1", "content1", owner1);
this.ownerProductCurator.mapProductToOwners(product, owner1, owner2);
product.setProductContent(Arrays.asList(new ProductContent(product, content, true)));
this.productCurator.merge(product);
Product output = this.productManager.addContentToProduct(
product, Arrays.asList(new ProductContent(null, content, false)), owner1, false
);
assertNotEquals(product, output);
assertTrue(product.hasContent(content.getId()));
assertTrue(output.hasContent(content.getId()));
assertTrue(product.getProductContent().iterator().next().isEnabled());
assertFalse(output.getProductContent().iterator().next().isEnabled());
assertFalse(this.ownerProductCurator.isProductMappedToOwner(product, owner1));
assertTrue(this.ownerProductCurator.isProductMappedToOwner(product, owner2));
assertTrue(this.ownerProductCurator.isProductMappedToOwner(output, owner1));
assertFalse(this.ownerProductCurator.isProductMappedToOwner(output, owner2));
verifyZeroInteractions(this.mockEntCertGenerator);
}
}