Merge lp:~karni/ubuntuone-music-java-library/playlist-methods into lp:ubuntuone-music-java-library

Proposed by Michał Karnicki
Status: Merged
Merged at revision: 10
Proposed branch: lp:~karni/ubuntuone-music-java-library/playlist-methods
Merge into: lp:ubuntuone-music-java-library
Prerequisite: lp:~karni/ubuntuone-music-java-library/content-streaming
Diff against target: 1005 lines (+698/-160)
13 files modified
.bzrignore (+1/-0)
ant.properties (+1/-1)
build.xml (+1/-1)
src/main/com/ubuntuone/api/music/U1MusicAPI.java (+58/-3)
src/main/com/ubuntuone/api/music/client/ResourceClient.java (+4/-1)
src/main/com/ubuntuone/api/music/json/U1CustomJson.java (+56/-0)
src/test/com/ubuntuone/api/music/CreatePlaylistTest.java (+213/-0)
src/test/com/ubuntuone/api/music/GetAlbumsTest.java (+49/-0)
src/test/com/ubuntuone/api/music/PutPlaylistTest.java (+0/-153)
src/test/com/ubuntuone/api/music/UpdatePlaylistTest.java (+157/-0)
src/test/com/ubuntuone/api/music/json/U1CustomJsonTest.java (+59/-0)
src/test/com/ubuntuone/test/util/SameHttpRequestMatcher.java (+72/-1)
src/test/com/ubuntuone/test/util/StreamUtils.java (+27/-0)
To merge this branch: bzr merge lp:~karni/ubuntuone-music-java-library/playlist-methods
Reviewer Review Type Date Requested Status
Chad Miller Pending
Review via email: mp+120578@code.launchpad.net

Description of the change

