1 /* 2 * Copyright (c) 2019, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.jfr.api.consumer.recordingstream; 27 28 import java.util.concurrent.CountDownLatch; 29 import java.util.concurrent.atomic.AtomicBoolean; 30 import java.util.concurrent.atomic.AtomicInteger; 31 32 import jdk.jfr.api.consumer.recordingstream.TestUtils.TestError; 33 import jdk.jfr.api.consumer.recordingstream.TestUtils.TestException; 34 import jdk.jfr.api.consumer.security.TestStreamingRemote.TestEvent; 35 import jdk.jfr.consumer.RecordingStream; 36 37 /** 38 * @test 39 * @summary Tests RecordingStream::onError(...) when using 40 * RecordingStream:startAsync 41 * @key jfr 42 * @requires vm.hasJFR 43 * @library /test/lib /test/jdk 44 * @run main/othervm jdk.jfr.api.consumer.recordingstream.TestOnErrorAsync 45 */ 46 public class TestOnErrorAsync { main(String... args)47 public static void main(String... args) throws Exception { 48 testDefaultError(); 49 testCustomError(); 50 testDefaultException(); 51 testCustomException(); 52 testOnFlushSanity(); 53 testOnCloseSanity(); 54 } 55 testDefaultError()56 private static void testDefaultError() throws Exception { 57 AtomicBoolean closed = new AtomicBoolean(); 58 CountDownLatch receivedError = new CountDownLatch(1); 59 try (RecordingStream r = new RecordingStream()) { 60 r.onEvent(e -> { 61 TestError error = new TestError(); 62 TestUtils.installUncaughtException(receivedError, error); 63 throw error; // closes stream 64 }); 65 r.onClose(() -> { 66 closed.set(true); 67 }); 68 r.startAsync(); 69 TestEvent e = new TestEvent(); 70 e.commit(); 71 r.awaitTermination(); 72 receivedError.await(); 73 if (!closed.get()) { 74 throw new Exception("Expected stream to be closed"); 75 } 76 } 77 } 78 testCustomError()79 private static void testCustomError() throws Exception { 80 AtomicBoolean onError = new AtomicBoolean(); 81 AtomicBoolean closed = new AtomicBoolean(); 82 CountDownLatch receivedError = new CountDownLatch(1); 83 try (RecordingStream r = new RecordingStream()) { 84 r.onEvent(e -> { 85 TestError error = new TestError(); 86 TestUtils.installUncaughtException(receivedError, error); 87 throw error; // closes stream 88 }); 89 r.onError(e -> { 90 onError.set(true); 91 }); 92 r.onClose(() -> { 93 closed.set(true); 94 }); 95 r.startAsync(); 96 TestEvent e = new TestEvent(); 97 e.commit(); 98 r.awaitTermination(); 99 receivedError.await(); 100 if (onError.get()) { 101 throw new Exception("onError handler should not be invoked on java.lang.Error."); 102 } 103 if (!closed.get()) { 104 throw new Exception("Expected stream to be closed"); 105 } 106 } 107 } 108 testDefaultException()109 private static void testDefaultException() throws Exception { 110 TestException exception = new TestException(); 111 AtomicBoolean closed = new AtomicBoolean(); 112 AtomicInteger counter = new AtomicInteger(); 113 try (RecordingStream r = new RecordingStream()) { 114 r.onEvent(e -> { 115 if (counter.incrementAndGet() == 2) { 116 r.close(); 117 return; 118 } 119 TestUtils.throwUnchecked(exception); 120 }); 121 r.onClose(() -> { 122 closed.set(true); 123 }); 124 r.startAsync(); 125 TestEvent e1 = new TestEvent(); 126 e1.commit(); 127 TestEvent e2 = new TestEvent(); 128 e2.commit(); 129 r.awaitTermination(); 130 if (!exception.isPrinted()) { 131 throw new Exception("Expected stack trace from Exception to be printed"); 132 } 133 if (!closed.get()) { 134 throw new Exception("Expected stream to be closed"); 135 } 136 } 137 } 138 testCustomException()139 private static void testCustomException() throws Exception { 140 TestException exception = new TestException(); 141 AtomicBoolean closed = new AtomicBoolean(); 142 AtomicBoolean received = new AtomicBoolean(); 143 try (RecordingStream r = new RecordingStream()) { 144 r.onEvent(e -> { 145 TestUtils.throwUnchecked(exception); 146 }); 147 r.onError(t -> { 148 received.set(t == exception); 149 r.close(); 150 }); 151 r.onClose(() -> { 152 closed.set(true); 153 }); 154 r.startAsync(); 155 TestEvent event = new TestEvent(); 156 event.commit(); 157 r.awaitTermination(); 158 if (!received.get()) { 159 throw new Exception("Did not receive expected exception in onError(...)"); 160 } 161 if (exception.isPrinted()) { 162 throw new Exception("Expected stack trace from Exception NOT to be printed"); 163 } 164 if (!closed.get()) { 165 throw new Exception("Expected stream to be closed"); 166 } 167 } 168 } 169 testOnFlushSanity()170 private static void testOnFlushSanity() throws Exception { 171 TestException exception = new TestException(); 172 CountDownLatch received = new CountDownLatch(1); 173 try (RecordingStream r = new RecordingStream()) { 174 r.onFlush(() -> { 175 TestUtils.throwUnchecked(exception); 176 }); 177 r.onError(t -> { 178 if (t == exception) { 179 received.countDown(); 180 } 181 }); 182 r.startAsync(); 183 received.await(); 184 } 185 } 186 testOnCloseSanity()187 private static void testOnCloseSanity() throws Exception { 188 TestException exception = new TestException(); 189 CountDownLatch received = new CountDownLatch(1); 190 try (RecordingStream r = new RecordingStream()) { 191 r.onFlush(() -> { 192 r.close(); // will trigger onClose 193 }); 194 r.onClose(() -> { 195 TestUtils.throwUnchecked(exception); // will trigger onError 196 }); 197 r.onError(t -> { 198 if (t == exception) { 199 received.countDown(); 200 } 201 }); 202 r.startAsync(); 203 received.await(); 204 } 205 } 206 } 207