1 /* 2 * Copyright (c) 2015, 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. 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.jcmd; 27 28 import java.io.IOException; 29 import java.nio.file.Files; 30 import java.nio.file.Path; 31 import java.nio.file.Paths; 32 import java.time.Duration; 33 import java.time.Instant; 34 import java.time.LocalDateTime; 35 import java.time.LocalTime; 36 import java.time.ZoneOffset; 37 import java.util.ArrayList; 38 import java.util.Collections; 39 import java.util.List; 40 41 import jdk.jfr.Event; 42 import jdk.jfr.Recording; 43 import jdk.test.lib.Asserts; 44 import jdk.test.lib.process.OutputAnalyzer; 45 46 /* 47 * @test 48 * @summary The test verifies JFR.dump command 49 * @key jfr 50 * @library /test/lib /test/jdk 51 * @run main/othervm jdk.jfr.jcmd.TestJcmdDumpLimited 52 */ 53 public class TestJcmdDumpLimited { 54 55 static class TestEvent extends Event { 56 int id; 57 int number; 58 } 59 60 static class TestRecording { 61 Instant time; 62 final Recording r; 63 Path path; 64 int size; 65 int total; 66 int id; 67 Instant now; 68 69 TestRecording(int id, int events) throws IOException, InterruptedException { 70 r = new Recording(); 71 r.start(); 72 for (int i = 0; i < events; i++) { 73 TestEvent event = new TestEvent(); 74 event.id = id; 75 event.number = i; 76 event.commit(); 77 if (i == events / 2) { 78 time = Instant.now(); 79 } 80 } 81 r.stop(); 82 Thread.sleep(1); 83 path = Paths.get("dump-" + id + ".jfr"); 84 r.dump(path); 85 size = (int) Files.size(path); 86 this.id = id; 87 this.now = Instant.now(); 88 } 89 90 public void close() { 91 r.close(); 92 } 93 } 94 95 private static long totalSize; 96 private static long lastFiveSize; 97 private static long firstFiveSize; 98 private static long middleSize; 99 private static long centerSize; 100 private static long lastSize; 101 102 private static Instant middle; 103 private static Instant centerLeft; 104 private static Instant centerRight; 105 106 public static void main(String[] args) throws Exception { 107 108 List<TestRecording> recs = new ArrayList<>(); 109 110 for (int i = 0; i < 9; i++) { 111 recs.add(new TestRecording(i, 100)); 112 } 113 int last = 0; 114 List<TestRecording> reversed = new ArrayList<>(recs); 115 Collections.reverse(reversed); 116 for (TestRecording r : reversed) { 117 r.total = r.size + last; 118 last += r.size; 119 } 120 121 for (TestRecording r : recs) { 122 System.out.println("Recording " + r.id + ": size=" + r.size + " (total=" + r.total + ", time=" + r.now + ")"); 123 } 124 125 centerLeft = recs.get(3).time; 126 middle = recs.get(4).time; 127 centerRight = recs.get(5).time; 128 129 totalSize = size(recs, 0, 9); 130 lastFiveSize = size(recs, 4, 5); 131 firstFiveSize = size(recs, 0, 5); 132 middleSize = size(recs, 4, 1); 133 centerSize = size(recs, 3, 3); 134 lastSize = size(recs, 8, 1); 135 136 testDump(); 137 testDumpMaxSize(); 138 testDumpMaxSizeSmall(); 139 testDumpBegin(); 140 testDumpEnd(); 141 testDumpBeginEndInstant(); 142 testDumpBeginEndLocalDateTime(); 143 testDumpBeginEndLocalTime(); 144 testDumpBeginEndSame(); 145 testDumpMaxAge(); 146 testDumpBeginEndRelative(); 147 testDumpTooEarly(); 148 testDumpTooLate(); 149 testDumpBeginMaxAge(); 150 TestDumpEndMaxage(); 151 testDumpEndBegin(); 152 testDumpInvalidTime(); 153 } 154 155 private static int size(List<TestRecording> recs, int skip, int limit) { 156 return recs.stream().skip(skip).limit(limit).mapToInt(r -> r.size).sum(); 157 } 158 159 private static void testDumpEndBegin() throws Exception { 160 Path testEndBegin = Paths.get("testEndBegin.jfr"); 161 OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump", "filename=" + testEndBegin.toFile().getAbsolutePath(), "begin=" + Instant.now(), "end=" + Instant.now().minusSeconds(200)); 162 output.shouldContain("Dump failed, begin must preceed end."); 163 assertMissingFile(testEndBegin); 164 } 165 166 private static void TestDumpEndMaxage() throws Exception { 167 Path testEndMaxAge = Paths.get("testEndMaxAge.jfr"); 168 OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump", "filename=" + testEndMaxAge.toFile().getAbsolutePath(), "end=" + Instant.now(), "maxage=2h"); 169 output.shouldContain("Dump failed, maxage can't be combined with begin or end."); 170 assertMissingFile(testEndMaxAge); 171 } 172 173 private static Path testDumpBeginMaxAge() throws Exception { 174 Path testBeginMaxAge = Paths.get("testBeginMaxAge.jfr"); 175 OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump", "filename=" + testBeginMaxAge.toFile().getAbsolutePath(), "begin=" + Instant.now().minusSeconds(100), "maxage=2h"); 176 output.shouldContain("Dump failed, maxage can't be combined with begin or end."); 177 assertMissingFile(testBeginMaxAge); 178 return testBeginMaxAge; 179 } 180 181 private static void testDumpTooLate() throws Exception { 182 Path missing = Paths.get("missing2.jfr"); 183 OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump", "filename=" + missing.toFile().getAbsolutePath(), "begin=" + Instant.now().plus(Duration.ofHours(1)), 184 "end=" + Instant.now().plus(Duration.ofHours(2))); 185 output.shouldContain("Dump failed. No data found in the specified interval."); 186 assertMissingFile(missing); 187 } 188 189 private static void testDumpTooEarly() throws Exception { 190 Path missing = Paths.get("missing.jfr"); 191 OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump", "filename=" + missing.toFile().getAbsolutePath(), "end=" + Instant.now().minus(Duration.ofHours(1))); 192 output.shouldContain("Dump failed. No data found in the specified interval."); 193 assertMissingFile(missing); 194 } 195 196 private static void testDumpBeginEndRelative() throws IOException { 197 Path testBeginEndRelative = Paths.get("testBeginEndRelative.jfr"); 198 JcmdHelper.jcmd("JFR.dump", "filename=" + testBeginEndRelative.toFile().getAbsolutePath(), "begin=-3h", "end=-0s"); 199 Asserts.assertEquals(totalSize, Files.size(testBeginEndRelative), "Expected dump with begin=-3h end=0s to contain data from all recordings"); 200 Files.delete(testBeginEndRelative); 201 } 202 203 private static void testDumpMaxAge() throws IOException { 204 Path testMaxAge = Paths.get("testMaxAge.jfr"); 205 JcmdHelper.jcmd("JFR.dump", "filename=" + testMaxAge.toFile().getAbsolutePath(), "maxage=2h"); 206 Asserts.assertEquals(totalSize, Files.size(testMaxAge), "Expected dump with maxage=2h to contain data from all recordings"); 207 Files.delete(testMaxAge); 208 } 209 210 private static void testDumpBeginEndSame() throws IOException { 211 Path testBeginEnd = Paths.get("testBeginEndSame.jfr"); 212 JcmdHelper.jcmd("JFR.dump", "filename=" + testBeginEnd.toFile().getAbsolutePath(), "begin=" + middle, "end=" + middle); 213 Asserts.assertEquals(middleSize, Files.size(testBeginEnd), "Expected dump with begin=" + middle + "end=" + middle + " contain data from middle recording"); 214 Files.delete(testBeginEnd); 215 } 216 217 private static void testDumpBeginEndInstant() throws IOException { 218 Path testBeginEnd = Paths.get("testBeginEndInstant.jfr"); 219 JcmdHelper.jcmd("JFR.dump", "filename=" + testBeginEnd.toFile().getAbsolutePath(), "begin=" + centerLeft, "end=" + centerRight); 220 Asserts.assertEquals(centerSize, Files.size(testBeginEnd), "Expected dump with begin=" + centerLeft + " end=" + centerRight + " contain data from the 'center'-recordings"); 221 Files.delete(testBeginEnd); 222 } 223 224 private static void testDumpBeginEndLocalDateTime() throws IOException { 225 LocalDateTime centerLeftLocal = LocalDateTime.ofInstant(centerLeft, ZoneOffset.systemDefault()); 226 LocalDateTime centerRightLocal = LocalDateTime.ofInstant(centerRight, ZoneOffset.systemDefault()); 227 Path testBeginEnd = Paths.get("testBeginEndLocalDateTime.jfr"); 228 JcmdHelper.jcmd("JFR.dump", "filename=" + testBeginEnd.toFile().getAbsolutePath(), "begin=" + centerLeftLocal, "end=" + centerRightLocal); 229 Asserts.assertEquals(centerSize, Files.size(testBeginEnd), "Expected dump with begin=" + centerLeftLocal + " end=" + centerRightLocal + " contain data from the 'center'-recordings"); 230 Files.delete(testBeginEnd); 231 } 232 233 private static void testDumpBeginEndLocalTime() throws IOException { 234 LocalTime centerLeftLocal = LocalTime.ofInstant(centerLeft, ZoneOffset.systemDefault()); 235 LocalTime centerRightLocal = LocalTime.ofInstant(centerRight, ZoneOffset.systemDefault()); 236 Path testBeginEnd = Paths.get("testBeginEndLocalTime.jfr"); 237 JcmdHelper.jcmd("JFR.dump", "filename=" + testBeginEnd.toFile().getAbsolutePath(), "begin=" + centerLeftLocal, "end=" + centerRightLocal); 238 Asserts.assertEquals(centerSize, Files.size(testBeginEnd), "Expected dump with begin=" + centerLeftLocal + " end=" + centerRightLocal + " contain data from the 'center'-recordings"); 239 Files.delete(testBeginEnd); 240 } 241 242 private static void testDumpEnd() throws IOException { 243 Path testEnd = Paths.get("testEnd.jfr"); 244 JcmdHelper.jcmd("JFR.dump", "filename=" + testEnd.toFile().getAbsolutePath(), "end=" + middle); 245 Asserts.assertEquals(firstFiveSize, Files.size(testEnd), "Expected dump with end=" + middle + " to contain data from the five first recordings"); 246 Files.delete(testEnd); 247 } 248 249 private static void testDumpBegin() throws IOException { 250 Path testBegin = Paths.get("testBegin.jfr"); 251 JcmdHelper.jcmd("JFR.dump", "filename=" + testBegin.toFile().getAbsolutePath(), "begin=" + middle); 252 Asserts.assertEquals(lastFiveSize, Files.size(testBegin), "Expected dump with begin=" + middle + " to contain data from the last five recordings"); 253 Files.delete(testBegin); 254 } 255 256 private static void testDumpMaxSize() throws IOException { 257 Path testMaxSize = Paths.get("testMaxSize.jfr"); 258 JcmdHelper.jcmd("JFR.dump", "filename=" + testMaxSize.toFile().getAbsolutePath(), "maxsize=" + lastFiveSize); 259 Asserts.assertEquals(lastFiveSize, Files.size(testMaxSize), "Expected dump with maxsize=" + lastFiveSize + " to contain data from the last five recordings"); 260 Files.delete(testMaxSize); 261 } 262 263 private static void testDumpMaxSizeSmall() throws IOException { 264 Path testMaxSizeSmall = Paths.get("testMaxSizeSmall.jfr"); 265 JcmdHelper.jcmd("JFR.dump", "filename=" + testMaxSizeSmall.toFile().getAbsolutePath(), "maxsize=1k"); 266 Asserts.assertEquals(lastSize, Files.size(testMaxSizeSmall), "Expected dump with maxsize=1k to contain data from the last recording"); 267 Files.delete(testMaxSizeSmall); 268 } 269 270 private static void testDump() throws IOException { 271 Path all = Paths.get("all.jfr"); 272 OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump", "filename=" + all.toFile().getAbsolutePath()); 273 JcmdAsserts.assertRecordingDumpedToFile(output, all.toFile()); 274 Asserts.assertEquals(totalSize, Files.size(all), "Expected dump to be sum of all recordings"); 275 Files.delete(all); 276 } 277 278 private static void testDumpInvalidTime() throws Exception { 279 Path invalidTime = Paths.get("invalidTime.jfr"); 280 OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump", "filename=" + invalidTime.toFile().getAbsolutePath(), "begin=4711"); 281 output.shouldContain("Dump failed, not a valid begin time."); 282 assertMissingFile(invalidTime); 283 } 284 285 private static void assertMissingFile(Path missing) throws Exception { 286 if (Files.exists(missing)) { 287 throw new Exception("Unexpected dumpfile found"); 288 } 289 } 290 291 }