All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tests.java.org.python.core.ByteBufferTestSupport Maven / Gradle / Ivy

Go to download

Jython is an implementation of the high-level, dynamic, object-oriented language Python written in 100% Pure Java, and seamlessly integrated with the Java platform. It thus allows you to run Python on any Java platform.

There is a newer version: 2.7.4
Show newest version
package org.python.core;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;

import java.nio.ByteBuffer;
import java.util.Arrays;

/**
 * Common apparatus for tests involving byte[] and java.nio.ByteBuffer
 * material, in particular the tests of {@link PyBuffer} implementations. A test case that extends
 * this class will be equipped with additional assertion methods and a class to represent
 * byte[] test material in several forms.
 */
public class ByteBufferTestSupport {

    /**
     * Class to hold test material representing the same sequence of values 0..255 in several
     * different ways.
     */
    protected static class ByteMaterial {

        /** Length in bytes (length of every array in this material). */
        final int length;
        /** The byte values. */
        byte[] bytes;
        /** The byte values individually as ints. */
        int[] ints;
        /** The byte values treated as characters (unicode < 256). */
        String string;

        /** Construct from int array. */
        public ByteMaterial(int[] a) {
            ints = a.clone();
            length = replicate();
        }

        /** Construct from String. */
        public ByteMaterial(String s) {
            ints = new int[s.length()];
            for (int i = 0; i < ints.length; i++) {
                ints[i] = 0xff & s.charAt(i);
            }
            length = replicate();
        }

        /** Construct from byte array. */
        public ByteMaterial(byte[] b) {
            ints = new int[b.length];
            for (int i = 0; i < ints.length; i++) {
                ints[i] = 0xff & b[i];
            }
            length = replicate();
        }

        /** Construct from pattern on values (used modulo 256). */
        public ByteMaterial(int start, int count, int inc) {
            ints = new int[count];
            int x = start;
            for (int i = 0; i < count; i++) {
                ints[i] = x;
                x = (x + inc) & 0xff;
            }
            length = replicate();
        }

        /**
         * Once the integer value array {@link #ints} has been initialised, fill the others from it.
         *
         * @return length of (all) arrays in units
         */
        private int replicate() {
            int n = ints.length;
            bytes = new byte[n];
            StringBuilder sb = new StringBuilder(n);

            for (int i = 0; i < n; i++) {
                int x = ints[i];
                bytes[i] = (byte)x;
                sb.appendCodePoint(x);
            }
            string = sb.toString();
            return n;
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder(100);
            sb.append("byte[").append(length).append("]={ ");
            for (int i = 0; i < length; i++) {
                if (i > 0) {
                    sb.append(", ");
                }
                if (i >= 5) {
                    sb.append(" ...");
                    break;
                } else {
                    sb.append(ints[i]);
                }
            }
            sb.append(" }");
            return sb.toString();
        }

        /**
         * @return a copy of the bytes array (that the client is allowed to modify)
         */
        byte[] getBytes() {
            return bytes.clone();
        }

        /**
         * @return a buffer on a copy of the bytes array (that the client is allowed to modify)
         */
        ByteBuffer getBuffer() {
            return ByteBuffer.wrap(getBytes());
        }

        /**
         * Create material equivalent to a slice of this material. This may act as a reference
         * result for testing slice operations.
         *
         * @param start first byte-index to include
         * @param length number of items
         * @param stride between byte-indices
         * @return ByteMaterial in which the arrays are a slice of this one
         */
        ByteMaterial slice(int start, int length, int stride) {
            return new ByteMaterial(sliceBytes(bytes, 1, start, length, stride));
        }

        /**
         * Create material equivalent to a slice of this material. This may act as a reference
         * result for testing slice operations.
         *
         * @param start first byte-index to include
         * @param itemsize number of consecutive bytes treated as one item
         * @param length number of items
         * @param stride between byte-indices
         * @return ByteMaterial in which the arrays are a slice of this one
         */
        ByteMaterial slice(int itemsize, int start, int length, int stride) {
            return new ByteMaterial(sliceBytes(bytes, itemsize, start, length, stride));
        }
    }

