/** * Copyright (C) 2008 Progress Software, Inc. All rights reserved. * http://fusesource.com * * The software in this package is published under the terms of the AGPL license * a copy of which has been included with this distribution in the license.txt file. */ package org.fusesource.cloudmix.agent.jbi; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; import java.net.URLStreamHandlerFactory; import java.util.HashMap; import java.util.Map; import javax.management.MBeanServer; import javax.management.ObjectName; import junit.framework.TestCase; import org.fusesource.cloudmix.agent.Bundle; import org.fusesource.cloudmix.agent.Feature; import org.fusesource.cloudmix.agent.security.SecurityUtils; import org.easymock.EasyMock; public class JBIInstallerAgentTest extends TestCase { // Constants for JMX invocations private static final String[] SIGNATURE_VOID = {}; private static final String[] SIGNATURE_STRING = {"java.lang.String"}; private static final String[] PARAMS_VOID = {}; private static final String[] EMPTY_STRING_ARRAY = {}; private static final String TEST_FEATURE_NAME_1 = "f1"; private static final String TEST_FEATURE_NAME_2 = "f2"; private static final String TEST_BUNDLE_URI_1 = "resource://foo:bar@example.com/sa_1.zip"; private static final String TEST_BUNDLE_URI_2 = "resource://foo:bar@example.com/sa_2.zip"; private static final String TEST_SERVICE_ASSEMBLY_NAME = "b1-sa"; private static final String TEST_COMP_1 = "comp_1"; private static final String TEST_COMP_2 = "comp_2"; private static final String TEST_COMP_3 = "comp_3"; private static boolean urlHandlerIsSet; private static final String DEPLOY_SUCCESS = "<jbi-task xmlns=\"http://java.sun.com/xml/ns/jbi/management-message\">" + " <jbi-task-result>" + " <frmwk-task-result>" + " <frmwk-task-result-details>" + " <task-result-details>" + " <task-id>deploy</task-id>" + " <task-result>SUCCESS</task-result>" + " </task-result-details>" + " </frmwk-task-result-details>" + " </frmwk-task-result>" + " <component-task-result>" + " <!-- ... -->" + " </component-task-result>" + " <component-task-result>" + " <!-- ... -->" + " </component-task-result>" + " </jbi-task-result>" + "</jbi-task>"; private static final String DEPLOY_FAILURE = "<jbi-task xmlns=\"http://java.sun.com/xml/ns/jbi/management-message\">" + " <jbi-task-result>" + " <frmwk-task-result>" + " <frmwk-task-result-details>" + " <task-result-details>" + " <task-id>deploy</task-id>" + " <task-result>FAILED</task-result>" + " </task-result-details>" + " </frmwk-task-result-details>" + " </frmwk-task-result>" + " <component-task-result>" + " <!-- ... -->" + " </component-task-result>" + " <component-task-result>" + " <!-- ... -->" + " </component-task-result>" + " </jbi-task-result>" + "</jbi-task>"; private static final String START_SUCCESS = "<jbi-task xmlns=\"http://java.sun.com/xml/ns/jbi/management-message\">" + " <jbi-task-result>" + " <frmwk-task-result>" + " <frmwk-task-result-details>" + " <task-result-details>" + " <task-id>start</task-id>" + " <task-result>SUCCESS</task-result>" + " </task-result-details>" + " </frmwk-task-result-details>" + " </frmwk-task-result>" + " </jbi-task-result>" + "</jbi-task>"; private static final String START_FAILURE = "<jbi-task xmlns=\"http://java.sun.com/xml/ns/jbi/management-message\">" + " <jbi-task-result>" + " <frmwk-task-result>" + " <frmwk-task-result-details>" + " <task-result-details>" + " <task-id>start</task-id>" + " <task-result>FAILED</task-result>" + " </task-result-details>" + " </frmwk-task-result-details>" + " </frmwk-task-result>" + " <component-task-result>" + " <!-- ... -->" + " </component-task-result>" + " <component-task-result>" + " <!-- ... -->" + " </component-task-result>" + " </jbi-task-result>" + "</jbi-task>"; private static final String SHUTDOWN_SUCCESS = "<jbi-task xmlns=\"http://java.sun.com/xml/ns/jbi/management-message\">" + " <jbi-task-result>" + " <frmwk-task-result>" + " <frmwk-task-result-details>" + " <task-result-details>" + " <task-id>shutDown</task-id>" + " <task-result>SUCCESS</task-result>" + " </task-result-details>" + " </frmwk-task-result-details>" + " </frmwk-task-result>" + " </jbi-task-result>" + "</jbi-task>"; private static final String SHUTDOWN_FAILURE = "<jbi-task xmlns=\"http://java.sun.com/xml/ns/jbi/management-message\">" + " <jbi-task-result>" + " <frmwk-task-result>" + " <frmwk-task-result-details>" + " <task-result-details>" + " <task-id>shutDown</task-id>" + " <task-result>FAILED</task-result>" + " <message-type>ERROR</message-type>" + " <task-status-msg>" + " <msg-loc-info>" + " <loc-token/>" + " <loc-message>Some error message</loc-message>" + " </msg-loc-info>" + " </task-status-msg>" + " </task-result-details>" + " </frmwk-task-result-details>" + " </frmwk-task-result>" + " </jbi-task-result>" + "</jbi-task>"; private static final String UNDEPLOY_FAILURE = "<jbi-task xmlns=\"http://java.sun.com/xml/ns/jbi/management-message\">" + " <jbi-task-result>" + " <frmwk-task-result>" + " <frmwk-task-result-details>" + " <task-result-details>" + " <task-id>undeploy</task-id>" + " <task-result>FAILED</task-result>" + " </task-result-details>" + " </frmwk-task-result-details>" + " </frmwk-task-result>" + " </jbi-task-result>" + "</jbi-task>"; private static final String BAD_XML = "<jbi-task xmlns=\"http://java.sun.com/xml/ns/jbi/management-message\">" + " <jbi-task-result>" + " <frmwk-task-result>"; private ObjectName mbeanName; private MBeanServer mbeanServer; private JBIInstallerAgent agent; private Bundle bundle1; private Bundle bundle2; private Feature feature1; private Feature feature2; public void setUp() throws Exception { agent = new JBIInstallerAgent(); mbeanName = new ObjectName("test:Name=Test"); mbeanServer = EasyMock.createStrictMock(MBeanServer.class); agent.setMBeanName(mbeanName); agent.setMBeanServer(mbeanServer); agent.setMaxDeployAttempts(3); agent.setDeployAttemptDelay(1); bundle1 = new Bundle("", "", TEST_BUNDLE_URI_1); feature1 = new Feature(TEST_FEATURE_NAME_1, null); feature1.addBundle(bundle1); bundle2 = new Bundle("", "", TEST_BUNDLE_URI_2); feature2 = new Feature(TEST_FEATURE_NAME_2, null); feature2.addBundle(bundle2); // Set up a URL handler for resource: URLs. These resolve to local // class resources. if (!urlHandlerIsSet) { URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory() { public URLStreamHandler createURLStreamHandler(String protocol) { if ("resource".equals(protocol)) { return new URLStreamHandler() { protected URLConnection openConnection(URL u) throws IOException { return new ResourceURLConnection(u); } }; } return null; } }); urlHandlerIsSet = true; } } public void testJBIAgentValidate() throws Exception { EasyMock.replay(mbeanServer); assertTrue(agent.validateAgent()); EasyMock.verify(mbeanServer); } public void setupDeployBundle() throws Exception { String[] comp1Params = {TEST_COMP_1}; String[] comp2Params = {TEST_COMP_2}; String[] deployParams = {TEST_BUNDLE_URI_1}; String deployRet = DEPLOY_SUCCESS; String[] getInstalledSARet2 = {TEST_SERVICE_ASSEMBLY_NAME}; String[] startParams = {TEST_SERVICE_ASSEMBLY_NAME}; String startRet = START_SUCCESS; EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("getDeployedServiceAssemblies"), EasyMock.aryEq(PARAMS_VOID), EasyMock.aryEq(SIGNATURE_VOID))) .andReturn(EMPTY_STRING_ARRAY); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("canDeployToComponent"), EasyMock.aryEq(comp1Params), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(Boolean.TRUE); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("canDeployToComponent"), EasyMock.aryEq(comp2Params), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(Boolean.TRUE); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("deploy"), EasyMock.aryEq(deployParams), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(deployRet); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("getDeployedServiceAssemblies"), EasyMock.aryEq(PARAMS_VOID), EasyMock.aryEq(SIGNATURE_VOID))) .andReturn(getInstalledSARet2); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("start"), EasyMock.aryEq(startParams), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(startRet); } public void testJBIAgentInstall() throws Exception { setupDeployBundle(); EasyMock.replay(mbeanServer); assertTrue(agent.installBundle(feature1, bundle1)); EasyMock.verify(mbeanServer); } public void testJBIAgentDeployFailure() throws Exception { String[] params2 = {TEST_BUNDLE_URI_1}; String[] comp1Params = {TEST_COMP_1}; String[] comp2Params = {TEST_COMP_2}; EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("getDeployedServiceAssemblies"), EasyMock.aryEq(PARAMS_VOID), EasyMock.aryEq(SIGNATURE_VOID))) .andReturn(EMPTY_STRING_ARRAY); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("canDeployToComponent"), EasyMock.aryEq(comp1Params), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(Boolean.TRUE); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("canDeployToComponent"), EasyMock.aryEq(comp2Params), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(Boolean.TRUE); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("deploy"), EasyMock.aryEq(params2), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(DEPLOY_FAILURE); EasyMock.replay(mbeanServer); assertFalse(agent.installBundle(feature1, bundle1)); EasyMock.verify(mbeanServer); } public void testJBIAgentDeployComponentUnavailable() throws Exception { String[] params2 = {TEST_BUNDLE_URI_2}; String[] comp3Params = {TEST_COMP_3}; EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("getDeployedServiceAssemblies"), EasyMock.aryEq(PARAMS_VOID), EasyMock.aryEq(SIGNATURE_VOID))) .andReturn(EMPTY_STRING_ARRAY); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("canDeployToComponent"), EasyMock.aryEq(comp3Params), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(Boolean.FALSE).anyTimes(); EasyMock.replay(mbeanServer); assertFalse(agent.installBundle(feature2, bundle2)); EasyMock.verify(mbeanServer); } public void testJBIAgentStartFailure() throws Exception { String[] comp1Params = {TEST_COMP_1}; String[] comp2Params = {TEST_COMP_2}; String[] deployParams = {TEST_BUNDLE_URI_1}; String deployRet = DEPLOY_SUCCESS; String[] getInstalledSARet2 = {TEST_SERVICE_ASSEMBLY_NAME}; String[] startParams = {TEST_SERVICE_ASSEMBLY_NAME}; String startRet = START_FAILURE; EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("getDeployedServiceAssemblies"), EasyMock.aryEq(PARAMS_VOID), EasyMock.aryEq(SIGNATURE_VOID))) .andReturn(EMPTY_STRING_ARRAY); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("canDeployToComponent"), EasyMock.aryEq(comp1Params), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(Boolean.TRUE); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("canDeployToComponent"), EasyMock.aryEq(comp2Params), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(Boolean.TRUE); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("deploy"), EasyMock.aryEq(deployParams), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(deployRet); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("getDeployedServiceAssemblies"), EasyMock.aryEq(PARAMS_VOID), EasyMock.aryEq(SIGNATURE_VOID))) .andReturn(getInstalledSARet2); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("start"), EasyMock.aryEq(startParams), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(startRet); EasyMock.replay(mbeanServer); assertFalse(agent.installBundle(feature1, bundle1)); EasyMock.verify(mbeanServer); } public void testJBIAgentUninstall() throws Exception { setupDeployBundle(); String[] shutDownParams = {TEST_SERVICE_ASSEMBLY_NAME}; String shutDownRet = SHUTDOWN_SUCCESS; String[] undeployParams = {TEST_SERVICE_ASSEMBLY_NAME}; Object undeployRet = null; EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("shutDown"), EasyMock.aryEq(shutDownParams), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(shutDownRet); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("undeploy"), EasyMock.aryEq(undeployParams), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(undeployRet); EasyMock.replay(mbeanServer); assertTrue(agent.installBundle(feature1, bundle1)); assertTrue(agent.uninstallBundle(feature1, bundle1)); EasyMock.verify(mbeanServer); } public void testJBIAgentShutdownFailure() throws Exception { setupDeployBundle(); String[] shutDownParams = {TEST_SERVICE_ASSEMBLY_NAME}; String shutDownRet = SHUTDOWN_FAILURE; EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("shutDown"), EasyMock.aryEq(shutDownParams), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(shutDownRet); EasyMock.replay(mbeanServer); assertTrue(agent.installBundle(feature1, bundle1)); assertFalse(agent.uninstallBundle(feature1, bundle1)); EasyMock.verify(mbeanServer); } public void testJBIAgentUndeployFailure() throws Exception { setupDeployBundle(); String[] shutDownParams = {TEST_SERVICE_ASSEMBLY_NAME}; String shutDownRet = SHUTDOWN_SUCCESS; String[] undeployParams = {TEST_SERVICE_ASSEMBLY_NAME}; String undeployRet = UNDEPLOY_FAILURE; EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("shutDown"), EasyMock.aryEq(shutDownParams), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(shutDownRet); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("undeploy"), EasyMock.aryEq(undeployParams), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(undeployRet); EasyMock.replay(mbeanServer); assertTrue(agent.installBundle(feature1, bundle1)); assertFalse(agent.uninstallBundle(feature1, bundle1)); EasyMock.verify(mbeanServer); } public void testJBIAgentUnknownSA() throws Exception { EasyMock.replay(mbeanServer); assertFalse(agent.uninstallBundle(feature1, bundle1)); EasyMock.verify(mbeanServer); } public void testJBIAgentBadXML() throws Exception { String[] deployParams = {TEST_BUNDLE_URI_1}; String[] comp1Params = {TEST_COMP_1}; String[] comp2Params = {TEST_COMP_2}; EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("getDeployedServiceAssemblies"), EasyMock.aryEq(PARAMS_VOID), EasyMock.aryEq(SIGNATURE_VOID))).andReturn(EMPTY_STRING_ARRAY); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("canDeployToComponent"), EasyMock.aryEq(comp1Params), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(Boolean.TRUE); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("canDeployToComponent"), EasyMock.aryEq(comp2Params), EasyMock.aryEq(SIGNATURE_STRING))) .andReturn(Boolean.TRUE); EasyMock.expect(mbeanServer.invoke(EasyMock.eq(mbeanName), EasyMock.eq("deploy"), EasyMock.aryEq(deployParams), EasyMock.aryEq(SIGNATURE_STRING))).andReturn(BAD_XML); EasyMock.replay(mbeanServer); assertFalse(agent.installBundle(feature1, bundle1)); EasyMock.verify(mbeanServer); } /** * URLConnection class to resolve resource URLS. * */ static class ResourceURLConnection extends URLConnection { public static Map<String, String> reqProps = new HashMap<String, String>(); protected ResourceURLConnection(URL url) { super(url); reqProps.clear(); } @Override public void connect() throws IOException { // Complete } @Override public InputStream getInputStream() throws IOException { String auth = reqProps.get("Authorization"); String usrInfo = getURL().getUserInfo(); if (usrInfo != null && !"".equals(usrInfo)) { assertEquals(SecurityUtils.getBasicAuthHeader(usrInfo), auth); } else { assertNull(auth); } return this.getClass().getResourceAsStream(url.getPath()); } @Override public void setRequestProperty(String key, String value) { reqProps.put(key, value); } } }