View Javadoc

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  			// okay
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  			// okay
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  			// okay
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 		// prepare the stream
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 		// prepare the stream
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 }