    /**
     * Create a byte array that is a strided copy of the one passed in. The specifications are
     * assumed correct for the size of that array.
     *
     * @param b source array
     * @param start first index to include
     * @param length number of indices
     * @param stride between indices
     * @return slice of b
     */
    protected static byte[] sliceBytes(byte[] b, int start, int length, int stride) {
        return sliceBytes(b, 1, start, length, stride);
    }

    /**
     * Create a multi-byte item array that is a strided copy of the one passed in. The
     * specifications are assumed correct for the size of that array.
     *
     * @param b source array
     * @param itemsize number of consecutive bytes treated as one item
     * @param start first byte-index to include
     * @param length number of indices to visit (items to copy)
     * @param stride between byte-indices
     * @return slice of b
     */
    protected static byte[] sliceBytes(byte[] b, int itemsize, int start, int length, int stride) {
        byte[] a = new byte[length];
        for (int i = 0, j = start; i < length; i++, j += stride) {
            for (int k = 0; k < itemsize; k++) {
                a[i + k] = b[j + k];
            }
        }
        return a;
    }

    /**
     * Custom assert method comparing the bytes in an NIO {@link ByteBuffer} to those in a byte
     * array, when that ByteBuffer is obtained from a contiguous PyBuffer.
     * Let bb[i] denote bb.get(bb.position()+i), by analogy with a C
     * pointer. It is required that bb[k] == expected[k], for every index
     * k in expected. If not, a fail() is declared.
     *
     * @param message to issue on failure
     * @param expected expected byte array
     * @param bb result to test
     */
    static void assertBytesEqual(String message, byte[] expected, ByteBuffer bb) {
        // Use the position-advancing buffer get()
        byte[] actual = new byte[expected.length];
        bb.get(actual);
        assertBytesEqual(message, expected, actual);
    }

    /**
     * Custom assert method comparing the bytes in an NIO {@link ByteBuffer} to those in a byte
     * array, when that ByteBuffer is obtained from a striding PyBuffer.
     * Let bb[i] denote bb.get(bb.position()+i), by analogy with a C
     * pointer. It is required that bb[k*stride] == expected[k], for every index
     * k in expected. If not, a fail() is declared.
     *
     * @param message to issue on failure
     * @param expected expected byte array
     * @param bb result to test
     * @param stride in the buffer bb
     */
    static void assertBytesEqual(String message, byte[] expected, ByteBuffer bb, int stride) {
        assertBytesEqual(message, expected, 0, expected.length, bb, stride);
    }

    /**
     * Custom assert method comparing the bytes in an NIO {@link ByteBuffer} to those in a byte
     * array, when that ByteBuffer is obtained from a striding PyBuffer.
     * Let bb[i] denote bb.get(bb.position()+i), by analogy with a C
     * pointer. It is required that bb[k*stride] == expected[expectedStart+k], for
     * k=0 to n-1. If not, a fail() is declared.
     *
     * @param message to issue on failure
     * @param expected expected byte array
     * @param expectedStart where to start the comparison in expected
     * @param n number of bytes to test
     * @param bb result to test
     * @param stride in the buffer bb
     */
    static void assertBytesEqual(String message, byte[] expected, int expectedStart, int n,
            ByteBuffer bb, int stride) {
        // Note that this approach leaves the buffer position unmodified
        int p = bb.position();
        byte[] actual = new byte[n];
        for (int k = 0; k < n; k++, p += stride) {
            actual[k] = bb.get(p);
        }
        assertBytesEqual(message, expected, expectedStart, n, actual, 0);
    }

    /**
     * Custom assert method comparing byte arrays: values in actual[] must match all
     * those in expected[], and they must be the same length.
     *
     * @param message to issue on failure
     * @param expected expected byte array
     * @param actual result to test
     */
    static void assertBytesEqual(String message, byte[] expected, byte[] actual) {
        assertEquals(message + " (array size)", expected.length, actual.length);
        assertBytesEqual(message, expected, 0, expected.length, actual, 0, 1);
    }

