/*
* RHQ Management Platform
* Copyright (C) 2012 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.core.pc.inventory;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.assertTrue;
import java.util.HashMap;
import java.util.Map;
import org.mockito.Mockito;
import org.testng.Assert;
import org.testng.annotations.Test;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.TargetsContainer;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.arquillian.testng.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.rhq.core.clientapi.server.discovery.InventoryReport;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.discovery.MergeResourceResponse;
import org.rhq.core.domain.resource.InventoryStatus;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.pc.PluginContainer;
import org.rhq.core.pc.PluginContainerConfiguration;
import org.rhq.core.pc.availability.AvailabilityContextImpl;
import org.rhq.core.pc.content.ContentContextImpl;
import org.rhq.core.pc.event.EventContextImpl;
import org.rhq.core.pc.inventory.testplugin.ManualAddDiscoveryComponent;
import org.rhq.core.pc.inventory.testplugin.TestResourceComponent;
import org.rhq.core.pc.inventory.testplugin.TestResourceDiscoveryComponent;
import org.rhq.core.pc.operation.OperationContextImpl;
import org.rhq.core.pluginapi.inventory.ResourceContext;
import org.rhq.test.arquillian.AfterDiscovery;
import org.rhq.test.arquillian.BeforeDiscovery;
import org.rhq.test.arquillian.FakeServerInventory;
import org.rhq.test.arquillian.MockingServerServices;
import org.rhq.test.arquillian.RunDiscovery;
import org.rhq.test.shrinkwrap.RhqAgentPluginArchive;
/**
* A unit test for testing discovery.
*/
public class DiscoveryTest extends Arquillian {
@Deployment(name = "test")
@TargetsContainer("pc")
public static RhqAgentPluginArchive getTestPlugin() {
RhqAgentPluginArchive pluginJar = ShrinkWrap.create(RhqAgentPluginArchive.class, "test-plugin.jar");
return pluginJar.setPluginDescriptor("test-great-grandchild-discovery-plugin.xml").addClasses(
TestResourceDiscoveryComponent.class, TestResourceComponent.class, ManualAddDiscoveryComponent.class);
}
@ArquillianResource
private MockingServerServices serverServices;
@ArquillianResource
private PluginContainerConfiguration pluginContainerConfiguration;
@ArquillianResource
private PluginContainer pluginContainer;
private FakeServerInventory fakeServerInventory;
private FakeServerInventory.CompleteDiscoveryChecker discoveryCompleteChecker;
@BeforeDiscovery
public void resetServerServices() throws Exception {
// Set up our fake server discovery ServerService, which will auto-import all Resources in reports it receives.
serverServices.resetMocks();
fakeServerInventory = new FakeServerInventory();
discoveryCompleteChecker = fakeServerInventory.createAsyncDiscoveryCompletionChecker(5);
when(serverServices.getDiscoveryServerService().mergeInventoryReport(any(InventoryReport.class))).then(
fakeServerInventory.mergeInventoryReport(InventoryStatus.COMMITTED));
when(serverServices.getDiscoveryServerService().getResourceSyncInfo(any(Integer.class))).then(
fakeServerInventory.getResourceSyncInfo());
}
@AfterDiscovery
public void waitForAsyncDiscoveries() throws Exception {
if (discoveryCompleteChecker != null) {
discoveryCompleteChecker.waitForDiscoveryComplete(10000);
}
}
/**
* Tests that discovery was only run once per ResourceType. This tests a deep, 4-level hierarchy.
*
* @throws Exception if an error occurs
*/
@RunDiscovery
@Test(groups = "pc.itest.discovery", priority = 10)
public void testDiscoveryRunsOnlyOncePerType() throws Exception {
waitForAsyncDiscoveries();
// make sure our inventory is as we expect it to be
validatePluginContainerInventory();
// reset our discovery component's internal storage
TestResourceDiscoveryComponent.getExecutionCountsByResourceType().clear();
// run our own discovery scan
this.pluginContainer.getInventoryManager().executeServiceScanImmediately();
Map<ResourceType, Integer> executionCountsByResourceType = TestResourceDiscoveryComponent
.getExecutionCountsByResourceType();
Map<ResourceType, Integer> flaggedExecutionCountsByResourceType = new HashMap<ResourceType, Integer>();
for (ResourceType resourceType : executionCountsByResourceType.keySet()) {
Integer count = executionCountsByResourceType.get(resourceType);
if (count != 1) {
flaggedExecutionCountsByResourceType.put(resourceType, count);
}
}
Assert.assertTrue(flaggedExecutionCountsByResourceType.isEmpty(),
"Discovery was not executed once (and only once) for the following types: "
+ flaggedExecutionCountsByResourceType);
}
@Test(groups = "pc.itest.discovery", priority = 10)
public void testResourceSyncedWithServerAfterManualAdd() throws Exception {
Mockito.when(serverServices.getDiscoveryServerService().addResource(any(Resource.class), anyInt())).then(
fakeServerInventory.addResource());
InventoryManager inventoryManager = pluginContainer.getInventoryManager();
Resource platform = inventoryManager.getPlatform();
Configuration myPluginConfig = new Configuration();
myPluginConfig.put(new PropertySimple("test", "value"));
ResourceType resourceType = pluginContainer.getPluginManager().getMetadataManager()
.getType("Manual Add Server", "test");
MergeResourceResponse response = inventoryManager.manuallyAddResource(resourceType, platform.getId(),
myPluginConfig, -1);
assertFalse(response.resourceAlreadyExisted(), "The manual add resource shouldn't have existed");
assertNotEquals(response.getResourceId(), 0, "The manual add resource should have had its resource id set");
ResourceContainer resourceContainer = inventoryManager.getResourceContainer(response.getResourceId());
ResourceContext<?> resourceContext = resourceContainer.getResourceContext();
assertEquals(resourceContext.getPluginConfiguration(), myPluginConfig,
"The manual add resource doesn't have the expected plugin config.");
assertTrue(resourceContext.getAvailabilityContext() instanceof AvailabilityContextImpl,
"Unexpected implementation clas of the AvailabilityContext, please fix this test.");
assertEquals(((AvailabilityContextImpl) resourceContext.getAvailabilityContext()).getResource().getId(),
response.getResourceId(),
"Availability subsystem isn't aware of the correct resource id for manual add resource");
assertTrue(resourceContext.getContentContext() instanceof ContentContextImpl,
"Unexpected implementation class of ContentContext, please fix this test");
assertEquals(((ContentContextImpl) resourceContext.getContentContext()).getResourceId(),
response.getResourceId(),
"Content subsystem isn't aware of the correct resource id for manual add resource");
assertTrue(resourceContext.getEventContext() instanceof EventContextImpl,
"Unexpected implementation clas of the EventContext, please fix this test.");
assertEquals(((EventContextImpl) resourceContext.getEventContext()).getResource().getId(),
response.getResourceId(), "Event subsystem isn't aware of the correct resource id for manual add resource");
assertTrue(resourceContext.getOperationContext() instanceof OperationContextImpl,
"Unexpected implementation clas of the OperationContext, please fix this test.");
assertEquals(((OperationContextImpl) resourceContext.getOperationContext()).getResourceId(),
response.getResourceId(),
"Operation subsystem isn't aware of the correct resource id for manual add resource");
}
private void validatePluginContainerInventory() throws Exception {
System.out.println("Validating PC inventory...");
Resource platform = pluginContainer.getInventoryManager().getPlatform();
Assert.assertNotNull(platform);
Assert.assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
Resource server = platform.getChildResources().iterator().next();
Assert.assertNotNull(server);
Assert.assertEquals(server.getInventoryStatus(), InventoryStatus.COMMITTED);
assert server.getResourceType().getName().equals("Test Server");
Resource child = server.getChildResources().iterator().next();
Assert.assertNotNull(child);
Assert.assertEquals(child.getInventoryStatus(), InventoryStatus.COMMITTED);
assert child.getResourceType().getName().equals("Test Service Child");
Resource grandchild = child.getChildResources().iterator().next();
Assert.assertNotNull(grandchild);
Assert.assertEquals(grandchild.getInventoryStatus(), InventoryStatus.COMMITTED);
assert grandchild.getResourceType().getName().equals("Test Service GrandChild");
Resource greatgrandchild = grandchild.getChildResources().iterator().next();
Assert.assertNotNull(greatgrandchild);
Assert.assertEquals(greatgrandchild.getInventoryStatus(), InventoryStatus.COMMITTED);
assert greatgrandchild.getResourceType().getName().equals("Test Service GreatGrandChild");
System.out.println("PC inventory validated successfully!");
}
}