jdk-24/test/hotspot/jtreg/runtime/os/TestMemoryAllocationLogging.java
Sonia Zaldana Calles 3b305d502b 8313306: More sensible memory reservation logging
Reviewed-by: dholmes, stuefe, coleenp
2024-03-19 15:35:25 +00:00

242 lines
9.6 KiB
Java

/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, Red Hat Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
import java.io.IOException;
import jdk.test.whitebox.WhiteBox;
/*
* @test id=testSuccessfulFlow
* @summary Test that memory allocation logging works when allocation operations run without error
* @library /test/lib
* @requires os.family != "windows" & os.family != "aix"
* @requires vm.flagless
* @requires vm.bits == "64"
* @requires vm.debug == false
* @modules java.base/jdk.internal.misc
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run driver TestMemoryAllocationLogging testSuccessfulFlow
*/
/*
* @test id=testAttemptedReserveFailed
* @summary Test that memory allocation logging warns when attempted reservation fails
* @library /test/lib
* @requires os.family != "windows" & os.family != "aix"
* @requires vm.flagless
* @requires vm.bits == "64"
* @requires vm.debug == false
* @modules java.base/jdk.internal.misc
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run driver TestMemoryAllocationLogging testAttemptedReserveFailed
*/
/*
* @test id=testCommitFailed
* @summary Test that memory allocation logging warns when commit attempts fail
* @library /test/lib
* @requires os.family != "windows" & os.family != "aix"
* @requires vm.flagless
* @requires vm.bits == "64"
* @requires vm.debug == false
* @modules java.base/jdk.internal.misc
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run driver TestMemoryAllocationLogging testCommitFailed
*/
/*
* @test id=testUncommitFailed
* @summary Test that memory allocation logging warns when memory uncommitment fails
* @library /test/lib
* @requires os.family != "windows" & os.family != "aix"
* @requires vm.flagless
* @requires vm.bits == "64"
* @requires vm.debug == false
* @modules java.base/jdk.internal.misc
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run driver TestMemoryAllocationLogging testUncommitFailed
*/
/*
* @test id=testReleaseFailed
* @summary Test that memory allocation logging warns when memory release fails
* @library /test/lib
* @requires os.family != "windows" & os.family != "aix"
* @requires vm.flagless
* @requires vm.bits == "64"
* @requires vm.debug == false
* @modules java.base/jdk.internal.misc
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run driver TestMemoryAllocationLogging testReleaseFailed
*/
public class TestMemoryAllocationLogging {
protected static final long PAGE_SIZE = 64 * 1024; // 64Kb - largest page size in any system
protected static final long COMMIT_SIZE = 1024;
public static void main(String[] args) throws Exception {
if (args.length == 0) {
throw new RuntimeException("Argument error");
}
String[] options = new String[] {
"-Xlog:os+map=trace", // trace level will also print debug level
"-XX:-CreateCoredumpOnCrash",
"-Xms17m",
"-Xmx17m",
// Options for WhiteBox below
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"-Xbootclasspath/a:.",
TestMemoryAllocationLogging.Tester.class.getName(),
args[0]};
String[] expectedLogs;
/* Debug logging level tests */
switch (args[0]) {
case "testSuccessfulFlow": {
expectedLogs = new String[]{
/* Debug level log */
String.format("Reserved \\[0x.* - 0x.*\\), \\(%d bytes\\)", PAGE_SIZE),
String.format("Committed \\[0x.* - 0x.*\\), \\(%d bytes\\)", COMMIT_SIZE),
String.format("Uncommitted \\[0x.* - 0x.*\\), \\(%d bytes\\)", COMMIT_SIZE),
String.format("Released \\[0x.* - 0x.*\\), \\(%d bytes\\)", PAGE_SIZE)
};
break;
}
case "testAttemptedReserveFailed": {
expectedLogs = new String[] {
/* Debug level log */
String.format("Reserved \\[0x.* - 0x.*\\), \\(%d bytes\\)", PAGE_SIZE),
String.format("Attempt to reserve \\[0x.* - 0x.*\\), \\(.* bytes\\) failed"),
};
break;
}
case "testCommitFailed": {
expectedLogs = new String[] {
/* Debug level log */
String.format("Failed to commit \\[0x.* - 0x.*\\), \\(%d bytes\\)", COMMIT_SIZE),
/* Trace level log */
"mmap failed: \\[0x.* - 0x.*\\), \\(.* bytes\\) errno=\\(Invalid argument\\)"
};
break;
}
case "testUncommitFailed": {
expectedLogs = new String[] {
/* Debug level log */
String.format("Reserved \\[0x.* - 0x.*\\), \\(%d bytes\\)", PAGE_SIZE),
"Failed to uncommit \\[0x.* - 0x.*\\), \\(.* bytes\\)",
/* Trace level log */
"mmap failed: \\[0x.* - 0x.*\\), \\(.* bytes\\) errno=\\(Invalid argument\\)"
};
break;
}
case "testReleaseFailed": {
expectedLogs = new String[] {
/* Debug level log */
"Failed to release \\[0x.* - 0x.*\\), \\(.* bytes\\)",
/* Trace level log */
"munmap failed: \\[0x.* - 0x.*\\), \\(.* bytes\\) errno=\\(Invalid argument\\)"
};
break;
}
default: {
throw new RuntimeException("Invalid test " + args[0]);
}
}
OutputAnalyzer output = runTestWithOptions(options);
checkExpectedLogMessages(output, expectedLogs);
}
private static OutputAnalyzer runTestWithOptions(String[] options) throws IOException {
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(options);
OutputAnalyzer output = new OutputAnalyzer(pb.start());
return output;
}
private static void checkExpectedLogMessages(OutputAnalyzer output, String[] regexs) throws RuntimeException {
for (String regex : regexs) {
output.shouldMatch(regex);
}
}
static class Tester {
public static void main(String[] args) throws Exception {
System.out.println("Tester execution...");
WhiteBox wb = WhiteBox.getWhiteBox();
switch (args[0]) {
case "testSuccessfulFlow": {
long addr = wb.NMTReserveMemory(PAGE_SIZE);
wb.NMTCommitMemory(addr, COMMIT_SIZE);
wb.NMTUncommitMemory(addr, COMMIT_SIZE);
wb.NMTReleaseMemory(addr, PAGE_SIZE);
break;
}
case "testAttemptedReserveFailed": {
long addr = wb.NMTReserveMemory(PAGE_SIZE);
/* attempting to reserve the same address should fail */
wb.NMTAttemptReserveMemoryAt(addr, PAGE_SIZE);
break;
}
case "testCommitFailed": {
long addr = wb.NMTReserveMemory(PAGE_SIZE);
/* addr is not a multiple of system page size, so it should fail */
wb.NMTCommitMemory(addr - 1, COMMIT_SIZE);
break;
}
case "testUncommitFailed": {
long addr = wb.NMTReserveMemory(PAGE_SIZE);
wb.NMTCommitMemory(addr, PAGE_SIZE);
/* addr is not a multiple of a system page size, so it should fail */
wb.NMTUncommitMemory(addr - 1, PAGE_SIZE);
break;
}
case "testReleaseFailed": {
long addr = wb.NMTReserveMemory(PAGE_SIZE);
/* addr is not a multiple of system page size, so it should fail */
wb.NMTReleaseMemory(addr - 1, PAGE_SIZE);
break;
}
default: {
throw new RuntimeException("Invalid test " + args[0]);
}
}
}
}
}