blob: 0d837120c1313481a01fe53afdd69425d4acd4f5 [file] [log] [blame]
/*******************************************************************************
* 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);
}
}