1 /***
2 * Ambient - A music player for the Android platform
3 Copyright (C) 2007 Martin Vysny
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 package sk.baka.ambient.stream.shoutcast;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.ByteArrayOutputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.util.Map;
26
27 import sk.baka.ambient.commons.TestUtils;
28
29 import junit.framework.TestCase;
30
31 /***
32 * Tests {@link ShoutcastInputStream}.
33 *
34 * @author Martin Vysny
35 */
36 public class ShoutcastInputStreamTest extends TestCase {
37 /***
38 *
39 */
40 public void testInvalidStream() {
41 try {
42 new ShoutcastInputStream(new ByteArrayInputStream(new byte[0]),
43 null);
44 fail("IOException should have been thrown");
45 } catch (IOException ex) {
46
47 }
48 try {
49 new ShoutcastInputStream(new ByteArrayInputStream(
50 TestUtils.toAscii("HTTP 200 OK\r\n")), null);
51 fail("IOException should have been thrown");
52 } catch (IOException ex) {
53
54 }
55 try {
56 new ShoutcastInputStream(new ByteArrayInputStream(
57 TestUtils.toAscii("ICY 300 FAIL\r\n")), null);
58 fail("IOException should have been thrown");
59 } catch (IOException ex) {
60
61 }
62 }
63
64 private static class SimpleListener implements IShoutcastListener {
65
66 public Map<String, String> lastMetadata;
67
68 public String lastTitle;
69
70 public void metadataReceived(String title, Map<String, String> metadata) {
71 lastTitle = title;
72 lastMetadata = metadata;
73 }
74
75 public Map<String, String> openedMetadata;
76
77 public String openedName;
78 public String openedGenre;
79 public boolean openedHasMetaint;
80
81 public void opened(String name, String genre, boolean hasMetaint,
82 Map<String, String> metadata) {
83 openedMetadata = metadata;
84 openedName = name;
85 openedGenre = genre;
86 openedHasMetaint = hasMetaint;
87 }
88 }
89
90 /***
91 * @throws Exception
92 */
93 public void testEmptyHeader() throws Exception {
94 SimpleListener l = new SimpleListener();
95 new ShoutcastInputStream(new ByteArrayInputStream(
96 TestUtils.toAscii("ICY 200 OK\r\n\r\n")), l);
97 assertNull(l.openedGenre);
98 assertNull(l.openedName);
99 assertFalse(l.openedHasMetaint);
100 assertTrue(l.openedMetadata.isEmpty());
101 }
102
103 /***
104 * @throws Exception
105 */
106 public void testSimpleHeader() throws Exception {
107 SimpleListener l = new SimpleListener();
108 new ShoutcastInputStream(
109 new ByteArrayInputStream(
110 TestUtils.toAscii("ICY 200 OK\r\nicy-name:NAME\r\nicy-genre:GENRE\r\n\r\n")),
111 l);
112 assertEquals("GENRE", l.openedGenre);
113 assertEquals("NAME", l.openedName);
114 assertFalse(l.openedHasMetaint);
115 assertEquals(2, l.openedMetadata.size());
116 }
117
118 /***
119 * @throws Exception
120 */
121 public void testSimpleContentSimpleReader() throws Exception {
122
123 final byte[] bout = createTestStream();
124 final SimpleListener l = new SimpleListener();
125 final InputStream in = new ShoutcastInputStream(
126 new ByteArrayInputStream(bout), l);
127 assertTrue(l.openedHasMetaint);
128 assertEquals(1, l.openedMetadata.size());
129 for (byte i = 0; i < 10; i++) {
130 assertEquals(i, in.read());
131 }
132 assertEquals(10, in.read());
133 assertNull(l.lastTitle);
134 assertNull(l.lastMetadata);
135 for (byte i = 11; i < 20; i++) {
136 assertEquals(i, in.read());
137 }
138 assertEquals(20, in.read());
139 assertEquals("Huhu", l.lastTitle);
140 assertEquals(2, l.lastMetadata.size());
141 for (byte i = 21; i < 30; i++) {
142 assertEquals(i, in.read());
143 }
144 }
145
146 /***
147 * @throws Exception
148 */
149 public void testSimpleContentBlockReader() throws Exception {
150
151 final byte[] bout = createTestStream();
152 final SimpleListener l = new SimpleListener();
153 final InputStream in = new ShoutcastInputStream(
154 new ByteArrayInputStream(bout), l);
155 assertTrue(l.openedHasMetaint);
156 assertEquals(1, l.openedMetadata.size());
157 byte[] expected = new byte[15];
158 for (byte i = 0; i < 15; i++) {
159 expected[i] = i;
160 }
161 assertNext(expected, in);
162 assertNull(l.lastTitle);
163 assertNull(l.lastMetadata);
164 expected = new byte[15];
165 for (byte i = 15; i < 30; i++) {
166 expected[i - 15] = i;
167 }
168 assertNext(expected, in);
169 assertEquals("Huhu", l.lastTitle);
170 assertEquals(2, l.lastMetadata.size());
171 }
172
173 private static void assertNext(byte[] expected, InputStream is)
174 throws IOException {
175 final byte[] read = new byte[expected.length];
176 int ptr = 0;
177 while (ptr < read.length) {
178 int bytesRead = is.read(read, ptr, expected.length - ptr);
179 if (bytesRead < 0)
180 throw new AssertionError("Unexpected EOS, matched " + ptr
181 + " bytes");
182 for (int i = 0; i < bytesRead; i++) {
183 assertEquals(expected[i + ptr], read[i + ptr]);
184 }
185 ptr += bytesRead;
186 }
187 }
188
189 private byte[] createTestStream() throws IOException {
190 final ByteArrayOutputStream bout = new ByteArrayOutputStream();
191 bout.write(TestUtils.toAscii("ICY 200 OK\r\nicy-metaint:10\r\n\r\n"));
192 for (byte i = 0; i < 10; i++) {
193 bout.write(i);
194 }
195 bout.write(0);
196 for (byte i = 10; i < 20; i++) {
197 bout.write(i);
198 }
199 bout.write(3);
200 final byte[] meta = TestUtils.toAscii("StreamTitle='Huhu';Meta='empty';");
201 bout.write(meta);
202 bout.write(new byte[48 - meta.length]);
203 for (byte i = 20; i < 30; i++) {
204 bout.write(i);
205 }
206 return bout.toByteArray();
207 }
208 }