alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (RicochetTest.java)

This example Java source code file (RicochetTest.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

byte_listers, class, int_listers, length, max, methodhandle, object, repeat, rfcb, stress, string, test, throwable, util, verbosity

The RicochetTest.java Java example source code

/*
 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 * 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.
 */

/* @test
 * @summary unit tests for recursive method handles
 * @run junit/othervm/timeout=3600 -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies -DRicochetTest.MAX_ARITY=10 test.java.lang.invoke.RicochetTest
 */
/*
 * @ignore The following test creates an unreasonable number of adapters in -Xcomp mode (7049122)
 * @run junit/othervm -DRicochetTest.MAX_ARITY=255 test.java.lang.invoke.RicochetTest
 */

package test.java.lang.invoke;

import java.lang.invoke.*;
import java.util.*;
import org.junit.*;
import static java.lang.invoke.MethodType.*;
import static java.lang.invoke.MethodHandles.*;
import static org.junit.Assert.*;


/**
 *
 * @author jrose
 */
public class RicochetTest {
    private static final Class<?> CLASS = RicochetTest.class;
    private static final int MAX_ARITY = Integer.getInteger(CLASS.getSimpleName()+".MAX_ARITY", 40);

    public static void main(String... av) throws Throwable {
        RicochetTest test = new RicochetTest();
        if (av.length > 0)  test.testOnly = Arrays.asList(av).toString();
        if (REPEAT == 1 || test.testOnly != null) {
            test.testAll();
            if (test.testOnlyTests == null)  throw new RuntimeException("no matching test: "+test.testOnly);
        } else if (REPEAT == 0) {
            org.junit.runner.JUnitCore.runClasses(RicochetTest.class);
        } else {
            verbose(1, "REPEAT="+REPEAT);
            for (int i = 0; i < REPEAT; i++) {
                test.testRepetition = (i+1);
                verbose(0, "[#"+test.testRepetition+"]");
                test.testAll();
            }
        }
    }
    int testRepetition;

    public void testAll() throws Throwable {
        testNull();
        testBoxInteger();
        testFilterReturnValue();
        testFilterObject();
        testBoxLong();
        testFilterInteger();
        testIntSpreads();
        testByteSpreads();
        testLongSpreads();
        testIntCollects();
        testReturns();
        testRecursion();
    }

    @Test
    public void testNull() throws Throwable {
        if (testRepetition > (1+REPEAT/100))  return;  // trivial test
        if (!startTest("testNull"))  return;
        assertEquals(opI(37), opI.invokeWithArguments(37));
        assertEqualFunction(opI, opI);
    }

    @Test
    public void testBoxInteger() throws Throwable {
        if (!startTest("testBoxInteger"))  return;
        assertEqualFunction(opI, opI.asType(opL_I.type()).asType(opI.type()));
    }

    @Test
    public void testFilterReturnValue() throws Throwable {
        if (!startTest("testFilterReturnValue"))  return;
        int[] ints = { 12, 23, 34, 45, 56, 67, 78, 89 };
        Object res = list8ints.invokeExact(ints[0], ints[1], ints[2], ints[3], ints[4], ints[5], ints[6], ints[7]);
        assertEquals(Arrays.toString(ints), res.toString());
        MethodHandle idreturn = filterReturnValue(list8ints, identity(Object.class));
        res = idreturn.invokeExact(ints[0], ints[1], ints[2], ints[3], ints[4], ints[5], ints[6], ints[7]);
        assertEquals(Arrays.toString(ints), res.toString());
        MethodHandle add0 = addL.bindTo(0);
        assertEqualFunction(filterReturnValue(opL2, add0), opL2);
    }

    @Test
    public void testFilterObject() throws Throwable {
        if (!startTest("testFilterObject"))  return;
        MethodHandle add0 = addL.bindTo(0);
        assertEqualFunction(sequence(opL2, add0), opL2);
        int bump13 = -13;  // value near 20 works as long as test values are near [-80..80]
        MethodHandle add13   = addL.bindTo(bump13);
        MethodHandle add13_0 = addL.bindTo(opI2(bump13, 0));
        MethodHandle add13_1 = addL.bindTo(opI2(0, bump13));
        assertEqualFunction(sequence(opL2, add13_0),
                            filterArguments(opL2, 0, add13));
        assertEqualFunction(sequence(opL2, add13_1),
                            filterArguments(opL2, 1, add13));
        System.out.println("[testFilterObject done]");
    }

    @Test
    public void testBoxLong() throws Throwable {
        if (!startTest("testBoxLong"))  return;
        assertEqualFunction(opJ, opJ.asType(opL_J.type()).asType(opJ.type()));
    }

    @Test
    public void testFilterInteger() throws Throwable {
        if (!startTest("testFilterInteger"))  return;
        assertEqualFunction(opI, sequence(convI_L, opL_I));
    }

    @Test
    public void testIntSpreads() throws Throwable {
        if (!startTest("testIntSpreads"))  return;
        MethodHandle id = identity(int[].class);
        final int MAX = MAX_ARITY-2;  // 253+1 would cause parameter overflow with 'this' added
        for (int nargs = 0; nargs <= MAX; nargs++) {
            if (nargs > 30 && nargs < MAX-20)  nargs += 10;
            int[] args = new int[nargs];
            for (int j = 0; j < args.length; j++)  args[j] = j + 11;
            //System.out.println("testIntSpreads "+Arrays.toString(args));
            int[] args1 = (int[]) id.invokeExact(args);
            assertArrayEquals(args, args1);
            MethodHandle coll = id.asCollector(int[].class, nargs);
            int[] args2 = args;
            switch (nargs) {
                case 0:  args2 = (int[]) coll.invokeExact(); break;
                case 1:  args2 = (int[]) coll.invokeExact(args[0]); break;
                case 2:  args2 = (int[]) coll.invokeExact(args[0], args[1]); break;
                case 3:  args2 = (int[]) coll.invokeExact(args[0], args[1], args[2]); break;
                case 4:  args2 = (int[]) coll.invokeExact(args[0], args[1], args[2], args[3]); break;
                case 5:  args2 = (int[]) coll.invokeExact(args[0], args[1], args[2], args[3], args[4]); break;
            }
            assertArrayEquals(args, args2);
            MethodHandle mh = coll.asSpreader(int[].class, nargs);
            int[] args3 = (int[]) mh.invokeExact(args);
            assertArrayEquals(args, args3);
        }
    }

    @Test
    public void testByteSpreads() throws Throwable {
        if (!startTest("testByteSpreads"))  return;
        MethodHandle id = identity(byte[].class);
        final int MAX = MAX_ARITY-2;  // 253+1 would cause parameter overflow with 'this' added
        for (int nargs = 0; nargs <= MAX; nargs++) {
            if (nargs > 30 && nargs < MAX-20)  nargs += 10;
            byte[] args = new byte[nargs];
            for (int j = 0; j < args.length; j++)  args[j] = (byte)(j + 11);
            //System.out.println("testByteSpreads "+Arrays.toString(args));
            byte[] args1 = (byte[]) id.invokeExact(args);
            assertArrayEquals(args, args1);
            MethodHandle coll = id.asCollector(byte[].class, nargs);
            byte[] args2 = args;
            switch (nargs) {
                case 0:  args2 = (byte[]) coll.invokeExact(); break;
                case 1:  args2 = (byte[]) coll.invokeExact(args[0]); break;
                case 2:  args2 = (byte[]) coll.invokeExact(args[0], args[1]); break;
                case 3:  args2 = (byte[]) coll.invokeExact(args[0], args[1], args[2]); break;
                case 4:  args2 = (byte[]) coll.invokeExact(args[0], args[1], args[2], args[3]); break;
                case 5:  args2 = (byte[]) coll.invokeExact(args[0], args[1], args[2], args[3], args[4]); break;
            }
            assertArrayEquals(args, args2);
            MethodHandle mh = coll.asSpreader(byte[].class, nargs);
            byte[] args3 = (byte[]) mh.invokeExact(args);
            assertArrayEquals(args, args3);
        }
    }

    @Test
    public void testLongSpreads() throws Throwable {
        if (!startTest("testLongSpreads"))  return;
        MethodHandle id = identity(long[].class);
        final int MAX = (MAX_ARITY - 2) / 2;  // 253/2+1 would cause parameter overflow with 'this' added
        for (int nargs = 0; nargs <= MAX; nargs++) {
            if (nargs > 30 && nargs < MAX-20)  nargs += 10;
            long[] args = new long[nargs];
            for (int j = 0; j < args.length; j++)  args[j] = (long)(j + 11);
            //System.out.println("testLongSpreads "+Arrays.toString(args));
            long[] args1 = (long[]) id.invokeExact(args);
            assertArrayEquals(args, args1);
            MethodHandle coll = id.asCollector(long[].class, nargs);
            long[] args2 = args;
            switch (nargs) {
                case 0:  args2 = (long[]) coll.invokeExact(); break;
                case 1:  args2 = (long[]) coll.invokeExact(args[0]); break;
                case 2:  args2 = (long[]) coll.invokeExact(args[0], args[1]); break;
                case 3:  args2 = (long[]) coll.invokeExact(args[0], args[1], args[2]); break;
                case 4:  args2 = (long[]) coll.invokeExact(args[0], args[1], args[2], args[3]); break;
                case 5:  args2 = (long[]) coll.invokeExact(args[0], args[1], args[2], args[3], args[4]); break;
            }
            assertArrayEquals(args, args2);
            MethodHandle mh = coll.asSpreader(long[].class, nargs);
            long[] args3 = (long[]) mh.invokeExact(args);
            assertArrayEquals(args, args3);
        }
    }

    @Test
    public void testIntCollects() throws Throwable {
        if (!startTest("testIntCollects"))  return;
        for (MethodHandle lister : INT_LISTERS) {
            int outputs = lister.type().parameterCount();
            for (int collects = 0; collects <= Math.min(outputs, INT_COLLECTORS.length-1); collects++) {
                int inputs = outputs - 1 + collects;
                if (inputs < 0)  continue;
                for (int pos = 0; pos + collects <= inputs; pos++) {
                    MethodHandle collector = INT_COLLECTORS[collects];
                    int[] args = new int[inputs];
                    int ap = 0, arg = 31;
                    for (int i = 0; i < pos; i++)
                        args[ap++] = arg++ + 0;
                    for (int i = 0; i < collects; i++)
                        args[ap++] = arg++ + 10;
                    while (ap < args.length)
                        args[ap++] = arg++ + 20;
                    // calculate piecemeal:
                    //System.out.println("testIntCollects "+Arrays.asList(lister, pos, collector)+" on "+Arrays.toString(args));
                    int[] collargs = Arrays.copyOfRange(args, pos, pos+collects);
                    int coll = (int) collector.asSpreader(int[].class, collargs.length).invokeExact(collargs);
                    int[] listargs = Arrays.copyOfRange(args, 0, outputs);
                    System.arraycopy(args, pos+collects, listargs, pos+1, outputs - (pos+1));
                    listargs[pos] = coll;
                    //System.out.println("  coll="+coll+" listargs="+Arrays.toString(listargs));
                    Object expect = lister.asSpreader(int[].class, listargs.length).invokeExact(listargs);
                    //System.out.println("  expect="+expect);

                    // now use the combined MH, and test the output:
                    MethodHandle mh = collectArguments(lister, pos, int[].class, INT_COLLECTORS[collects]);
                    if (mh == null)  continue;  // no infix collection, yet
                    assert(mh.type().parameterCount() == inputs);
                    Object observe = mh.asSpreader(int[].class, args.length).invokeExact(args);
                    assertEquals(expect, observe);
                }
            }
        }
    }

    @Test
    public void testByteCollects() throws Throwable {
        if (!startTest("testByteCollects"))  return;
        for (MethodHandle lister : BYTE_LISTERS) {
            int outputs = lister.type().parameterCount();
            for (int collects = 0; collects <= Math.min(outputs, BYTE_COLLECTORS.length-1); collects++) {
                int inputs = outputs - 1 + collects;
                if (inputs < 0)  continue;
                for (int pos = 0; pos + collects <= inputs; pos++) {
                    MethodHandle collector = BYTE_COLLECTORS[collects];
                    byte[] args = new byte[inputs];
                    int ap = 0, arg = 31;
                    for (int i = 0; i < pos; i++)
                        args[ap++] = (byte)(arg++ + 0);
                    for (int i = 0; i < collects; i++)
                        args[ap++] = (byte)(arg++ + 10);
                    while (ap < args.length)
                        args[ap++] = (byte)(arg++ + 20);
                    // calculate piecemeal:
                    //System.out.println("testIntCollects "+Arrays.asList(lister, pos, collector)+" on "+Arrays.toString(args));
                    byte[] collargs = Arrays.copyOfRange(args, pos, pos+collects);
                    byte coll = (byte) collector.asSpreader(byte[].class, collargs.length).invokeExact(collargs);
                    byte[] listargs = Arrays.copyOfRange(args, 0, outputs);
                    System.arraycopy(args, pos+collects, listargs, pos+1, outputs - (pos+1));
                    listargs[pos] = coll;
                    //System.out.println("  coll="+coll+" listargs="+Arrays.toString(listargs));
                    Object expect = lister.asSpreader(byte[].class, listargs.length).invokeExact(listargs);
                    //System.out.println("  expect="+expect);

                    // now use the combined MH, and test the output:
                    MethodHandle mh = collectArguments(lister, pos, byte[].class, BYTE_COLLECTORS[collects]);
                    if (mh == null)  continue;  // no infix collection, yet
                    assert(mh.type().parameterCount() == inputs);
                    Object observe = mh.asSpreader(byte[].class, args.length).invokeExact(args);
                    assertEquals(expect, observe);
                }
            }
        }
    }

    private static MethodHandle collectArguments(MethodHandle lister, int pos, Class<?> array, MethodHandle collector) {
        int collects = collector.type().parameterCount();
        int outputs = lister.type().parameterCount();
        if (pos == outputs - 1)
            return MethodHandles.filterArguments(lister, pos,
                        collector.asSpreader(array, collects))
                            .asCollector(array, collects);
        //return MethodHandles.collectArguments(lister, pos, collector); //no such animal
        return null;
    }

    private static final Class<?>[] RETURN_TYPES = {
        Object.class, String.class, Integer.class,
        int.class, long.class,
        boolean.class, byte.class, char.class, short.class,
        float.class, double.class,
        void.class,
    };

    @Test
    public void testReturns() throws Throwable {
        if (!startTest("testReturns"))  return;
        // fault injection:
        int faultCount = 0;  // total of 1296 tests
        faultCount = Integer.getInteger("testReturns.faultCount", 0);
        for (Class<?> ret : RETURN_TYPES) {
            // make a complicated identity function and pass something through it
            System.out.println(ret.getSimpleName());
            Class<?> vret = (ret == void.class) ? Void.class : ret;
            MethodHandle id = // (vret)->ret
                identity(vret).asType(methodType(ret, vret));
            final int LENGTH = 4;
            int[] index = {0};
            Object vals = java.lang.reflect.Array.newInstance(vret, LENGTH);
            MethodHandle indexGetter =  //()->int
                insertArguments(arrayElementGetter(index.getClass()), 0, index, 0);
            MethodHandle valSelector =  // (int)->vret
                arrayElementGetter(vals.getClass()).bindTo(vals);
            MethodHandle valGetter =  // ()->vret
                foldArguments(valSelector, indexGetter);
            if (ret != void.class) {
                for (int i = 0; i < LENGTH; i++) {
                    Object val = (i + 50);
                    if (ret == boolean.class)  val = (i % 3 == 0);
                    if (ret == String.class)   val = "#"+i;
                    if (ret == char.class)     val = (char)('a'+i);
                    if (ret == byte.class)     val = (byte)~i;
                    if (ret == short.class)    val = (short)(1< to) {
        for (int i = 0; i < mt.parameterCount(); i++) {
            if (mt.parameterType(i) == from)
                mt = mt.changeParameterType(i, to);
        }
        if (mt.returnType() == from)
            mt = mt.changeReturnType(to);
        return mt;
    }


    private static Object  convI_L(int     x) { stress(); return (Object)  x; }
    private static int     convL_I(Object  x) { stress(); return (int)     x; }
    private static Object  convJ_L(long    x) { stress(); return (Object)  x; }
    private static long    convL_J(Object  x) { stress(); return (long)    x; }
    private static int     convJ_I(long    x) { stress(); return (int)     x; }
    private static long    convI_J(int     x) { stress(); return (long)    x; }
    private static final MethodHandle convI_L, convL_I, convJ_L, convL_J, convJ_I, convI_J;
    static {
        convI_L = findStatic("convI_L", Object.class, int.class);
        convL_I = findStatic("convL_I", int.class, Object.class);
        convJ_L = findStatic("convJ_L", Object.class, long.class);
        convL_J = findStatic("convL_J", long.class, Object.class);
        convJ_I = findStatic("convJ_I", int.class, long.class);
        convI_J = findStatic("convI_J", long.class, int.class);
    }

    // stress modes:
    private static final int MAX_DEPTH = getProperty("MAX_DEPTH", 5);
    private static final int REPEAT = getProperty("REPEAT", 0);
    private static final int STRESS = getProperty("STRESS", 0);
    private static /*v*/ int STRESS_COUNT;
    private static final Object[] SINK = new Object[4];
    private static void stress() {
        if (STRESS <= 0) return;
        int count = STRESS + (STRESS_COUNT++ & 0x1);  // non-constant value
        for (int i = 0; i < count; i++) {
            SINK[i % SINK.length] = new Object[STRESS + i % (SINK.length + 1)];
        }
    }

    // verbosity:
    private static final int VERBOSITY = getProperty("VERBOSITY", 0) + (REPEAT == 0 ? 0 : -1);
    private static void verbose(Object a, Object b, Object c, Object d) {
        if (VERBOSITY <= 0)  return;
        verbose(1, a, b, c, d);
    }
    private static void verbose(Object a, Object b, Object c) {
        if (VERBOSITY <= 0)  return;
        verbose(1, a, b, c);
    }
    private static void verbose(int level, Object a, Object... bcd) {
        if (level > VERBOSITY)  return;
        String m = a.toString();
        if (bcd != null && bcd.length > 0) {
            List<Object> l = new ArrayList<>(bcd.length);
            for (Object x : bcd) {
                if (x instanceof Object[])  x = Arrays.asList((Object[])x);
                if (x instanceof int[])     x = Arrays.toString((int[])x);
                if (x instanceof long[])    x = Arrays.toString((long[])x);
                l.add(x);
            }
            m = m+Arrays.asList(bcd);
        }
        System.out.println(m);
    }
    String testOnly;
    String testOnlyTests;
    private boolean startTest(String name) {
        if (testOnly != null && !testOnly.contains(name))
            return false;
        verbose(0, "["+name+"]");
        testOnlyTests = (testOnlyTests == null) ? name : testOnlyTests+" "+name;
        return true;
    }

}

Other Java examples (source code examples)

Here is a short list of links related to this Java RicochetTest.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.