< prev index next >

test/java/lang/invoke/LoopCombinatorTest.java

Print this page
rev 14211 : 8152667: MHs.iteratedLoop(...) throws unexpected WMTE, disallows Iterator subclasses, generates inconsistent loop result type

*** 398,411 **** caught = true; } assertTrue(caught); } ! @Test ! public static void testIterateVoidIterator() { boolean caught = false; ! MethodType v = methodType(void.class); try { MethodHandles.iteratedLoop(MethodHandles.empty(v), null, MethodHandles.empty(v)); } catch(IllegalArgumentException iae) { assertEquals("iteratedLoop first argument must have Iterator return type", iae.getMessage()); caught = true; --- 398,416 ---- caught = true; } assertTrue(caught); } ! @DataProvider ! static Object[][] wrongIteratorTypes() { ! return new Object[][]{{void.class}, {Object.class}, {Iterable.class}}; ! } ! ! @Test(dataProvider = "wrongIteratorTypes") ! public static void testIterateVoidIterator(Class<?> it) { boolean caught = false; ! MethodType v = methodType(it); try { MethodHandles.iteratedLoop(MethodHandles.empty(v), null, MethodHandles.empty(v)); } catch(IllegalArgumentException iae) { assertEquals("iteratedLoop first argument must have Iterator return type", iae.getMessage()); caught = true;
*** 418,427 **** --- 423,503 ---- MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_voidInit, Iterate.MH_printStep); assertEquals(Iterate.MT_print, loop.type()); loop.invoke(Arrays.asList("hello", "world")); } + @DataProvider + static Object[][] iterateParameters() { + MethodType i = methodType(int.class); + MethodType sil_i = methodType(int.class, String.class, int.class, List.class); + MethodType sl_v = methodType(void.class, String.class, List.class); + MethodType l_it = methodType(Iterator.class, List.class); + MethodType li_it = methodType(Iterator.class, List.class, int.class); + MethodType l_i = methodType(int.class, List.class); + MethodType _it = methodType(Iterator.class); + MethodType si_i = methodType(int.class, String.class, int.class); + MethodType s_i = methodType(int.class, String.class); + return new Object[][]{ + {null, null, sl_v}, + {null, i, sil_i}, + {null, l_i, sil_i}, + {l_it, null, sl_v}, + {l_it, i, sil_i}, + {li_it, l_i, sil_i}, + {l_it, null, sil_i}, + {li_it, null, sl_v}, + {_it, l_i, si_i}, + {_it, l_i, s_i} + }; + } + + @Test(dataProvider = "iterateParameters") + public static void testIterateParameters(MethodType it, MethodType in, MethodType bo) throws Throwable { + MethodHandle iterator = it == null ? null : MethodHandles.empty(it); + MethodHandle init = in == null ? null : MethodHandles.empty(in); + MethodHandle loop = MethodHandles.iteratedLoop(iterator, init, MethodHandles.empty(bo)); + MethodType lt = loop.type(); + if (it == null && in == null) { + assertEquals(bo.dropParameterTypes(0, 1), lt); + } else if (it == null) { + if (in.parameterCount() == 0) { + assertEquals(bo.dropParameterTypes(0, in.returnType() == void.class ? 1 : 2), lt); + } else { + assertEquals(methodType(bo.returnType(), in.parameterArray()), lt); + } + } else if (in == null) { + assertEquals(methodType(bo.returnType(), it.parameterArray()), lt); + } else if (it.parameterCount() > in.parameterCount()) { + assertEquals(methodType(bo.returnType(), it.parameterArray()), lt); + } else if (it.parameterCount() < in.parameterCount()) { + assertEquals(methodType(bo.returnType(), in.parameterArray()), lt); + } else { + // both it, in present; with equal parameter list lengths + assertEquals(it.parameterList(), lt.parameterList()); + assertEquals(in.parameterList(), lt.parameterList()); + assertEquals(bo.returnType(), lt.returnType()); + } + } + + @Test + public static void testIteratorSubclass() throws Throwable { + MethodHandle loop = MethodHandles.iteratedLoop(MethodHandles.empty(methodType(BogusIterator.class, List.class)), + null, MethodHandles.empty(methodType(void.class, String.class))); + assertEquals(methodType(void.class, List.class), loop.type()); + } + + static class BogusIterator implements Iterator { + @Override + public boolean hasNext() { + return false; + } + @Override + public Object next() { + return null; + } + } + static class Empty { static void f() { } static boolean pred() {
< prev index next >