1   package org.musicontroller.core;
2   
3   import static org.junit.Assert.assertEquals;
4   import static org.junit.Assert.assertFalse;
5   import static org.junit.Assert.assertNotNull;
6   import static org.junit.Assert.assertNull;
7   import static org.junit.Assert.assertTrue;
8   
9   import java.util.ArrayList;
10  import java.util.Date;
11  import java.util.HashSet;
12  import java.util.List;
13  import java.util.Set;
14  import java.util.TreeSet;
15  
16  import org.junit.Test;
17  import org.musicontroller.security.IUser;
18  import org.musicontroller.security.User;
19  import org.varienaja.util.DateTools;
20  
21  /**
22   * Unit test for the song class.
23   * @author Hans Drexler
24   * @version $Id: TestSong.java,v 1.1 2010/03/16 18:54:48 varienaja Exp $
25   */
26  public class TestSong {
27  	
28  	
29  	/**
30  	 * Test the properties of the Song class.
31  	 */
32  	@Test
33  	public void testSong() {
34  		Song song = new Song();
35  		Band band = new Band();
36  		song.setId(100L);
37  		song.setBand(band);
38  		song.setLength(100);
39  		song.setName("song");
40  		assertEquals(100L, song.getId());
41  		assertTrue(band.equals(song.getBand()));
42  		assertTrue("song".equals(song.getName()));
43  		assertEquals(100L, song.getLength());
44  		// Null values are allowed for String properties
45  		song.setBand(null);
46  		song.setName(null);
47  		song.setKeywordbag(null);
48  		assertNull(song.getBand());
49  		assertEquals("", song.getName());
50  		assertNull(song.getKeywordbag());
51  	}
52  	
53  	/**
54  	 * Tests the max 150 characters name limit
55  	 */
56  	@Test
57  	public void testSongnameSetter() {
58  		String ten = "1234567890";
59  		String onehundredandfifty = ten+ten+ten+ten+ten+ten+ten+ten+ten+ten+ten+ten+ten+ten+ten; 
60  		Song song = new Song();
61  		song.setName(onehundredandfifty+"A");
62  		assertEquals(song.getName(), onehundredandfifty);
63  	}
64  
65  	@Test
66  	public void testToString() {
67  		Song song = new Song();
68  		assertEquals("The representation of the empty song was incorrect.","[-1]  (0:00) [] ",song.toString());
69  		song.setName(null);
70  		assertEquals("The representation of the empty song was incorrect.","[-1]  (0:00) [] ",song.toString());
71  		song.setName("This song has a <strange> name.");
72  		assertEquals("The representation of the song was incorrect.","[-1] This song has a <strange> name. (0:00) [] ",song.toString());		
73  	}
74  	
75  	/**
76  	 * Tests adding a requested event to the song.
77  	 */
78  	@Test
79  	public void testAddRequestedEvent() {
80  		Song s = new Song();
81  		IUser u = new User();
82  		Event e = s.addRequestedEvent(DateTools.currentDate(), u);
83  		assertNotNull("No event was created.",e);
84  		assertEquals("Event type was wrong.",Event.requested,e.getEventkind());
85  	}
86  	
87  	/**
88  	 * Tests adding a skip event to the song.
89  	 */
90  	@Test
91  	public void testAddSkippedEvent() {
92  		Song s = new Song();
93  		IUser u = new User();
94  		Event e = s.addSkippedEvent(DateTools.currentDate(), u);
95  		assertNotNull("No event was created.",e);
96  		assertEquals("Event type was wrong.",Event.skipped,e.getEventkind());
97  	}
98  
99  	/**
100 	 * Tests adding a downloaded event to the song.
101 	 */
102 	@Test
103 	public void testAddDownloadedEvent() {
104 		Song s = new Song();
105 		IUser u = new User();
106 		Event e = s.addDownloadedEvent(DateTools.currentDate(), u);
107 		assertNotNull("No event was created.",e);
108 		assertEquals("Event type was wrong.",Event.downloaded,e.getEventkind());
109 	}
110 
111 	/**
112 	 * Tests adding null as an event set, which should be ignored.
113 	 *
114 	 */
115 	@Test
116 	public void testSetEventsNull() {
117 		Song s = new Song();
118 		assertNotNull("Event set was not initialized.",s.getEvents());
119 		assertEquals("Event set was't empty initially.",0,s.getEvents().size());
120 		s.addDownloadedEvent(DateTools.currentDate(), new User());
121 		assertEquals("Event wasn't added.",1,s.getEvents().size());
122 		s.setEvents(null);
123 		assertEquals("Event set wasn't kept.",1,s.getEvents().size());
124 	}
125 	
126 	/**
127 	 * Tests the <tt>playlistSet</tt> property.
128 	 * Tests setting a <tt>null</tt> as playlist set, which should be ignored.
129 	 */
130 	@Test
131 	public void testSetPlaylists() {
132 		Song s = new Song();
133 		Set<Contract_PS> plset = new HashSet<Contract_PS>();
134 		plset.add(new Contract_PS());
135 		s.setPlaylists(plset);
136 		assertEquals("Playlist set has wrong size.",1,s.getPlaylists().size());
137 		s.setPlaylists(null);
138 		assertEquals("Playlist set has wrong size.",1,s.getPlaylists().size());		
139 	}
140 	
141 	/**
142 	 * Tests the listing of keywords as a comma separated list.
143 	 */
144 	@Test
145 	public void testListKeywords() {
146 		Song s = new Song();
147 		assertEquals("Keyword list was not empty.","",s.listKeywords());
148 		Keyword kw = new Keyword();
149 		kw.setName("kw1");
150 		// Now try the empty keyword bag.
151 		Keywordbag bag = new Keywordbag();
152 		s.setKeywordbag(bag);
153 		assertEquals("Keyword list was wrong.","",s.listKeywords());
154 		// Then try with 1 keywoord in the bag.
155 		List<Keyword> kwList = new ArrayList<Keyword>();
156 		kwList.add(kw);
157 		bag.setKeywords(kwList);
158 		assertEquals("Keyword list was wrong.","kw1",s.listKeywords());
159 		// Then try with 2 keywords in the bag.
160 		Keyword kw2 = new Keyword();
161 		kw2.setName("kw2");
162 		kwList.add(kw2);
163 		assertEquals("Keyword list was wrong.","kw1, kw2",s.listKeywords());		
164 	}
165 	
166 	/**
167 	 * Tests the listing of playlists containing the song as a comma separated list.
168 	 *
169 	 */
170 	@Test
171 	public void testListPlaylists() {
172 		Song s = new Song();
173 		// test with empty playlists
174 		assertEquals("Playlist list was wrong.","",s.listPlaylists());
175 		// test playlist contract with null playlist object. This should be ignored. 
176 		Set<Contract_PS> playlistlist = new HashSet<Contract_PS>();
177 		s.setPlaylists(playlistlist);
178 		Contract_PS c_ps1 = new Contract_PS();
179 		playlistlist.add(c_ps1);
180 		assertEquals("Playlist list was wrong.","",s.listPlaylists());
181 		// test with one playlist. whose title is empty.
182 		Playlist pl = new Playlist();
183 		c_ps1.setPlaylist(pl);
184 		assertEquals("Playlist list was wrong.","",s.listPlaylists());
185 		// test with one playlist. The playlist has a null name.
186 		pl.setName(null);
187 		assertEquals("Playlist list was wrong.","",s.listPlaylists());
188 		// test with one playlist. whose title is not empty
189 		pl.setName("pl");
190 		assertEquals("Playlist list was wrong.","pl",s.listPlaylists());
191 		// test with 2 playlists.
192 		Contract_PS c_ps2 = new Contract_PS();
193 		playlistlist.add(c_ps2);
194 		c_ps2.setPlaylist(pl);
195 		assertEquals("Playlist list was wrong.","pl, pl",s.listPlaylists());
196 	}
197 	
198 	/**
199 	 * Tests the string representation of the song length.
200 	 */
201 	@Test
202 	public void testGetFormattedLength() {
203 		Song s = new Song();
204 		s.setLength(0);
205 		assertEquals("Wrong length.","0:00",s.getFormattedLength());
206 		s.setLength(60000);
207 		assertEquals("Wrong length.","1:00",s.getFormattedLength());
208 		s.setLength(11000);
209 		assertEquals("Wrong length.","0:11",s.getFormattedLength());
210 		s.setLength(-20000);
211 		assertEquals("Wrong length.","0:20",s.getFormattedLength());
212 		// This is the longest song we can record.
213 		s.setLength(Integer.MAX_VALUE);
214 		assertEquals("Wrong length.","35791:23",s.getFormattedLength());
215 	}
216 	
217 	/**
218 	 * Tests getting the play count.
219 	 */
220 	@Test
221 	public void testGetPlaycount() {
222 		Song s = new Song();
223 		assertEquals("Wrong play count",0,s.getPlaycount(null));
224 	}
225 	
226 	/**
227 	 * Tests getting the request count.
228 	 */
229 	@Test
230 	public void testGetRequestcount() {
231 		Song s = new Song();
232 		assertEquals("Wrong request count",0,s.getRequestcount(null));
233 	}
234 
235 	/**
236 	 * Tests getting the skip count.
237 	 */
238 	@Test
239 	public void testGetSkipcount() {
240 		Song s = new Song();
241 		assertEquals("Wrong skip count",0,s.getSkipcount(null));
242 	}
243 
244 	/**
245 	 * Tests getting the event count.
246 	 */
247 	@Test
248 	public void testGetEventcount() {
249 		Song s = new Song();
250 		assertEquals("Wrong event count",0,s.getEventcount(null,Event.played));
251 		IUser u = new User();
252 		Date eventdate = DateTools.encodeDate(01, 01, 2008);
253 		s.addPlayedEvent(eventdate, u);
254 		assertEquals("wrong event count",1,s.getEventCount(u, Event.played,DateTools.encodeDate(01, 01, 2007),null));
255 		assertEquals("wrong event count",1,s.getEventCount(u, Event.played,DateTools.encodeDate(01, 01, 2007),DateTools.encodeDate(01, 01, 2009)));
256 		assertEquals("wrong event count",1,s.getEventCount(u, Event.played,null,DateTools.encodeDate(01, 01, 2009)));
257 	}
258 	
259 	/**
260 	 * Test getting the date of last play.
261 	 */
262 	@Test
263 	public void testGetLastPlay() {
264 		Song s = new Song();
265 		s.setId(3);
266 		assertNull("Wrong last play date",s.getLastPlay(null));
267 		try {
268 			s.addPlayedEvent(DateTools.encodeDate(01, 04, 2005), null);
269 			assertTrue("Exception expected: adding events without user should be forbidden.", false);
270 		} catch (IllegalArgumentException e) {
271 			//ok.
272 		}
273 		IUser u = new User();
274 		s.addPlayedEvent(DateTools.encodeDate(01, 04, 2004), u);
275 		s.addPlayedEvent(DateTools.encodeDate(01, 05, 2005), u);
276 		s.addPlayedEvent(DateTools.encodeDate(01, 06, 2005), u);
277 		assertEquals("wrong last play date.",DateTools.encodeDate(01, 06, 2005),s.getLastPlay(u));
278 		assertEquals("wrong eventcount", 3, s.getEventcount(u, Event.played));
279 		assertEquals("wrong eventcount", 0, s.getEventcount(u, Event.skipped));
280 	}
281 	
282 	/**
283 	 * Test object equality.
284 	 */
285 	@Test
286 	public void testEquals() {
287 		Song s1 = new Song();
288 		Song s2 = new Song();
289 		assertEquals("Should be equal.",s1,s2);
290 		assertEquals("Should be equal.",s2,s1);
291 		assertFalse("Should not be equal.",s1.equals(null));
292 		assertFalse("Should not be equal.",s1.equals(""));
293 	}
294 	
295 	/**
296 	 * Test the Eventcount lookup-construct.
297 	 */
298 	@Test
299 	public void testEvencountLookup() {
300 		Integer[] eventkinds = new Integer[]{Event.downloaded, Event.played, 
301 				Event.requested, Event.skipped, Event.unknown};
302 		long userId = 20;
303 		long firstEventInMillis = System.currentTimeMillis();
304 		
305 		User user = new User();
306 		user.setId(userId);
307 		
308 		// We create a lot of Songs, to make sure the LRUMap of the
309 		// EventCountlookup class gets full.
310 		for (int i=1; i<=2*EventCountLookup.CACHESIZE; i++) {
311 			Song s = new Song();
312 			s.setId(i);
313 			s.setName("Testsong " + i);
314 			
315 			//We create a Set of idCounter / 1000 Events.
316 			Set<Event> events = new TreeSet<Event>();
317 			for (int j=1000; j<=i; j+=1000) {
318 				for (int k=0; k<eventkinds.length; k++) {
319 					Event e = new Event();
320 					e.setMoment(new Date(firstEventInMillis++)); //Generate unique moments.
321 					e.setId(10000000*i+j);
322 					e.setEventkind(eventkinds[k]);
323 					e.setSong(s);
324 					e.setUser(user);
325 					events.add(e);
326 				}
327 			}
328 			s.setEvents(events);
329 
330 			//The next statement makes sure the EventCountLookup for this Song
331 			//is created. The pupularity is plays+requests+downloads-skips.
332 			//Since i/1000 == plays == downloads == skips == requests,
333 			//we expect 1+1+1-1 = 2 --> 2 * (i/1000) as popularity.
334 			int cnt = 2*(i/1000);
335 			assertEquals(s.toString(), cnt, s.getPopularity(user, null, null));
336 		}
337 		
338 		//Now, it is time for assertions. The last CACHESIZE Songs should be
339 		//contained in the EventCountLookup class. So let's query directly!
340 		
341 		for (int i=2*EventCountLookup.CACHESIZE; i>EventCountLookup.CACHESIZE; i--) {
342 			EventCountLookup lookup = EventCountLookup.create(null, i);
343 			assertNotNull(lookup);
344 			for (int k=0; k<eventkinds.length; k++) {
345 				if (eventkinds[k] == Event.unknown) { //Unknown eventcounts are not cached, they return 0.
346 					assertEquals("Error in EventCount for song: "+i, 0, lookup.getEventCount(userId, eventkinds[k]));
347 					assertEquals("Error in EventCount for song: "+i, 0, lookup.getEventCountLastYear(userId, eventkinds[k]));
348 				} else {
349 					assertEquals("Error in EventCount for song: "+i, i/1000, lookup.getEventCount(userId, eventkinds[k]));
350 					assertEquals("Error in EventCount for song: "+i, i/1000, lookup.getEventCountLastYear(userId, eventkinds[k]));
351 				}
352 				assertEquals("Count should be 0 for an user that did not generate events for song: "+i, 0, lookup.getEventCountLastYear(3L, eventkinds[k]));
353 				assertNull("Last play shoul be null for a user that did not generate events for song: "+i, lookup.getLastPlay(3));
354 			}
355 		}
356 	}
357 }