/** * 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.sync; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doNothing; 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 org.candlepin.audit.EventSink; import org.candlepin.common.config.MapConfiguration; import org.candlepin.config.CandlepinCommonTestConfig; import org.candlepin.config.ConfigProperties; import org.candlepin.controller.PoolManager; import org.candlepin.controller.Refresher; import org.candlepin.jackson.ProductCachedSerializationModule; import org.candlepin.model.CertificateSerialCurator; import org.candlepin.model.ConsumerType; import org.candlepin.model.ConsumerType.ConsumerTypeEnum; import org.candlepin.model.ConsumerTypeCurator; import org.candlepin.model.DistributorVersion; import org.candlepin.model.DistributorVersionCapability; import org.candlepin.model.DistributorVersionCurator; import org.candlepin.model.Entitlement; import org.candlepin.model.ExporterMetadata; import org.candlepin.model.ExporterMetadataCurator; import org.candlepin.model.IdentityCertificateCurator; import org.candlepin.model.ImportRecord; import org.candlepin.model.ImportRecordCurator; import org.candlepin.model.ImportUpstreamConsumer; import org.candlepin.model.Owner; import org.candlepin.model.OwnerCurator; import org.candlepin.model.Pool; import org.candlepin.model.Product; import org.candlepin.model.ProductCurator; import org.candlepin.model.UpstreamConsumer; import org.candlepin.model.dto.Subscription; import org.candlepin.pki.PKIUtility; import org.candlepin.pki.impl.BouncyCastlePKIUtility; import org.candlepin.pki.impl.DefaultSubjectKeyIdentifierWriter; import org.candlepin.service.SubscriptionServiceAdapter; import org.candlepin.sync.Importer.ImportFile; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.mockito.Mockito; import org.xnap.commons.i18n.I18n; import org.xnap.commons.i18n.I18nFactory; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.PrintStream; import java.io.Reader; import java.net.URISyntaxException; import java.security.Security; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * ImporterTest */ public class ImporterTest { @Rule public TemporaryFolder folder = new TemporaryFolder(); @Rule public ExpectedException ee = ExpectedException.none(); private ObjectMapper mapper; private I18n i18n; private String mockJsPath; private CandlepinCommonTestConfig config; private ClassLoader classLoader = getClass().getClassLoader(); private SyncUtils su; private ProductCurator pc; private SubscriptionReconciler mockSubReconciler; @Before public void init() throws URISyntaxException, IOException { mapper = TestSyncUtils.getTestSyncUtils(new MapConfiguration( new HashMap<String, String>() { { put(ConfigProperties.FAIL_ON_UNKNOWN_IMPORT_PROPERTIES, "false"); } } )); i18n = I18nFactory.getI18n(getClass(), Locale.US, I18nFactory.FALLBACK); config = new CandlepinCommonTestConfig(); pc = Mockito.mock(ProductCurator.class); ProductCachedSerializationModule productCachedModule = new ProductCachedSerializationModule(pc); su = new SyncUtils(config, productCachedModule); PrintStream ps = new PrintStream( new File(this.getClass().getClassLoader().getResource("version.properties").toURI())); ps.println("version=0.0.3"); ps.println("release=1"); ps.close(); mockJsPath = new File(folder.getRoot(), "empty.js").getPath(); this.mockSubReconciler = Mockito.mock(SubscriptionReconciler.class); } @After public void tearDown() throws Exception { PrintStream ps = new PrintStream(new File(this.getClass() .getClassLoader().getResource("version.properties").toURI())); ps.println("version=${version}"); ps.println("release=${release}"); ps.close(); } @Test public void validateMetaJson() throws Exception { /* read file * read in version * read in created date * make sure created date is XYZ * make sure version is > ABC */ Date now = new Date(); File file = createFile("meta", "0.0.3", now, "test_user", "prefix"); File actual = createFile("meta.json", "0.0.3", now, "test_user", "prefix"); ExporterMetadataCurator emc = mock(ExporterMetadataCurator.class); ExporterMetadata em = new ExporterMetadata(); Date daybefore = getDateBeforeDays(1); em.setExported(daybefore); em.setId("42"); em.setType(ExporterMetadata.TYPE_SYSTEM); when(emc.lookupByType(ExporterMetadata.TYPE_SYSTEM)).thenReturn(em); Importer i = new Importer(null, null, null, null, null, null, null, null, null, emc, null, null, i18n, null, null, su, null, this.mockSubReconciler); i.validateMetadata(ExporterMetadata.TYPE_SYSTEM, null, actual, new ConflictOverrides()); Meta fileMeta = mapper.readValue(file, Meta.class); Meta actualMeta = mapper.readValue(actual, Meta.class); assertEquals(fileMeta.getPrincipalName(), actualMeta.getPrincipalName()); assertEquals(fileMeta.getCreated().getTime(), actualMeta.getCreated().getTime()); assertEquals(fileMeta.getWebAppPrefix(), actualMeta.getWebAppPrefix()); assertTrue(file.delete()); assertTrue(actual.delete()); assertTrue(daybefore.compareTo(em.getExported()) < 0); } @Test public void firstRun() throws Exception { File f = createFile("meta", "0.0.3", new Date(), "test_user", "prefix"); File actualmeta = createFile("meta.json", "0.0.3", new Date(), "test_user", "prefix"); ExporterMetadataCurator emc = mock(ExporterMetadataCurator.class); when(emc.lookupByType(ExporterMetadata.TYPE_SYSTEM)).thenReturn(null); Importer i = new Importer(null, null, null, null, null, null, null, null, null, emc, null, null, i18n, null, null, su, null, this.mockSubReconciler); i.validateMetadata(ExporterMetadata.TYPE_SYSTEM, null, actualmeta, new ConflictOverrides()); assertTrue(f.delete()); assertTrue(actualmeta.delete()); verify(emc).create(any(ExporterMetadata.class)); } @Test public void oldImport() throws Exception { // actualmeta is the mock for the import itself File actualmeta = createFile("meta.json", "0.0.3", getDateBeforeDays(10), "test_user", "prefix"); ExporterMetadataCurator emc = mock(ExporterMetadataCurator.class); // emc is the mock for lastrun (i.e., the most recent import in CP) ExporterMetadata em = new ExporterMetadata(); em.setExported(getDateBeforeDays(3)); em.setId("42"); em.setType(ExporterMetadata.TYPE_SYSTEM); when(emc.lookupByType(ExporterMetadata.TYPE_SYSTEM)).thenReturn(em); Importer i = new Importer(null, null, null, null, null, null, null, null, null, emc, null, null, i18n, null, null, su, null, this.mockSubReconciler); try { i.validateMetadata(ExporterMetadata.TYPE_SYSTEM, null, actualmeta, new ConflictOverrides()); fail(); } catch (ImportConflictException e) { assertFalse(e.message().getConflicts().isEmpty()); assertEquals(1, e.message().getConflicts().size()); assertTrue(e.message().getConflicts().contains( Importer.Conflict.MANIFEST_OLD)); } } @Test public void sameImport() throws Exception { // actualmeta is the mock for the import itself Date date = getDateBeforeDays(10); File actualmeta = createFile("meta.json", "0.0.3", date, "test_user", "prefix"); ExporterMetadataCurator emc = mock(ExporterMetadataCurator.class); // emc is the mock for lastrun (i.e., the most recent import in CP) ExporterMetadata em = new ExporterMetadata(); em.setExported(date); // exact same date = assumed same manifest em.setId("42"); em.setType(ExporterMetadata.TYPE_SYSTEM); when(emc.lookupByType(ExporterMetadata.TYPE_SYSTEM)).thenReturn(em); Importer i = new Importer(null, null, null, null, null, null, null, null, null, emc, null, null, i18n, null, null, su, null, this.mockSubReconciler); try { i.validateMetadata(ExporterMetadata.TYPE_SYSTEM, null, actualmeta, new ConflictOverrides()); fail(); } catch (ImportConflictException e) { assertFalse(e.message().getConflicts().isEmpty()); assertEquals(1, e.message().getConflicts().size()); assertTrue(e.message().getConflicts().contains( Importer.Conflict.MANIFEST_SAME)); } } @Test public void mergeConflicts() { ImportConflictException e2 = new ImportConflictException("testing", Importer.Conflict.DISTRIBUTOR_CONFLICT); ImportConflictException e3 = new ImportConflictException("testing2", Importer.Conflict.MANIFEST_OLD); List<ImportConflictException> exceptions = new LinkedList<ImportConflictException>(); exceptions.add(e2); exceptions.add(e3); ImportConflictException e1 = new ImportConflictException(exceptions); assertEquals("testing\ntesting2", e1.message().getDisplayMessage()); assertEquals(2, e1.message().getConflicts().size()); assertTrue(e1.message().getConflicts().contains( Importer.Conflict.DISTRIBUTOR_CONFLICT)); assertTrue(e1.message().getConflicts().contains(Importer.Conflict.MANIFEST_OLD)); } @Test public void newerImport() throws Exception { // this tests bz #790751 Date importDate = getDateBeforeDays(10); // actualmeta is the mock for the import itself File actualmeta = createFile("meta.json", "0.0.3", importDate, "test_user", "prefix"); ExporterMetadataCurator emc = mock(ExporterMetadataCurator.class); // em is the mock for lastrun (i.e., the most recent import in CP) ExporterMetadata em = new ExporterMetadata(); em.setExported(getDateBeforeDays(30)); em.setId("42"); em.setType(ExporterMetadata.TYPE_SYSTEM); when(emc.lookupByType(ExporterMetadata.TYPE_SYSTEM)).thenReturn(em); Importer i = new Importer(null, null, null, null, null, null, null, null, null, emc, null, null, i18n, null, null, su, null, this.mockSubReconciler); i.validateMetadata(ExporterMetadata.TYPE_SYSTEM, null, actualmeta, new ConflictOverrides()); assertEquals(importDate, em.getExported()); } @Test(expected = ImporterException.class) public void nullType() throws ImporterException, IOException { File actualmeta = createFile("meta.json", "0.0.3", new Date(), "test_user", "prefix"); try { Importer i = new Importer(null, null, null, null, null, null, null, null, null, null, null, null, i18n, null, null, su, null, this.mockSubReconciler); // null Type should cause exception i.validateMetadata(null, null, actualmeta, new ConflictOverrides()); } finally { assertTrue(actualmeta.delete()); } } @Test(expected = ImporterException.class) public void expectOwner() throws ImporterException, IOException { File actualmeta = createFile("meta.json", "0.0.3", new Date(), "test_user", "prefix"); ExporterMetadataCurator emc = mock(ExporterMetadataCurator.class); when(emc.lookupByTypeAndOwner(ExporterMetadata.TYPE_PER_USER, null)) .thenReturn(null); Importer i = new Importer(null, null, null, null, null, null, null, null, null, emc, null, null, i18n, null, null, su, null, this.mockSubReconciler); // null Type should cause exception i.validateMetadata(ExporterMetadata.TYPE_PER_USER, null, actualmeta, new ConflictOverrides()); verify(emc, never()).create(any(ExporterMetadata.class)); } @Test public void testImportWithNonZipArchive() throws IOException, ImporterException { Importer i = new Importer(null, null, null, null, null, null, null, null, config, null, null, null, i18n, null, null, su, null, this.mockSubReconciler); Owner owner = mock(Owner.class); ConflictOverrides co = mock(ConflictOverrides.class); File archive = new File(folder.getRoot(), "non_zip_file.zip"); FileWriter fw = new FileWriter(archive); fw.write("Just a flat file"); fw.close(); String m = i18n.tr("The archive {0} is not a properly compressed file or is empty", "non_zip_file.zip"); ee.expect(ImportExtractionException.class); ee.expectMessage(m); i.loadExport(owner, archive, co, "original_file.zip"); } @Test public void testImportZipArchiveNoContent() throws IOException, ImporterException { Importer i = new Importer(null, null, null, null, null, null, null, null, config, null, null, null, i18n, null, null, su, null, this.mockSubReconciler); Owner owner = mock(Owner.class); ConflictOverrides co = mock(ConflictOverrides.class); File archive = new File(folder.getRoot(), "file.zip"); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(archive)); out.putNextEntry(new ZipEntry("no_content")); out.close(); String m = i18n.tr("The archive does not contain the required signature file"); ee.expect(ImportExtractionException.class); ee.expectMessage(m); i.loadExport(owner, archive, co, "original_file.zip"); } @Test(expected = ImportConflictException.class) public void testImportBadSignature() throws IOException, ImporterException { PKIUtility pki = mock(PKIUtility.class); Importer i = new Importer(null, null, null, null, null, null, null, pki, config, null, null, null, i18n, null, null, su, null, this.mockSubReconciler); Owner owner = mock(Owner.class); ConflictOverrides co = mock(ConflictOverrides.class); File archive = new File(folder.getRoot(), "file.zip"); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(archive)); out.putNextEntry(new ZipEntry("signature")); out.write("This is the placeholder for the signature file".getBytes()); File ceArchive = new File(folder.getRoot(), "consumer_export.zip"); FileOutputStream fos = new FileOutputStream(ceArchive); fos.write("This is just a flat file".getBytes()); fos.close(); addFileToArchive(out, ceArchive); out.close(); i.loadExport(owner, archive, co, "original_file.zip"); } @Test public void testImportBadConsumerZip() throws Exception { PKIUtility pki = mock(PKIUtility.class); Importer i = new Importer(null, null, null, null, null, null, null, pki, config, null, null, null, i18n, null, null, su, null, this.mockSubReconciler); Owner owner = mock(Owner.class); ConflictOverrides co = mock(ConflictOverrides.class); // Mock a passed signature check: when(pki.verifySHA256WithRSAHashAgainstCACerts(any(File.class), any(byte [].class))).thenReturn(true); File archive = new File(folder.getRoot(), "file.zip"); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(archive)); out.putNextEntry(new ZipEntry("signature")); out.write("This is the placeholder for the signature file".getBytes()); File ceArchive = new File(folder.getRoot(), "consumer_export.zip"); FileOutputStream fos = new FileOutputStream(ceArchive); fos.write("This is just a flat file".getBytes()); fos.close(); addFileToArchive(out, ceArchive); out.close(); ee.expect(ImportExtractionException.class); ee.expectMessage("not a properly compressed file or is empty"); i.loadExport(owner, archive, co, "original_file.zip"); } @Test public void testImportZipSigAndEmptyConsumerZip() throws Exception { PKIUtility pki = mock(PKIUtility.class); Importer i = new Importer(null, null, null, null, null, null, null, pki, config, null, null, null, i18n, null, null, su, null, this.mockSubReconciler); Owner owner = mock(Owner.class); ConflictOverrides co = mock(ConflictOverrides.class); // Mock a passed signature check: when(pki.verifySHA256WithRSAHashAgainstCACerts(any(File.class), any(byte [].class))).thenReturn(true); File archive = new File(folder.getRoot(), "file.zip"); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(archive)); out.putNextEntry(new ZipEntry("signature")); out.write("This is the placeholder for the signature file".getBytes()); File ceArchive = new File(folder.getRoot(), "consumer_export.zip"); ZipOutputStream cezip = new ZipOutputStream(new FileOutputStream(ceArchive)); cezip.putNextEntry(new ZipEntry("no_content")); cezip.close(); addFileToArchive(out, ceArchive); out.close(); ee.expect(ImportExtractionException.class); ee.expectMessage("consumer_export archive has no contents"); i.loadExport(owner, archive, co, "original_file.zip"); } private Map<String, File> getTestImportFiles() { Map<String, File> importFiles = new HashMap<String, File>(); importFiles.put(ImportFile.META.fileName(), mock(File.class)); importFiles.put(ImportFile.RULES_FILE.fileName(), mock(File.class)); importFiles.put(ImportFile.CONSUMER_TYPE.fileName(), mock(File.class)); importFiles.put(ImportFile.CONSUMER.fileName(), mock(File.class)); importFiles.put(ImportFile.PRODUCTS.fileName(), mock(File.class)); importFiles.put(ImportFile.ENTITLEMENTS.fileName(), mock(File.class)); importFiles.put(ImportFile.DISTRIBUTOR_VERSIONS.fileName(), mock(File.class)); return importFiles; } @Test public void testImportNoMeta() throws IOException, ImporterException { OwnerCurator oc = mock(OwnerCurator.class); Importer i = new Importer(null, null, null, oc, null, null, null, null, config, null, null, null, i18n, null, null, su, null, this.mockSubReconciler); Owner owner = mock(Owner.class); ConflictOverrides co = mock(ConflictOverrides.class); Map<String, File> importFiles = getTestImportFiles(); importFiles.put(ImportFile.META.fileName(), null); String m = i18n.tr("The archive does not contain the " + "required meta.json file"); ee.expect(ImporterException.class); ee.expectMessage(m); i.importObjects(owner, importFiles, co); } @Test public void testImportNoConsumerTypesDir() throws IOException, ImporterException { OwnerCurator oc = mock(OwnerCurator.class); Importer i = new Importer(null, null, null, oc, null, null, null, null, config, null, null, null, i18n, null, null, su, null, this.mockSubReconciler); Owner owner = mock(Owner.class); ConflictOverrides co = mock(ConflictOverrides.class); Map<String, File> importFiles = getTestImportFiles(); importFiles.put(ImportFile.CONSUMER_TYPE.fileName(), null); String m = i18n.tr("The archive does not contain the " + "required consumer_types directory"); ee.expect(ImporterException.class); ee.expectMessage(m); i.importObjects(owner, importFiles, co); } @Test public void testImportNoConsumer() throws IOException, ImporterException { OwnerCurator oc = mock(OwnerCurator.class); Importer i = new Importer(null, null, null, oc, null, null, null, null, config, null, null, null, i18n, null, null, su, null, this.mockSubReconciler); Owner owner = mock(Owner.class); ConflictOverrides co = mock(ConflictOverrides.class); Map<String, File> importFiles = getTestImportFiles(); importFiles.put(ImportFile.CONSUMER.fileName(), null); String m = i18n.tr("The archive does not contain the " + "required consumer.json file"); ee.expect(ImporterException.class); ee.expectMessage(m); i.importObjects(owner, importFiles, co); } @Test public void testImportNoProductDir() throws IOException, ImporterException { RulesImporter ri = mock(RulesImporter.class); OwnerCurator oc = mock(OwnerCurator.class); Importer i = new Importer(null, null, ri, oc, null, null, null, null, config, null, null, null, i18n, null, null, su, null, this.mockSubReconciler); Owner owner = mock(Owner.class); ConflictOverrides co = mock(ConflictOverrides.class); Map<String, File> importFiles = getTestImportFiles(); File ruleDir = mock(File.class); File[] rulesFiles = createMockJsFile(mockJsPath); when(ruleDir.listFiles()).thenReturn(rulesFiles); File actualmeta = createFile("meta.json", "0.0.3", new Date(), "test_user", "prefix"); // this is the hook to stop testing. we confirm that the archive component tests // are passed and then jump out instead of trying to fake the actual file // processing. doThrow(new RuntimeException("Done with the test")).when(ri).importObject( any(Reader.class)); importFiles.put(ImportFile.META.fileName(), actualmeta); importFiles.put(ImportFile.RULES_FILE.fileName(), rulesFiles[0]); importFiles.put(ImportFile.PRODUCTS.fileName(), null); importFiles.put(ImportFile.ENTITLEMENTS.fileName(), null); importFiles.put(ImportFile.UPSTREAM_CONSUMER.fileName(), mock(File.class)); ee.expect(RuntimeException.class); ee.expectMessage("Done with the test"); i.importObjects(owner, importFiles, co); } @Test public void testReturnsSubscriptionsFromManifest() throws IOException, ImporterException { Owner owner = new Owner("admin", "Admin Owner"); ExporterMetadataCurator emc = mock(ExporterMetadataCurator.class); when(emc.lookupByTypeAndOwner("per_user", owner)).thenReturn(null); ConsumerType type = new ConsumerType(ConsumerTypeEnum.SYSTEM); ConsumerTypeCurator ctc = mock(ConsumerTypeCurator.class); when(ctc.lookupByLabel(eq("system"))).thenReturn(type); OwnerCurator oc = mock(OwnerCurator.class); when(oc.lookupWithUpstreamUuid(any(String.class))).thenReturn(null); PoolManager pm = mock(PoolManager.class); Refresher refresher = mock(Refresher.class); when(pm.getRefresher(any(SubscriptionServiceAdapter.class))).thenReturn(refresher); Map<String, File> importFiles = new HashMap<String, File>(); File ruleDir = mock(File.class); File[] rulesFiles = createMockJsFile(mockJsPath); when(ruleDir.listFiles()).thenReturn(rulesFiles); File actualmeta = createFile("meta.json", "0.0.3", new Date(), "test_user", "prefix"); importFiles.put(ImportFile.META.fileName(), actualmeta); ConsumerDto consumer = new ConsumerDto("eb5e04bf-be27-44cf-abe3-0c0b1edd523e", "mymachine", new ConsumerType(ConsumerTypeEnum.CANDLEPIN), owner, "foo.example.com/subscription", "/candlepin", ""); File consumerFile = new File(folder.getRoot(), "consumer.json"); mapper.writeValue(consumerFile, consumer); importFiles.put(ImportFile.CONSUMER.fileName(), consumerFile); File cTypes = mock(File.class); when(cTypes.listFiles()).thenReturn(new File[]{}); importFiles.put(ImportFile.CONSUMER_TYPE.fileName(), cTypes); Product prod = new Product("prodId", "prodTest", null); prod.setDependentProductIds(null); File prodFile = new File(folder.getRoot(), "product.json"); mapper.writeValue(prodFile, prod); File products = mock(File.class); when(products.listFiles()).thenReturn(new File[]{prodFile}); importFiles.put(ImportFile.PRODUCTS.fileName(), products); Entitlement ent = new Entitlement(); Pool pool = new Pool(); pool.setProduct(prod); ent.setPool(pool); ent.setQuantity(2); File entFile = new File(folder.getRoot(), "entitlement.json"); mapper.writeValue(entFile, ent); File entitlements = mock(File.class); when(entitlements.listFiles()).thenReturn(new File[]{entFile}); importFiles.put(ImportFile.ENTITLEMENTS.fileName(), entitlements); RulesImporter ri = mock(RulesImporter.class); importFiles.put(ImportFile.RULES_FILE.fileName(), rulesFiles[0]); ConflictOverrides co = mock(ConflictOverrides.class); Importer i = new Importer(ctc, pc, ri, oc, null, null, pm, null, config, emc, null, null, i18n, null, null, su, null, this.mockSubReconciler); List<Subscription> subscriptions = i.importObjects(owner, importFiles, co); assertEquals(1, subscriptions.size()); assertEquals("prodId", subscriptions.get(0).getProduct().getId()); assertEquals(2, subscriptions.get(0).getQuantity().longValue()); } @Test public void testImportProductNoEntitlementDir() throws IOException, ImporterException { OwnerCurator oc = mock(OwnerCurator.class); Importer i = new Importer(null, null, null, oc, null, null, null, null, config, null, null, null, i18n, null, null, su, null, this.mockSubReconciler); Owner owner = mock(Owner.class); ConflictOverrides co = mock(ConflictOverrides.class); Map<String, File> importFiles = getTestImportFiles(); importFiles.put(ImportFile.ENTITLEMENTS.fileName(), null); String m = i18n.tr("The archive does not contain the " + "required entitlements directory"); ee.expect(ImporterException.class); ee.expectMessage(m); i.importObjects(owner, importFiles, co); } private File createFile(String filename, String version, Date date, String username, String prefix) throws JsonGenerationException, JsonMappingException, IOException { File f = new File(folder.getRoot(), filename); Meta meta = new Meta(version, date, username, prefix, null); mapper.writeValue(f, meta); return f; } private File[] createMockJsFile(String filename) throws IOException { FileWriter f = new FileWriter(filename); f.write("// nothing to see here"); f.close(); File[] fileArray = new File[1]; fileArray[0] = new File(filename); return fileArray; } private Date getDateBeforeDays(int days) { long daysinmillis = 24 * 60 * 60 * 1000; long ms = System.currentTimeMillis() - (days * daysinmillis); Date backDate = new Date(); backDate.setTime(ms); return backDate; } private void addFileToArchive(ZipOutputStream out, File file) throws IOException, FileNotFoundException { out.putNextEntry(new ZipEntry(file.getName())); FileInputStream in = new FileInputStream(file); byte [] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } out.closeEntry(); in.close(); } @Test public void importConsumer() throws Exception { Security.addProvider(new BouncyCastleProvider()); PKIUtility pki = new BouncyCastlePKIUtility(null, new DefaultSubjectKeyIdentifierWriter(), null); OwnerCurator oc = mock(OwnerCurator.class); ConsumerType type = new ConsumerType(ConsumerTypeEnum.CANDLEPIN); ConsumerTypeCurator ctc = mock(ConsumerTypeCurator.class); when(ctc.lookupByLabel(eq("candlepin"))).thenReturn(type); Importer i = new Importer(ctc, null, null, oc, mock(IdentityCertificateCurator.class), null, null, pki, null, null, mock(CertificateSerialCurator.class), null, i18n, null, null, su, null, this.mockSubReconciler); File[] upstream = createUpstreamFiles(); Owner owner = new Owner("admin", "Admin Owner"); ConsumerDto consumer = new ConsumerDto("eb5e04bf-be27-44cf-abe3-0c0b1edd523e", "mymachine", new ConsumerType(ConsumerTypeEnum.CANDLEPIN), owner, "foo.example.com/subscription", "/candlepin", "access_mode"); File consumerfile = new File(folder.getRoot(), "consumer.json"); mapper.writeValue(consumerfile, consumer); ConflictOverrides forcedConflicts = mock(ConflictOverrides.class); when(forcedConflicts.isForced(any(Importer.Conflict.class))).thenReturn(false); Meta meta = new Meta("1.0", new Date(), "admin", "/candlepin/owners", null); i.importConsumer(owner, consumerfile, upstream, forcedConflicts, meta); verify(oc).merge(eq(owner)); } private File[] createUpstreamFiles() throws URISyntaxException { File[] upstream = new File[2]; File idcertfile = new File(classLoader.getResource("upstream/testidcert.json").toURI()); File kpfile = new File(classLoader.getResource("upstream/keypair.pem").toURI()); upstream[0] = idcertfile; upstream[1] = kpfile; return upstream; } private DistributorVersion createTestDistributerVersion() { DistributorVersion dVersion = new DistributorVersion("test-dist-ver"); Set<DistributorVersionCapability> capabilities = new HashSet<DistributorVersionCapability>(); capabilities.add(new DistributorVersionCapability(null, "capability-1")); capabilities.add(new DistributorVersionCapability(null, "capability-2")); capabilities.add(new DistributorVersionCapability(null, "capability-3")); dVersion.setCapabilities(capabilities); return dVersion; } @Test public void importDistributorVersionCreate() throws Exception { DistributorVersionCurator dvc = mock(DistributorVersionCurator.class); Importer i = new Importer(null, null, null, null, null, null, null, null, null, null, null, null, i18n, dvc, null, su, null, this.mockSubReconciler); File[] distVer = new File[1]; distVer[0] = new File(folder.getRoot(), "dist-ver.json"); mapper.writeValue(distVer[0], createTestDistributerVersion()); i.importDistributorVersions(distVer); verify(dvc).create(any(DistributorVersion.class)); verify(dvc, never()).merge(any(DistributorVersion.class)); } @Test public void importDistributorVersionUpdate() throws Exception { DistributorVersionCurator dvc = mock(DistributorVersionCurator.class); Importer i = new Importer(null, null, null, null, null, null, null, null, null, null, null, null, i18n, dvc, null, su, null, this.mockSubReconciler); when(dvc.findByName("test-dist-ver")).thenReturn( new DistributorVersion("test-dist-ver")); File[] distVer = new File[1]; distVer[0] = new File(folder.getRoot(), "dist-ver.json"); mapper.writeValue(distVer[0], createTestDistributerVersion()); i.importDistributorVersions(distVer); verify(dvc, never()).create(any(DistributorVersion.class)); verify(dvc).merge(any(DistributorVersion.class)); } @Test public void testImportNoDistributorVersions() throws IOException, ImporterException { RulesImporter ri = mock(RulesImporter.class); doNothing().when(ri).importObject(any(Reader.class)); ExporterMetadataCurator emc = mock(ExporterMetadataCurator.class); // this is the hook to stop testing. we confirm that the dist version null test // is passed and then jump out instead of trying to fake the actual file // processing. doThrow(new RuntimeException("Done with the test")).when(emc) .lookupByTypeAndOwner(any(String.class), any(Owner.class)); OwnerCurator oc = mock(OwnerCurator.class); Owner owner = mock(Owner.class); ConflictOverrides co = mock(ConflictOverrides.class); Map<String, File> importFiles = createAndSetImportFiles(); Importer i = new Importer(null, null, ri, oc, null, null, null, null, config, emc, null, null, i18n, null, null, su, null, this.mockSubReconciler); ee.expect(RuntimeException.class); ee.expectMessage("Done with the test"); i.importObjects(owner, importFiles, co); } private Map<String, File> createAndSetImportFiles() throws IOException, JsonGenerationException, JsonMappingException { File[] rulesFiles = createMockJsFile(mockJsPath); File ruleDir = mock(File.class); when(ruleDir.listFiles()).thenReturn(rulesFiles); File actualmeta = createFile("meta.json", "0.0.3", new Date(), "test_user", "prefix"); Map<String, File> importFiles = getTestImportFiles(); importFiles.put(ImportFile.META.fileName(), actualmeta); importFiles.put(ImportFile.RULES_FILE.fileName(), rulesFiles[0]); importFiles.put(ImportFile.PRODUCTS.fileName(), null); importFiles.put(ImportFile.ENTITLEMENTS.fileName(), null); importFiles.put(ImportFile.DISTRIBUTOR_VERSIONS.fileName(), null); File cTypes = mock(File.class); when(cTypes.listFiles()).thenReturn(new File[]{}); importFiles.put(ImportFile.CONSUMER_TYPE.fileName(), cTypes); return importFiles; } @Test public void testRecordImportSuccess() { String expectedOwnerKey = "TEST_OWNER"; Owner owner = new Owner(expectedOwnerKey); EventSink eventSinkMock = mock(EventSink.class); ImportRecordCurator importRecordCurator = mock(ImportRecordCurator.class); Importer importer = new Importer(null, null, null, null, null, null, null, null, config, null, null, eventSinkMock, i18n, null, null, su, importRecordCurator, this.mockSubReconciler); Meta meta = new Meta("1.0", new Date(), "test-user", "candlepin", "testcdn"); List<Subscription> subscriptions = new ArrayList<Subscription>(); Subscription subscription = new Subscription(); subscriptions.add(subscription); Map<String, Object> data = new HashMap<String, Object>(); data.put("meta", meta); data.put("subscriptions", subscriptions); ImportRecord record = importer.recordImportSuccess(owner, data, new ConflictOverrides(), "test.zip"); assertEquals(meta.getPrincipalName(), record.getGeneratedBy()); assertEquals(meta.getCreated(), record.getGeneratedDate()); assertEquals(ImportRecord.Status.SUCCESS, record.getStatus()); assertEquals(owner.getKey() + " file imported successfully.", record.getStatusMessage()); assertEquals("test.zip", record.getFileName()); verify(importRecordCurator).create(eq(record)); verify(eventSinkMock, never()).emitSubscriptionExpired(subscription); } @Test public void testRecordImportSetsUpstreamConsumerFromOwner() { String expectedOwnerKey = "TEST_OWNER"; Owner owner = new Owner(expectedOwnerKey); UpstreamConsumer uc = new UpstreamConsumer("uc", owner, new ConsumerType(ConsumerType.ConsumerTypeEnum.CANDLEPIN), "uuid"); uc.setContentAccessMode("mode"); owner.setUpstreamConsumer(uc); EventSink eventSinkMock = mock(EventSink.class); ImportRecordCurator importRecordCurator = mock(ImportRecordCurator.class); Importer importer = new Importer(null, null, null, null, null, null, null, null, config, null, null, eventSinkMock, i18n, null, null, su, importRecordCurator, this.mockSubReconciler); Meta meta = new Meta("1.0", new Date(), "test-user", "candlepin", "testcdn"); Map<String, Object> data = new HashMap<String, Object>(); data.put("meta", meta); data.put("subscriptions", new ArrayList<Subscription>()); ImportRecord record = importer.recordImportSuccess(owner, data, new ConflictOverrides(), "test.zip"); ImportUpstreamConsumer iuc = record.getUpstreamConsumer(); assertNotNull(iuc); assertEquals(uc.getOwnerId(), iuc.getOwnerId()); assertEquals(uc.getName(), iuc.getName()); assertEquals(uc.getUuid(), iuc.getUuid()); assertEquals(uc.getType(), iuc.getType()); assertEquals(uc.getWebUrl(), iuc.getWebUrl()); assertEquals(uc.getApiUrl(), iuc.getApiUrl()); assertEquals(uc.getContentAccessMode(), iuc.getContentAccessMode()); verify(importRecordCurator).create(eq(record)); } @Test public void testRecordImportIgnoresUpstreamConsumerIfNotSetOnOwner() { String expectedOwnerKey = "TEST_OWNER"; Owner owner = new Owner(expectedOwnerKey); EventSink eventSinkMock = mock(EventSink.class); ImportRecordCurator importRecordCurator = mock(ImportRecordCurator.class); Importer importer = new Importer(null, null, null, null, null, null, null, null, config, null, null, eventSinkMock, i18n, null, null, su, importRecordCurator, this.mockSubReconciler); Meta meta = new Meta("1.0", new Date(), "test-user", "candlepin", "testcdn"); Map<String, Object> data = new HashMap<String, Object>(); data.put("meta", meta); data.put("subscriptions", new ArrayList<Subscription>()); ImportRecord record = importer.recordImportSuccess(owner, data, new ConflictOverrides(), "test.zip"); assertNull(record.getUpstreamConsumer()); verify(importRecordCurator).create(eq(record)); } @Test public void testRecordImportExpiredSubsFound() { String expectedOwnerKey = "TEST_OWNER"; Owner owner = new Owner(expectedOwnerKey); EventSink eventSinkMock = mock(EventSink.class); ImportRecordCurator importRecordCurator = mock(ImportRecordCurator.class); Importer importer = new Importer(null, null, null, null, null, null, null, null, config, null, null, eventSinkMock, i18n, null, null, su, importRecordCurator, this.mockSubReconciler); Map<String, Object> data = new HashMap<String, Object>(); List<Subscription> subscriptions = new ArrayList<Subscription>(); Subscription subscription1 = new Subscription(); //expires tomorrow subscription1.setEndDate(new Date((new Date()).getTime() + (1000 * 60 * 60 * 24))); subscriptions.add(subscription1); Subscription subscription2 = new Subscription(); //expires yesterday subscription2.setEndDate(new Date((new Date()).getTime() - (1000 * 60 * 60 * 24))); subscriptions.add(subscription2); data.put("subscriptions", subscriptions); ImportRecord record = importer.recordImportSuccess(owner, data, new ConflictOverrides(), "test.zip"); assertEquals(ImportRecord.Status.SUCCESS_WITH_WARNING, record.getStatus()); assertEquals(owner.getKey() + " file imported successfully." + "One or more inactive subscriptions found in the file.", record.getStatusMessage()); verify(eventSinkMock, never()).emitSubscriptionExpired(subscription1); verify(eventSinkMock).emitSubscriptionExpired(subscription2); verify(importRecordCurator).create(eq(record)); } @Test public void testRecordImportNoActiveSubsFound() { String expectedOwnerKey = "TEST_OWNER"; Owner owner = new Owner(expectedOwnerKey); EventSink eventSinkMock = mock(EventSink.class); ImportRecordCurator importRecordCurator = mock(ImportRecordCurator.class); Importer importer = new Importer(null, null, null, null, null, null, null, null, config, null, null, eventSinkMock, i18n, null, null, su, importRecordCurator, this.mockSubReconciler); Map<String, Object> data = new HashMap<String, Object>(); data.put("subscriptions", new ArrayList<Subscription>()); ImportRecord record = importer.recordImportSuccess(owner, data, new ConflictOverrides(), "test.zip"); assertEquals(ImportRecord.Status.SUCCESS_WITH_WARNING, record.getStatus()); assertEquals(owner.getKey() + " file imported successfully." + "No active subscriptions found in the file.", record.getStatusMessage()); verify(eventSinkMock, never()).emitSubscriptionExpired(any(Subscription.class)); verify(importRecordCurator).create(eq(record)); } }