| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.ignite; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.Closeable; |
| import java.io.Externalizable; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.ObjectInputStream; |
| import java.io.ObjectOutputStream; |
| import java.io.ObjectStreamClass; |
| import java.io.Serializable; |
| import java.util.Arrays; |
| import org.apache.commons.io.IOUtils; |
| import org.apache.ignite.marshaller.Marshaller; |
| import org.jetbrains.annotations.Nullable; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| /** |
| * IO test utilities. |
| */ |
| public final class GridTestIoUtils { |
| /** |
| * Serializes a given object into byte array. |
| * |
| * @param obj Object to serialize. |
| * @return Byte array containing serialized object. |
| * @throws IOException If serialization failed. |
| */ |
| public static byte[] serializeJdk(Object obj) throws IOException { |
| ByteArrayOutputStream byteOut = null; |
| |
| ObjectOutputStream objOut = null; |
| |
| try { |
| // Allocate half of kilobyte to avoid very small resizings. |
| byteOut = new ByteArrayOutputStream(512); |
| |
| objOut = new ObjectOutputStream(byteOut); |
| |
| // Make sure that we serialize only task, without |
| // class loader. |
| objOut.writeObject(obj); |
| |
| objOut.flush(); |
| |
| return byteOut.toByteArray(); |
| } |
| finally { |
| close(objOut); |
| close(byteOut); |
| } |
| } |
| |
| /** |
| * Deserializes passed in bytes using provided class loader. |
| * |
| * @param <T> Type of result object. |
| * @param bytes Object bytes to deserialize. |
| * @return Deserialized object. |
| * @throws IOException If deserialization failed. |
| * @throws ClassNotFoundException If deserialization failed. |
| */ |
| public static <T extends Serializable> T deserializeJdk(byte[] bytes) throws IOException, ClassNotFoundException { |
| ObjectInputStream in = null; |
| |
| try { |
| in = new ObjectInputStream(new ByteArrayInputStream(bytes)); |
| |
| return (T)in.readObject(); |
| } |
| finally { |
| close(in); |
| } |
| } |
| |
| /** |
| * Deserializes passed in bytes using provided class loader. |
| * |
| * @param <T> Type of result object. |
| * @param bytes Object bytes to deserialize. |
| * @param clsLdr Class loader. |
| * @return Deserialized object. |
| * @throws IOException If deserialization failed. |
| * @throws ClassNotFoundException If deserialization failed. |
| */ |
| public static <T> T deserializeJdk(byte[] bytes, final ClassLoader clsLdr) |
| throws IOException, ClassNotFoundException { |
| ObjectInputStream in = null; |
| |
| try { |
| in = new ObjectInputStream(new ByteArrayInputStream(bytes)) { |
| @Override protected Class<?> resolveClass(ObjectStreamClass desc) throws ClassNotFoundException { |
| return clsLdr.loadClass(desc.getName()); |
| } |
| }; |
| |
| return (T)in.readObject(); |
| } |
| finally { |
| close(in); |
| } |
| } |
| |
| /** |
| * @param <T> Type of result object. |
| * @param obj Object to marshal/unmarshal. |
| * @param marshaller Marshaller to use for serialization. |
| * @return The same object, but passed through marshaller: obj->marshal->buf->unmarshal->copy. |
| * @throws Exception If failed. |
| */ |
| public static <T> T externalize(Externalizable obj, Marshaller marshaller) throws Exception { |
| assert marshaller != null; |
| |
| byte[] buf = marshaller.marshal(obj); |
| |
| // Sleep to make sure that clock advances (necessary for some tests) |
| Thread.sleep(10); |
| |
| return (T)marshaller.unmarshal(buf, obj.getClass().getClassLoader()); |
| } |
| |
| /** |
| * Validate streams generate the same output. |
| * |
| * @param expIn Expected input stream. |
| * @param actIn Actual input stream. |
| * @param expSize Expected size of the streams. |
| * @throws IOException In case of any IO exception. |
| */ |
| public static void assertEqualStreams(InputStream expIn, InputStream actIn, |
| @Nullable Long expSize) throws IOException { |
| int bufSize = 2345; |
| byte buf1[] = new byte[bufSize]; |
| byte buf2[] = new byte[bufSize]; |
| long pos = 0; |
| |
| while (true) { |
| int i1 = actIn.read(buf1, 0, bufSize); |
| |
| int i2; |
| |
| if (i1 == -1) // Expects EOF? |
| i2 = expIn.read(buf2, 0, 1); // Try to read at least 1 byte guaranted by stream's API. |
| else |
| IOUtils.readFully(expIn, buf2, 0, i2 = i1); // Read the same bytes count as from actual stream. |
| |
| if (i1 != i2) |
| fail("Expects the same data [pos=" + pos + ", i1=" + i1 + ", i2=" + i2 + ']'); |
| |
| if (i1 == -1) |
| break; // EOF |
| |
| // i1 == bufSize => compare buffers. |
| // i1 < bufSize => Compare part of buffers, rest of buffers are equal from previous iteration. |
| assertTrue("Expects the same data [pos=" + pos + ", i1=" + i1 + ", i2=" + i2 + ']', |
| Arrays.equals(buf1, buf2)); |
| |
| pos += i1; |
| } |
| |
| if (expSize != null) |
| assertEquals(expSize.longValue(), pos); |
| } |
| |
| /** |
| * Gets short value from byte array assuming that value stored in little-endian byte order. |
| * |
| * @param arr Byte array. |
| */ |
| public static short getShortByByteLE(byte[] arr) { |
| return getShortByByteLE(arr, 0); |
| } |
| |
| /** |
| * Gets short value from byte array assuming that value stored in little-endian byte order. |
| * |
| * @param arr Byte array. |
| * @param off Offset. |
| */ |
| public static short getShortByByteLE(byte[] arr, int off) { |
| return (short)((arr[off] & 0xff) | arr[off + 1] << 8); |
| } |
| |
| /** |
| * Gets char value from byte array assuming that value stored in little-endian byte order. |
| * |
| * @param arr Byte array. |
| */ |
| public static char getCharByByteLE(byte[] arr) { |
| return getCharByByteLE(arr, 0); |
| } |
| |
| /** |
| * Gets char value from byte array assuming that value stored in little-endian byte order. |
| * |
| * @param arr Byte array. |
| * @param off Offset. |
| */ |
| public static char getCharByByteLE(byte[] arr, int off) { |
| return (char)((arr[off] & 0xff) | arr[off + 1] << 8); |
| } |
| |
| /** |
| * Gets integer value from byte array assuming that value stored in little-endian byte order. |
| * |
| * @param arr Byte array. |
| */ |
| public static int getIntByByteLE(byte[] arr) { |
| return getIntByByteLE(arr, 0); |
| } |
| |
| /** |
| * Gets integer value from byte array assuming that value stored in little-endian byte order. |
| * |
| * @param arr Byte array. |
| * @param off Offset. |
| */ |
| public static int getIntByByteLE(byte[] arr, int off) { |
| return ((int)arr[off] & 0xff) | ((int)arr[off + 1] & 0xff) << 8 | |
| ((int)arr[off + 2] & 0xff) << 16 | ((int)arr[off + 3] & 0xff) << 24; |
| } |
| |
| /** |
| * Gets long value from byte array assuming that value stored in little-endian byte order. |
| * |
| * @param arr Byte array. |
| */ |
| public static long getLongByByteLE(byte[] arr) { |
| return getLongByByteLE(arr, 0); |
| } |
| |
| /** |
| * Gets long value from byte array assuming that value stored in little-endian byte order. |
| * |
| * @param arr Byte array. |
| * @param off Offset. |
| */ |
| public static long getLongByByteLE(byte[] arr, int off) { |
| return ((long)arr[off] & 0xff) | ((long)arr[off + 1] & 0xff) << 8 | ((long)arr[off + 2] & 0xff) << 16 | |
| ((long)arr[off + 3] & 0xff) << 24 | ((long)arr[off + 4] & 0xff) << 32 | ((long)arr[off + 5] & 0xff) << 40 | |
| ((long)arr[off + 6] & 0xff) << 48 | ((long)arr[off + 7] & 0xff) << 56; |
| } |
| |
| /** |
| * Gets float value from byte array assuming that value stored in little-endian byte order. |
| * |
| * @param arr Byte array. |
| */ |
| public static float getFloatByByteLE(byte[] arr) { |
| return getFloatByByteLE(arr, 0); |
| } |
| |
| /** |
| * Gets float value from byte array assuming that value stored in little-endian byte order. |
| * |
| * @param arr Byte array. |
| * @param off Offset. |
| */ |
| public static float getFloatByByteLE(byte[] arr, int off) { |
| return Float.intBitsToFloat(getIntByByteLE(arr, off)); |
| } |
| |
| /** |
| * Gets double value from byte array assuming that value stored in little-endian byte order. |
| * |
| * @param arr Byte array. |
| */ |
| public static double getDoubleByByteLE(byte[] arr) { |
| return getDoubleByByteLE(arr, 0); |
| } |
| |
| /** |
| * Gets double value from byte array assuming that value stored in little-endian byte order. |
| * |
| * @param arr Byte array. |
| * @param off Offset. |
| */ |
| public static double getDoubleByByteLE(byte[] arr, int off) { |
| return Double.longBitsToDouble(getLongByByteLE(arr, off)); |
| } |
| |
| /** |
| * Closes resource. |
| * |
| * @param c Resource |
| * @throws IOException If failed to close resource. |
| */ |
| private static void close(Closeable c) throws IOException { |
| if (c != null) |
| c.close(); |
| } |
| |
| /** |
| * Ensure singleton. |
| */ |
| private GridTestIoUtils() { |
| // No-op. |
| } |
| } |