1 /*
2  * Copyright (c) 2005, 2018, 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 6222826
27  * @summary Test that tasks are cancelled properly when
28  *          monitors are started and stopped in a loop.
29  * @author Luis-Miguel Alventosa
30  *
31  * @library /test/lib
32  *
33  * @run clean StartStopTest
34  * @run build StartStopTest
35  * @run main/othervm/timeout=300 StartStopTest 1
36  * @run main/othervm/timeout=300 StartStopTest 2
37  * @run main/othervm/timeout=300 StartStopTest 3
38  * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=5 StartStopTest 1
39  * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=5 StartStopTest 2
40  * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=5 StartStopTest 3
41  * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=-5 StartStopTest 1
42  * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=-5 StartStopTest 2
43  * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=-5 StartStopTest 3
44  */
45 
46 import java.util.concurrent.atomic.AtomicInteger;
47 import javax.management.MBeanServer;
48 import javax.management.MBeanServerFactory;
49 import javax.management.Notification;
50 import javax.management.NotificationListener;
51 import javax.management.ObjectName;
52 import javax.management.monitor.CounterMonitor;
53 import javax.management.monitor.GaugeMonitor;
54 import javax.management.monitor.Monitor;
55 import javax.management.monitor.MonitorNotification;
56 import javax.management.monitor.StringMonitor;
57 
58 import jdk.test.lib.Utils;
59 
60 public class StartStopTest {
61     static int maxPoolSize;
62     static final AtomicInteger counter = new AtomicInteger();
63 
64     // MBean class
65     public class ObservedObject implements ObservedObjectMBean {
66         volatile public boolean called = false;
getInteger()67         public Integer getInteger() {
68             task("Integer");
69             return 0;
70         }
getDouble()71         public Double getDouble() {
72             task("Double");
73             return 0.0;
74         }
getString()75         public String getString() {
76             task("String");
77             return "";
78         }
task(String prop)79         private void task(String prop) {
80             called = true;
81             final int c = counter.incrementAndGet();
82             echo("\tTASK [" + c + "] in get" + prop);
83         }
84     }
85 
86     // MBean interface
87     public interface ObservedObjectMBean {
getInteger()88         public Integer getInteger();
getDouble()89         public Double getDouble();
getString()90         public String getString();
91     }
92 
93     /**
94      * Run test
95      */
runTest(int monitorType)96     public int runTest(int monitorType) throws Exception {
97 
98         int nTasks = maxPoolSize + 2;
99         ObjectName[] mbeanNames = new ObjectName[nTasks];
100         ObservedObject[] monitored = new ObservedObject[nTasks];
101         ObjectName[] monitorNames = new ObjectName[nTasks];
102         Monitor[] monitor = new Monitor[nTasks];
103         String[] attributes = { "Integer", "Double", "String" };
104 
105         try {
106             echo(">>> CREATE MBeanServer");
107             MBeanServer server = MBeanServerFactory.newMBeanServer();
108 
109             String domain = server.getDefaultDomain();
110 
111             for (int i = 0; i < nTasks; i++) {
112                 mbeanNames[i] =
113                     new ObjectName(":type=ObservedObject,instance=" + (i + 1));
114                 monitored[i] = new ObservedObject();
115                 echo(">>> CREATE ObservedObject = " + mbeanNames[i].toString());
116                 server.registerMBean(monitored[i], mbeanNames[i]);
117                 switch (monitorType) {
118                 case 1:
119                     monitorNames[i] = new ObjectName(":type=CounterMonitor," +
120                                                      "instance=" + (i + 1));
121                     monitor[i] = new CounterMonitor();
122                     break;
123                 case 2:
124                     monitorNames[i] = new ObjectName(":type=GaugeMonitor," +
125                                                      "instance=" + (i + 1));
126                     monitor[i] = new GaugeMonitor();
127                     break;
128                 case 3:
129                     monitorNames[i] = new ObjectName(":type=StringMonitor," +
130                                                      "instance=" + (i + 1));
131                     monitor[i] = new StringMonitor();
132                     break;
133                 default:
134                     echo("Unsupported monitor type");
135                     return 1;
136                 }
137                 echo(">>> CREATE Monitor = " + monitorNames[i].toString());
138                 server.registerMBean(monitor[i], monitorNames[i]);
139                 monitor[i].addObservedObject(mbeanNames[i]);
140                 monitor[i].setObservedAttribute(attributes[monitorType-1]);
141                 monitor[i].setGranularityPeriod(50);
142             }
143 
144             for (int j = 0; j < 2; j++) {
145                 echo(">>> Start MONITORS");
146                 for (int i = 0; i < nTasks; i++)
147                     monitor[i].start();
148                 echo(">>> MONITORS started");
149                 doSleep(500);
150                 echo(">>> Check FLAGS true");
151                 for (int i = 0; i < nTasks; i++)
152                     if (!monitored[i].called) {
153                         echo("KO: At least one attribute was not called");
154                         return 1;
155                     }
156                 echo(">>> FLAGS checked true");
157                 echo(">>> Stop MONITORS");
158                 for (int i = 0; i < nTasks; i++)
159                     monitor[i].stop();
160                 echo(">>> MONITORS stopped");
161                 doSleep(500);
162                 echo(">>> Set FLAGS to false");
163                 for (int i = 0; i < nTasks; i++)
164                     monitored[i].called = false;
165                 echo(">>> FLAGS set to false");
166                 echo(">>> Check FLAGS remain false");
167                 for (int i = 0; i < nTasks; i++)
168                     if (monitored[i].called) {
169                         echo("KO: At least one attribute " +
170                              "continued to get called");
171                         return 1;
172                     }
173                 echo(">>> FLAGS checked false");
174             }
175         } finally {
176             for (int i = 0; i < nTasks; i++)
177                 if (monitor[i] != null)
178                     monitor[i].stop();
179         }
180 
181         return 0;
182     }
183 
184     /*
185      * Print message
186      */
echo(String message)187     private static void echo(String message) {
188         System.out.println(message);
189     }
190 
191     /*
192      * Standalone entry point.
193      *
194      * Run the test and report to stdout.
195      */
main(String args[])196     public static void main (String args[]) throws Exception {
197         Integer size = Integer.getInteger("jmx.x.monitor.maximum.pool.size");
198         if (size == null) {
199             maxPoolSize = 10;
200             echo(">>> MAXIMUM POOL SIZE = 10 [default value]");
201         } else {
202             maxPoolSize = size.intValue() < 1 ? 1 : size.intValue();
203             echo(">>> MAXIMUM POOL SIZE = " + maxPoolSize);
204         }
205         StartStopTest test = new StartStopTest();
206         int error = test.runTest(Integer.parseInt(args[0]));
207         if (error > 0) {
208             echo(">>> Unhappy Bye, Bye!");
209             throw new IllegalStateException(
210                 "Test FAILED: Unexpected Maximum Pool Size Overflow!");
211         } else {
212             echo(">>> Happy Bye, Bye!");
213         }
214     }
215 
216     private static void doSleep(long ms) throws Exception {
217         Thread.sleep(Utils.adjustTimeout(ms));
218     }
219 }
220