| /******************************************************************************* |
| * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| *******************************************************************************/ |
| |
| package org.eclipse.tracecompass.statesystem.core.tests.backend.historytree; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.fail; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.nio.ByteBuffer; |
| import java.nio.ByteOrder; |
| import java.nio.channels.FileChannel; |
| import java.nio.charset.Charset; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.stream.Collectors; |
| import java.util.stream.IntStream; |
| |
| import org.eclipse.jdt.annotation.NonNullByDefault; |
| import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.HTInterval; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.Parameterized; |
| import org.junit.runners.Parameterized.Parameters; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.common.collect.Sets; |
| |
| /** |
| * Test the reading/writing logic in {@link HTInterval}, particularly regarding |
| * the string length limitations. |
| * |
| * @author Alexandre Montplaisir |
| */ |
| @RunWith(Parameterized.class) |
| @NonNullByDefault({}) |
| public class HTIntervalStringReadWriteTest { |
| |
| private static final Charset CHARSET = Charset.forName("UTF-8"); |
| |
| private int fNbChars; |
| private int fCharLength; |
| private char fChar; |
| |
| /** |
| * Parameter generator. |
| * |
| * Generates a combination of all possible string lengths and all possible |
| * character lengths. |
| * |
| * @return The test parameters |
| */ |
| @Parameters(name = "nb of chars: {0}, char length: {1}") |
| public static Iterable<Object[]> getTestParams() { |
| Set<List<Integer>> set = Sets.cartesianProduct(ImmutableList.of( |
| ImmutableSet.of( |
| 0, |
| 10, |
| Byte.MAX_VALUE - 1, |
| (int) Byte.MAX_VALUE, |
| Byte.MAX_VALUE + 1, |
| |
| Short.MAX_VALUE / 2 - 1, |
| Short.MAX_VALUE / 2, |
| Short.MAX_VALUE / 2 + 1, |
| |
| Short.MAX_VALUE / 3 - 1, |
| Short.MAX_VALUE / 3, |
| Short.MAX_VALUE / 3 + 1, |
| |
| Short.MAX_VALUE - 1, |
| (int) Short.MAX_VALUE, |
| Short.MAX_VALUE + 1), |
| |
| ImmutableSet.of(1, 2, 3) |
| )); |
| |
| return set.stream() |
| .map(List::toArray) |
| .collect(Collectors.toList()); |
| } |
| |
| /** |
| * Test constructor, take the generated parameters as parameters. |
| * |
| * @param nbChars |
| * The number of characters in the test string. |
| * @param charLength |
| * The length (in bytes) of the UTF-8-encoded form of the |
| * character being used. |
| */ |
| public HTIntervalStringReadWriteTest(Integer nbChars, Integer charLength) { |
| fNbChars = nbChars.intValue(); |
| fCharLength = charLength.intValue(); |
| switch (charLength) { |
| case 1: |
| fChar = 'a'; |
| break; |
| case 2: |
| fChar = 'é'; |
| break; |
| case 3: |
| fChar = '长'; // "chang" means long / length in Chinese! |
| break; |
| default: |
| throw new IllegalArgumentException(); |
| } |
| } |
| |
| /** |
| * Test method |
| * |
| * @throws IOException |
| * Fails the test |
| */ |
| @Test |
| public void testStringWithChars() throws IOException { |
| StringBuilder sb = new StringBuilder(); |
| IntStream.range(0, fNbChars).forEach(i -> sb.append(fChar)); |
| String str = sb.toString(); |
| assertEquals(fNbChars, str.length()); |
| assertEquals(fNbChars * fCharLength, str.getBytes(CHARSET).length); |
| |
| if (fNbChars * fCharLength > Short.MAX_VALUE) { |
| /* For sizes that are known to be too long, expect an exception */ |
| try { |
| new HTInterval(0, 10, 1, str); |
| } catch (IllegalArgumentException e) { |
| return; |
| } |
| fail(); |
| } |
| HTInterval interval = new HTInterval(0, 10, 1, str); |
| writeAndReadInterval(interval); |
| } |
| |
| private static void writeAndReadInterval(HTInterval interval) throws IOException { |
| int sizeOnDisk = interval.getSizeOnDisk(); |
| |
| /* Write the interval to a file */ |
| File tempFile = File.createTempFile("test-interval", ".interval"); |
| try (FileOutputStream fos = new FileOutputStream(tempFile, false); |
| FileChannel fc = fos.getChannel();) { |
| |
| ByteBuffer bb = ByteBuffer.allocate(sizeOnDisk); |
| bb.order(ByteOrder.LITTLE_ENDIAN); |
| bb.clear(); |
| |
| interval.writeInterval(bb, 1); |
| bb.flip(); |
| int written = fc.write(bb); |
| assertEquals(sizeOnDisk, written); |
| } |
| |
| /* Read the interval from the file */ |
| HTInterval readInterval; |
| try (FileInputStream fis = new FileInputStream(tempFile); |
| FileChannel fc = fis.getChannel();) { |
| |
| ByteBuffer bb = ByteBuffer.allocate(sizeOnDisk); |
| bb.order(ByteOrder.LITTLE_ENDIAN); |
| bb.clear(); |
| |
| int read = fc.read(bb); |
| assertEquals(sizeOnDisk, read); |
| bb.flip(); |
| readInterval = HTInterval.readFrom(bb, 1); |
| } |
| |
| assertEquals(interval, readInterval); |
| } |
| } |