1 /* 2 * Copyright (c) 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 import jdk.internal.net.http.common.OperationTrackers; 25 import jdk.internal.net.http.common.OperationTrackers.Tracker; 26 27 import java.net.http.HttpClient; 28 import java.util.concurrent.ConcurrentLinkedQueue; 29 import java.util.stream.Collectors; 30 31 /** 32 * A small helper class to help track clients which still 33 * have pending operations at the end of a test. 34 */ 35 public class ReferenceTracker { 36 private final ConcurrentLinkedQueue<Tracker> TRACKERS 37 = new ConcurrentLinkedQueue<Tracker>(); 38 39 public static final ReferenceTracker INSTANCE 40 = new ReferenceTracker(); 41 track(HttpClient client)42 public HttpClient track(HttpClient client) { 43 Tracker tracker = OperationTrackers.getTracker(client); 44 assert tracker != null; 45 TRACKERS.add(tracker); 46 return client; 47 } 48 getTrackedClientCount()49 public long getTrackedClientCount() { 50 return TRACKERS.size(); 51 } 52 diagnose(StringBuilder warnings)53 public StringBuilder diagnose(StringBuilder warnings) { 54 for (Tracker tracker : TRACKERS) { 55 checkOutstandingOperations(warnings, tracker); 56 } 57 return warnings; 58 } 59 hasOutstandingOperations()60 public boolean hasOutstandingOperations() { 61 return TRACKERS.stream().anyMatch(t -> t.getOutstandingOperations() > 0); 62 } 63 getOutstandingOperationsCount()64 public long getOutstandingOperationsCount() { 65 return TRACKERS.stream() 66 .map(Tracker::getOutstandingOperations) 67 .filter(n -> n > 0) 68 .collect(Collectors.summingLong(n -> n)); 69 } 70 getOutstandingClientCount()71 public long getOutstandingClientCount() { 72 return TRACKERS.stream() 73 .map(Tracker::getOutstandingOperations) 74 .filter(n -> n > 0) 75 .count(); 76 } 77 check(long graceDelayMs)78 public AssertionError check(long graceDelayMs) { 79 AssertionError fail = null; 80 if (hasOutstandingOperations()) { 81 try { 82 Thread.sleep(graceDelayMs); 83 } catch (InterruptedException x) { 84 // OK 85 } 86 StringBuilder warnings = diagnose(new StringBuilder()); 87 addSummary(warnings); 88 if (hasOutstandingOperations()) { 89 fail = new AssertionError(warnings.toString()); 90 } 91 } else { 92 System.out.println("PASSED: No outstanding operations found in " 93 + getTrackedClientCount() + " clients"); 94 } 95 return fail; 96 } 97 addSummary(StringBuilder warning)98 private void addSummary(StringBuilder warning) { 99 long activeClients = getOutstandingClientCount(); 100 long operations = getOutstandingOperationsCount(); 101 long tracked = getTrackedClientCount(); 102 if (warning.length() > 0) warning.append("\n"); 103 int pos = warning.length(); 104 warning.append("Found ") 105 .append(activeClients) 106 .append(" client still active, with ") 107 .append(operations) 108 .append(" operations still pending out of ") 109 .append(tracked) 110 .append(" tracked clients."); 111 System.out.println(warning.toString().substring(pos)); 112 System.err.println(warning.toString().substring(pos)); 113 } 114 checkOutstandingOperations(StringBuilder warning, Tracker tracker)115 private static void checkOutstandingOperations(StringBuilder warning, Tracker tracker) { 116 if (tracker.getOutstandingOperations() > 0) { 117 if (warning.length() > 0) warning.append("\n"); 118 int pos = warning.length(); 119 warning.append("WARNING: tracker for " + tracker.getName() + " has outstanding operations:"); 120 warning.append("\n\tPending HTTP/1.1 operations: " + tracker.getOutstandingHttpOperations()); 121 warning.append("\n\tPending HTTP/2 streams: " + tracker.getOutstandingHttp2Streams()); 122 warning.append("\n\tPending WebSocket operations: " + tracker.getOutstandingWebSocketOperations()); 123 warning.append("\n\tTotal pending operations: " + tracker.getOutstandingOperations()); 124 warning.append("\n\tFacade referenced: " + tracker.isFacadeReferenced()); 125 System.out.println(warning.toString().substring(pos)); 126 System.err.println(warning.toString().substring(pos)); 127 } 128 } 129 130 } 131