    /**
     * Custom assert method comparing byte arrays. It is required that
     * actual[k] == expected[k], for k=0 to expected.length-1
     * . If not, a fail() is declared.
     *
     * @param message to issue on failure
     * @param expected expected byte array
     * @param actual result to test
     * @param actualStart where to start the comparison in actual
     */
    static void assertBytesEqual(String message, byte[] expected, byte[] actual, int actualStart) {
        assertBytesEqual(message, expected, 0, expected.length, actual, actualStart, 1);
    }

    /**
     * Custom assert method comparing byte arrays. It is required that
     * actual[actualStart+k] == expected[expectedStart+k], for k=0 to
     * n-1. If not, a fail() is declared.
     *
     * @param message to issue on failure
     * @param expected expected byte array
     * @param expectedStart where to start the comparison in expected
     * @param n number of bytes to test
     * @param actual result to test
     * @param actualStart where to start the comparison in actual
     */
    protected static void assertBytesEqual(String message, byte[] expected, int expectedStart,
            int n, byte[] actual, int actualStart) {
        assertBytesEqual(message, expected, expectedStart, n, actual, actualStart, 1);
    }

    /**
     * Custom assert method comparing byte arrays. It is required that
     * actual[actualStart+k*stride] == expected[expectedStart+k], for k=0
     * to n-1. If not, a fail() is declared.
     *
     * @param message to issue on failure
     * @param expected expected byte array
     * @param expectedStart where to start the comparison in expected
     * @param n number of bytes to test
     * @param actual result to test
     * @param actualStart where to start the comparison in actual
     * @param stride spacing of bytes in actual array
     */
    static void assertBytesEqual(String message, byte[] expected, int expectedStart, int n,
            byte[] actual, int actualStart, int stride) {

        if (actualStart < 0) {
            fail(message + " (start<0 in result)");

        } else if (expectedStart < 0) {
            fail(message + " (start<0 in expected result): bug in test?");

        } else if (actualStart + (n - 1) * stride + 1 > actual.length) {
            fail(message + " (result too short)");

        } else if (expectedStart + n > expected.length) {
            fail(message + " (expected result too short): bug in test?");

        } else {
            // Should be safe to compare the values
            int i = actualStart, j, jLimit = expectedStart + n;
            for (j = expectedStart; j < jLimit; j++) {
                if (actual[i] != expected[j]) {
                    break;
                }
                i += stride;
            }

            // If we stopped early, diagnose the problem
            if (j < jLimit) {
                byte[] a = Arrays.copyOfRange(actual, actualStart, actualStart + n);
                byte[] e = Arrays.copyOfRange(expected, expectedStart, expectedStart + n);
                System.out.println("  expected:" + Arrays.toString(e));
                System.out.println("    actual:" + Arrays.toString(a));
                System.out.println("  _actual_:" + Arrays.toString(actual));
                fail(message + " (byte at " + j + ")");
            }
        }
    }

    /**
     * Customised assert method comparing a int arrays: values in the actual value starting at
     * actual[offset] must match all those in expected[], and there must be enough of them.
     *
     * @param message to issue on failure
     * @param expected expected array
     * @param actual result to test
     * @param offset where to start the comparison in actual
     */
    static void assertIntsEqual(String message, int[] expected, int[] actual, int offset) {
        int n = expected.length;
        if (offset < 0) {
            fail(message + " (offset<0)");
        } else if (offset + n > actual.length) {
            fail(message + " (too short)");
        } else {
            // Should be safe to compare the values
            int i = offset, j;
            for (j = 0; j < n; j++) {
                if (actual[i++] != expected[j]) {
                    break;
                }
            }
            if (j < n) {
                System.out.println("  expected:" + Arrays.toString(expected));
                System.out.println("    actual:" + Arrays.toString(actual));
                fail(message + " (int at " + j + ")");
            }
        }
    }

