/*
* JBoss, Home of Professional Open Source.
* Copyright 2011, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
/**
*
*/
package org.jboss.as.controller;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.INCLUDE_RUNTIME;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OUTCOME;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.READ_RESOURCE_OPERATION;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESULT;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUCCESS;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.as.controller.descriptions.NonResolvingResourceDescriptionResolver;
import org.jboss.as.controller.operations.common.Util;
import org.jboss.as.controller.operations.global.GlobalNotifications;
import org.jboss.as.controller.operations.global.GlobalOperationHandlers;
import org.jboss.as.controller.registry.ManagementResourceRegistration;
import org.jboss.as.controller.registry.Resource;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;
import org.jboss.msc.service.ServiceBuilder;
import org.jboss.msc.service.ServiceContainer;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.ServiceTarget;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
/**
* Unit tests of {@link ModelControllerImpl}.
*
* @author Brian Stansberry (c) 2011 Red Hat Inc.
*/
public class MetricsUndefinedValueUnitTestCase {
private static final PathElement ELEMENT = PathElement.pathElement("testing", "resource");
private static final PathAddress ADDRESS = PathAddress.pathAddress(ELEMENT);
private static final String TEST_METRIC = "test-metric";
private static final Executor executor = Executors.newCachedThreadPool();
private static CountDownLatch blockObject;
private static CountDownLatch latch;
private ServiceContainer container;
private ModelController controller;
private ModelControllerClient client;
// BES 2015/08/28 The WFCORE-831 spec does not require this assertion. The requirement is that read-attribute
// not return undefined, but AttributeDefinition.getUndefinedMetricValue() is not the only way to achieve this.
// The read-attribute handler can simply always work.
// @Test
// public void testRegisterNonNillableNoUndefinedMetricsValueMetricRegistration() throws Exception {
// ManagementResourceRegistration reg = setupController(new TestResourceDefinition());
// SimpleAttributeDefinition def = new SimpleAttributeDefinitionBuilder(TEST_METRIC, ModelType.STRING)
// .setStorageRuntime()
// .build();
// registerFailingMetric(reg, def, new EmptyHandler());
// }
@Test
public void testRegisterNillableAndUndefinedMetricsValueMetricRegistration() throws Exception {
ManagementResourceRegistration reg = setupController(new TestResourceDefinition());
SimpleAttributeDefinition def = new SimpleAttributeDefinitionBuilder(TEST_METRIC, ModelType.STRING, true)
.setStorageRuntime()
.setUndefinedMetricValue(new ModelNode(TEST_METRIC))
.build();
registerFailingMetric(reg, def, new EmptyHandler());
}
@Test
public void testRegisterNonNillableAndDefinedMetricsValueMetricRegistration() throws Exception {
ManagementResourceRegistration reg = setupController(new TestResourceDefinition());
SimpleAttributeDefinition def = new SimpleAttributeDefinitionBuilder(TEST_METRIC, ModelType.STRING)
.setStorageRuntime()
.setUndefinedMetricValue(new ModelNode(TEST_METRIC))
.build();
reg.registerMetric(def, new EmptyHandler());
}
@Test
public void testReadMetricDefinedByHandler() throws Exception {
ManagementResourceRegistration reg = setupController(new TestResourceDefinition());
SimpleAttributeDefinition def = new SimpleAttributeDefinitionBuilder(TEST_METRIC, ModelType.STRING)
.setStorageRuntime()
.setUndefinedMetricValue(new ModelNode("test"))
.build();
reg.registerMetric(def, new HardCodedValueHandler(new ModelNode("test2")));
checkTestMetric("test2");
}
@Test
public void testReadMetricNotDefinedByHandler() throws Exception {
ManagementResourceRegistration reg = setupController(new TestResourceDefinition());
SimpleAttributeDefinition def = new SimpleAttributeDefinitionBuilder(TEST_METRIC, ModelType.STRING)
.setStorageRuntime()
.setUndefinedMetricValue(new ModelNode("test"))
.build();
reg.registerMetric(def, new EmptyHandler());
checkTestMetric("test");
}
private void checkTestMetric(String expectedValue) throws Exception {
ModelNode result = getResult(client.execute(Util.getReadAttributeOperation(ADDRESS, TEST_METRIC)));
Assert.assertEquals(expectedValue, result.asString());
ModelNode rr = Util.createEmptyOperation(READ_RESOURCE_OPERATION, ADDRESS);
rr.get(INCLUDE_RUNTIME).set(true);
result = getResult(client.execute(rr));
Assert.assertTrue(result.hasDefined(TEST_METRIC));
Assert.assertEquals(expectedValue, result.get(TEST_METRIC).asString());
}
private ModelNode getResult(ModelNode result) {
Assert.assertEquals(SUCCESS, result.get(OUTCOME).asString());
return result.get(RESULT);
}
private void registerFailingMetric(ManagementResourceRegistration reg, AttributeDefinition def, OperationStepHandler handler) {
boolean worked = false;
try {
reg.registerMetric(def, new EmptyHandler());
worked = true;
} catch (AssertionError expected) {
}
Assert.assertFalse("Should not have worked registering a non-nillable metric with no undefined metrics value", worked);
}
@After
public void shutdownServiceContainer() {
if (client != null) {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (container != null) {
container.shutdown();
try {
container.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
container = null;
}
}
}
private ManagementResourceRegistration setupController(TestResourceDefinition resourceDefinition) throws InterruptedException {
// restore default
blockObject = new CountDownLatch(1);
latch = new CountDownLatch(1);
System.out.println("========= New Test \n");
container = ServiceContainer.Factory.create(TEST_METRIC);
ServiceTarget target = container.subTarget();
ModelControllerService svc = new ModelControllerService(resourceDefinition);
ServiceBuilder<ModelController> builder = target.addService(ServiceName.of("ModelController"), svc);
builder.install();
svc.awaitStartup(30, TimeUnit.SECONDS);
controller = svc.getValue();
ModelNode setup = Util.getEmptyOperation("setup", new ModelNode());
controller.execute(setup, null, null, null);
client = controller.createClient(executor);
return svc.managementControllerResource;
}
private static class ModelControllerService extends TestModelControllerService {
private final TestResourceDefinition resourceDefinition;
public ManagementResourceRegistration managementControllerResource;
public ModelControllerService(TestResourceDefinition resourceDefinition) {
this.resourceDefinition = resourceDefinition;
}
@Override
protected void initModel(ManagementModel managementModel, Resource modelControllerResource) {
ManagementResourceRegistration rootRegistration = managementModel.getRootResourceRegistration();
GlobalOperationHandlers.registerGlobalOperations(rootRegistration, processType);
GlobalNotifications.registerGlobalNotifications(rootRegistration, processType);
managementControllerResource = rootRegistration.registerSubModel(resourceDefinition);
Resource rootResource = managementModel.getRootResource();
rootResource.registerChild(resourceDefinition.getPathElement(), Resource.Factory.create());
}
}
private static class TestResourceDefinition extends SimpleResourceDefinition {
private static final SimpleAttributeDefinitionBuilder builder =
new SimpleAttributeDefinitionBuilder(TEST_METRIC, ModelType.INT, true);
public TestResourceDefinition() {
super(ELEMENT, new NonResolvingResourceDescriptionResolver(),
new ModelOnlyAddStepHandler(), new ModelOnlyRemoveStepHandler());
}
// @Override
// public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
// resourceRegistration.registerMetric(createAttribute(builder), new OperationStepHandler() {
// @Override
// public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
// //Don't return anything
// }
// });
// }
//
// protected abstract AttributeDefinition createAttribute(SimpleAttributeDefinitionBuilder builder);
}
private class EmptyHandler implements OperationStepHandler {
@Override
public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
}
}
private class HardCodedValueHandler implements OperationStepHandler {
final ModelNode result;
private HardCodedValueHandler(ModelNode result) {
this.result = result;
}
@Override
public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
context.getResult().set(result);
}
}
}