Commit | Line | Data |
---|---|---|
8182f36f AM |
1 | /******************************************************************************* |
2 | * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir | |
3 | * | |
4 | * All rights reserved. This program and the accompanying materials | |
5 | * are made available under the terms of the Eclipse Public License v1.0 | |
6 | * which accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | *******************************************************************************/ | |
9 | ||
10 | package org.eclipse.tracecompass.statesystem.core.tests.backend.historytree; | |
11 | ||
12 | import static org.junit.Assert.assertEquals; | |
13 | import static org.junit.Assert.fail; | |
14 | ||
15 | import java.io.File; | |
16 | import java.io.FileInputStream; | |
17 | import java.io.FileOutputStream; | |
18 | import java.io.IOException; | |
19 | import java.nio.ByteBuffer; | |
20 | import java.nio.ByteOrder; | |
21 | import java.nio.channels.FileChannel; | |
22 | import java.nio.charset.Charset; | |
23 | import java.util.List; | |
24 | import java.util.Set; | |
25 | import java.util.stream.Collectors; | |
26 | import java.util.stream.IntStream; | |
27 | ||
28 | import org.eclipse.jdt.annotation.NonNullByDefault; | |
29 | import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.HTInterval; | |
30 | import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; | |
31 | import org.junit.Test; | |
32 | import org.junit.runner.RunWith; | |
33 | import org.junit.runners.Parameterized; | |
34 | import org.junit.runners.Parameterized.Parameters; | |
35 | ||
36 | import com.google.common.collect.ImmutableList; | |
37 | import com.google.common.collect.ImmutableSet; | |
38 | import com.google.common.collect.Sets; | |
39 | ||
40 | /** | |
41 | * Test the reading/writing logic in {@link HTInterval}, particularly regarding | |
42 | * the string length limitations. | |
43 | * | |
44 | * @author Alexandre Montplaisir | |
45 | */ | |
46 | @RunWith(Parameterized.class) | |
47 | @NonNullByDefault({}) | |
48 | public class HTIntervalStringReadWriteTest { | |
49 | ||
50 | private static final Charset CHARSET = Charset.forName("UTF-8"); | |
51 | ||
52 | private int fNbChars; | |
53 | private int fCharLength; | |
54 | private char fChar; | |
55 | ||
56 | /** | |
57 | * Parameter generator. | |
58 | * | |
59 | * Generates a combination of all possible string lenghts and all possible | |
60 | * character lengths. | |
61 | * | |
62 | * @return The test parameters | |
63 | */ | |
64 | @Parameters(name = "nb of chars: {0}, char length: {1}") | |
65 | public static Iterable<Object[]> getTestParams() { | |
66 | Set<List<Integer>> set = Sets.cartesianProduct(ImmutableList.of( | |
67 | ImmutableSet.of( | |
68 | 0, | |
69 | 10, | |
70 | Byte.MAX_VALUE - 1, | |
71 | (int) Byte.MAX_VALUE, | |
72 | Byte.MAX_VALUE + 1, | |
73 | ||
74 | Short.MAX_VALUE / 2 - 1, | |
75 | Short.MAX_VALUE / 2, | |
76 | Short.MAX_VALUE / 2 + 1, | |
77 | ||
78 | Short.MAX_VALUE / 3 - 1, | |
79 | Short.MAX_VALUE / 3, | |
80 | Short.MAX_VALUE / 3 + 1, | |
81 | ||
82 | Short.MAX_VALUE - 1, | |
83 | (int) Short.MAX_VALUE, | |
84 | Short.MAX_VALUE + 1), | |
85 | ||
86 | ImmutableSet.of(1, 2, 3) | |
87 | )); | |
88 | ||
89 | return set.stream() | |
90 | .map(List::toArray) | |
91 | .collect(Collectors.toList()); | |
92 | } | |
93 | ||
94 | /** | |
95 | * Test constructor, take the generated parameters as parameters. | |
96 | * | |
97 | * @param nbChars | |
98 | * The number of characters in the test string. | |
99 | * @param charLength | |
100 | * The length (in bytes) of the UTF-8-encoded form of the | |
101 | * character being used. | |
102 | */ | |
103 | public HTIntervalStringReadWriteTest(Integer nbChars, Integer charLength) { | |
104 | fNbChars = nbChars.intValue(); | |
105 | fCharLength = charLength.intValue(); | |
106 | switch (charLength) { | |
107 | case 1: | |
108 | fChar = 'a'; | |
109 | break; | |
110 | case 2: | |
111 | fChar = 'é'; | |
112 | break; | |
113 | case 3: | |
114 | fChar = '长'; // "chang" means long / length in Chinese! | |
115 | break; | |
116 | default: | |
117 | throw new IllegalArgumentException(); | |
118 | } | |
119 | } | |
120 | ||
121 | /** | |
122 | * Test method | |
123 | * | |
124 | * @throws IOException | |
125 | * Fails the test | |
126 | */ | |
127 | @Test | |
128 | public void testStringWithChars() throws IOException { | |
129 | StringBuilder sb = new StringBuilder(); | |
130 | IntStream.range(0, fNbChars).forEach(i -> sb.append(fChar)); | |
131 | String str = sb.toString(); | |
132 | assertEquals(fNbChars, str.length()); | |
133 | assertEquals(fNbChars * fCharLength, str.getBytes(CHARSET).length); | |
134 | ||
135 | TmfStateValue value = TmfStateValue.newValueString(str); | |
136 | if (fNbChars * fCharLength > Short.MAX_VALUE) { | |
137 | /* For sizes that are known to be too long, expect an exception */ | |
138 | try { | |
139 | new HTInterval(0, 10, 1, value); | |
140 | } catch (IllegalArgumentException e) { | |
141 | return; | |
142 | } | |
143 | fail(); | |
144 | } | |
145 | HTInterval interval = new HTInterval(0, 10, 1, value); | |
146 | writeAndReadInterval(interval); | |
147 | } | |
148 | ||
149 | private static void writeAndReadInterval(HTInterval interval) throws IOException { | |
150 | int sizeOnDisk = interval.getSizeOnDisk(); | |
151 | ||
152 | /* Write the interval to a file */ | |
153 | File tempFile = File.createTempFile("test-interval", ".interval"); | |
154 | try (FileOutputStream fos = new FileOutputStream(tempFile, false); | |
155 | FileChannel fc = fos.getChannel();) { | |
156 | ||
157 | ByteBuffer bb = ByteBuffer.allocate(sizeOnDisk); | |
158 | bb.order(ByteOrder.LITTLE_ENDIAN); | |
159 | bb.clear(); | |
160 | ||
161 | interval.writeInterval(bb); | |
162 | bb.flip(); | |
163 | int written = fc.write(bb); | |
164 | assertEquals(sizeOnDisk, written); | |
165 | } | |
166 | ||
167 | /* Read the interval from the file */ | |
168 | HTInterval readInterval; | |
169 | try (FileInputStream fis = new FileInputStream(tempFile); | |
170 | FileChannel fc = fis.getChannel();) { | |
171 | ||
172 | ByteBuffer bb = ByteBuffer.allocate(sizeOnDisk); | |
173 | bb.order(ByteOrder.LITTLE_ENDIAN); | |
174 | bb.clear(); | |
175 | ||
176 | int read = fc.read(bb); | |
177 | assertEquals(sizeOnDisk, read); | |
178 | bb.flip(); | |
179 | readInterval = HTInterval.readFrom(bb); | |
180 | } | |
181 | ||
182 | assertEquals(interval, readInterval); | |
183 | } | |
184 | } |