/*
DConnectTestCase.java
Copyright (c) 2014 NTT DOCOMO,INC.
Released under the MIT license
http://opensource.org/licenses/mit-license.php
*/
package org.deviceconnect.android.test;
import android.support.test.InstrumentationRegistry;
import android.test.AndroidTestCase;
import org.deviceconnect.android.profile.AuthorizationProfile;
import org.deviceconnect.android.profile.ServiceDiscoveryProfile;
import org.deviceconnect.message.DConnectMessage;
import org.deviceconnect.message.DConnectResponseMessage;
import org.deviceconnect.message.DConnectSDK;
import org.deviceconnect.profile.ServiceDiscoveryProfileConstants;
import org.deviceconnect.profile.ServiceInformationProfileConstants;
import org.deviceconnect.profile.SystemProfileConstants;
import org.junit.Before;
import java.util.ArrayList;
import java.util.List;
/**
* DeviceConnectのTestCaseのスーパークラス.
* @author NTT DOCOMO, INC.
*/
public abstract class DConnectTestCase extends AndroidTestCase {
/**
* DeviceConnectManagerへのURI.
*/
protected static final String MANAGER_URI = "http://localhost:4035/gotapi";
/**
* テスト用デバイス名.
*/
private static final String DEVICE_NAME = "Test Success Device";
/**
* DeviceConnectManagerへアクセスするインターフェース.
*/
protected DConnectSDK mDConnectSDK;
/**
* プロファイル一覧.
* <p>
* OAuth処理でのスコープの指定に使用する.
* </p>
*/
private static final String[] PROFILES = {
ServiceDiscoveryProfileConstants.PROFILE_NAME,
ServiceInformationProfileConstants.PROFILE_NAME,
SystemProfileConstants.PROFILE_NAME,
"deviceOrientation",
"files",
"unique",
"jsonTest",
"dataTest",
"allGetControl",
"abc" // 実際には実装しないプロファイル
};
/** デバイス一覧. */
private List<ServiceInfo> mServiceInfoList;
/** アクセストークン. */
private static String sAccessToken;
@Before
public void setUp() throws Exception {
setContext(InstrumentationRegistry.getContext());
mDConnectSDK.setOrigin(getOrigin());
waitForManager();
if (isLocalOAuth()) {
// アクセストークン取得
if (sAccessToken == null) {
sAccessToken = requestAccessToken(PROFILES);
assertNotNull(sAccessToken);
}
if (mDConnectSDK != null) {
mDConnectSDK.setAccessToken(sAccessToken);
}
}
}
/**
* Managerが起動するまでブロックする.
* @throws InterruptedException スレッドが割り込まれた場合
*/
private void waitForManager() throws InterruptedException {
mDConnectSDK.startManager(getContext());
long timeout = 30 * 1000;
final long interval = 250;
while (!isManagerAvailable()) {
Thread.sleep(interval);
timeout -= interval;
if (timeout <= 0) {
fail("Manager launching timeout.");
}
}
}
/**
* Device Connect Managerに対してアクセストークン取得リクエストを送信する.
* <p>
* レスポンスとしてアクセストークンを受信できなかった場合はnullを返す。
* </p>
* @param scopes スコープ指定
* @return アクセストークン
*/
private String requestAccessToken(final String[] scopes) {
DConnectResponseMessage response = mDConnectSDK.authorization("JUnitTest", scopes);
if (response.getResult() == DConnectMessage.RESULT_OK) {
return response.getString(AuthorizationProfile.PARAM_ACCESS_TOKEN);
} else {
return null;
}
}
/**
* デバイス一覧をRestfulAPIで取得する.
* @return デバイス一覧
*/
private List<ServiceInfo> searchServices() {
List<ServiceInfo> services = new ArrayList<>();
DConnectResponseMessage response = mDConnectSDK.serviceDiscovery();
if (response.getResult() == DConnectMessage.RESULT_ERROR) {
fail("Failed to discover services.");
}
List<Object> list = response.getList(ServiceDiscoveryProfile.PARAM_SERVICES);
for (Object value : list) {
DConnectMessage service = (DConnectMessage) value;
String serviceId = service.getString(ServiceDiscoveryProfileConstants.PARAM_ID);
String deviceName = service.getString(ServiceDiscoveryProfileConstants.PARAM_NAME);
services.add(new ServiceInfo(serviceId, deviceName));
}
return services;
}
/**
* Device Connect Managerが起動しているかどうかを確認する.
* @return Device Connect Managerが起動している場合はtrue、そうでない場合はfalse
*/
private boolean isManagerAvailable() {
DConnectResponseMessage response = mDConnectSDK.availability();
return response.getResult() == DConnectMessage.RESULT_OK;
}
/**
* Originを取得する.
*
* @return Origin
*/
protected String getOrigin() {
return InstrumentationRegistry.getContext().getPackageName();
}
/**
* アクセストークンのオンメモリ上のキャッシュを取得する.
*
* @return アクセストークンのオンメモリ上のキャッシュ
*/
protected String getAccessToken() {
return sAccessToken;
}
/**
* スコープを連結する.
* @param scopes 連結するスコープ
* @return 連結した文字列
*/
protected String combineStr(final String[] scopes) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < scopes.length; i++) {
if (i > 0) {
builder.append(",");
}
builder.append(scopes[i].trim());
}
return builder.toString();
}
/**
* 各テストメソッド実行前に、LocalOAuth認証を行うかどうかの設定を取得する.
* @return テスト実行前にLocalOAuth認証を行う場合はtrue、そうでない場合はfalse
*/
protected boolean isLocalOAuth() {
return true;
}
/**
* サービスIDを取得する.
* @return サービスID
*/
protected String getServiceId() {
if (mServiceInfoList == null) {
mServiceInfoList = searchServices();
}
return getServiceIdByName(DEVICE_NAME);
}
/**
* 指定したデバイス名をもつデバイスのIDを取得する.
* @param deviceName デバイス名
* @return サービスID
*/
private String getServiceIdByName(final String deviceName) {
for (int i = 0; i < mServiceInfoList.size(); i++) {
ServiceInfo obj = mServiceInfoList.get(i);
if (deviceName.equals(obj.getDeviceName())) {
return obj.getServiceId();
}
}
return null;
}
/**
* サービス情報.
*/
private static class ServiceInfo {
/**
* サービスID.
*/
private final String mServiceId;
/**
* デバイス名.
*/
private final String mDeviceName;
/**
* コンストラクタ.
* @param serviceId サービスID
* @param deviceName デバイス名
*/
ServiceInfo(final String serviceId, final String deviceName) {
mServiceId = serviceId;
mDeviceName = deviceName;
}
/**
* サービスIDを取得する.
*
* @return サービスID
*/
private String getServiceId() {
return mServiceId;
}
/**
* デバイス名を取得する.
*
* @return デバイス名
*/
private String getDeviceName() {
return mDeviceName;
}
}
}