2 * Sonitus - MetadataStreamTest.java - Copyright © 2013 David Roden
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 package net.pterodactylus.sonitus.io;
20 import static org.hamcrest.CoreMatchers.is;
21 import static org.junit.Assert.assertThat;
23 import java.io.ByteArrayInputStream;
24 import java.io.ByteArrayOutputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.util.Arrays;
28 import java.util.Iterator;
29 import java.util.Random;
31 import com.google.common.collect.FluentIterable;
32 import com.google.common.io.ByteStreams;
33 import org.testng.annotations.DataProvider;
34 import org.testng.annotations.Test;
37 * Test for {@link MetadataStream}.
39 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
41 public class MetadataStreamTest {
44 * Returns test data for {@link #testMetadataStream(int, int, String[])}.
46 * @return Test data for {@link #testMetadataStream(int, int, String[])}
48 @DataProvider(name = "testData")
49 public Object[][] getStreamTestParameters() {
50 return new Object[][] {
51 { 5, 18, new String[] { "Test 1", "Test 2", "Test 3" } },
52 { 1024, 10240, new String[] { "Test 1", "Test 2" } },
53 { 1024, 10240, new String[] { "Test 1", "", "", "", "Test 2" } },
54 { 8192, 10240, new String[] { "Test 1" } },
55 { 8192, 262144, new String[] { "Test 1", "Test 2" } }
60 * Returns test data for {@link #testMetadataEncoding(String, String)}.
62 * @return Test data for {@link #testMetadataEncoding(String, String)}
64 @DataProvider(name = "encodingTestData")
65 public Object[][] getEncodingTestParameters() {
66 return new Object[][] {
67 { "Metadata mit Ümläute!", "UTF-8" },
68 { "Metadata mit Ümläute!", "ISO8859-1" }
73 * Tests that the {@link MetadataStream} can successfully separate the payload
74 * from the metadata, and that the stream returns the expected bytes.
76 * @param metadataInterval
77 * The interval of the metadata
79 * The length of the stream to test
81 * The metadata strings to write (empty strings allowed to signify “no
84 * if an I/O error occurs
86 @Test(dataProvider = "testData")
87 public void testMetadataStream(int metadataInterval, int length, String[] metadatas) throws IOException {
88 byte[] randomData = generateData(length);
89 InputStream testInputStream = generateInputStream(metadataInterval, randomData, "UTF-8", metadatas);
90 MetadataStream metadataStream = new MetadataStream(testInputStream, metadataInterval);
91 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
93 ByteStreams.copy(metadataStream, outputStream);
94 assertThat(outputStream.toByteArray().length, is(length));
95 assertThat(outputStream.toByteArray(), is(randomData));
99 * Tests that the metadata is decoded correcty.
102 * The string to encode
104 * The charset in which to encode the string
105 * @throws IOException
106 * if an I/O error occurs
108 @Test(dataProvider = "encodingTestData")
109 public void testMetadataEncoding(String metadata, String charset) throws IOException {
110 InputStream testInputStream = generateInputStream(8192, 10240, charset, metadata);
111 MetadataStream metadataStream = new MetadataStream(testInputStream, 8192);
113 ByteStreams.copy(metadataStream, new ByteArrayOutputStream());
114 assertThat(metadataStream.getContentMetadata().isPresent(), is(true));
115 assertThat(metadataStream.getContentMetadata().get().title(), is(metadata));
123 * Generates a random amount of data.
126 * The length of the data
127 * @return The generated random data
129 private static byte[] generateData(int length) {
130 Random random = new Random();
131 byte[] buffer = new byte[length];
132 random.nextBytes(buffer);
137 * Generates an input stream of the given length that has the given metadata
138 * strings (cycled) embedded in the given intervals.
140 * @param metadataInterval
141 * The interval of the embedded metadata
143 * The length of the stream to generate
145 * The charset with which to encode the metadata strings
147 * The metadata strings which will be cycled
148 * @return The generated input stream
149 * @throws IOException
150 * if an I/O error occurs
152 private static InputStream generateInputStream(int metadataInterval, int length, String charset, String... metadatas) throws IOException {
153 return generateInputStream(metadataInterval, generateData(length), charset, metadatas);
157 * Generates an input stream of the given buffer that has the given metadata
158 * strings (cycled) embedded in the given intervals.
160 * @param metadataInterval
161 * The interval of the embedded metadata
163 * The data to embed the metadata into
165 * The charset with which to encode the metadata strings
167 * The metadata strings which will be cycled
168 * @return The generated input stream
169 * @throws IOException
170 * if an I/O error occurs
172 private static InputStream generateInputStream(int metadataInterval, byte[] buffer, String charset, String... metadatas) throws IOException {
173 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
174 Iterator<String> metadataIterator = FluentIterable.from(Arrays.asList(metadatas)).cycle().iterator();
175 int bufferPosition = 0;
176 int remaining = buffer.length;
177 while (remaining > 0) {
178 int bytesToWrite = Math.min(remaining, metadataInterval);
179 outputStream.write(buffer, bufferPosition, bytesToWrite);
180 remaining -= bytesToWrite;
181 bufferPosition += bytesToWrite;
183 String nextMetadata = "StreamTitle='" + metadataIterator.next() + "';";
184 byte[] metadata = nextMetadata.getBytes(charset);
185 outputStream.write((metadata.length + 15) / 16);
186 outputStream.write(metadata);
187 outputStream.write(new byte[(16 - metadata.length % 16) % 16]);
190 return new ByteArrayInputStream(outputStream.toByteArray());