/**
* 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.model;
import static org.hamcrest.Matchers.hasItem;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import org.candlepin.common.config.Configuration;
import org.candlepin.config.ConfigProperties;
import org.candlepin.test.DatabaseTestFixture;
import org.candlepin.test.TestUtil;
import org.candlepin.util.AttributeValidator;
import org.candlepin.util.PropertyValidationException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.persistence.PersistenceException;
import javax.validation.ConstraintViolationException;
public class ProductCuratorTest extends DatabaseTestFixture {
private static Logger log = LoggerFactory.getLogger(ProductCuratorTest.class);
@Inject private Configuration config;
private Owner owner;
private Product product;
private Product derivedProduct;
private Product providedProduct;
private Product derivedProvidedProduct;
private Pool pool;
@Before
public void setUp() throws Exception {
config.setProperty(ConfigProperties.INTEGER_ATTRIBUTES, "product.count, product.multiplier");
config.setProperty(ConfigProperties.NON_NEG_INTEGER_ATTRIBUTES, "product.pos_count");
config.setProperty(ConfigProperties.LONG_ATTRIBUTES, "product.long_count, product.long_multiplier");
config.setProperty(ConfigProperties.NON_NEG_LONG_ATTRIBUTES, "product.long_pos_count");
config.setProperty(ConfigProperties.BOOLEAN_ATTRIBUTES, "product.bool_val_str, product.bool_val_num");
// Inject this attributeValidator into the curator
Field field = ProductCurator.class.getDeclaredField("attributeValidator");
field.setAccessible(true);
field.set(this.productCurator, new AttributeValidator(this.config, this.i18n));
this.owner = this.createOwner();
product = TestUtil.createProduct();
productCurator.create(product);
providedProduct = TestUtil.createProduct();
productCurator.create(providedProduct);
Set<Product> providedProducts = new HashSet<Product>();
providedProducts.add(providedProduct);
derivedProduct = TestUtil.createProduct();
productCurator.create(derivedProduct);
derivedProvidedProduct = TestUtil.createProduct();
productCurator.create(derivedProvidedProduct);
Set<Product> derivedProvidedProducts = new HashSet<Product>();
derivedProvidedProducts.add(derivedProvidedProduct);
pool = new Pool(
owner,
product,
providedProducts,
16L,
TestUtil.createDate(2006, 10, 21),
TestUtil.createDate(2020, 1, 1),
"1",
"2",
"3"
);
pool.setDerivedProduct(derivedProduct);
pool.setDerivedProvidedProducts(derivedProvidedProducts);
poolCurator.create(pool);
}
@Test
@SuppressWarnings("unchecked")
public void normalCreate() {
Product prod = new Product("cptest-label", "My Product");
productCurator.create(prod);
List<Product> results = this.getEntityManager().createQuery("select p from Product as p")
.getResultList();
assertEquals(5, results.size());
}
@Test(expected = PersistenceException.class)
public void nameRequired() {
Product prod = new Product("someproductlabel", null);
productCurator.create(prod);
}
@Test(expected = ConstraintViolationException.class)
public void labelRequired() {
Product prod = new Product(null, "My Product Name");
productCurator.create(prod);
}
@Test
public void nameNonUnique() {
Product prod = new Product("label1", "name");
productCurator.create(prod);
Product prod2 = new Product("label2", "name");
productCurator.create(prod2);
assertEquals(prod.getName(), prod2.getName());
assertFalse(prod.getUuid().equals(prod2.getUuid()));
}
@Test
public void testWithSimpleJsonAttribute() throws Exception {
Map<String, String> data = new HashMap<String, String>();
data.put("a", "1");
data.put("b", "2");
ObjectMapper mapper = new ObjectMapper();
String jsonData = mapper.writeValueAsString(data);
Product prod = new Product("cptest-label", "My Product");
prod.setAttribute("content_sets", jsonData);
productCurator.create(prod);
Product lookedUp = productCurator.find(prod.getUuid());
assertEquals(jsonData, lookedUp.getAttributeValue("content_sets"));
data = mapper.readValue(lookedUp.getAttributeValue("content_sets"),
new TypeReference<Map<String, String>>(){});
assertEquals("1", data.get("a"));
assertEquals("2", data.get("b"));
}
@Test
public void testJsonListOfHashes() throws Exception {
List<Map<String, String>> data = new LinkedList<Map<String, String>>();
Map<String, String> contentSet1 = new HashMap<String, String>();
contentSet1.put("name", "cs1");
contentSet1.put("url", "url");
Map<String, String> contentSet2 = new HashMap<String, String>();
contentSet2.put("name", "cs2");
contentSet2.put("url", "url2");
data.add(contentSet1);
data.add(contentSet2);
ObjectMapper mapper = new ObjectMapper();
String jsonData = mapper.writeValueAsString(data);
Product prod = TestUtil.createProduct("cptest-label", "My Product");
prod.setAttribute("content_sets", jsonData);
productCurator.create(prod);
Product lookedUp = productCurator.find(prod.getUuid());
assertEquals(jsonData, lookedUp.getAttributeValue("content_sets"));
data = mapper.readValue(lookedUp.getAttributeValue("content_sets"),
new TypeReference<List<Map<String, String>>>(){});
Map<String, String> cs1 = data.get(0);
assertEquals("cs1", cs1.get("name"));
Map<String, String> cs2 = data.get(1);
assertEquals("cs2", cs2.get("name"));
}
/**
*Test whether the creation date of the product variable is set properly
*when persisted for the first time.
*/
@Test
public void testCreationDate() {
Product prod = TestUtil.createProduct("test-label", "test-product-name");
productCurator.create(prod);
assertNotNull(prod.getCreated());
}
@Test
public void testInitialUpdate() {
Product prod = TestUtil.createProduct("test-label", "test-product-name");
productCurator.create(prod);
assertNotNull(prod.getUpdated());
}
@Test
public void testDependentProducts() {
Product prod = new Product("test-label", "test-product-name");
HashSet<String> dependentProductIds = new HashSet<String>();
dependentProductIds.add("ProductX");
prod.setDependentProductIds(dependentProductIds);
productCurator.create(prod);
Product lookedUp = productCurator.find(prod.getUuid());
assertThat(lookedUp.getDependentProductIds(), hasItem("ProductX"));
}
/**
* Test whether the product updation date is updated when merging.
*/
@Test
public void testSubsequentUpdate() {
Product prod = TestUtil.createProduct("test-label", "test-product-name");
productCurator.create(prod);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MONTH, -2);
prod.setUpdated(calendar.getTime());
long updated = prod.getUpdated().getTime();
prod.setName("test-changed-name");
prod = this.productCurator.merge(prod);
this.productCurator.flush();
assertTrue(prod.getUpdated().getTime() > updated);
}
@Test
public void testProductFullConstructor() {
Product prod = new Product("cp_test-label", "variant", "version", "arch", "", "SVC");
productCurator.create(prod);
productCurator.find(prod.getUuid());
}
@Test
public void setMultiplierBasic() {
Product product = TestUtil.createProduct("test", "Test Product");
product.setMultiplier(4L);
assertEquals(Long.valueOf(4), product.getMultiplier());
}
@Test
public void setMultiplierNull() {
Product product = TestUtil.createProduct("test", "Test Product");
product.setMultiplier(null);
assertEquals(Long.valueOf(1), product.getMultiplier());
}
@Test
public void setMultiplierNegative() {
Product product = TestUtil.createProduct("test", "Test Product");
product.setMultiplier(-15L);
assertEquals(Long.valueOf(1), product.getMultiplier());
}
private Product createTestProduct() {
Product product = TestUtil.createProduct("testProductId", "Test Product");
product.setAttribute("a1", "a1");
product.setAttribute("a2", "a2");
product.setAttribute("a3", "a3");
product.setMultiplier(1L);
return product;
}
@Test
public void testUpdateProduct() {
Product original = createTestProduct();
productCurator.create(original);
Product modified = productCurator.find(original.getUuid());
String newName = "new name";
modified.setName(newName);
// Hack up the attributes, keep a1, remove a2, modify a3, add a4:
modified.removeAttribute("a2");
modified.setAttribute("a3", "a3-modified");
modified.setAttribute("a4", "a4");
productCurator.merge(modified);
Product lookedUp = productCurator.find(original.getUuid());
assertEquals(newName, lookedUp.getName());
assertEquals(3, lookedUp.getAttributes().size());
assertEquals("a1", lookedUp.getAttributeValue("a1"));
assertEquals("a3-modified", lookedUp.getAttributeValue("a3"));
assertEquals("a4", lookedUp.getAttributeValue("a4"));
}
@Test
public void testProductAttributeValidationSuccessCreate() {
Product original = createTestProduct();
original.setAttribute("product.count", "1");
original.setAttribute("product.pos_count", "5");
original.setAttribute("product.long_multiplier", (new Long(Integer.MAX_VALUE * 1000)).toString());
original.setAttribute("product.long_pos_count", "23");
original.setAttribute("product.bool_val_str", "true");
original.setAttribute("product.bool_val_num", "0");
productCurator.create(original);
assertTrue(original.getUuid() != null);
}
@Test
public void testProductAttributeValidationSuccessUpdate() {
Product original = createTestProduct();
productCurator.create(original);
assertTrue(original.getUuid() != null);
original.setAttribute("product.count", "134");
original.setAttribute("product.pos_count", "333");
original.setAttribute("product.long_multiplier", (new Long(Integer.MAX_VALUE * 100)).toString());
original.setAttribute("product.long_pos_count", "10");
original.setAttribute("product.bool_val_str", "false");
original.setAttribute("product.bool_val_num", "1");
productCurator.merge(original);
}
@Test(expected = PropertyValidationException.class)
public void testProductAttributeCreationFailBadInt() {
Product original = createTestProduct();
original.setAttribute("product.count", "1.0");
productCurator.create(original);
}
@Test
public void testProductAttributeCreationSuccessZeroInt() {
Product original = createTestProduct();
original.setAttribute("product.pos_count", "0");
productCurator.create(original);
}
@Test(expected = PropertyValidationException.class)
public void testProductAttributeCreationFailBadPosInt() {
Product original = createTestProduct();
original.setAttribute("product.pos_count", "-5");
productCurator.create(original);
}
@Test(expected = PropertyValidationException.class)
public void testProductAttributeCreationFailBadLong() {
Product original = createTestProduct();
original.setAttribute("product.long_multiplier", "ZZ");
productCurator.create(original);
}
@Test(expected = PropertyValidationException.class)
public void testProductAttributeCreationFailBadPosLong() {
Product original = createTestProduct();
original.setAttribute("product.long_pos_count", "-1");
productCurator.create(original);
}
@Test(expected = PropertyValidationException.class)
public void testProductAttributeCreationFailBadStringBool() {
Product original = createTestProduct();
original.setAttribute("product.bool_val_str", "yes");
productCurator.create(original);
}
@Test(expected = PropertyValidationException.class)
public void testProductAttributeCreationFailNumberBool() {
Product original = createTestProduct();
original.setAttribute("product.bool_val_num", "2");
productCurator.create(original);
}
@Test(expected = PropertyValidationException.class)
public void testProductAttributeUpdateFailInt() {
Product original = createTestProduct();
productCurator.create(original);
assertTrue(original.getUuid() != null);
original.setAttribute("product.count", "one");
productCurator.merge(original);
}
@Test(expected = PropertyValidationException.class)
public void testProductAttributeUpdateFailPosInt() {
Product original = createTestProduct();
productCurator.create(original);
assertTrue(original.getUuid() != null);
original.setAttribute("product.pos_count", "-44");
productCurator.merge(original);
}
@Test
public void testProductAttributeUpdateSuccessZeroInt() {
Product original = createTestProduct();
productCurator.create(original);
assertTrue(original.getUuid() != null);
original.setAttribute("product.pos_count", "0");
productCurator.merge(original);
}
@Test(expected = PropertyValidationException.class)
public void testProductAttributeUpdateFailLong() {
Product original = createTestProduct();
productCurator.create(original);
assertTrue(original.getUuid() != null);
original.setAttribute("product.long_multiplier", "10^23");
productCurator.merge(original);
}
@Test(expected = PropertyValidationException.class)
public void testProductAttributeUpdateFailPosLong() {
Product original = createTestProduct();
productCurator.create(original);
assertTrue(original.getUuid() != null);
original.setAttribute("product.long_pos_count", "-23");
productCurator.merge(original);
}
@Test(expected = PropertyValidationException.class)
public void testProductAttributeUpdateFailStringBool() {
Product original = createTestProduct();
productCurator.create(original);
assertTrue(original.getUuid() != null);
original.setAttribute("product.bool_val_str", "flase");
productCurator.merge(original);
}
@Test(expected = PropertyValidationException.class)
public void testProductAttributeUpdateFailNumberBool() {
Product original = createTestProduct();
productCurator.create(original);
assertTrue(original.getUuid() != null);
original.setAttribute("product.bool_val_num", "6");
productCurator.merge(original);
}
@Test
public void testSubstringConfigList() {
Product original = createTestProduct();
original.setAttribute("product.pos", "-5");
productCurator.create(original);
}
@Test
public void testGetProductIdFromContentId() {
Product p = createTestProduct();
Content content = TestUtil.createContent("best-content");
p.addContent(content, true);
contentCurator.create(content);
productCurator.create(p);
this.ownerProductCurator.mapProductToOwner(p, this.owner);
this.ownerContentCurator.mapContentToOwner(content, this.owner);
List<String> contentIds = new LinkedList<String>();
contentIds.add(content.getId());
List<Product> products = productCurator.getProductsByContent(owner, contentIds).list();
assertEquals(1, products.size());
assertEquals(p, products.get(0));
}
@Test
public void testGetProductIdFromContentUuid() {
Product p = createTestProduct();
Content content = TestUtil.createContent("best-content");
p.addContent(content, true);
contentCurator.create(content);
productCurator.create(p);
List<String> contentUuids = new LinkedList<String>();
contentUuids.add(content.getUuid());
List<Product> products = productCurator.getProductsByContentUuids(contentUuids).list();
assertEquals(1, products.size());
assertEquals(p, products.get(0));
}
@Test
public void ensureProductHasSubscription() {
assertTrue(productCurator.productHasSubscriptions(owner, product));
}
@Test
public void ensureProvidedProductHasSubscription() {
assertTrue(productCurator.productHasSubscriptions(owner, providedProduct));
}
@Test
public void ensureDerivedProductHasSubscription() {
assertTrue(productCurator.productHasSubscriptions(owner, derivedProduct));
}
@Test
public void ensureDerivedProvidedProductHasSubscription() {
assertTrue(productCurator.productHasSubscriptions(owner, derivedProvidedProduct));
}
@Test
public void ensureDoesNotHaveSubscription() {
Product noSub = this.createProduct("p1", "p1", owner);
assertFalse(productCurator.productHasSubscriptions(owner, noSub));
}
@Test
public void testSaveOrUpdateProductNoDuplicateProdContent() {
// TODO:
// This test may have lost meaning after the various changes and addition of the product
// manager
Product p = createTestProduct();
Content content = TestUtil.createContent("best-content");
p.addContent(content, true);
contentCurator.create(content);
productCurator.create(p);
// Technically the same product:
Product p2 = createTestProduct();
p2.setUuid(p.getUuid());
// The content isn't quite the same. We just care about matching
// product ids with content ids
Content contentUpdate = TestUtil.createContent("best-content");
contentUpdate.setUuid(content.getUuid());
contentUpdate.setGpgUrl("different");
p2.addContent(contentUpdate, true);
productCurator.merge(p2);
Product result = productCurator.find(p.getUuid());
assertEquals(1, result.getProductContent().size());
}
@Test
public void testGetHydratedProductsByUuid() {
Product prod = TestUtil.createProduct("test-label-hydrated", "test-product-name-hydrated");
productCurator.create(prod);
prod.setAttribute("testattr", "testVal");
Set<String> uuids = new HashSet<String>();
uuids.add(prod.getUuid());
uuids.add(product.getUuid());
Map<String, Product> products = productCurator.getHydratedProductsByUuid(uuids);
assertEquals(2, products.size());
}
@Test
public void testPoolProvidedProducts() {
Set<String> uuids = productCurator.getPoolProvidedProductUuids(pool.getId());
assertEquals(new HashSet<String>(Arrays.asList(providedProduct.getUuid())), uuids);
}
@Test
public void testDerivedPoolProvidedProducts() {
Set<String> uuids = productCurator.getDerivedPoolProvidedProductUuids(pool.getId());
assertEquals(new HashSet<String>(Arrays.asList(derivedProvidedProduct.getUuid())), uuids);
}
}