/** * JBoss, Home of Professional Open Source * Copyright Red Hat, Inc., and individual contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.aerogear.simplepush.subsystem; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.jboss.aerogear.simplepush.subsystem.DataStoreDefinition.Element.DATASOURCE; import static org.jboss.aerogear.simplepush.subsystem.DataStoreDefinition.Element.PERSISTENCE_UNIT; import static org.jboss.aerogear.simplepush.subsystem.ServerDefinition.Element.*; import static org.jboss.aerogear.simplepush.subsystem.SimplePushExtension.NAMESPACE; import static org.jboss.aerogear.simplepush.subsystem.SimplePushExtension.SUBSYSTEM_NAME; import static org.jboss.as.controller.PathAddress.pathAddress; import static org.jboss.as.controller.PathElement.pathElement; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DESCRIBE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OUTCOME; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUCCESS; import static org.mockito.Mockito.mock; import java.util.List; import org.jboss.as.controller.PathAddress; import org.jboss.as.naming.deployment.ContextNames; import org.jboss.as.naming.deployment.ContextNames.BindInfo; import org.jboss.as.subsystem.test.AbstractSubsystemTest; import org.jboss.as.subsystem.test.AdditionalInitialization; import org.jboss.as.subsystem.test.ControllerInitializer; import org.jboss.as.subsystem.test.KernelServices; import org.jboss.dmr.ModelNode; import org.jboss.msc.service.Service; import org.jboss.msc.service.ServiceBuilder; import org.jboss.msc.service.ServiceNotFoundException; import org.jboss.msc.service.ServiceTarget; import org.junit.Test; public class SubsystemParsingTestCase extends AbstractSubsystemTest { static { System.setProperty("org.jboss.logging.provider", "slf4j"); } private final String subsystemXml = "<subsystem xmlns=\"" + NAMESPACE + "\">" + "<server socket-binding=\"simplepush\" " + "password=\"testing\" " + "useragent-reaper-timeout=\"16000\" " + "endpoint-prefix=\"/update\" " + "endpoint-tls=\"false\" " + "endpoint-ack-interval=\"120000\" " + "endpoint-socket-binding=\"simplepush-notify\" " + "notifier-max-threads=\"4\" " + "sockjs-prefix=\"/someServiceName\" " + "sockjs-cookies-needed=\"false\" " + "sockjs-url=\"http://somehost.com/sockjs.js\" " + "sockjs-session-timeout=\"2000\" " + "sockjs-heartbeat-interval=\"8000\" " + "sockjs-max-streaming-bytes-size=\"65356\" " + "sockjs-tls=\"true\" " + "sockjs-keystore=\"/simplepush-sample.keystore\" " + "sockjs-keystore-password=\"simplepush\" " + "sockjs-websocket-enable=\"false\" " + "sockjs-websocket-heartbeat-interval=\"600000\" " + "sockjs-websocket-protocols=\"push-notification, myproto\">" + "<datastore>" + "<jpa datasource-jndi-name=\"java:jboss/datasources/TestDS\" persistence-unit=\"SimplePushPU\"/>" + "</datastore>" + "</server>" + "</subsystem>"; public SubsystemParsingTestCase() { super(SUBSYSTEM_NAME, new SimplePushExtension()); } @Test public void parseSubsystem() throws Exception { final List<ModelNode> operations = parse(subsystemXml); assertThat(operations.size(), is(3)); final ModelNode subsystem = operations.get(0); assertThat(subsystem.get(OP).asString(), equalTo(ADD)); final PathAddress address = pathAddress(subsystem.get(OP_ADDR)); assertThat(address.size(), is(1)); assertThat(address.getElement(0).getKey(), equalTo(SUBSYSTEM)); assertThat(address.getElement(0).getValue(), equalTo(SUBSYSTEM_NAME)); } @Test public void parseServerAttributes() throws Exception { final List<ModelNode> operations = parse(subsystemXml); final ModelNode options = operations.get(1); assertThat(options.get(OP).asString(), equalTo(ADD)); assertOptions(options); final ModelNode datastore = operations.get(2); assertThat(datastore.get(DATASOURCE.localName()).asString(), equalTo("java:jboss/datasources/TestDS")); assertThat(datastore.get(PERSISTENCE_UNIT.localName()).asString(), equalTo("SimplePushPU")); } @Test public void installIntoController() throws Exception { final KernelServices services = installInController(new AdditionalServices(), subsystemXml); final ModelNode model = services.readWholeModel(); assertThat(model.get(SUBSYSTEM).hasDefined(SUBSYSTEM_NAME), is(true)); assertThat(model.get(SUBSYSTEM, SUBSYSTEM_NAME).hasDefined("server"), is(true)); assertOptions(model.get(SUBSYSTEM, SUBSYSTEM_NAME, "server", "simplepush")); } @Test public void parseAndMarshalModel() throws Exception { final KernelServices servicesA = installInController(new AdditionalServices(), subsystemXml); final ModelNode modelA = servicesA.readWholeModel(); servicesA.shutdown(); final String marshalled = servicesA.getPersistedSubsystemXml(); final KernelServices servicesB = installInController(new AdditionalServices(), marshalled); final ModelNode modelB = servicesB.readWholeModel(); super.compare(modelA, modelB); } @Test public void describeHandler() throws Exception { final String subsystemXml = "<subsystem xmlns=\"" + NAMESPACE + "\">" + "</subsystem>"; final KernelServices servicesA = installInController(new AdditionalServices(), subsystemXml); final ModelNode modelA = servicesA.readWholeModel(); final ModelNode describeOp = new ModelNode(); describeOp.get(OP).set(DESCRIBE); describeOp.get(OP_ADDR).set(pathAddress(pathElement(SUBSYSTEM, SUBSYSTEM_NAME)).toModelNode()); final List<ModelNode> operations = checkResultAndGetContents(servicesA.executeOperation(describeOp)).asList(); final KernelServices servicesB = installInController(new AdditionalServices(), operations); final ModelNode modelB = servicesB.readWholeModel(); super.compare(modelA, modelB); } @Test (expected = ServiceNotFoundException.class) public void subsystemRemoval() throws Exception { final KernelServices services = installInController(new AdditionalServices(), subsystemXml); services.getContainer().getRequiredService(SimplePushService.createServiceName("simplepush")); super.assertRemoveSubsystemResources(services); services.getContainer().getRequiredService(SimplePushService.createServiceName("simplepush")); } @Test public void addSecondServer() throws Exception { final KernelServices services = installInController(new AdditionalServices(), subsystemXml); final PathAddress serverAddress = pathAddress(pathElement(SUBSYSTEM, SUBSYSTEM_NAME), pathElement("server", "foo")); final ModelNode operation = new ModelNode(); operation.get(OP).set("composite"); operation.get(ADD).setEmptyList(); ModelNode steps = operation.get("steps"); final ModelNode serverTwo = new ModelNode(); serverTwo.get(OP).set(ADD); serverTwo.get(OP_ADDR).set(serverAddress.toModelNode()); serverTwo.get(SOCKET_BINDING.localName()).set("mysocket"); serverTwo.get(PASSWORD.localName()).set("123456"); serverTwo.get(ENDPOINT_TLS.localName()).set("true"); serverTwo.get(REAPER_TIMEOUT.localName()).set(20000); serverTwo.get(ENDPOINT_PREFIX.localName()).set("/endpoints"); serverTwo.get(ENDPOINT_TLS.localName()).set(false); serverTwo.get(ENDPOINT_ACK_INTERVAL.localName()).set(10000); serverTwo.get(ENDPOINT_SOCKET_BINDING.localName()).set("simplepush-notify"); serverTwo.get(NOTIFIER_MAX_THREADS.localName()).set("4"); serverTwo.get(SOCKJS_PREFIX.localName()).set("/foo"); serverTwo.get(SOCKJS_COOKIES_NEEDED.localName()).set("false"); serverTwo.get(SOCKJS_URL.localName()).set("http://foo.com/sockjs.js"); serverTwo.get(SOCKJS_SESSION_TIMEOUT.localName()).set(3000); serverTwo.get(SOCKJS_HEARTBEAT_INTERVAL.localName()).set(9000); serverTwo.get(SOCKJS_MAX_STREAMING_BYTES_SIZE.localName()).set(23333); serverTwo.get(SOCKJS_TLS.localName()).set(false); serverTwo.get(SOCKJS_ENABLE_WEBSOCKET.localName()).set(true); serverTwo.get(SOCKJS_WEBSOCKET_HEARTBEAT_INTERVAL.localName()).set(300000L); steps.add(serverTwo); final ModelNode serverTwoDatastore = new ModelNode(); serverTwoDatastore.get(OP).set(ADD); serverTwoDatastore.get(OP_ADDR).set(serverAddress.toModelNode().add(DataStoreDefinition.DATASTORE, DataStoreDefinition.Element.JPA.localName())); serverTwoDatastore.get(DATASOURCE.localName()).set("java:jboss/datasources/NettyDS"); serverTwoDatastore.get(PERSISTENCE_UNIT.localName()).set("SimplePushPU"); steps.add(serverTwoDatastore); assertThat(services.executeOperation(operation).get(OUTCOME).asString(), equalTo(SUCCESS)); final ModelNode model = services.readWholeModel(); assertThat(model.get(SUBSYSTEM, SUBSYSTEM_NAME, "server").hasDefined("foo"), is(true)); final ModelNode fooOptions = model.get(SUBSYSTEM, SUBSYSTEM_NAME, "server", "foo"); assertThat(fooOptions.get(SOCKET_BINDING.localName()).asString(), equalTo("mysocket")); assertThat(fooOptions.get(PASSWORD.localName()).asString(), equalTo("123456")); assertThat(fooOptions.get(REAPER_TIMEOUT.localName()).asLong(), is(20000L)); assertThat(fooOptions.get(ENDPOINT_TLS.localName()).asBoolean(), is(false)); assertThat(fooOptions.get(ENDPOINT_PREFIX.localName()).asString(), equalTo("/endpoints")); assertThat(fooOptions.get(ENDPOINT_ACK_INTERVAL.localName()).asLong(), is(10000L)); assertThat(fooOptions.get(ENDPOINT_SOCKET_BINDING.localName()).asString(), equalTo("simplepush-notify")); assertThat(fooOptions.get(NOTIFIER_MAX_THREADS.localName()).asInt(), is(4)); assertThat(fooOptions.get(SOCKJS_PREFIX.localName()).asString(), equalTo("/foo")); assertThat(fooOptions.get(SOCKJS_COOKIES_NEEDED.localName()).asBoolean(), is(false)); assertThat(fooOptions.get(SOCKJS_URL.localName()).asString(), equalTo("http://foo.com/sockjs.js")); assertThat(fooOptions.get(SOCKJS_SESSION_TIMEOUT.localName()).asLong(), is(3000L)); assertThat(fooOptions.get(SOCKJS_HEARTBEAT_INTERVAL.localName()).asLong(), is(9000L)); assertThat(fooOptions.get(SOCKJS_MAX_STREAMING_BYTES_SIZE.localName()).asLong(), is(23333L)); assertThat(fooOptions.get(SOCKJS_TLS.localName()).asBoolean(), is(false)); assertThat(fooOptions.get(SOCKJS_ENABLE_WEBSOCKET.localName()).asBoolean(), is(true)); assertThat(fooOptions.get(SOCKJS_WEBSOCKET_HEARTBEAT_INTERVAL.localName()).asLong(), is(300000L)); assertThat(fooOptions.get(SOCKJS_WEBSOCKET_PROTOCOLS.localName()).asString(), equalTo("push-notification")); final ModelNode fooJpa = fooOptions.get(DataStoreDefinition.DATASTORE, DataStoreDefinition.Element.JPA.localName()); assertThat(fooJpa.get(DATASOURCE.localName()).asString(), equalTo("java:jboss/datasources/NettyDS")); } private void assertOptions(final ModelNode options) { assertThat(options.get(SOCKET_BINDING.localName()).asString(), equalTo("simplepush")); assertThat(options.get(PASSWORD.localName()).asString(), equalTo("testing")); assertThat(options.get(REAPER_TIMEOUT.localName()).asLong(), is(16000L)); assertThat(options.get(ENDPOINT_PREFIX.localName()).asString(), equalTo("/update")); assertThat(options.get(ENDPOINT_TLS.localName()).asBoolean(), is(false)); assertThat(options.get(ENDPOINT_ACK_INTERVAL.localName()).asLong(), equalTo(120000L)); assertThat(options.get(ENDPOINT_SOCKET_BINDING.localName()).asString(), equalTo("simplepush-notify")); assertThat(options.get(NOTIFIER_MAX_THREADS.localName()).asInt(), is(4)); assertThat(options.get(SOCKJS_PREFIX.localName()).asString(), equalTo("/someServiceName")); assertThat(options.get(SOCKJS_COOKIES_NEEDED.localName()).asBoolean(), is(false)); assertThat(options.get(SOCKJS_URL.localName()).asString(), equalTo("http://somehost.com/sockjs.js")); assertThat(options.get(SOCKJS_SESSION_TIMEOUT.localName()).asLong(), is(2000L)); assertThat(options.get(SOCKJS_HEARTBEAT_INTERVAL.localName()).asLong(), is(8000L)); assertThat(options.get(SOCKJS_MAX_STREAMING_BYTES_SIZE.localName()).asLong(), is(65356L)); assertThat(options.get(SOCKJS_TLS.localName()).asBoolean(), is(true)); assertThat(options.get(SOCKJS_KEYSTORE.localName()).asString(), equalTo("/simplepush-sample.keystore")); assertThat(options.get(SOCKJS_KEYSTORE_PASSWORD.localName()).asString(), equalTo("simplepush")); assertThat(options.get(SOCKJS_ENABLE_WEBSOCKET.localName()).asBoolean(), is(false)); assertThat(options.get(SOCKJS_WEBSOCKET_HEARTBEAT_INTERVAL.localName()).asLong(), is(600000L)); assertThat(options.get(SOCKJS_WEBSOCKET_PROTOCOLS.localName()).asString(), equalTo("push-notification, myproto")); } private static class AdditionalServices extends AdditionalInitialization { @Override protected void setupController(final ControllerInitializer controllerInitializer) { controllerInitializer.setBindAddress("127.0.0.1"); controllerInitializer.addSocketBinding("mysocket", 18888); controllerInitializer.addSocketBinding("simplepush", 17777); controllerInitializer.addSocketBinding("simplepush-notify", 8000); } @Override protected void addExtraServices(final ServiceTarget serviceTarget) { final Service<?> ds = mock(Service.class); final BindInfo testBindInfo = ContextNames.bindInfoFor("java:jboss/datasources/TestDS"); final ServiceBuilder<?> testDS = serviceTarget.addService(testBindInfo.getBinderServiceName(), ds); testDS.install(); final BindInfo nettyBindInfo = ContextNames.bindInfoFor("java:jboss/datasources/NettyDS"); final ServiceBuilder<?> nettyDS = serviceTarget.addService(nettyBindInfo.getBinderServiceName(), ds); nettyDS.install(); } } }