1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * 
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * The contents of this file are subject to the terms of either the Universal Permissive License
   7  * v 1.0 as shown at http://oss.oracle.com/licenses/upl
   8  *
   9  * or the following license:
  10  *
  11  * Redistribution and use in source and binary forms, with or without modification, are permitted
  12  * provided that the following conditions are met:
  13  * 
  14  * 1. Redistributions of source code must retain the above copyright notice, this list of conditions
  15  * and the following disclaimer.
  16  * 
  17  * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
  18  * conditions and the following disclaimer in the documentation and/or other materials provided with
  19  * the distribution.
  20  * 
  21  * 3. Neither the name of the copyright holder nor the names of its contributors may be used to
  22  * endorse or promote products derived from this software without specific prior written permission.
  23  * 
  24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  26  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  27  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
  31  * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32  */
  33 package org.openjdk.jmc.rjmx.test.triggers;
  34 
  35 import static org.junit.Assert.assertEquals;
  36 import static org.junit.Assert.assertNotNull;
  37 import static org.junit.Assert.assertTrue;
  38 import static org.junit.Assert.fail;
  39 
  40 import java.io.IOException;
  41 import java.util.UUID;
  42 
  43 import javax.management.JMException;
  44 import javax.security.auth.login.FailedLoginException;
  45 
  46 import org.junit.Before;
  47 import org.junit.Test;
  48 
  49 import org.openjdk.jmc.common.unit.IUnit;
  50 import org.openjdk.jmc.common.unit.UnitLookup;
  51 import org.openjdk.jmc.rjmx.ConnectionToolkit;
  52 import org.openjdk.jmc.rjmx.subscription.IMRIMetadata;
  53 import org.openjdk.jmc.rjmx.subscription.MRI;
  54 import org.openjdk.jmc.rjmx.subscription.MRI.Type;
  55 import org.openjdk.jmc.rjmx.test.RjmxTestCase;
  56 import org.openjdk.jmc.rjmx.test.testutil.TestToolkit;
  57 import org.openjdk.jmc.rjmx.test.triggers.NotificationActionCallback.NotificationActionCallbackReceiver;
  58 import org.openjdk.jmc.rjmx.triggers.TriggerEvent;
  59 import org.openjdk.jmc.rjmx.triggers.TriggerRule;
  60 import org.openjdk.jmc.rjmx.triggers.internal.NotificationRegistry;
  61 import org.openjdk.jmc.rjmx.triggers.internal.NotificationTrigger;
  62 import org.openjdk.jmc.rjmx.triggers.internal.ValueEvaluatorBoolean;
  63 import org.openjdk.jmc.rjmx.triggers.internal.ValueEvaluatorNumberMax;
  64 
  65 /**
  66  * Tests for the notification framework.
  67  */
  68 public class NotificationTriggerAndRuleTest extends RjmxTestCase
  69                 implements NotificationActionCallback.NotificationActionCallbackReceiver {
  70         /** For code coverage */
  71 
  72         public final static int TIMEOUT = 9000;
  73         public static final Class<?>[] COVERED_CLASSES = new Class[] {
  74                         // NotificationRule.class,
  75                         NotificationTrigger.class};
  76 
  77         private TriggerEvent m_lastEvent;
  78         private final Object m_notifObj = new Object();
  79         private NotificationRegistry m_notificationRegistry;
  80 
  81         /**
  82          * Tests registering and unregistering a rule.
  83          *
  84          * @throws IOException
  85          * @throws FailedLoginException
  86          */
  87         @Test
  88         public void testUnregisterRule() throws FailedLoginException, IOException {
  89                 TriggerRule rule = createTestNotificationRule(
  90                                 new MRI(Type.ATTRIBUTE, "java.lang:type=OperatingSystem", "SystemCpuLoad")); //$NON-NLS-1$ //$NON-NLS-2$
  91                 String serverGuid = UUID.randomUUID().toString();
  92                 m_notificationRegistry.registerRule(rule, serverGuid);
  93                 m_notificationRegistry.unregisterRule(rule, serverGuid);
  94                 assertEquals("Failed to remove rule!", m_notificationRegistry.getRegisteredRules(serverGuid).size(), 0); //$NON-NLS-1$
  95         }
  96 
  97         /**
  98          * Tests that a notification rule triggers correctly.
  99          *
 100          * @throws JMException
 101          * @throws IOException
 102          * @throws InterruptedException
 103          */
 104         @Test
 105         public void testTriggerNotification() throws Exception {
 106                 assertNull(m_lastEvent);
 107                 TriggerRule rule = createRule();
 108                 String serverGuid = m_connectionHandle.getServerDescriptor().getGUID();
 109                 m_notificationRegistry.activateTriggersFor(m_connectionHandle);
 110                 m_notificationRegistry.registerRule(rule, serverGuid);
 111                 assertEquals("Didn't register rule!", 1, m_notificationRegistry.getRegisteredRules(serverGuid).size()); //$NON-NLS-1$
 112                 synchronized (m_notifObj) {
 113 
 114                         try {
 115                                 m_notifObj.wait(TIMEOUT);
 116                         } catch (InterruptedException e) {
 117                                 fail("Timedout while waiting for notification!"); //$NON-NLS-1$
 118                         }
 119                 }
 120                 m_notificationRegistry.unregisterRule(rule, serverGuid);
 121                 assertNotNull("Never received any notification!", m_lastEvent); //$NON-NLS-1$
 122         }
 123 
 124         /**
 125          * Tests creating a rule and that it is setup correctly.
 126          *
 127          * @throws IOException
 128          * @throws FailedLoginException
 129          */
 130         @Test
 131         public void testRuleCreation() throws FailedLoginException, IOException {
 132                 TriggerRule aRule = new TriggerRule();
 133                 assertNotNull(aRule);
 134                 assertTrue(!aRule.hasAction());
 135                 assertTrue(!aRule.hasTrigger());
 136                 assertTrue(!aRule.isComplete());
 137 
 138                 TriggerRule anotherRule = createTestNotificationRule(
 139                                 new MRI(Type.ATTRIBUTE, "java.lang:type=OperatingSystem", "SystemCpuLoad")); //$NON-NLS-1$ //$NON-NLS-2$
 140                 assertTrue(anotherRule.hasAction());
 141                 assertTrue(!anotherRule.hasConstraints());
 142                 assertTrue(anotherRule.hasTrigger());
 143                 assertTrue(anotherRule.isComplete());
 144                 assertEquals("TestRule", anotherRule.toString()); //$NON-NLS-1$
 145                 assertEquals("TestRule", anotherRule.getName()); //$NON-NLS-1$
 146 
 147                 aRule.setName("Abrakadabra"); //$NON-NLS-1$
 148                 // Test sorting
 149                 assertTrue(aRule.compareTo(anotherRule) < 0);
 150         }
 151 
 152         private TriggerRule createTestNotificationRule(MRI descriptor) {
 153                 NotificationTrigger trigger = new NotificationTrigger(descriptor, new ValueEvaluatorBoolean());
 154                 return new TriggerRule("TestRule", trigger, new NotificationActionCallback(this)); //$NON-NLS-1$
 155         }
 156 
 157         /**
 158          * @see NotificationActionCallbackReceiver#callback(TriggerEvent)
 159          */
 160         @Override
 161         public void onNotificationAction(TriggerEvent e) {
 162                 synchronized (m_notifObj) {
 163                         TestToolkit.println("Got a callback: " + e); //$NON-NLS-1$
 164                         m_lastEvent = e;
 165                         m_notifObj.notify();
 166                 }
 167         }
 168 
 169         /**
 170          * Registers a rule used by the test.
 171          *
 172          * @return the new rule
 173          * @throws JMException
 174          * @throws IOException
 175          */
 176         protected TriggerRule createRule() throws Exception {
 177                 MRI uptimeDescriptor = new MRI(Type.ATTRIBUTE, "java.lang:type=Runtime", //$NON-NLS-1$
 178                                 "Uptime"); //$NON-NLS-1$
 179                 long uptime = ConnectionToolkit.getRuntimeBean(getMBeanServerConnection()).getUptime();
 180                 IMRIMetadata metadata = getMRIMetadataService().getMetadata(uptimeDescriptor);
 181                 IUnit unit = UnitLookup.getUnitOrDefault(metadata.getUnitString());
 182                 TriggerRule rule = createTestNotificationRule(uptimeDescriptor);
 183                 ValueEvaluatorNumberMax eval = new ValueEvaluatorNumberMax();
 184                 eval.setMax(unit.quantity(uptime));
 185                 rule.setTrigger(new NotificationTrigger(uptimeDescriptor, eval));
 186                 return rule;
 187         }
 188 
 189         @Before
 190         public void setUp() throws Exception {
 191                 m_notificationRegistry = new NotificationRegistry();
 192         }
 193 }