Added playlist creation and updating methods.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2012-06-05 15:16:38 +0000
3+++ .bzrignore 2012-08-21 14:13:25 +0000
4@@ -16,3 +16,4 @@
5 libs/jmock-*.jar
6 libs/jmock-junit4-*.jar
7 libs/hamcrest-all-*.jar
8+src/main/com/ubuntuone/api/music/MusicTest.java
9
10=== modified file 'ant.properties'
11--- ant.properties 2012-06-05 15:16:38 +0000
12+++ ant.properties 2012-08-21 14:13:25 +0000
13@@ -61,4 +61,4 @@
14
15 # Only used by official ubuntuone-hackers team.
16
17-project.version=0.1
18+project.version=0.1.0
19
20=== modified file 'build.xml'
21--- build.xml 2012-08-21 14:13:25 +0000
22+++ build.xml 2012-08-21 14:13:25 +0000
23@@ -1,5 +1,5 @@
24 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
25-<project name="ubuntuone-files-java-library" basedir="." default="jar">
26+<project name="ubuntuone-music-java-library" basedir="." default="jar">
27
28 <description>
29 *** UbuntuOne Music Java library ***
30
31=== modified file 'src/main/com/ubuntuone/api/music/U1MusicAPI.java'
32--- src/main/com/ubuntuone/api/music/U1MusicAPI.java 2012-08-21 14:13:25 +0000
33+++ src/main/com/ubuntuone/api/music/U1MusicAPI.java 2012-08-21 14:13:25 +0000
34@@ -53,6 +53,7 @@
35 import com.ubuntuone.api.music.client.StreamingClient;
36 import com.ubuntuone.api.music.json.U1AlbumJson;
37 import com.ubuntuone.api.music.json.U1ArtistJson;
38+import com.ubuntuone.api.music.json.U1CustomJson;
39 import com.ubuntuone.api.music.json.U1PlaylistJson;
40 import com.ubuntuone.api.music.json.U1PlaylistSongJson;
41 import com.ubuntuone.api.music.json.U1SongJson;
42@@ -196,6 +197,44 @@
43 }
44 }
45
46+ public void getAlbumsByArtist(String artistId, U1AlbumRequestListener callback) {
47+ callback.onStart();
48+ String path = resourceClient.getPath(ALBUMS, artistId);
49+ HttpResponse response = null;
50+ try {
51+ response = resourceClient.request(HttpGet.METHOD_NAME, path);
52+ final int statusCode = getStatusCode(response);
53+ if (statusCode == HttpStatus.SC_OK) {
54+ U1AlbumJson.fromJson(getContentInputStream(response), callback);
55+ } else {
56+ handleHttpResponse(response, "Could not get artist albums.", callback);
57+ }
58+ } catch (JsonParseException jpe) {
59+ // Received corrupt JSON. At this stage, response != null
60+ final String bzrRev = getHeaderValue(ResponseHeader.X_BZR_REVISION_NUMBER, response);
61+ final String date = getHeaderValue(ResponseHeader.DATE, response);
62+
63+ callback.onFailure(new Failure("Could not get artist albums. Corrupt JSON.",
64+ jpe, 0, null, bzrRev, date));
65+ } catch (OutOfMemoryError e) {
66+ callback.onFailure(new Failure("Out of memory!", e));
67+ throw e; // We're not expected to recover from this.
68+ } catch (SSLException sslException) {
69+ callback.onFailure(new Failure("SSL connection problem. This may be intermittent issue, " +
70+ "please try again later.", sslException));
71+ } catch (IOException ioException) {
72+ // Failed to read the response.
73+ callback.onFailure(new Failure("Could not get artist albums (network error).", ioException));
74+ } catch (URISyntaxException uriSyntaxException) {
75+ // Failed due to invalid URL within the library code.
76+ throw new IllegalStateException(uriSyntaxException);
77+ } catch (AuthorizerException signingException) {
78+ callback.onFailure(new Failure("Could not get artist albums (signing exception).", signingException));
79+ } finally {
80+ callback.onFinish();
81+ }
82+ }
83+
84 public void getSongs(U1SongRequestListener callback) {
85 callback.onStart();
86 String path = resourceClient.getPath(SONGS);
87@@ -310,13 +349,29 @@
88 }
89 }
90
91- public void createPlaylist(String name, ArrayList<U1Song> songList,
92+ public void createPlaylist(String name,
93+ ArrayList<U1Song> songs, U1PlaylistSongRequestListener callback) {
94+ putPlaylist(null, name, songs, callback);
95+ }
96+
97+ public void updatePlaylist(String playlistId, String name,
98+ ArrayList<U1Song> songs, U1PlaylistSongRequestListener callback) {
99+ putPlaylist(playlistId, name, songs, callback);
100+ }
101+
102+ public void putPlaylist(String playlistId, String name, ArrayList<U1Song> songs,
103 U1PlaylistSongRequestListener callback) {
104 callback.onStart();
105- String path = resourceClient.getPath(PLAYLISTS);
106+ String path;
107+ if (playlistId != null) {
108+ path = resourceClient.getPath(PLAYLISTS, playlistId);
109+ } else {
110+ path = resourceClient.getPath(PLAYLISTS);
111+ }
112 HttpResponse response = null;
113 try {
114- response = resourceClient.request(HttpPost.METHOD_NAME, path);
115+ String data = U1CustomJson.toSongIdListJson(name, songs);
116+ response = resourceClient.request(HttpPost.METHOD_NAME, path, null, data);
117 final int statusCode = getStatusCode(response);
118 if (statusCode == HttpStatus.SC_OK) {
119 U1PlaylistSongJson.fromJson(getContentInputStream(response), callback);
120
121=== modified file 'src/main/com/ubuntuone/api/music/client/ResourceClient.java'
122--- src/main/com/ubuntuone/api/music/client/ResourceClient.java 2012-08-21 14:13:25 +0000
123+++ src/main/com/ubuntuone/api/music/client/ResourceClient.java 2012-08-21 14:13:25 +0000
124@@ -32,6 +32,7 @@
125 import org.apache.http.HttpResponse;
126 import org.apache.http.NameValuePair;
127 import org.apache.http.client.HttpClient;
128+import org.apache.http.client.methods.HttpPost;
129 import org.apache.http.client.methods.HttpPut;
130 import org.apache.http.client.methods.HttpUriRequest;
131 import org.apache.http.client.utils.URLEncodedUtils;
132@@ -95,7 +96,9 @@
133 request.addHeader(HttpHeaders.USER_AGENT, userAgent);
134 request.addHeader(HttpHeaders.CONNECTION, CONNECTION);
135 request.addHeader(HttpHeaders.ACCEPT, ACCEPT);
136- if (data != null && HttpPut.METHOD_NAME.equals(method)) {
137+ if (data != null && HttpPost.METHOD_NAME.equals(method)) {
138+ ((HttpPost) request).setEntity(new StringEntity(data, UTF8));
139+ } else if (data != null && HttpPut.METHOD_NAME.equals(method)) {
140 ((HttpPut) request).setEntity(new StringEntity(data, UTF8));
141 }
142
143
144=== added file 'src/main/com/ubuntuone/api/music/json/U1CustomJson.java'
145--- src/main/com/ubuntuone/api/music/json/U1CustomJson.java 1970-01-01 00:00:00 +0000
146+++ src/main/com/ubuntuone/api/music/json/U1CustomJson.java 2012-08-21 14:13:25 +0000
147@@ -0,0 +1,56 @@
148+/*
149+ * Ubuntu One Music Java library - communicate with Ubuntu One music API
150+ *
151+ * Copyright 2012 Canonical Ltd.
152+ *
153+ * This file is part of Ubuntu One Files Java library.
154+ *
155+ * This program is free software: you can redistribute it and/or modify
156+ * it under the terms of the GNU Affero General Public License as
157+ * published by the Free Software Foundation, either version 3 of the
158+ * License, or (at your option) any later version.
159+ *
160+ * This program is distributed in the hope that it will be useful,
161+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
162+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
163+ * GNU Affero General Public License for more details.
164+ *
165+ * You should have received a copy of the GNU Affero General Public License
166+ * along with this program. If not, see http://www.gnu.org/licenses
167+ */
168+
169+package com.ubuntuone.api.music.json;
170+
171+import java.io.IOException;
172+import java.io.StringWriter;
173+import java.util.ArrayList;
174+
175+import org.codehaus.jackson.JsonFactory;
176+import org.codehaus.jackson.JsonGenerator;
177+
178+import com.ubuntuone.api.music.model.U1Song;
179+
180+public class U1CustomJson
181+{
182+ public static String toSongIdListJson(String name, ArrayList<U1Song> songs)
183+ throws IOException {
184+ final JsonFactory factory = new JsonFactory();
185+ final StringWriter writer = new StringWriter(128);
186+ final JsonGenerator g = factory.createJsonGenerator(writer);
187+
188+ g.writeStartObject();
189+ g.writeStringField("name", name);
190+
191+ g.writeArrayFieldStart("song_id_list"); {
192+ for (U1Song song : songs) {
193+ g.writeString(song.getId());
194+ }
195+ }
196+ g.writeEndArray();
197+
198+ g.writeEndObject();
199+ g.close();
200+
201+ return writer.toString();
202+ }
203+}
204
205=== added file 'src/test/com/ubuntuone/api/music/CreatePlaylistTest.java'
206--- src/test/com/ubuntuone/api/music/CreatePlaylistTest.java 1970-01-01 00:00:00 +0000
207+++ src/test/com/ubuntuone/api/music/CreatePlaylistTest.java 2012-08-21 14:13:25 +0000
208@@ -0,0 +1,213 @@
209+/*
210+ * Ubuntu One Music Java library - communicate with Ubuntu One music API
211+ *
212+ * Copyright 2012 Canonical Ltd.
213+ *
214+ * This file is part of Ubuntu One Files Java library.
215+ *
216+ * This program is free software: you can redistribute it and/or modify
217+ * it under the terms of the GNU Affero General Public License as
218+ * published by the Free Software Foundation, either version 3 of the
219+ * License, or (at your option) any later version.
220+ *
221+ * This program is distributed in the hope that it will be useful,
222+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
223+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
224+ * GNU Affero General Public License for more details.
225+ *
226+ * You should have received a copy of the GNU Affero General Public License
227+ * along with this program. If not, see http://www.gnu.org/licenses
228+ */
229+
230+package com.ubuntuone.api.music;
231+
232+import static com.ubuntuone.test.util.SameHttpRequestMatcher.sameRequest;
233+
234+import java.io.IOException;
235+import java.util.ArrayList;
236+
237+import org.apache.http.HttpHost;
238+import org.apache.http.HttpResponse;
239+import org.apache.http.HttpStatus;
240+import org.apache.http.client.HttpClient;
241+import org.apache.http.client.methods.HttpPost;
242+import org.apache.http.entity.StringEntity;
243+import org.jmock.Expectations;
244+import org.jmock.Mockery;
245+import org.jmock.Sequence;
246+import org.jmock.integration.junit4.JMock;
247+import org.jmock.integration.junit4.JUnit4Mockery;
248+import org.junit.Before;
249+import org.junit.Test;
250+import org.junit.runner.RunWith;
251+
252+import com.ubuntuone.api.music.client.BaseClient;
253+import com.ubuntuone.api.music.client.Failure;
254+import com.ubuntuone.api.music.json.U1CustomJson;
255+import com.ubuntuone.api.music.model.U1Meta;
256+import com.ubuntuone.api.music.model.U1PlaylistSong;
257+import com.ubuntuone.api.music.model.U1Song;
258+import com.ubuntuone.api.music.util.RequestListener.U1PlaylistSongRequestListener;
259+import com.ubuntuone.music.util.U1ResponseBuilder;
260+import com.ubuntuone.music.util.U1SongBuilder;
261+import com.ubuntuone.music.util.Util;
262+import com.ubuntuone.test.util.DummyAuthorizer;
263+
264+@RunWith(JMock.class)
265+public class CreatePlaylistTest
266+{
267+ private final Mockery context = new JUnit4Mockery();
268+
269+ private HttpResponse httpResponse;
270+
271+ private HttpHost httpHost =
272+ new HttpHost(U1MusicAPI.RESOURCE_HOST, -1, BaseClient.HTTPS);
273+
274+ private HttpClient httpClient;
275+ private U1MusicAPI musicApi;
276+
277+ private U1PlaylistSongRequestListener playlistSongCallback;
278+
279+ @Before
280+ public void setUp() throws IOException {
281+ httpResponse = Util.buildResponse(HttpStatus.SC_OK);
282+
283+ httpClient = context.mock(HttpClient.class);
284+ musicApi = new U1MusicAPI("ua/1.0", httpClient, new DummyAuthorizer());
285+
286+ playlistSongCallback = context.mock(U1PlaylistSongRequestListener.class);
287+ }
288+
289+ @Test
290+ public void testCreatePlaylistLifeCycleCallbacks() {
291+ String name = "playlist name";
292+ ArrayList<U1Song> songList = new ArrayList<U1Song>();
293+
294+ final Sequence requestSequence = context.sequence("lifecycle");
295+ context.checking(new Expectations() {{
296+ oneOf(playlistSongCallback).onStart();
297+ inSequence(requestSequence);
298+
299+ ignoring(httpClient);
300+ allowing(playlistSongCallback).onSuccess(with(any(U1PlaylistSong.class)));
301+ allowing(playlistSongCallback).onFailure(with(any(Failure.class)));
302+
303+ oneOf(playlistSongCallback).onFinish();
304+ inSequence(requestSequence);
305+ }});
306+
307+ musicApi.createPlaylist(name, songList, playlistSongCallback);
308+ }
309+
310+ @Test
311+ public void testCreatePlaylist() throws IOException {
312+ final U1Meta meta = new U1Meta();
313+ String id = "playlistId";
314+ String name = "playlist name";
315+ ArrayList<U1Song> songList = new ArrayList<U1Song>();
316+
317+ final U1Song song1 = new U1SongBuilder()
318+ .withId("songId1").withAlbumId("Song album 1").build();
319+ songList.add(song1);
320+ final U1PlaylistSong playlistSong1 = new U1PlaylistSong(id, name, song1);
321+
322+ final U1Song song2 = new U1SongBuilder()
323+ .withId("songId2").withAlbumId("Song album 2").build();
324+ songList.add(song2);
325+ final U1PlaylistSong playlistSong2 = new U1PlaylistSong(id, name, song2);
326+
327+ final U1Song song3 = new U1SongBuilder()
328+ .withId("songId3").withAlbumId("Song album 3").build();
329+ songList.add(song3);
330+ final U1PlaylistSong playlistSong3 = new U1PlaylistSong(id, name, song3);
331+
332+ final HttpPost httpRequest = new HttpPost("https://one.ubuntu.com" +
333+ "/music/api/2.0/playlists/");
334+
335+ httpRequest.setEntity(new StringEntity(U1CustomJson
336+ .toSongIdListJson(name, songList)));
337+
338+ String responseJson = U1ResponseBuilder.toJson(
339+ meta, U1MusicAPI.SONGS, id, name, song1, song2, song3);
340+
341+ httpResponse.setEntity(new StringEntity(responseJson, "UTF-8"));
342+
343+ final Sequence requestSequence = context.sequence("lifecycle");
344+ context.checking(new Expectations() {{
345+ oneOf(playlistSongCallback).onStart();
346+ inSequence(requestSequence);
347+
348+ oneOf(httpClient).execute(with(httpHost), with(sameRequest(httpRequest)));
349+ inSequence(requestSequence);
350+ will(returnValue(httpResponse));
351+
352+ oneOf(playlistSongCallback).onSuccess(with(playlistSong1));
353+ inSequence(requestSequence);
354+ oneOf(playlistSongCallback).onSuccess(with(playlistSong2));
355+ inSequence(requestSequence);
356+ oneOf(playlistSongCallback).onSuccess(with(playlistSong3));
357+ inSequence(requestSequence);
358+
359+ oneOf(playlistSongCallback).onFinish();
360+ inSequence(requestSequence);
361+ }});
362+
363+ musicApi.createPlaylist(name, songList, playlistSongCallback);
364+ }
365+
366+ @Test
367+ public void testUpdatePlaylist() throws IOException {
368+ final U1Meta meta = new U1Meta();
369+ String id = "playlistId";
370+ String name = "playlist name";
371+ ArrayList<U1Song> songList = new ArrayList<U1Song>();
372+
373+ final U1Song song1 = new U1SongBuilder()
374+ .withId("songId1").withAlbumId("Song album 1").build();
375+ songList.add(song1);
376+ final U1PlaylistSong playlistSong1 = new U1PlaylistSong(id, name, song1);
377+
378+ final U1Song song2 = new U1SongBuilder()
379+ .withId("songId2").withAlbumId("Song album 2").build();
380+ songList.add(song2);
381+ final U1PlaylistSong playlistSong2 = new U1PlaylistSong(id, name, song2);
382+
383+ final U1Song song3 = new U1SongBuilder()
384+ .withId("songId3").withAlbumId("Song album 3").build();
385+ songList.add(song3);
386+ final U1PlaylistSong playlistSong3 = new U1PlaylistSong(id, name, song3);
387+
388+ final HttpPost httpRequest = new HttpPost("https://one.ubuntu.com" +
389+ "/music/api/2.0/playlists/");
390+
391+ httpRequest.setEntity(new StringEntity(U1CustomJson
392+ .toSongIdListJson(name, songList)));
393+
394+ String responseJson = U1ResponseBuilder.toJson(
395+ meta, U1MusicAPI.SONGS, id, name, song1, song2, song3);
396+
397+ httpResponse.setEntity(new StringEntity(responseJson, "UTF-8"));
398+
399+ final Sequence requestSequence = context.sequence("lifecycle");
400+ context.checking(new Expectations() {{
401+ oneOf(playlistSongCallback).onStart();
402+ inSequence(requestSequence);
403+
404+ oneOf(httpClient).execute(with(httpHost), with(sameRequest(httpRequest)));
405+ inSequence(requestSequence);
406+ will(returnValue(httpResponse));
407+
408+ oneOf(playlistSongCallback).onSuccess(with(playlistSong1));
409+ inSequence(requestSequence);
410+ oneOf(playlistSongCallback).onSuccess(with(playlistSong2));
411+ inSequence(requestSequence);
412+ oneOf(playlistSongCallback).onSuccess(with(playlistSong3));
413+ inSequence(requestSequence);
414+
415+ oneOf(playlistSongCallback).onFinish();
416+ inSequence(requestSequence);
417+ }});
418+
419+ musicApi.createPlaylist(name, songList, playlistSongCallback);
420+ }
421+}
422
423=== modified file 'src/test/com/ubuntuone/api/music/GetAlbumsTest.java'
424--- src/test/com/ubuntuone/api/music/GetAlbumsTest.java 2012-08-21 14:13:25 +0000
425+++ src/test/com/ubuntuone/api/music/GetAlbumsTest.java 2012-08-21 14:13:25 +0000
426@@ -43,9 +43,11 @@
427 import com.ubuntuone.api.music.client.BaseClient;
428 import com.ubuntuone.api.music.client.Failure;
429 import com.ubuntuone.api.music.model.U1Album;
430+import com.ubuntuone.api.music.model.U1Artist;
431 import com.ubuntuone.api.music.model.U1Meta;
432 import com.ubuntuone.api.music.util.RequestListener.U1AlbumRequestListener;
433 import com.ubuntuone.music.util.U1AlbumBuilder;
434+import com.ubuntuone.music.util.U1ArtistBuilder;
435 import com.ubuntuone.music.util.U1ResponseBuilder;
436 import com.ubuntuone.music.util.Util;
437 import com.ubuntuone.test.util.DummyAuthorizer;
438@@ -164,4 +166,51 @@
439
440 musicApi.getAlbums(albumCallback);
441 }
442+
443+ @Test
444+ public void testGetMultipleAlbumsByArtist() throws IOException {
445+ final U1Meta meta = new U1Meta();
446+ final U1Album album1 = new U1AlbumBuilder()
447+ .withId("albumId1").withTitle("Album 1")
448+ .withArtist("Artist 1").build();
449+ final U1Album album2 = new U1AlbumBuilder()
450+ .withId("albumId2").withTitle("Album 2")
451+ .withArtist("Artist 2").build();
452+ final U1Album album3 = new U1AlbumBuilder()
453+ .withId("albumId3").withTitle("Album 3")
454+ .withArtist("Artist 3").build();
455+
456+ final U1Artist artist = new U1ArtistBuilder().build();
457+
458+ httpRequest = new HttpGet(String.format(
459+ "https://one.ubuntu.com/music/api/2.0/albums/%s/",
460+ artist.getId()));
461+
462+ String responseJson = U1ResponseBuilder.toJson(
463+ meta, U1MusicAPI.ALBUMS, album1, album2, album3);
464+
465+ httpResponse.setEntity(new StringEntity(responseJson, "UTF-8"));
466+
467+ final Sequence requestSequence = context.sequence("lifecycle");
468+ context.checking(new Expectations() {{
469+ oneOf(albumCallback).onStart();
470+ inSequence(requestSequence);
471+
472+ oneOf(httpClient).execute(with(httpHost), with(sameRequest(httpRequest)));
473+ inSequence(requestSequence);
474+ will(returnValue(httpResponse));
475+
476+ oneOf(albumCallback).onSuccess(with(album1));
477+ inSequence(requestSequence);
478+ oneOf(albumCallback).onSuccess(with(album2));
479+ inSequence(requestSequence);
480+ oneOf(albumCallback).onSuccess(with(album3));
481+ inSequence(requestSequence);
482+
483+ oneOf(albumCallback).onFinish();
484+ inSequence(requestSequence);
485+ }});
486+
487+ musicApi.getAlbumsByArtist(artist.getId(), albumCallback);
488+ }
489 }
490
491=== removed file 'src/test/com/ubuntuone/api/music/PutPlaylistTest.java'
492--- src/test/com/ubuntuone/api/music/PutPlaylistTest.java 2012-08-21 14:13:25 +0000
493+++ src/test/com/ubuntuone/api/music/PutPlaylistTest.java 1970-01-01 00:00:00 +0000
494@@ -1,153 +0,0 @@
495-/*
496- * Ubuntu One Music Java library - communicate with Ubuntu One music API
497- *
498- * Copyright 2012 Canonical Ltd.
499- *
500- * This file is part of Ubuntu One Files Java library.
501- *
502- * This program is free software: you can redistribute it and/or modify
503- * it under the terms of the GNU Affero General Public License as
504- * published by the Free Software Foundation, either version 3 of the
505- * License, or (at your option) any later version.
506- *
507- * This program is distributed in the hope that it will be useful,
508- * but WITHOUT ANY WARRANTY; without even the implied warranty of
509- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
510- * GNU Affero General Public License for more details.
511- *
512- * You should have received a copy of the GNU Affero General Public License
513- * along with this program. If not, see http://www.gnu.org/licenses
514- */
515-
516-package com.ubuntuone.api.music;
517-
518-import static com.ubuntuone.test.util.SameHttpRequestMatcher.sameRequest;
519-
520-import java.io.IOException;
521-import java.util.ArrayList;
522-
523-import org.apache.http.HttpHost;
524-import org.apache.http.HttpResponse;
525-import org.apache.http.HttpStatus;
526-import org.apache.http.client.HttpClient;
527-import org.apache.http.client.methods.HttpPost;
528-import org.apache.http.entity.StringEntity;
529-import org.jmock.Expectations;
530-import org.jmock.Mockery;
531-import org.jmock.Sequence;
532-import org.jmock.integration.junit4.JMock;
533-import org.jmock.integration.junit4.JUnit4Mockery;
534-import org.junit.Before;
535-import org.junit.Test;
536-import org.junit.runner.RunWith;
537-
538-import com.ubuntuone.api.music.client.BaseClient;
539-import com.ubuntuone.api.music.client.Failure;
540-import com.ubuntuone.api.music.model.U1Meta;
541-import com.ubuntuone.api.music.model.U1PlaylistSong;
542-import com.ubuntuone.api.music.model.U1Song;
543-import com.ubuntuone.api.music.util.RequestListener.U1PlaylistSongRequestListener;
544-import com.ubuntuone.music.util.U1ResponseBuilder;
545-import com.ubuntuone.music.util.U1SongBuilder;
546-import com.ubuntuone.music.util.Util;
547-import com.ubuntuone.test.util.DummyAuthorizer;
548-
549-@RunWith(JMock.class)
550-public class PutPlaylistTest
551-{
552- private final Mockery context = new JUnit4Mockery();
553-
554- private HttpResponse httpResponse;
555-
556- private HttpHost httpHost =
557- new HttpHost(U1MusicAPI.RESOURCE_HOST, -1, BaseClient.HTTPS);
558-
559- private HttpClient httpClient;
560- private U1MusicAPI musicApi;
561-
562- private U1PlaylistSongRequestListener playlistSongCallback;
563-
564- @Before
565- public void setUp() throws IOException {
566- httpResponse = Util.buildResponse(HttpStatus.SC_OK);
567-
568- httpClient = context.mock(HttpClient.class);
569- musicApi = new U1MusicAPI("ua/1.0", httpClient, new DummyAuthorizer());
570-
571- playlistSongCallback = context.mock(U1PlaylistSongRequestListener.class);
572- }
573-
574- @Test
575- public void testCreatePlaylistLifeCycleCallbacks() {
576- String name = "playlist name";
577- ArrayList<U1Song> songList = new ArrayList<U1Song>();
578-
579- final Sequence requestSequence = context.sequence("lifecycle");
580- context.checking(new Expectations() {{
581- oneOf(playlistSongCallback).onStart();
582- inSequence(requestSequence);
583-
584- ignoring(httpClient);
585- allowing(playlistSongCallback).onSuccess(with(any(U1PlaylistSong.class)));
586- allowing(playlistSongCallback).onFailure(with(any(Failure.class)));
587-
588- oneOf(playlistSongCallback).onFinish();
589- inSequence(requestSequence);
590- }});
591-
592- musicApi.createPlaylist(name, songList, playlistSongCallback);
593- }
594-
595- @Test
596- public void testCreatePlaylist() throws IOException {
597- final U1Meta meta = new U1Meta();
598- String id = "playlistId";
599- String name = "playlist name";
600- ArrayList<U1Song> songList = new ArrayList<U1Song>();
601-
602- final U1Song song1 = new U1SongBuilder()
603- .withId("songId1").withAlbumId("Song album 1").build();
604- songList.add(song1);
605- final U1PlaylistSong playlistSong1 = new U1PlaylistSong(id, name, song1);
606-
607- final U1Song song2 = new U1SongBuilder()
608- .withId("songId2").withAlbumId("Song album 2").build();
609- songList.add(song2);
610- final U1PlaylistSong playlistSong2 = new U1PlaylistSong(id, name, song2);
611-
612- final U1Song song3 = new U1SongBuilder()
613- .withId("songId3").withAlbumId("Song album 3").build();
614- songList.add(song3);
615- final U1PlaylistSong playlistSong3 = new U1PlaylistSong(id, name, song3);
616-
617- final HttpPost httpRequest = new HttpPost("https://one.ubuntu.com" +
618- "/music/api/2.0/playlists/");
619-
620- String responseJson = U1ResponseBuilder.toJson(
621- meta, U1MusicAPI.SONGS, id, name, song1, song2, song3);
622-
623- httpResponse.setEntity(new StringEntity(responseJson, "UTF-8"));
624-
625- final Sequence requestSequence = context.sequence("lifecycle");
626- context.checking(new Expectations() {{
627- oneOf(playlistSongCallback).onStart();
628- inSequence(requestSequence);
629-
630- oneOf(httpClient).execute(with(httpHost), with(sameRequest(httpRequest)));
631- inSequence(requestSequence);
632- will(returnValue(httpResponse));
633-
634- oneOf(playlistSongCallback).onSuccess(with(playlistSong1));
635- inSequence(requestSequence);
636- oneOf(playlistSongCallback).onSuccess(with(playlistSong2));
637- inSequence(requestSequence);
638- oneOf(playlistSongCallback).onSuccess(with(playlistSong3));
639- inSequence(requestSequence);
640-
641- oneOf(playlistSongCallback).onFinish();
642- inSequence(requestSequence);
643- }});
644-
645- musicApi.createPlaylist(name, songList, playlistSongCallback);
646- }
647-}
648
649=== added file 'src/test/com/ubuntuone/api/music/UpdatePlaylistTest.java'
650--- src/test/com/ubuntuone/api/music/UpdatePlaylistTest.java 1970-01-01 00:00:00 +0000
651+++ src/test/com/ubuntuone/api/music/UpdatePlaylistTest.java 2012-08-21 14:13:25 +0000
652@@ -0,0 +1,157 @@
653+/*
654+ * Ubuntu One Music Java library - communicate with Ubuntu One music API
655+ *
656+ * Copyright 2012 Canonical Ltd.
657+ *
658+ * This file is part of Ubuntu One Files Java library.
659+ *
660+ * This program is free software: you can redistribute it and/or modify
661+ * it under the terms of the GNU Affero General Public License as
662+ * published by the Free Software Foundation, either version 3 of the
663+ * License, or (at your option) any later version.
664+ *
665+ * This program is distributed in the hope that it will be useful,
666+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
667+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
668+ * GNU Affero General Public License for more details.
669+ *
670+ * You should have received a copy of the GNU Affero General Public License
671+ * along with this program. If not, see http://www.gnu.org/licenses
672+ */
673+
674+package com.ubuntuone.api.music;
675+
676+import static com.ubuntuone.test.util.SameHttpRequestMatcher.sameRequest;
677+
678+import java.io.IOException;
679+import java.util.ArrayList;
680+
681+import org.apache.http.HttpHost;
682+import org.apache.http.HttpResponse;
683+import org.apache.http.HttpStatus;
684+import org.apache.http.client.HttpClient;
685+import org.apache.http.client.methods.HttpPost;
686+import org.apache.http.entity.StringEntity;
687+import org.jmock.Expectations;
688+import org.jmock.Mockery;
689+import org.jmock.Sequence;
690+import org.jmock.integration.junit4.JMock;
691+import org.jmock.integration.junit4.JUnit4Mockery;
692+import org.junit.Before;
693+import org.junit.Test;
694+import org.junit.runner.RunWith;
695+
696+import com.ubuntuone.api.music.client.BaseClient;
697+import com.ubuntuone.api.music.client.Failure;
698+import com.ubuntuone.api.music.json.U1CustomJson;
699+import com.ubuntuone.api.music.model.U1Meta;
700+import com.ubuntuone.api.music.model.U1PlaylistSong;
701+import com.ubuntuone.api.music.model.U1Song;
702+import com.ubuntuone.api.music.util.RequestListener.U1PlaylistSongRequestListener;
703+import com.ubuntuone.music.util.U1ResponseBuilder;
704+import com.ubuntuone.music.util.U1SongBuilder;
705+import com.ubuntuone.music.util.Util;
706+import com.ubuntuone.test.util.DummyAuthorizer;
707+
708+@RunWith(JMock.class)
709+public class UpdatePlaylistTest
710+{
711+ private final Mockery context = new JUnit4Mockery();
712+
713+ private HttpResponse httpResponse;
714+
715+ private HttpHost httpHost =
716+ new HttpHost(U1MusicAPI.RESOURCE_HOST, -1, BaseClient.HTTPS);
717+
718+ private HttpClient httpClient;
719+ private U1MusicAPI musicApi;
720+
721+ private U1PlaylistSongRequestListener playlistSongCallback;
722+
723+ @Before
724+ public void setUp() throws IOException {
725+ httpResponse = Util.buildResponse(HttpStatus.SC_OK);
726+
727+ httpClient = context.mock(HttpClient.class);
728+ musicApi = new U1MusicAPI("ua/1.0", httpClient, new DummyAuthorizer());
729+
730+ playlistSongCallback = context.mock(U1PlaylistSongRequestListener.class);
731+ }
732+
733+ @Test
734+ public void testCreatePlaylistLifeCycleCallbacks() {
735+ String name = "playlist name";
736+ ArrayList<U1Song> songList = new ArrayList<U1Song>();
737+
738+ final Sequence requestSequence = context.sequence("lifecycle");
739+ context.checking(new Expectations() {{
740+ oneOf(playlistSongCallback).onStart();
741+ inSequence(requestSequence);
742+
743+ ignoring(httpClient);
744+ allowing(playlistSongCallback).onSuccess(with(any(U1PlaylistSong.class)));
745+ allowing(playlistSongCallback).onFailure(with(any(Failure.class)));
746+
747+ oneOf(playlistSongCallback).onFinish();
748+ inSequence(requestSequence);
749+ }});
750+
751+ musicApi.createPlaylist(name, songList, playlistSongCallback);
752+ }
753+
754+ @Test
755+ public void testCreatePlaylist() throws IOException {
756+ final U1Meta meta = new U1Meta();
757+ String id = "playlistId";
758+ String name = "playlist name";
759+ ArrayList<U1Song> songList = new ArrayList<U1Song>();
760+
761+ final U1Song song1 = new U1SongBuilder()
762+ .withId("songId1").withAlbumId("Song album 1").build();
763+ songList.add(song1);
764+ final U1PlaylistSong playlistSong1 = new U1PlaylistSong(id, name, song1);
765+
766+ final U1Song song2 = new U1SongBuilder()
767+ .withId("songId2").withAlbumId("Song album 2").build();
768+ songList.add(song2);
769+ final U1PlaylistSong playlistSong2 = new U1PlaylistSong(id, name, song2);
770+
771+ final U1Song song3 = new U1SongBuilder()
772+ .withId("songId3").withAlbumId("Song album 3").build();
773+ songList.add(song3);
774+ final U1PlaylistSong playlistSong3 = new U1PlaylistSong(id, name, song3);
775+
776+ final HttpPost httpRequest = new HttpPost("https://one.ubuntu.com" +
777+ "/music/api/2.0/playlists/");
778+
779+ httpRequest.setEntity(new StringEntity(U1CustomJson
780+ .toSongIdListJson(name, songList)));
781+
782+ String responseJson = U1ResponseBuilder.toJson(
783+ meta, U1MusicAPI.SONGS, id, name, song1, song2, song3);
784+
785+ httpResponse.setEntity(new StringEntity(responseJson, "UTF-8"));
786+
787+ final Sequence requestSequence = context.sequence("lifecycle");
788+ context.checking(new Expectations() {{
789+ oneOf(playlistSongCallback).onStart();
790+ inSequence(requestSequence);
791+
792+ oneOf(httpClient).execute(with(httpHost), with(sameRequest(httpRequest)));
793+ inSequence(requestSequence);
794+ will(returnValue(httpResponse));
795+
796+ oneOf(playlistSongCallback).onSuccess(with(playlistSong1));
797+ inSequence(requestSequence);
798+ oneOf(playlistSongCallback).onSuccess(with(playlistSong2));
799+ inSequence(requestSequence);
800+ oneOf(playlistSongCallback).onSuccess(with(playlistSong3));
801+ inSequence(requestSequence);
802+
803+ oneOf(playlistSongCallback).onFinish();
804+ inSequence(requestSequence);
805+ }});
806+
807+ musicApi.createPlaylist(name, songList, playlistSongCallback);
808+ }
809+}
810
811=== added file 'src/test/com/ubuntuone/api/music/json/U1CustomJsonTest.java'
812--- src/test/com/ubuntuone/api/music/json/U1CustomJsonTest.java 1970-01-01 00:00:00 +0000
813+++ src/test/com/ubuntuone/api/music/json/U1CustomJsonTest.java 2012-08-21 14:13:25 +0000
814@@ -0,0 +1,59 @@
815+/*
816+ * Ubuntu One Music Java library - communicate with Ubuntu One music API
817+ *
818+ * Copyright 2012 Canonical Ltd.
819+ *
820+ * This file is part of Ubuntu One Files Java library.
821+ *
822+ * This program is free software: you can redistribute it and/or modify
823+ * it under the terms of the GNU Affero General Public License as
824+ * published by the Free Software Foundation, either version 3 of the
825+ * License, or (at your option) any later version.
826+ *
827+ * This program is distributed in the hope that it will be useful,
828+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
829+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
830+ * GNU Affero General Public License for more details.
831+ *
832+ * You should have received a copy of the GNU Affero General Public License
833+ * along with this program. If not, see http://www.gnu.org/licenses
834+ */
835+
836+package com.ubuntuone.api.music.json;
837+
838+import static junit.framework.Assert.assertEquals;
839+
840+import java.io.IOException;
841+import java.util.ArrayList;
842+
843+import org.junit.Test;
844+
845+import com.ubuntuone.api.music.model.U1Song;
846+import com.ubuntuone.music.util.U1SongBuilder;
847+
848+public class U1CustomJsonTest
849+{
850+ @Test
851+ public void testEncodeU1SongIdListPlaylist() throws IOException {
852+ final ArrayList<U1Song> songList = new ArrayList<U1Song>();
853+
854+ final U1Song song1 = new U1SongBuilder()
855+ .withId("id1").build();
856+ songList.add(song1);
857+ final U1Song song2 = new U1SongBuilder()
858+ .withId("id2").build();
859+ songList.add(song2);
860+
861+ String name = "the playlist name";
862+
863+ String json = U1CustomJson.toSongIdListJson(name, songList);
864+
865+ String expectedJson = "{\"name\":\"" + name + "\"," +
866+ "\"song_id_list\":[" +
867+ "\"" + song1.getId() + "\"," +
868+ "\"" + song2.getId() + "\"" +
869+ "]}";
870+
871+ assertEquals(expectedJson, json);
872+ }
873+}
874
875=== modified file 'src/test/com/ubuntuone/test/util/SameHttpRequestMatcher.java'
876--- src/test/com/ubuntuone/test/util/SameHttpRequestMatcher.java 2012-08-21 14:13:25 +0000
877+++ src/test/com/ubuntuone/test/util/SameHttpRequestMatcher.java 2012-08-21 14:13:25 +0000
878@@ -21,7 +21,14 @@
879
880 package com.ubuntuone.test.util;
881
882+import java.io.IOException;
883+import java.io.InputStream;
884+
885+import org.apache.http.ParseException;
886+import org.apache.http.client.methods.HttpPost;
887+import org.apache.http.client.methods.HttpPut;
888 import org.apache.http.client.methods.HttpUriRequest;
889+import org.apache.http.util.EntityUtils;
890 import org.hamcrest.Description;
891 import org.hamcrest.Factory;
892 import org.hamcrest.Matcher;
893@@ -40,6 +47,31 @@
894 public void describeTo(Description description) {
895 description.appendText("a request with request line ")
896 .appendValue(request.getRequestLine());
897+ if (request.getClass() == HttpPost.class) {
898+ HttpPost post = (HttpPost) request;
899+ if (post.getEntity() != null) {
900+ try {
901+ description.appendText("and POST body ")
902+ .appendValue(EntityUtils.toString(post.getEntity()));
903+ } catch (ParseException e) {
904+ description.appendText("and broken POST body!");
905+ } catch (IOException e) {
906+ description.appendText("and broken POST body!");
907+ }
908+ }
909+ } else if (request.getClass() == HttpPut.class) {
910+ HttpPut put = (HttpPut) request;
911+ if (put.getEntity() != null) {
912+ try {
913+ description.appendText("and PUT body ")
914+ .appendValue(EntityUtils.toString(put.getEntity()));
915+ } catch (ParseException e) {
916+ description.appendText("and broken PUT body ");
917+ } catch (IOException e) {
918+ description.appendText("and broken PUT body ");
919+ }
920+ }
921+ }
922 }
923
924 @Override
925@@ -48,8 +80,47 @@
926 return false;
927 if (item == request)
928 return true;
929+ boolean sameBody = true;
930+ if (request.getClass() == HttpPost.class) {
931+ HttpPost postRequest = (HttpPost) request;
932+ HttpPost postItem = (HttpPost) item;
933+ if (postRequest.getEntity() != null) {
934+ try {
935+ InputStream in1 = postRequest.getEntity().getContent();
936+ if (postItem.getEntity() != null) {
937+ InputStream in2 = postItem.getEntity().getContent();
938+ sameBody = StreamUtils.streamsHaveSameContent(in1, in2);
939+ } else {
940+ sameBody = false;
941+ }
942+ } catch (IllegalStateException e) {
943+ return false;
944+ } catch (IOException e) {
945+ return false;
946+ }
947+ }
948+ } else if (request.getClass() == HttpPut.class) {
949+ HttpPut putRequest = (HttpPut) request;
950+ HttpPut putItem = (HttpPut) item;
951+ if (putRequest.getEntity() != null) {
952+ try {
953+ InputStream in1 = putRequest.getEntity().getContent();
954+ if (putItem.getEntity() != null) {
955+ InputStream in2 = putItem.getEntity().getContent();
956+ sameBody = StreamUtils.streamsHaveSameContent(in1, in2);
957+ } else {
958+ sameBody = false;
959+ }
960+ } catch (IllegalStateException e) {
961+ return false;
962+ } catch (IOException e) {
963+ return false;
964+ }
965+ }
966+ }
967 return request.getMethod().equals(item.getMethod())
968- && request.getURI().equals(item.getURI());
969+ && request.getURI().equals(item.getURI())
970+ && sameBody;
971 }
972
973 @Factory
974
975=== added file 'src/test/com/ubuntuone/test/util/StreamUtils.java'
976--- src/test/com/ubuntuone/test/util/StreamUtils.java 1970-01-01 00:00:00 +0000
977+++ src/test/com/ubuntuone/test/util/StreamUtils.java 2012-08-21 14:13:25 +0000
978@@ -0,0 +1,27 @@
979+package com.ubuntuone.test.util;
980+
981+import java.io.IOException;
982+import java.io.InputStream;
983+
984+public class StreamUtils
985+{
986+ public static boolean streamsHaveSameContent(InputStream in1, InputStream in2) {
987+ boolean same = true;
988+ int b1, b2;
989+ try {
990+ while ((b1 = in1.read()) != -1) {
991+ b2 = in2.read();
992+ if (b1 != b2) {
993+ same = false;
994+ break;
995+ }
996+ }
997+ if (in2.read() != -1) {
998+ same = false;
999+ }
1000+ } catch (IOException e) {
1001+ same = false;
1002+ }
1003+ return same;
1004+ }
1005+}

Subscribers

People subscribed via source and target branches