1 /*
   2  * Copyright (c) 2008, 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  * @run clean DerivedGaugeMonitorTest
  30  * @run build DerivedGaugeMonitorTest
  31  * @run main DerivedGaugeMonitorTest
  32  */
  33 
  34 import java.io.Serializable;
  35 import java.util.concurrent.CountDownLatch;
  36 import java.util.concurrent.TimeUnit;
  37 import javax.management.MBeanServer;
  38 import javax.management.MBeanServerFactory;
  39 import javax.management.ObjectName;
  40 import javax.management.monitor.CounterMonitor;
  41 import javax.management.monitor.GaugeMonitor;
  42 
  43 public class DerivedGaugeMonitorTest {
  44 
  45     public static interface Things {
  46         public long getALong();
  47         public int getAnInt();
  48         public double getADouble();
  49         public short getAShort();
  50         public byte getAByte();
  51         public float getAFloat();
  52     }
  53     public static interface MyMBean extends Things {
  54         public Things getAThing();
  55     }
  56 
  57     public static class MyThings implements Things, Serializable {
  58         private static final long serialVersionUID = -4333982919572564126L;
  59 
  60         private volatile long along = 0;
  61         private volatile int anint = 0;
  62         private volatile short ashort = 0;
  63         private volatile byte abyte = 0;
  64         private volatile float afloat = 0;
  65         private volatile double adouble = 0;
  66 
  67         private volatile transient boolean mutable;
  68 
  69         public MyThings() {
  70             this(false);
  71         }
  72 
  73         protected MyThings(boolean mutable) {
  74             this.mutable=mutable;
  75         }
  76 
  77         public long getALong() {
  78             return mutable?along++:along;
  79         }
  80 
  81         public int getAnInt() {
  82             return mutable?anint++:anint;
  83         }
  84 
  85         public double getADouble() {
  86             return mutable?adouble++:adouble;
  87         }
  88 
  89         public short getAShort() {
  90             return mutable?ashort++:ashort;
  91         }
  92 
  93         public byte getAByte() {
  94             return mutable?abyte++:abyte;
  95         }
  96 
  97         public float getAFloat() {
  98             return mutable?afloat++:afloat;
  99         }
 100 
 101         @Override
 102         public Object clone() throws CloneNotSupportedException {
 103             final MyThings other = (MyThings)super.clone();
 104             other.mutable=false;
 105             return other;
 106         }
 107     }
 108 
 109     public static class My implements MyMBean {
 110 
 111         public final CountDownLatch cdl = new CountDownLatch(6);
 112 
 113         private final MyThings things = new MyThings(true);
 114         private volatile int count = 0;
 115 
 116         public Things getAThing() {
 117             count++;
 118             cdl.countDown();
 119             try {
 120                 return (Things) things.clone();
 121             } catch (CloneNotSupportedException ex) {
 122                 return null;
 123             }
 124         }
 125 
 126         public long getALong() {
 127             count++;
 128             cdl.countDown();
 129             return things.getALong();
 130         }
 131 
 132         public int getAnInt() {
 133             count++;
 134             cdl.countDown();
 135             return things.getAnInt();
 136         }
 137 
 138         public double getADouble() {
 139             count++;
 140             cdl.countDown();
 141             return things.getADouble();
 142         }
 143 
 144         public short getAShort() {
 145             count++;
 146             cdl.countDown();
 147             return things.getAShort();
 148         }
 149 
 150         public byte getAByte() {
 151             count++;
 152             cdl.countDown();
 153             return things.getAByte();
 154         }
 155 
 156         public float getAFloat() {
 157             count++;
 158             cdl.countDown();
 159             return things.getAFloat();
 160         }
 161 
 162     }
 163 
 164 
 165     public static String[] attributes = {
 166         "AByte","AShort","AnInt","ALong","AFloat","ADouble"
 167     };
 168     public static String[] things = {
 169         "AThing.AByte","AThing.AShort","AThing.AnInt","AThing.ALong",
 170         "AThing.AFloat","AThing.ADouble"
 171     };
 172 
 173     public static void check(String attr, MBeanServer server, ObjectName mon,
 174             ObjectName mbean) throws Exception {
 175         final Object obj = server.getAttribute(mon, "DerivedGauge");
 176         check(attr,server,mon,mbean,obj);
 177     }
 178 
 179     public static void check(String attr, MBeanServer server, ObjectName mon,
 180             ObjectName mbean, Object obj) throws Exception  {
 181         if (obj == null)
 182             throw new Exception("Derived gauge for: " + attr +
 183                     " ["+mon+", "+mbean+"] is null!");
 184         if (!Integer.valueOf(0).equals(obj))
 185             throw new Exception("Derived gauge for: " + attr +
 186                     " ["+mon+", "+mbean+"] is "+obj);
 187     }
 188 
 189     public static void check(String attr, MBeanServer server, ObjectName mon,
 190             ObjectName mbean, long start) throws Exception {
 191         final Object obj = server.getAttribute(mon, "DerivedGauge");
 192         final long now = System.currentTimeMillis();
 193         final long gran = (Long)server.getAttribute(mon, "GranularityPeriod");
 194         if (now > start +2*gran) {
 195             throw new Exception(attr+": Can't verify test case: " +
 196                     "granularity period expired!");
 197         }
 198         check(attr,server,mon,mbean,obj);
 199     }
 200 
 201     public static void test(String attr) throws Exception {
 202         System.err.println("Testing "+ attr);
 203         final MBeanServer server = MBeanServerFactory.createMBeanServer();
 204         final ObjectName mbean = new ObjectName("ugly:type=cr.p");
 205         final My my = new My();
 206         final GaugeMonitor mon2 = new GaugeMonitor();
 207         final ObjectName mon2n = new ObjectName("mon1:type=GaugeMonitor");
 208         final CounterMonitor mon1 = new CounterMonitor();
 209         final ObjectName mon1n = new ObjectName("mon2:type=CounterMonitor");
 210 
 211         server.registerMBean(my, mbean);
 212         server.registerMBean(mon1, mon1n);
 213         server.registerMBean(mon2, mon2n);
 214 
 215         mon1.addObservedObject(mbean);
 216         mon1.setGranularityPeriod(60000); // 60 sec...
 217         mon1.setObservedAttribute(attr);
 218         mon1.setDifferenceMode(true);
 219         check(attr,server,mon1n,mbean);
 220 
 221         mon2.addObservedObject(mbean);
 222         mon2.setGranularityPeriod(60000); // 60 sec...
 223         mon2.setObservedAttribute(attr);
 224         mon2.setDifferenceMode(true);
 225         check(attr,server,mon2n,mbean);
 226 
 227         final long approxStart = System.currentTimeMillis();
 228         mon1.start();
 229         mon2.start();
 230 
 231         try {
 232             check(attr,server,mon1n,mbean,approxStart);
 233             check(attr,server,mon2n,mbean,approxStart);
 234             check(attr,server,mon1n,mbean,approxStart);
 235             check(attr,server,mon2n,mbean,approxStart);
 236 
 237 
 238             mon1.setGranularityPeriod(5);
 239             mon2.setGranularityPeriod(5);
 240 
 241             my.cdl.await(1000, TimeUnit.MILLISECONDS);
 242             if (my.cdl.getCount() > 0)
 243                 throw new Exception(attr+": Count down not reached!");
 244 
 245             // just check that we don't get an exception now...
 246             System.err.println(attr+": [" + mon1n+
 247                     "] DerivedGauge is now "+
 248                     server.getAttribute(mon1n, "DerivedGauge"));
 249             System.err.println(attr+": [" + mon2n+
 250                     "] DerivedGauge is now "+
 251                     server.getAttribute(mon2n, "DerivedGauge"));
 252         } finally {
 253            try {mon1.stop();} catch (Exception x) {}
 254            try {mon2.stop();} catch (Exception x) {}
 255         }
 256     }
 257 
 258 
 259 
 260 
 261     public static void main(String[] args) throws Exception {
 262         for (String attr:attributes) {
 263             test(attr);
 264         }
 265         for (String attr:things) {
 266             test(attr);
 267         }
 268     }
 269 
 270 }