/* * Copyright (c) 2012 Diamond Light Source Ltd. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package uk.ac.diamond.scisoft.analysis.io; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.util.Arrays; import org.eclipse.january.dataset.Dataset; import org.eclipse.january.dataset.DatasetFactory; import org.eclipse.january.dataset.FloatDataset; import org.eclipse.january.dataset.Random; import org.junit.Test; /** * Test IO utils * */ public class UtilsTest { static int answer = 0xdeadbeef; static int sLeAnswer = 0xbeef; static int sBeAnswer = 0xdead; static byte[] leAnswer = {(byte) 0xef, (byte) 0xbe, (byte) 0xad, (byte) 0xde}; static byte[] beAnswer = {(byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef}; /** * */ @Test public void testLeInt() { int attempt = Utils.leInt(0xef, 0xbe, 0xad, 0xde); assertEquals(answer, attempt); } /** * */ @Test public void testBeInt() { int attempt = Utils.beInt(0xde, 0xad, 0xbe, 0xef); assertEquals(answer, attempt); } /** * */ @Test public void testLeIntSigns() { int attempt = Utils.leIntSE(255, -1); assertEquals(-1, attempt, 1e-8); attempt = Utils.leInt(255, -1); assertEquals(256*255+255, attempt); } /** * */ @Test public void testReadLeInt() throws Exception { ByteArrayInputStream is = new ByteArrayInputStream(leAnswer); int attempt = Utils.readLeInt(is); assertEquals(answer, attempt); } /** * */ @Test public void testReadBeInt() throws Exception { ByteArrayInputStream is = new ByteArrayInputStream(beAnswer); int attempt = Utils.readBeInt(is); assertEquals(answer, attempt); } /** * */ @Test public void testReadLeShort() throws Exception { ByteArrayInputStream is = new ByteArrayInputStream(leAnswer); int attempt = Utils.readLeShort(is); assertEquals(sLeAnswer, attempt); } /** * */ @Test public void testReadBeShort() throws Exception { ByteArrayInputStream is = new ByteArrayInputStream(beAnswer); int attempt = Utils.readBeShort(is); assertEquals(sBeAnswer, attempt); } /** * */ @Test public void testWriteLeInt() throws Exception { ByteArrayOutputStream os = new ByteArrayOutputStream(); Utils.writeLeInt(os, answer); byte[] attempt = os.toByteArray(); assertArrayEquals(leAnswer, attempt); } /** * */ @Test public void testWriteBeInt() throws Exception { ByteArrayOutputStream os = new ByteArrayOutputStream(); Utils.writeBeInt(os, answer); byte[] attempt = os.toByteArray(); assertArrayEquals(beAnswer, attempt); } @Test public void testReadFloat() throws Exception { ByteBuffer bb = ByteBuffer.allocate(16).order(ByteOrder.BIG_ENDIAN); FloatBuffer fb = bb.asFloatBuffer(); float[] answer = new float[] {0, 1, -2, -3}; fb.put(answer); FloatDataset fd = DatasetFactory.zeros(FloatDataset.class, 4); ByteArrayInputStream is = new ByteArrayInputStream(bb.array()); Utils.readBeFloat(is, fd, 0); is.close(); assertArrayEquals(answer, fd.getData(), 1f-8); bb = ByteBuffer.allocate(16).order(ByteOrder.LITTLE_ENDIAN); fb = bb.asFloatBuffer(); fb.put(answer); is = new ByteArrayInputStream(bb.array()); Utils.readLeFloat(is, fd, 0); is.close(); assertArrayEquals(answer, fd.getData(), 1f-8); } @Test public void testParsing() { // check checkNumber("9223372036854775807", 9223372036854775807L); checkNumber("-9223372036854775808", -9223372036854775808L); checkNumber("4000000001", 4000000001L); checkNumber("-4000000001", -4000000001L); checkNumber("2147483648", 2147483648L); checkNumber("-2147483649", -2147483649L); checkNumber("2147483647", 2147483647); checkNumber("-2147483648", -2147483648); checkNumber("4000001", 4000001); checkNumber("-4000001", -4000001); checkNumber("32768", 32768); checkNumber("-32769", -32769); checkNumber("32767", (short) 32767); checkNumber("-32768", (short) -32768); checkNumber("4001", (short) 4001); checkNumber("-4001", (short) -4001); checkNumber("128", (short) 128); checkNumber("-129", (short) -129); checkNumber("127", (byte) 127); checkNumber("-128", (byte) -128); checkNumber("40", (byte) 40); checkNumber("-40", (byte) -40); checkNumber("9223372036854775808", 9223372036854775808.); checkNumber("-9223372036854775809", -9223372036854775809.); checkNumber("101.1", 101.1); checkNumber("-101.1", -101.1); checkNumber("301.1e16", 301.1e16); checkNumber("-301.1e16", -301.1e16); checkNumber("301.1e-16", 301.1e-16); checkNumber("-301.1e-16", -301.1e-16); String bis; BigInteger bi; bis = "123456789012345678901"; bi = new BigInteger(bis); double x = bi.doubleValue(); assertEquals("Double", bi.doubleValue(), Utils.parseValue(bis).doubleValue(), Math.abs(x)*1e-14); bis = "-123456789012345678901"; bi = new BigInteger(bis); x = bi.doubleValue(); assertEquals("Double", bi.doubleValue(), Utils.parseValue(bis).doubleValue(), Math.abs(x)*1e-14); } private void checkNumber(String text, Number value) { Number n = Utils.parseValue(text); if (value instanceof Long) { assertTrue("Long", n instanceof Long); long l = (Long) value; assertEquals("Long", l, n.longValue()); } else if (value instanceof Integer) { assertTrue("Integer", n instanceof Integer); int i = (Integer) value; assertEquals("Integer", i, n.intValue()); } else if (value instanceof Short) { assertTrue("Short", n instanceof Short); short s = (Short) value; assertEquals("Short", s, n.shortValue()); } else if (value instanceof Byte) { assertTrue("Byte", n instanceof Byte); byte b = (Byte) value; assertEquals("Byte", b, n.byteValue()); } else if (value instanceof Double) { assertTrue("Double", n instanceof Double); double d = (Double) value; assertEquals("Double", d, n.doubleValue(), 1e-14*Math.abs(d)); } } @Test public void testParsingTiming() { Dataset a; Random.seed(12371); int LENGTH = 10240; a = Random.randint(-2000000000, 2000000000, new int[] {LENGTH}); String[] intText = new String[LENGTH]; for (int i = 0; i < LENGTH; i++) { intText[i] = a.getString(i); } assertEquals("Int", a.getInt(LENGTH/2), Utils.parseValue(intText[LENGTH/2]).intValue()); a = Random.randint(-60000, 60000, new int[] {LENGTH}); String[] shortText = new String[LENGTH]; for (int i = 0; i < LENGTH; i++) { shortText[i] = a.getString(i); } assertEquals("Short", a.getShort(LENGTH/2), Utils.parseValue(shortText[LENGTH/2]).shortValue()); a = Random.randint(-128, 128, new int[] {LENGTH}); String[] byteText = new String[LENGTH]; for (int i = 0; i < LENGTH; i++) { byteText[i] = a.getString(i); } assertEquals("Byte", a.getByte(LENGTH/2), Utils.parseValue(byteText[LENGTH/2]).byteValue()); a = Random.rand(-1e28, 1e28, new int[] {LENGTH}); String[] doubleText = new String[LENGTH]; for (int i = 0; i < LENGTH; i++) { doubleText[i] = a.getString(i); } double x = a.getDouble(LENGTH/2); assertEquals("Double", x, Utils.parseValue(doubleText[LENGTH/2]).doubleValue(), 1e-7*Math.abs(x)); // timing int REPEAT = 5; long[] times = new long[REPEAT]; // in nanoseconds for (int i = 0; i < REPEAT; i++) { times[i] = -System.nanoTime(); for (int j = 0; j < LENGTH; j++) { Utils.parseValue(intText[j]); } times[i] += System.nanoTime(); } Arrays.sort(times); System.out.printf("Ints took %.2fms\n", times[0]/1e6); for (int i = 0; i < REPEAT; i++) { times[i] = -System.nanoTime(); for (int j = 0; j < LENGTH; j++) { Utils.parseValue(shortText[j]); } times[i] += System.nanoTime(); } Arrays.sort(times); System.out.printf("Shorts took %.2fms\n", times[0]/1e6); for (int i = 0; i < REPEAT; i++) { times[i] = -System.nanoTime(); for (int j = 0; j < LENGTH; j++) { Utils.parseValue(byteText[j]); } times[i] += System.nanoTime(); } Arrays.sort(times); System.out.printf("Bytes took %.2fms\n", times[0]/1e6); for (int i = 0; i < REPEAT; i++) { times[i] = -System.nanoTime(); for (int j = 0; j < LENGTH; j++) { Utils.parseValue(doubleText[j]); } times[i] += System.nanoTime(); } Arrays.sort(times); System.out.printf("Doubles took %.2fms\n", times[0]/1e6); for (int i = 0; i < REPEAT; i++) { times[i] = -System.nanoTime(); for (int j = 0; j < LENGTH; j++) { Utils.parseDouble(doubleText[j]); } times[i] += System.nanoTime(); } Arrays.sort(times); System.out.printf("Doubles took %.2fms\n", times[0]/1e6); for (int i = 0; i < REPEAT; i++) { times[i] = -System.nanoTime(); for (int j = 0; j < LENGTH; j++) { Double.parseDouble(doubleText[j]); } times[i] += System.nanoTime(); } Arrays.sort(times); System.out.printf("Doubles took %.2fms\n", times[0]/1e6); for (int i = 0; i < REPEAT; i++) { times[i] = -System.nanoTime(); for (int j = 0; j < LENGTH; j++) { oldParseValue(intText[j]); } times[i] += System.nanoTime(); } Arrays.sort(times); System.out.printf("Ints took %.2fms\n", times[0]/1e6); for (int i = 0; i < REPEAT; i++) { times[i] = -System.nanoTime(); for (int j = 0; j < LENGTH; j++) { oldParseValue(shortText[j]); } times[i] += System.nanoTime(); } Arrays.sort(times); System.out.printf("Shorts took %.2fms\n", times[0]/1e6); for (int i = 0; i < REPEAT; i++) { times[i] = -System.nanoTime(); for (int j = 0; j < LENGTH; j++) { oldParseValue(byteText[j]); } times[i] += System.nanoTime(); } Arrays.sort(times); System.out.printf("Bytes took %.2fms\n", times[0]/1e6); for (int i = 0; i < REPEAT; i++) { times[i] = -System.nanoTime(); for (int j = 0; j < LENGTH; j++) { oldParseValue(doubleText[j]); } times[i] += System.nanoTime(); } Arrays.sort(times); System.out.printf("Doubles took %.2fms\n", times[0]/1e6); } public static Number oldParseValue(String text) { try { return Byte.parseByte(text); } catch (NumberFormatException be) { try { return Short.parseShort(text); } catch (NumberFormatException se) { try { return Integer.parseInt(text); } catch (NumberFormatException ie) { try { return Long.parseLong(text); } catch (NumberFormatException le) { try { // nb no float as precision return Double.parseDouble(text); } catch (NumberFormatException de) { SRSLoader.logger.info("Value {} is not a number", text); } } } } } return null; } }