/** * 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.pinsetter.tasks; import static org.junit.Assert.*; import static org.mockito.Matchers.*; import static org.mockito.Mockito.*; import org.candlepin.auth.Principal; import org.candlepin.model.Consumer; import org.candlepin.model.ConsumerCurator; import org.candlepin.model.HypervisorId; import org.candlepin.model.JobCurator; import org.candlepin.model.Owner; import org.candlepin.model.OwnerCurator; import org.candlepin.model.VirtConsumerMap; import org.candlepin.pinsetter.core.model.JobStatus; import org.candlepin.pinsetter.core.model.JobStatus.JobState; import org.candlepin.resource.ConsumerResource; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.ListenerManager; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.xnap.commons.i18n.I18n; import org.xnap.commons.i18n.I18nFactory; import java.util.HashSet; import java.util.Locale; import java.util.Set; /** * HypervisorUpdateJobTest */ public class HypervisorUpdateJobTest { private Owner owner; private Principal principal; private String hypervisorJson; private OwnerCurator ownerCurator; private ConsumerCurator consumerCurator; private ConsumerResource consumerResource; private I18n i18n; @Before public void init() { i18n = I18nFactory.getI18n( getClass(), Locale.US, I18nFactory.READ_PROPERTIES | I18nFactory.FALLBACK ); owner = mock(Owner.class); principal = mock(Principal.class); ownerCurator = mock(OwnerCurator.class); consumerCurator = mock(ConsumerCurator.class); consumerResource = mock(ConsumerResource.class); when(owner.getKey()).thenReturn("joe"); when(principal.getUsername()).thenReturn("joe user"); hypervisorJson = "{\"hypervisors\":" + "[{" + "\"name\" : \"hypervisor_999\"," + "\"hypervisorId\" : {\"hypervisorId\":\"uuid_999\"}," + "\"guestIds\" : [{\"guestId\" : \"guestId_1_999\"}]" + "}]}"; } @Test public void createJobDetail() { JobDetail detail = HypervisorUpdateJob.forOwner(owner, hypervisorJson, true, principal, null); assertNotNull(detail); assertEquals("joe", detail.getJobDataMap().get(JobStatus.TARGET_ID)); assertEquals("joe user", ((Principal) detail.getJobDataMap().get("principal")).getUsername()); assertTrue(detail.getJobClass().equals(HypervisorUpdateJob.class)); } @Test public void hypervisorUpdateExecCreate() throws JobExecutionException { when(ownerCurator.lookupByKey(eq("joe"))).thenReturn(owner); JobDetail detail = HypervisorUpdateJob.forOwner(owner, hypervisorJson, true, principal, null); JobExecutionContext ctx = mock(JobExecutionContext.class); when(ctx.getMergedJobDataMap()).thenReturn(detail.getJobDataMap()); when(consumerCurator.getHostConsumersMap(eq(owner), any(Set.class))) .thenReturn(new VirtConsumerMap()); HypervisorUpdateJob job = new HypervisorUpdateJob(ownerCurator, consumerCurator, consumerResource, i18n); job.execute(ctx); verify(consumerResource).create(any(Consumer.class), eq(principal), anyString(), eq("joe"), anyString(), eq(false)); } @Test public void reporterIdOnCreateTest() throws JobExecutionException { when(ownerCurator.lookupByKey(eq("joe"))).thenReturn(owner); JobDetail detail = HypervisorUpdateJob.forOwner(owner, hypervisorJson, true, principal, "createReporterId"); JobExecutionContext ctx = mock(JobExecutionContext.class); when(ctx.getMergedJobDataMap()).thenReturn(detail.getJobDataMap()); when(consumerCurator.getHostConsumersMap(eq(owner), any(Set.class))).thenReturn( new VirtConsumerMap()); HypervisorUpdateJob job = new HypervisorUpdateJob(ownerCurator, consumerCurator, consumerResource, i18n); job.execute(ctx); ArgumentCaptor<Consumer> argument = ArgumentCaptor.forClass(Consumer.class); verify(consumerResource).create(argument.capture(), eq(principal), anyString(), eq("joe"), anyString(), eq(false)); assertEquals("createReporterId", argument.getValue().getHypervisorId().getReporterId()); } @Test public void hypervisorUpdateExecUpdate() throws JobExecutionException { when(ownerCurator.lookupByKey(eq("joe"))).thenReturn(owner); Consumer hypervisor = new Consumer(); String hypervisorId = "uuid_999"; hypervisor.setHypervisorId(new HypervisorId(hypervisorId)); VirtConsumerMap vcm = new VirtConsumerMap(); vcm.add(hypervisorId, hypervisor); when(consumerCurator.getHostConsumersMap(eq(owner), any(Set.class))).thenReturn(vcm); JobDetail detail = HypervisorUpdateJob.forOwner(owner, hypervisorJson, true, principal, null); JobExecutionContext ctx = mock(JobExecutionContext.class); when(ctx.getMergedJobDataMap()).thenReturn(detail.getJobDataMap()); HypervisorUpdateJob job = new HypervisorUpdateJob(ownerCurator, consumerCurator, consumerResource, i18n); job.execute(ctx); verify(consumerResource).performConsumerUpdates(any(Consumer.class), eq(hypervisor), any(VirtConsumerMap.class), eq(false)); } @Test public void reporterIdOnUpdateTest() throws JobExecutionException { when(ownerCurator.lookupByKey(eq("joe"))).thenReturn(owner); Consumer hypervisor = new Consumer(); String hypervisorId = "uuid_999"; hypervisor.setHypervisorId(new HypervisorId(hypervisorId)); VirtConsumerMap vcm = new VirtConsumerMap(); vcm.add(hypervisorId, hypervisor); when(consumerCurator.getHostConsumersMap(eq(owner), any(Set.class))).thenReturn(vcm); JobDetail detail = HypervisorUpdateJob.forOwner(owner, hypervisorJson, true, principal, "updateReporterId"); JobExecutionContext ctx = mock(JobExecutionContext.class); when(ctx.getMergedJobDataMap()).thenReturn(detail.getJobDataMap()); HypervisorUpdateJob job = new HypervisorUpdateJob(ownerCurator, consumerCurator, consumerResource, i18n); job.execute(ctx); assertEquals("updateReporterId", hypervisor.getHypervisorId().getReporterId()); } @Test public void hypervisorUpdateExecCreateNoHypervisorId() throws JobExecutionException { when(ownerCurator.lookupByKey(eq("joe"))).thenReturn(owner); hypervisorJson = "{\"hypervisors\":" + "[{" + "\"name\" : \"hypervisor_999\"," + "\"guestIds\" : [{\"guestId\" : \"guestId_1_999\"}]" + "}]}"; JobDetail detail = HypervisorUpdateJob.forOwner(owner, hypervisorJson, true, principal, null); JobExecutionContext ctx = mock(JobExecutionContext.class); when(ctx.getMergedJobDataMap()).thenReturn(detail.getJobDataMap()); HypervisorUpdateJob job = new HypervisorUpdateJob(ownerCurator, consumerCurator, consumerResource, i18n); job.execute(ctx); verify(consumerResource, never()).create(any(Consumer.class), any(Principal.class), anyString(), anyString(), anyString(), eq(false)); } @Test public void hypervisorUpdateIgnoresEmptyGuestIds() throws Exception { when(ownerCurator.lookupByKey(eq("joe"))).thenReturn(owner); hypervisorJson = "{\"hypervisors\":" + "[{" + "\"hypervisorId\" : {\"hypervisorId\" : \"hypervisor_999\"}," + "\"name\" : \"hypervisor_999\"," + "\"guestIds\" : [{\"guestId\" : \"guestId_1_999\"}, {\"guestId\" : \"\"}]" + "}]}"; JobDetail detail = HypervisorUpdateJob.forOwner(owner, hypervisorJson, true, principal, null); JobExecutionContext ctx = mock(JobExecutionContext.class); when(ctx.getMergedJobDataMap()).thenReturn(detail.getJobDataMap()); when(consumerCurator.getHostConsumersMap(eq(owner), any(Set.class))) .thenReturn(new VirtConsumerMap()); when(consumerCurator.getGuestConsumersMap(eq(owner), any(Set.class))) .thenReturn(new VirtConsumerMap()); HypervisorUpdateJob job = new HypervisorUpdateJob(ownerCurator, consumerCurator, consumerResource, i18n); job.execute(ctx); Set<String> expectedSet = new HashSet<String>(); expectedSet.add("guestId_1_999"); verify(consumerCurator, times(1)).getGuestConsumersMap(eq(owner), eq(expectedSet)); } /* * Schedule the job to be executed later even if a similar job exists. */ @Test public void dontSkipIfExistsTest() throws JobExecutionException, SchedulerException { JobDetail detail = HypervisorUpdateJob.forOwner(owner, hypervisorJson, true, principal, null); JobStatus preExistingJobStatus = new JobStatus(); preExistingJobStatus.setState(JobState.WAITING); HypervisorUpdateJob job = new HypervisorUpdateJob(ownerCurator, consumerCurator, consumerResource, i18n); JobStatus newlyScheduledJobStatus = new JobStatus(); JobCurator jobCurator = mock(JobCurator.class); Scheduler scheduler = mock(Scheduler.class); ListenerManager lm = mock(ListenerManager.class); when(jobCurator.getByClassAndTarget(anyString(), any(Class.class))).thenReturn( preExistingJobStatus); when(scheduler.getListenerManager()).thenReturn(lm); when(jobCurator.create(any(JobStatus.class))).thenReturn(newlyScheduledJobStatus); JobStatus resultStatus = job.scheduleJob(jobCurator, scheduler, detail, null); assertEquals(newlyScheduledJobStatus, resultStatus); } /* * Make sure only one test is running at a time. */ @Test public void monogamousJobTest() throws JobExecutionException, SchedulerException { JobDetail detail = HypervisorUpdateJob.forOwner(owner, hypervisorJson, true, principal, null); JobStatus newJob = new JobStatus(detail); JobCurator jobCurator = mock(JobCurator.class); when(jobCurator.findNumRunningByClassAndTarget(owner.getKey(), HypervisorUpdateJob.class)) .thenReturn(1L); assertFalse(HypervisorUpdateJob.isSchedulable(jobCurator, newJob)); } @Test public void ensureJobFailsWhenAutobindDisabledForTargetOwner() throws Exception { // Disabled autobind when(owner.autobindDisabled()).thenReturn(true); when(ownerCurator.lookupByKey(eq("joe"))).thenReturn(owner); JobDetail detail = HypervisorUpdateJob.forOwner(owner, hypervisorJson, true, principal, null); JobExecutionContext ctx = mock(JobExecutionContext.class); when(ctx.getMergedJobDataMap()).thenReturn(detail.getJobDataMap()); when(consumerCurator.getHostConsumersMap(eq(owner), any(Set.class))) .thenReturn(new VirtConsumerMap()); HypervisorUpdateJob job = new HypervisorUpdateJob(ownerCurator, consumerCurator, consumerResource, i18n); try { job.execute(ctx); fail("Expected exception due to autobind being disabled."); } catch (JobExecutionException jee) { assertEquals(jee.getCause().getMessage(), "Could not update host/guest mapping. Auto-attach is disabled for owner joe."); } } }