commit
b9cfc0ed6d
|
@ -0,0 +1,47 @@
|
||||||
|
package org.moire.ultrasonic.api.subsonic
|
||||||
|
|
||||||
|
import okhttp3.mockwebserver.MockResponse
|
||||||
|
import org.amshove.kluent.`should equal to`
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.moire.ultrasonic.api.subsonic.SubsonicAPIVersions.V1_6_0
|
||||||
|
import org.moire.ultrasonic.api.subsonic.rules.MockWebServerRule
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration test for [SubsonicAPIClient.getStreamUrl] method.
|
||||||
|
*/
|
||||||
|
class GetStreamUrlTest {
|
||||||
|
@JvmField @Rule val mockWebServerRule = MockWebServerRule()
|
||||||
|
|
||||||
|
val id = "boom"
|
||||||
|
private lateinit var client: SubsonicAPIClient
|
||||||
|
private lateinit var expectedUrl: String
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
client = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(),
|
||||||
|
USERNAME, PASSWORD, V1_6_0, CLIENT_ID)
|
||||||
|
val baseExpectedUrl = mockWebServerRule.mockWebServer.url("").toString()
|
||||||
|
expectedUrl = "$baseExpectedUrl/rest/stream.view?id=$id&u=$USERNAME" +
|
||||||
|
"&p=${client.passwordHex}&v=${V1_6_0.restApiVersion}&c=$CLIENT_ID&f=json"
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Should return valid stream url`() {
|
||||||
|
mockWebServerRule.enqueueResponse("ping_ok.json")
|
||||||
|
|
||||||
|
val streamUrl = client.getStreamUrl(id)
|
||||||
|
|
||||||
|
streamUrl `should equal to` expectedUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Should still return stream url if connection failed`() {
|
||||||
|
mockWebServerRule.mockWebServer.enqueue(MockResponse().setResponseCode(500))
|
||||||
|
|
||||||
|
val streamUrl = client.getStreamUrl(id)
|
||||||
|
|
||||||
|
streamUrl `should equal to` expectedUrl
|
||||||
|
}
|
||||||
|
}
|
|
@ -131,6 +131,22 @@ class SubsonicAPIClient(baseUrl: String,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get stream url.
|
||||||
|
*
|
||||||
|
* Calling this method do actual connection to the backend, though not downloading all content.
|
||||||
|
*
|
||||||
|
* Consider do not use this method, but [stream] call.
|
||||||
|
*/
|
||||||
|
fun getStreamUrl(id: String): String {
|
||||||
|
val request = api.stream(id).execute()
|
||||||
|
val url = request.raw().request().url().toString()
|
||||||
|
if (request.isSuccessful) {
|
||||||
|
request.body().close()
|
||||||
|
}
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
|
||||||
private val salt: String by lazy {
|
private val salt: String by lazy {
|
||||||
val secureRandom = SecureRandom()
|
val secureRandom = SecureRandom()
|
||||||
BigInteger(130, secureRandom).toString(32)
|
BigInteger(130, secureRandom).toString(32)
|
||||||
|
@ -145,7 +161,7 @@ class SubsonicAPIClient(baseUrl: String,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val passwordHex: String by lazy {
|
internal val passwordHex: String by lazy {
|
||||||
"enc:${password.toHexBytes()}"
|
"enc:${password.toHexBytes()}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,8 @@ import java.io.OutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import kotlin.Pair;
|
import kotlin.Pair;
|
||||||
import retrofit2.Response;
|
import retrofit2.Response;
|
||||||
|
@ -739,12 +741,30 @@ public class RESTMusicService implements MusicService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getVideoUrl(Context context, String id, boolean useFlash) throws Exception {
|
public String getVideoUrl(final Context context,
|
||||||
|
final String id,
|
||||||
|
final boolean useFlash) throws Exception {
|
||||||
// This method should not exists as video should be loaded using stream method
|
// This method should not exists as video should be loaded using stream method
|
||||||
// Previous method implementation uses assumption that video will be available
|
// Previous method implementation uses assumption that video will be available
|
||||||
// by videoPlayer.view?id=<id>&maxBitRate=500&autoplay=true, but this url is not
|
// by videoPlayer.view?id=<id>&maxBitRate=500&autoplay=true, but this url is not
|
||||||
// official Subsonic API call.
|
// official Subsonic API call.
|
||||||
throw new UnsupportedOperationException("This method is not longer supported");
|
if (id == null) {
|
||||||
|
throw new IllegalArgumentException("Id is null");
|
||||||
|
}
|
||||||
|
final String[] expectedResult = new String[1];
|
||||||
|
expectedResult[0] = null;
|
||||||
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
expectedResult[0] = subsonicAPIClient.getStreamUrl(id) + "&format=raw";
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
}, "Get-Video-Url").start();
|
||||||
|
|
||||||
|
latch.await(3, TimeUnit.SECONDS);
|
||||||
|
return expectedResult[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue