1 /*
   2  * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 6683213
  27  * @summary Test that the initial derived gauge is (Integer)0
  28  * @author Daniel Fuchs
  29  * @modules java.management
  30  * @run clean DerivedGaugeMonitorTest
  31  * @run build DerivedGaugeMonitorTest
  32  * @run main DerivedGaugeMonitorTest
  33  */
  34 
  35 import java.io.Serializable;
  36 import java.util.concurrent.CountDownLatch;
  37 import java.util.concurrent.TimeUnit;
  38 import javax.management.MBeanServer;
  39 import javax.management.MBeanServerFactory;
  40 import javax.management.ObjectName;
  41 import javax.management.monitor.CounterMonitor;
  42 import javax.management.monitor.GaugeMonitor;
  43 
  44 public class DerivedGaugeMonitorTest {
  45 
  46     public static interface Things {
  47         public long getALong();
  48         public int getAnInt();
  49         public double getADouble();
  50         public short getAShort();
  51         public byte getAByte();
  52         public float getAFloat();
  53     }
  54     public static interface MyMBean extends Things {
  55         public Things getAThing();
  56     }
  57 
  58     public static class MyThings implements Things, Serializable {
  59         private static final long serialVersionUID = -4333982919572564126L;
  60 
  61         private volatile long along = 0;
  62         private volatile int anint = 0;
  63         private volatile short ashort = 0;
  64         private volatile byte abyte = 0;
  65         private volatile float afloat = 0;
  66         private volatile double adouble = 0;
  67 
  68         private volatile transient boolean mutable;
  69 
  70         public MyThings() {
  71             this(false);
  72         }
  73 
  74         protected MyThings(boolean mutable) {
  75             this.mutable=mutable;
  76         }
  77 
  78         public long getALong() {
  79             return mutable?along++:along;
  80         }
  81 
  82         public int getAnInt() {
  83             return mutable?anint++:anint;
  84         }
  85 
  86         public double getADouble() {
  87             return mutable?adouble++:adouble;
  88         }
  89 
  90         public short getAShort() {
  91             return mutable?ashort++:ashort;
  92         }
  93 
  94         public byte getAByte() {
  95             return mutable?abyte++:abyte;
  96         }
  97 
  98         public float getAFloat() {
  99             return mutable?afloat++:afloat;
 100         }
 101 
 102         @Override
 103         public Object clone() throws CloneNotSupportedException {
 104             final MyThings other = (MyThings)super.clone();
 105             other.mutable=false;
 106             return other;
 107         }
 108     }
 109 
 110     public static class My implements MyMBean {
 111 
 112         public final CountDownLatch cdl = new CountDownLatch(6);
 113 
 114         private final MyThings things = new MyThings(true);
 115         private volatile int count = 0;
 116 
 117         public Things getAThing() {
 118             count++;
 119             cdl.countDown();
 120             try {
 121                 return (Things) things.clone();
 122             } catch (CloneNotSupportedException ex) {
 123                 return null;
 124             }
 125         }
 126 
 127         public long getALong() {
 128             count++;
 129             cdl.countDown();
 130             return things.getALong();
 131         }
 132 
 133         public int getAnInt() {
 134             count++;
 135             cdl.countDown();
 136             return things.getAnInt();
 137         }
 138 
 139         public double getADouble() {
 140             count++;
 141             cdl.countDown();
 142             return things.getADouble();
 143         }
 144 
 145         public short getAShort() {
 146             count++;
 147             cdl.countDown();
 148             return things.getAShort();
 149         }
 150 
 151         public byte getAByte() {
 152             count++;
 153             cdl.countDown();
 154             return things.getAByte();
 155         }
 156 
 157         public float getAFloat() {
 158             count++;
 159             cdl.countDown();
 160             return things.getAFloat();
 161         }
 162 
 163     }
 164 
 165 
 166     public static String[] attributes = {
 167         "AByte","AShort","AnInt","ALong","AFloat","ADouble"
 168     };
 169     public static String[] things = {
 170         "AThing.AByte","AThing.AShort","AThing.AnInt","AThing.ALong",
 171         "AThing.AFloat","AThing.ADouble"
 172     };
 173 
 174     public static void check(String attr, MBeanServer server, ObjectName mon,
 175             ObjectName mbean) throws Exception {
 176         final Object obj = server.getAttribute(mon, "DerivedGauge");
 177         check(attr,server,mon,mbean,obj);
 178     }
 179 
 180     public static void check(String attr, MBeanServer server, ObjectName mon,
 181             ObjectName mbean, Object obj) throws Exception  {
 182         if (obj == null)
 183             throw new Exception("Derived gauge for: " + attr +
 184                     " ["+mon+", "+mbean+"] is null!");
 185         if (!Integer.valueOf(0).equals(obj))
 186             throw new Exception("Derived gauge for: " + attr +
 187                     " ["+mon+", "+mbean+"] is "+obj);
 188     }
 189 
 190     public static void check(String attr, MBeanServer server, ObjectName mon,
 191             ObjectName mbean, long start) throws Exception {
 192         final Object obj = server.getAttribute(mon, "DerivedGauge");
 193         final long now = System.currentTimeMillis();
 194         final long gran = (Long)server.getAttribute(mon, "GranularityPeriod");
 195         if (now > start +2*gran) {
 196             throw new Exception(attr+": Can't verify test case: " +
 197                     "granularity period expired!");
 198         }
 199         check(attr,server,mon,mbean,obj);
 200     }
 201 
 202     public static void test(String attr) throws Exception {
 203         System.err.println("Testing "+ attr);
 204         final MBeanServer server = MBeanServerFactory.createMBeanServer();
 205         final ObjectName mbean = new ObjectName("ugly:type=cr.p");
 206         final My my = new My();
 207         final GaugeMonitor mon2 = new GaugeMonitor();
 208         final ObjectName mon2n = new ObjectName("mon1:type=GaugeMonitor");
 209         final CounterMonitor mon1 = new CounterMonitor();
 210         final ObjectName mon1n = new ObjectName("mon2:type=CounterMonitor");
 211 
 212         server.registerMBean(my, mbean);
 213         server.registerMBean(mon1, mon1n);
 214         server.registerMBean(mon2, mon2n);
 215 
 216         mon1.addObservedObject(mbean);
 217         mon1.setGranularityPeriod(60000); // 60 sec...
 218         mon1.setObservedAttribute(attr);
 219         mon1.setDifferenceMode(true);
 220         check(attr,server,mon1n,mbean);
 221 
 222         mon2.addObservedObject(mbean);
 223         mon2.setGranularityPeriod(60000); // 60 sec...
 224         mon2.setObservedAttribute(attr);
 225         mon2.setDifferenceMode(true);
 226         check(attr,server,mon2n,mbean);
 227 
 228         final long approxStart = System.currentTimeMillis();
 229         mon1.start();
 230         mon2.start();
 231 
 232         try {
 233             check(attr,server,mon1n,mbean,approxStart);
 234             check(attr,server,mon2n,mbean,approxStart);
 235             check(attr,server,mon1n,mbean,approxStart);
 236             check(attr,server,mon2n,mbean,approxStart);
 237 
 238 
 239             mon1.setGranularityPeriod(5);
 240             mon2.setGranularityPeriod(5);
 241 
 242             my.cdl.await(1000, TimeUnit.MILLISECONDS);
 243             if (my.cdl.getCount() > 0)
 244                 throw new Exception(attr+": Count down not reached!");
 245 
 246             // just check that we don't get an exception now...
 247             System.err.println(attr+": [" + mon1n+
 248                     "] DerivedGauge is now "+
 249                     server.getAttribute(mon1n, "DerivedGauge"));
 250             System.err.println(attr+": [" + mon2n+
 251                     "] DerivedGauge is now "+
 252                     server.getAttribute(mon2n, "DerivedGauge"));
 253         } finally {
 254            try {mon1.stop();} catch (Exception x) {}
 255            try {mon2.stop();} catch (Exception x) {}
 256         }
 257     }
 258 
 259 
 260 
 261 
 262     public static void main(String[] args) throws Exception {
 263         for (String attr:attributes) {
 264             test(attr);
 265         }
 266         for (String attr:things) {
 267             test(attr);
 268         }
 269     }
 270 
 271 }