提交 7d9ea8c0 authored 作者: andrei's avatar andrei

Make disk OOME test a forked process, for travis mute in-memory OOME tests

Eliminate usage of OOME in memory measurements
上级 41af1194
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
package org.h2.test; package org.h2.test;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
...@@ -30,7 +31,9 @@ import java.sql.Types; ...@@ -30,7 +31,9 @@ import java.sql.Types;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.SimpleTimeZone; import java.util.SimpleTimeZone;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
...@@ -40,6 +43,7 @@ import org.h2.store.fs.FilePath; ...@@ -40,6 +43,7 @@ import org.h2.store.fs.FilePath;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.test.utils.ProxyCodeGenerator; import org.h2.test.utils.ProxyCodeGenerator;
import org.h2.test.utils.ResultVerifier; import org.h2.test.utils.ResultVerifier;
import org.h2.test.utils.SelfDestructor;
import org.h2.tools.DeleteDbFiles; import org.h2.tools.DeleteDbFiles;
/** /**
...@@ -1444,6 +1448,16 @@ public abstract class TestBase { ...@@ -1444,6 +1448,16 @@ public abstract class TestBase {
return System.getProperty("java.class.path"); return System.getProperty("java.class.path");
} }
/**
* Get the path to a java executable of the current process
*
* @return the path to java
*/
private String getJVM() {
return System.getProperty("java.home") + File.separatorChar + "bin" +
File.separator + "java";
}
/** /**
* Use up almost all memory. * Use up almost all memory.
* *
...@@ -1687,4 +1701,45 @@ public abstract class TestBase { ...@@ -1687,4 +1701,45 @@ public abstract class TestBase {
return getClass().getSimpleName(); return getClass().getSimpleName();
} }
public ProcessBuilder buildChild(String name, Class<? extends TestBase> childClass,
String... jvmArgs) {
List<String> args = new ArrayList<>(16);
args.add(getJVM());
Collections.addAll(args, jvmArgs);
Collections.addAll(args, "-cp", getClassPath(),
SelfDestructor.getPropertyString(1),
childClass.getName(),
"-url", getURL(name, true),
"-user", getUser(),
"-password", getPassword());
ProcessBuilder processBuilder = new ProcessBuilder()
// .redirectError(ProcessBuilder.Redirect.INHERIT)
.redirectErrorStream(true)
.redirectOutput(ProcessBuilder.Redirect.INHERIT)
.command(args);
return processBuilder;
}
public abstract static class Child extends TestBase
{
private String url;
private String user;
private String password;
public Child(String... args) {
for (int i = 0; i < args.length; i++) {
if ("-url".equals(args[i])) {
url = args[++i];
} else if ("-user".equals(args[i])) {
user = args[++i];
} else if ("-password".equals(args[i])) {
password = args[++i];
}
}
}
public Connection getConnection() throws SQLException {
return getConnection(url, user, password);
}
}
} }
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
*/ */
package org.h2.test.db; package org.h2.test.db;
import java.io.File;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
...@@ -21,7 +20,6 @@ import org.h2.store.fs.FilePath; ...@@ -21,7 +20,6 @@ import org.h2.store.fs.FilePath;
import org.h2.store.fs.FilePathMem; import org.h2.store.fs.FilePathMem;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.test.utils.SelfDestructor;
/** /**
* Tests out of memory situations. The database must not get corrupted, and * Tests out of memory situations. The database must not get corrupted, and
...@@ -29,6 +27,8 @@ import org.h2.test.utils.SelfDestructor; ...@@ -29,6 +27,8 @@ import org.h2.test.utils.SelfDestructor;
*/ */
public class TestOutOfMemory extends TestBase { public class TestOutOfMemory extends TestBase {
private static final String DB_NAME = "outOfMemory";
/** /**
* Run just this test. * Run just this test.
* *
...@@ -45,10 +45,12 @@ public class TestOutOfMemory extends TestBase { ...@@ -45,10 +45,12 @@ public class TestOutOfMemory extends TestBase {
return; return;
} }
try { try {
if (!config.travis) {
System.gc(); System.gc();
testMVStoreUsingInMemoryFileSystem(); testMVStoreUsingInMemoryFileSystem();
System.gc(); System.gc();
testDatabaseUsingInMemoryFileSystem(); testDatabaseUsingInMemoryFileSystem();
}
System.gc(); System.gc();
testUpdateWhenNearlyOutOfMemory(); testUpdateWhenNearlyOutOfMemory();
} finally { } finally {
...@@ -152,52 +154,61 @@ public class TestOutOfMemory extends TestBase { ...@@ -152,52 +154,61 @@ public class TestOutOfMemory extends TestBase {
if (config.memory) { if (config.memory) {
return; return;
} }
deleteDb("outOfMemory"); deleteDb(DB_NAME);
String url = getURL("outOfMemory", true);
ProcessBuilder processBuilder = buildChild(
DB_NAME + ";MAX_OPERATION_MEMORY=1000000",
MyChild.class,
"-XX:+UseParallelGC",
// "-XX:+UseG1GC",
"-Xmx128m");
//* //*
String selfDestructor = SelfDestructor.getPropertyString(1); processBuilder.start().waitFor();
String args[] = {System.getProperty("java.home") + File.separatorChar + "bin" + File.separator + "java",
"-Xmx128m", "-XX:+UseParallelGC", // "-XX:+UseG1GC",
"-cp", getClassPath(),
selfDestructor,
Child.class.getName(), url};
ProcessBuilder pb = new ProcessBuilder()
.redirectOutput(ProcessBuilder.Redirect.INHERIT)
.redirectError(ProcessBuilder.Redirect.INHERIT)
.command(args);
Process p = pb.start();
int exitValue = p.waitFor();
assertEquals("Exit code", 0, exitValue);
/*/ /*/
Child.main(url); List<String> args = processBuilder.command();
for (Iterator<String> iter = args.iterator(); iter.hasNext(); ) {
String arg = iter.next();
if(arg.equals(MyChild.class.getName())) {
iter.remove();
break;
}
iter.remove();
}
MyChild.main(args.toArray(new String[0]));
//*/ //*/
try (Connection conn = getConnection("outOfMemory")) { try (Connection conn = getConnection(DB_NAME)) {
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT count(*) FROM stuff"); ResultSet rs = stat.executeQuery("SELECT count(*) FROM stuff");
assertTrue(rs.next()); assertTrue(rs.next());
assertEquals(3000, rs.getInt(1)); assertEquals(3000, rs.getInt(1));
rs = stat.executeQuery("SELECT * FROM stuff WHERE id = 3000"); rs = stat.executeQuery("SELECT * FROM stuff WHERE id = 3000");
assertTrue(rs.next()); assertTrue(rs.next());
String text = rs.getString(2); String text = rs.getString(2);
assertFalse(rs.wasNull()); assertFalse(rs.wasNull());
assertEquals(1004, text.length()); assertEquals(1004, text.length());
rs = stat.executeQuery("SELECT sum(length(text)) FROM stuff");
assertTrue(rs.next());
assertEquals(3010893, rs.getInt(1));
} finally { } finally {
deleteDb("outOfMemory"); deleteDb(DB_NAME);
} }
} }
public static final class Child extends TestBase public static final class MyChild extends TestBase.Child
{ {
private static String URL; public static void main(String... args) throws Exception {
new MyChild(args).init().test();
}
public static void main(String... a) throws Exception { private MyChild(String... args) {
URL = a[0]; super(args);
TestBase.createCaller().init().test();
} }
@Override @Override
public void test() throws SQLException { public void test() {
Connection conn = getConnection(URL + ";MAX_OPERATION_MEMORY=1000000"); try (Connection conn = getConnection()) {
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
stat.execute("DROP ALL OBJECTS"); stat.execute("DROP ALL OBJECTS");
stat.execute("CREATE TABLE stuff (id INT, text VARCHAR)"); stat.execute("CREATE TABLE stuff (id INT, text VARCHAR)");
...@@ -206,14 +217,17 @@ public class TestOutOfMemory extends TestBase { ...@@ -206,14 +217,17 @@ public class TestOutOfMemory extends TestBase {
"UPDATE stuff SET text = IFNULL(text,'') || space(1000) || id"); "UPDATE stuff SET text = IFNULL(text,'') || space(1000) || id");
prep.execute(); prep.execute();
stat.execute("CHECKPOINT"); stat.execute("CHECKPOINT");
eatMemory(80);
try { ResultSet rs = stat.executeQuery("SELECT sum(length(text)) FROM stuff");
assertTrue(rs.next());
assertEquals(3010893, rs.getInt(1));
eatMemory(15_000);
prep.execute(); prep.execute();
fail(); fail();
} catch (Throwable ex) { } catch (SQLException ignore) {
freeMemory();
} finally { } finally {
try { conn.close(); } catch (Throwable ignore) {/**/} freeMemory();
} }
} }
} }
......
...@@ -124,14 +124,6 @@ public class TestMVStoreBenchmark extends TestBase { ...@@ -124,14 +124,6 @@ public class TestMVStoreBenchmark extends TestBase {
} }
static long getMemory() { static long getMemory() {
try {
LinkedList<byte[]> list = new LinkedList<>();
while (true) {
list.add(new byte[1024]);
}
} catch (OutOfMemoryError e) {
// ok
}
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
System.gc(); System.gc();
try { try {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论