    /**
     * Customised assert method comparing a int arrays: int in the actual value must match all those
     * in expected[], and there must be the same number of them.
     *
     * @param message to issue on failure
     * @param expected expected array
     * @param actual result to test
     */
    protected static void assertIntsEqual(String message, int[] expected, int[] actual) {
        int n = expected.length;
        assertEquals(message, n, actual.length);
        // Should be safe to compare the values
        int j;
        for (j = 0; j < n; j++) {
            if (actual[j] != expected[j]) {
                break;
            }
        }
        if (j < n) {
            System.out.println("  expected:" + Arrays.toString(expected));
            System.out.println("    actual:" + Arrays.toString(actual));
            fail(message + " (int at " + j + ")");
        }
    }

    /**
     * Method comparing byte arrays after a read (or view creation) operation involving a slice.
     * 

* The invariant asserted must be explained carefully because of its generality. Suppose there * to be three arrays of bytes a, b and c. Let a represent the state * of some byte storage of length L before an operation. Let b represent the state * of the same storage after an operation. Let c be related as follows. *

* c is the result, representing n blocks of u bytes copied from the * storage, the kth block starting at position s+kp in the storage and at * t+ku in c. c is of length M≥nu, and we assume * 0≤s+kp<L. After a read operation, it is required that: *

    *
  1. c[t+iu+j] = b[s+ip+j] for 0≤i<n and 0≤j<u, and
  2. *
  3. a[k] = b[k] for 0≤k<L. *
*

* * @param a storage state before the operation (typically reference data) * @param b storage state after the operation (typically from object under test) * @param c bytes read * @param t index in c of the start byte of item 0 * @param n number of items * @param u number of consecutive bytes per item * @param s index in b of the start byte of item 0 * @param p the distance in b between the start bytes of successive items */ static void checkReadCorrect(byte[] a, byte[] b, byte[] c, int t, int n, int u, int s, int p) { // Check the b is the same as a assertEquals("Storage size differs from reference", a.length, b.length); for (int k = 0; k < b.length; k++) { if (a[k] != b[k]) { fail("Stored data changed during read"); } } // Check slice read out checkEqualInSlice(b, c, t, n, u, s, p); } /** * Method comparing byte arrays where a change operation has taken place involving a slice. *

* The invariant asserted must be explained carefully because of its generality. Suppose there * to be three arrays of bytes a, b and c. Let a represent the state * of some byte storage of length L before an operation. Let b represent the state * of the same storage after an operation. Let c be related as follows. *

* c is the source, contaning at index t, n blocks of u bytes copied * to the storage. As before, the kth block starts at position s+kp in the storage * and at t+ku in c. c is of length M≥t+nu, and we assume * 0≤s+kp<L. After a write operation, it is required that: *

    *
  1. c[t+iu+j] = b[s+ip+j] for 0≤i<n and 0≤j<u, and
  2. *
  3. a[k] = b[k] for 0≤k<L and k≠s+ip+j for any choice of * and j where 0≤i<n and 0≤j<u. *
* Note that the first of these is the same as for a read and the second requires equality * "everywhere else". * * @param a storage state before the operation (typically reference data) * @param b storage state after the operation (typically from object under test) * @param c bytes written * @param t index in c of the start byte of item 0 * @param n number of items * @param u number of consecutive bytes per item * @param s index in b of the start byte of item 0 * @param p the distance in b between the start bytes of successive items */ static void checkWriteCorrect(byte[] a, byte[] b, byte[] c, int t, int n, int u, int s, int p) { assertEquals("Stored size has changed", a.length, b.length); checkEqualInSlice(b, c, t, n, u, s, p); checkUnchangedElsewhere(a, b, n, u, s, p); } /** * Method comparing bytes in a slice pattern of one byte array to bytes taken consecutively in * another array. This is needed in testing when bytes have been copied into or out of an array * slice. *

* Let b represent the state of the byte storage of length L after the copy * operation (the sliced array). Let c be a source or destination array, a section of * which at index t represents n blocks of u bytes copied to or from the * storage. c is of length at least t+nu. The kth block starts at position * s+kp in the storage b and at t+ku in c, and we assume * 0≤s+kp<L. After a write operation, it is required that: c[t+iu+j] = * b[s+ip+j] for 0≤i<n and 0≤j<u. * * * @param b storage state after the operation (typically from object under test) * @param c bytes written * @param t index in c of the start byte of item 0 * @param n number of items * @param u number of consecutive bytes per item * @param s index in b of the start byte of item 0 * @param p the distance in b between the start bytes of successive items */ static void checkEqualInSlice(byte[] b, byte[] c, int t, int n, int u, int s, int p) { // Check correct use of the test checkSliceArgs(b, c, t, n, u, s, p); // Check the data in copied units (and p-u bytes following) for (int i = 0; i < n; i++) { int ci = t + i * u, bi = s + i * p; for (int j = 0; j < u; j++, bi++, ci++) { // Compare corresponding bytes of this unit in c and b if (c[ci] != b[bi]) { fail(String.format("contiguous data at %d not equal to buffer at %d", ci, bi)); } } } } /** * Method comparing the before and after state of the parts of a byte array that should be * untouched where a change operation has taken place involving a slice. *

* Let a represent the state of some byte storage of length L before an operation. * Let b represent the state of the same storage after an operation. After a write * operation, it is required that: a[k] = b[k] for 0≤k<L and * k≠s+ip+j for any choice of and j where 0≤i<n and * 0≤j<u. *

* Note that requires equality "everywhere else" than in the slice defined by n units of * size u starting at s. * * @param a storage state before the operation (typically reference data) * @param b storage state after the operation (typically from object under test) * @param n number of items * @param u number of consecutive bytes per item * @param s index in b of the start byte of item 0 * @param p the distance in b between the start bytes of successive items */ static void checkUnchangedElsewhere(byte[] a, byte[] b, int n, int u, int s, int p) { // Check correct use of the test assertEquals("Stored size has changed", a.length, b.length); assertFalse("Unit size exceeds spacing", u > p && u + p > 0); String bufferChangedAt = "buffer changed at %d (outside slice)"; int absp, low, high; if (n < 1) { // No elements: check whole array. absp = low = high = 0; } else if (p >= 0) { // Stride is forwards in the range (easy case) absp = p; // Lowest byte index in the data is byte 0 of first unit in slice low = s; // One after highest byte index is just beyond last byte of last unit in slice high = s + (n - 1) * p + u; } else { // p<0: stride is backwards in the range (delicate case) absp = -p; // Lowest byte index in the data is byte 0 of last unit in slice low = s + (n - 1) * p; // One after highest byte index is just beyond last byte of first unit in slice high = s + u; } // Visit each copied unit (from low to high byte index) except the highest. for (int i = 0; i < n - 1; i++) { int bi = low + i * absp + u; // Check there was no change to the absp-u bytes following unit in b for (int j = u; j < absp; j++, bi++) { if (b[bi] != a[bi]) { fail(String.format(bufferChangedAt, bi)); } } } // Check that b[0:low] is unchanged for (int k = 0; k < low; k++) { if (b[k] != a[k]) { fail(String.format(bufferChangedAt, k)); } } // Check that [high:] is unchanged for (int k = Math.max(high, 0); k < b.length; k++) { if (b[k] != a[k]) { fail(String.format(bufferChangedAt, k)); } } } /** Common code for checkReadCorrect and checkWriteCorrect. */ private static void checkSliceArgs(byte[] b, byte[] c, int t, int n, int u, int s, int p) { // Check correct use of the test assertFalse("Slice data less than n units", c.length < t + n * u); assertFalse("Slice data exceeds destination", n * u > b.length); assertFalse("Unit size exceeds spacing", u > p && u + p > 0); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy