Skip to content

Commit 57ec95c

Browse files
cpovirkGoogle Java Core Libraries
authored and
Google Java Core Libraries
committed
Throw StackOverflowError manually instead of triggering a real stack overflow, which sometimes hoses subsequent tests or crashes Android.
Remove existing attempted workarounds for such trouble. Run some tests under Android now that we can. RELNOTES=n/a PiperOrigin-RevId: 724380185
1 parent 7719744 commit 57ec95c

File tree

2 files changed

+68
-140
lines changed

2 files changed

+68
-140
lines changed

android/guava-tests/test/com/google/common/util/concurrent/FuturesTest.java

+34-70
Original file line numberDiff line numberDiff line change
@@ -257,26 +257,17 @@ public BarChild apply(Foo unused) {
257257
assertSame(barChild, bar);
258258
}
259259

260-
@AndroidIncompatible // b/391667564: crashes from stack overflows
261260
@J2ktIncompatible
262261
@GwtIncompatible // StackOverflowError
263262
public void testTransform_stackOverflow() throws Exception {
264-
{
265-
/*
266-
* Initialize all relevant classes before running the test, which may otherwise poison any
267-
* classes it is trying to load during its stack overflow.
268-
*/
269-
SettableFuture<Object> root = SettableFuture.create();
270-
ListenableFuture<Object> unused = transform(root, identity(), directExecutor());
271-
root.set("foo");
272-
}
273-
274-
SettableFuture<Object> root = SettableFuture.create();
275-
ListenableFuture<Object> output = root;
276-
for (int i = 0; i < 10000; i++) {
277-
output = transform(output, identity(), directExecutor());
278-
}
279-
assertThrows(StackOverflowError.class, () -> root.set("foo"));
263+
SettableFuture<Object> input = SettableFuture.create();
264+
ListenableFuture<Object> output = transform(input, identity(), directExecutor());
265+
output.addListener(
266+
() -> {
267+
throw new StackOverflowError();
268+
},
269+
directExecutor());
270+
assertThrows(StackOverflowError.class, () -> input.set("foo"));
280271
}
281272

282273
public void testTransform_errorAfterCancellation() throws Exception {
@@ -469,26 +460,17 @@ public ListenableFuture<Bar> apply(Foo unused) {
469460
assertFalse(((AbstractFuture<?>) f2).wasInterrupted());
470461
}
471462

472-
@AndroidIncompatible // b/391667564: crashes from stack overflows
473463
@J2ktIncompatible
474464
@GwtIncompatible // StackOverflowError
475465
public void testTransformAsync_stackOverflow() throws Exception {
476-
{
477-
/*
478-
* Initialize all relevant classes before running the test, which may otherwise poison any
479-
* classes it is trying to load during its stack overflow.
480-
*/
481-
SettableFuture<Object> root = SettableFuture.create();
482-
ListenableFuture<Object> unused = transformAsync(root, asyncIdentity(), directExecutor());
483-
root.set("foo");
484-
}
485-
486-
SettableFuture<Object> root = SettableFuture.create();
487-
ListenableFuture<Object> output = root;
488-
for (int i = 0; i < 10000; i++) {
489-
output = transformAsync(output, asyncIdentity(), directExecutor());
490-
}
491-
assertThrows(StackOverflowError.class, () -> root.set("foo"));
466+
SettableFuture<Object> input = SettableFuture.create();
467+
ListenableFuture<Object> output = transformAsync(input, asyncIdentity(), directExecutor());
468+
output.addListener(
469+
() -> {
470+
throw new StackOverflowError();
471+
},
472+
directExecutor());
473+
assertThrows(StackOverflowError.class, () -> input.set("foo"));
492474
}
493475

494476
public void testTransformAsync_errorAfterCancellation() throws Exception {
@@ -1305,27 +1287,18 @@ public void testCatching_customTypeNoMatch() throws Exception {
13051287
assertThat(expected).hasCauseThat().isInstanceOf(RuntimeException.class);
13061288
}
13071289

1308-
@AndroidIncompatible // b/391667564: crashes from stack overflows
13091290
@J2ktIncompatible
13101291
@GwtIncompatible // StackOverflowError
13111292
public void testCatching_stackOverflow() throws Exception {
1312-
{
1313-
/*
1314-
* Initialize all relevant classes before running the test, which may otherwise poison any
1315-
* classes it is trying to load during its stack overflow.
1316-
*/
1317-
SettableFuture<Object> root = SettableFuture.create();
1318-
ListenableFuture<Object> unused =
1319-
catching(root, MyException.class, identity(), directExecutor());
1320-
root.setException(new MyException());
1321-
}
1322-
1323-
SettableFuture<Object> root = SettableFuture.create();
1324-
ListenableFuture<Object> output = root;
1325-
for (int i = 0; i < 10000; i++) {
1326-
output = catching(output, MyException.class, identity(), directExecutor());
1327-
}
1328-
assertThrows(StackOverflowError.class, () -> root.setException(new MyException()));
1293+
SettableFuture<Object> input = SettableFuture.create();
1294+
ListenableFuture<Object> output =
1295+
catching(input, MyException.class, identity(), directExecutor());
1296+
output.addListener(
1297+
() -> {
1298+
throw new StackOverflowError();
1299+
},
1300+
directExecutor());
1301+
assertThrows(StackOverflowError.class, () -> input.setException(new MyException()));
13291302
}
13301303

13311304
public void testCatching_errorAfterCancellation() throws Exception {
@@ -1435,27 +1408,18 @@ public void testCatchingAsync_customTypeNoMatch() throws Exception {
14351408
assertThat(expected).hasCauseThat().isInstanceOf(RuntimeException.class);
14361409
}
14371410

1438-
@AndroidIncompatible // b/391667564: crashes from stack overflows
14391411
@J2ktIncompatible
14401412
@GwtIncompatible // StackOverflowError
14411413
public void testCatchingAsync_stackOverflow() throws Exception {
1442-
{
1443-
/*
1444-
* Initialize all relevant classes before running the test, which may otherwise poison any
1445-
* classes it is trying to load during its stack overflow.
1446-
*/
1447-
SettableFuture<Object> root = SettableFuture.create();
1448-
ListenableFuture<Object> unused =
1449-
catchingAsync(root, MyException.class, asyncIdentity(), directExecutor());
1450-
root.setException(new MyException());
1451-
}
1452-
1453-
SettableFuture<Object> root = SettableFuture.create();
1454-
ListenableFuture<Object> output = root;
1455-
for (int i = 0; i < 10000; i++) {
1456-
output = catchingAsync(output, MyException.class, asyncIdentity(), directExecutor());
1457-
}
1458-
assertThrows(StackOverflowError.class, () -> root.setException(new MyException()));
1414+
SettableFuture<Object> input = SettableFuture.create();
1415+
ListenableFuture<Object> output =
1416+
catchingAsync(input, MyException.class, asyncIdentity(), directExecutor());
1417+
output.addListener(
1418+
() -> {
1419+
throw new StackOverflowError();
1420+
},
1421+
directExecutor());
1422+
assertThrows(StackOverflowError.class, () -> input.setException(new MyException()));
14591423
}
14601424

14611425
public void testCatchingAsync_errorAfterCancellation() throws Exception {

guava-tests/test/com/google/common/util/concurrent/FuturesTest.java

+34-70
Original file line numberDiff line numberDiff line change
@@ -257,26 +257,17 @@ public BarChild apply(Foo unused) {
257257
assertSame(barChild, bar);
258258
}
259259

260-
@AndroidIncompatible // b/391667564: crashes from stack overflows
261260
@J2ktIncompatible
262261
@GwtIncompatible // StackOverflowError
263262
public void testTransform_stackOverflow() throws Exception {
264-
{
265-
/*
266-
* Initialize all relevant classes before running the test, which may otherwise poison any
267-
* classes it is trying to load during its stack overflow.
268-
*/
269-
SettableFuture<Object> root = SettableFuture.create();
270-
ListenableFuture<Object> unused = transform(root, identity(), directExecutor());
271-
root.set("foo");
272-
}
273-
274-
SettableFuture<Object> root = SettableFuture.create();
275-
ListenableFuture<Object> output = root;
276-
for (int i = 0; i < 10000; i++) {
277-
output = transform(output, identity(), directExecutor());
278-
}
279-
assertThrows(StackOverflowError.class, () -> root.set("foo"));
263+
SettableFuture<Object> input = SettableFuture.create();
264+
ListenableFuture<Object> output = transform(input, identity(), directExecutor());
265+
output.addListener(
266+
() -> {
267+
throw new StackOverflowError();
268+
},
269+
directExecutor());
270+
assertThrows(StackOverflowError.class, () -> input.set("foo"));
280271
}
281272

282273
public void testTransform_errorAfterCancellation() throws Exception {
@@ -469,26 +460,17 @@ public ListenableFuture<Bar> apply(Foo unused) {
469460
assertFalse(((AbstractFuture<?>) f2).wasInterrupted());
470461
}
471462

472-
@AndroidIncompatible // b/391667564: crashes from stack overflows
473463
@J2ktIncompatible
474464
@GwtIncompatible // StackOverflowError
475465
public void testTransformAsync_stackOverflow() throws Exception {
476-
{
477-
/*
478-
* Initialize all relevant classes before running the test, which may otherwise poison any
479-
* classes it is trying to load during its stack overflow.
480-
*/
481-
SettableFuture<Object> root = SettableFuture.create();
482-
ListenableFuture<Object> unused = transformAsync(root, asyncIdentity(), directExecutor());
483-
root.set("foo");
484-
}
485-
486-
SettableFuture<Object> root = SettableFuture.create();
487-
ListenableFuture<Object> output = root;
488-
for (int i = 0; i < 10000; i++) {
489-
output = transformAsync(output, asyncIdentity(), directExecutor());
490-
}
491-
assertThrows(StackOverflowError.class, () -> root.set("foo"));
466+
SettableFuture<Object> input = SettableFuture.create();
467+
ListenableFuture<Object> output = transformAsync(input, asyncIdentity(), directExecutor());
468+
output.addListener(
469+
() -> {
470+
throw new StackOverflowError();
471+
},
472+
directExecutor());
473+
assertThrows(StackOverflowError.class, () -> input.set("foo"));
492474
}
493475

494476
public void testTransformAsync_errorAfterCancellation() throws Exception {
@@ -1305,27 +1287,18 @@ public void testCatching_customTypeNoMatch() throws Exception {
13051287
assertThat(expected).hasCauseThat().isInstanceOf(RuntimeException.class);
13061288
}
13071289

1308-
@AndroidIncompatible // b/391667564: crashes from stack overflows
13091290
@J2ktIncompatible
13101291
@GwtIncompatible // StackOverflowError
13111292
public void testCatching_stackOverflow() throws Exception {
1312-
{
1313-
/*
1314-
* Initialize all relevant classes before running the test, which may otherwise poison any
1315-
* classes it is trying to load during its stack overflow.
1316-
*/
1317-
SettableFuture<Object> root = SettableFuture.create();
1318-
ListenableFuture<Object> unused =
1319-
catching(root, MyException.class, identity(), directExecutor());
1320-
root.setException(new MyException());
1321-
}
1322-
1323-
SettableFuture<Object> root = SettableFuture.create();
1324-
ListenableFuture<Object> output = root;
1325-
for (int i = 0; i < 10000; i++) {
1326-
output = catching(output, MyException.class, identity(), directExecutor());
1327-
}
1328-
assertThrows(StackOverflowError.class, () -> root.setException(new MyException()));
1293+
SettableFuture<Object> input = SettableFuture.create();
1294+
ListenableFuture<Object> output =
1295+
catching(input, MyException.class, identity(), directExecutor());
1296+
output.addListener(
1297+
() -> {
1298+
throw new StackOverflowError();
1299+
},
1300+
directExecutor());
1301+
assertThrows(StackOverflowError.class, () -> input.setException(new MyException()));
13291302
}
13301303

13311304
public void testCatching_errorAfterCancellation() throws Exception {
@@ -1435,27 +1408,18 @@ public void testCatchingAsync_customTypeNoMatch() throws Exception {
14351408
assertThat(expected).hasCauseThat().isInstanceOf(RuntimeException.class);
14361409
}
14371410

1438-
@AndroidIncompatible // b/391667564: crashes from stack overflows
14391411
@J2ktIncompatible
14401412
@GwtIncompatible // StackOverflowError
14411413
public void testCatchingAsync_stackOverflow() throws Exception {
1442-
{
1443-
/*
1444-
* Initialize all relevant classes before running the test, which may otherwise poison any
1445-
* classes it is trying to load during its stack overflow.
1446-
*/
1447-
SettableFuture<Object> root = SettableFuture.create();
1448-
ListenableFuture<Object> unused =
1449-
catchingAsync(root, MyException.class, asyncIdentity(), directExecutor());
1450-
root.setException(new MyException());
1451-
}
1452-
1453-
SettableFuture<Object> root = SettableFuture.create();
1454-
ListenableFuture<Object> output = root;
1455-
for (int i = 0; i < 10000; i++) {
1456-
output = catchingAsync(output, MyException.class, asyncIdentity(), directExecutor());
1457-
}
1458-
assertThrows(StackOverflowError.class, () -> root.setException(new MyException()));
1414+
SettableFuture<Object> input = SettableFuture.create();
1415+
ListenableFuture<Object> output =
1416+
catchingAsync(input, MyException.class, asyncIdentity(), directExecutor());
1417+
output.addListener(
1418+
() -> {
1419+
throw new StackOverflowError();
1420+
},
1421+
directExecutor());
1422+
assertThrows(StackOverflowError.class, () -> input.setException(new MyException()));
14591423
}
14601424

14611425
public void testCatchingAsync_errorAfterCancellation() throws Exception {

0 commit comments

Comments
 (0)