diff options
Diffstat (limited to 'android/sdl_android/src/androidTest/java/com/smartdevicelink/managers')
10 files changed, 3090 insertions, 0 deletions
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/SdlManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/SdlManagerTests.java new file mode 100644 index 000000000..b1a1df0ed --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/SdlManagerTests.java @@ -0,0 +1,393 @@ +package com.smartdevicelink.managers; + +import android.content.Context; + +import com.smartdevicelink.AndroidTestCase2; +import com.smartdevicelink.exception.SdlException; +import com.smartdevicelink.managers.lockscreen.LockScreenConfig; +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.proxy.RPCMessage; +import com.smartdevicelink.proxy.RPCRequest; +import com.smartdevicelink.proxy.RPCResponse; +import com.smartdevicelink.proxy.SdlProxyBase; +import com.smartdevicelink.proxy.rpc.GetAppServiceDataResponse; +import com.smartdevicelink.proxy.rpc.GetVehicleData; +import com.smartdevicelink.proxy.rpc.OnAppServiceData; +import com.smartdevicelink.proxy.rpc.Show; +import com.smartdevicelink.proxy.rpc.TemplateColorScheme; +import com.smartdevicelink.proxy.rpc.enums.AppHMIType; +import com.smartdevicelink.proxy.rpc.enums.Language; +import com.smartdevicelink.proxy.rpc.enums.Result; +import com.smartdevicelink.proxy.rpc.listeners.OnMultipleRequestListener; +import com.smartdevicelink.proxy.rpc.listeners.OnRPCResponseListener; +import com.smartdevicelink.test.Test; +import com.smartdevicelink.transport.BaseTransportConfig; +import com.smartdevicelink.transport.TCPTransportConfig; + +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.util.Arrays; +import java.util.List; +import java.util.Vector; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; + +/** + * This is a unit test class for the SmartDeviceLink library manager class : + * {@link com.smartdevicelink.managers.SdlManager} + */ +public class SdlManagerTests extends AndroidTestCase2 { + + public static BaseTransportConfig transport = null; + private Context mTestContext; + private Vector<AppHMIType> appType; + private TemplateColorScheme templateColorScheme; + private int listenerCalledCounter; + private SdlManager sdlManager; + private SdlProxyBase sdlProxyBase; + + // transport related + @SuppressWarnings("FieldCanBeLocal") + private int TCP_PORT = 12345; + @SuppressWarnings("FieldCanBeLocal") + private String DEV_MACHINE_IP_ADDRESS = "0.0.0.0"; + + @Override + public void setUp() throws Exception{ + super.setUp(); + + // set transport + transport = new TCPTransportConfig(TCP_PORT, DEV_MACHINE_IP_ADDRESS, true); + + // add AppTypes + appType = new Vector<>(); + appType.add(AppHMIType.DEFAULT); + + // Color Scheme + templateColorScheme = new TemplateColorScheme(); + templateColorScheme.setBackgroundColor(Test.GENERAL_RGBCOLOR); + templateColorScheme.setPrimaryColor(Test.GENERAL_RGBCOLOR); + templateColorScheme.setSecondaryColor(Test.GENERAL_RGBCOLOR); + + sdlManager = createSampleManager("heyApp", "123456", Test.GENERAL_LOCKSCREENCONFIG); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + } + + // SETUP / HELPERS + + private Context getTestContext() { + return mTestContext; + } + + private SdlManager createSampleManager(String appName, String appId, LockScreenConfig lockScreenConfig){ + SdlManager manager; + + SdlManagerListener listener = new SdlManagerListener() { + @Override + public void onStart() { + listenerCalledCounter++; + } + + @Override + public void onDestroy() { + + } + + @Override + public void onError(String info, Exception e) { + + } + }; + + // build manager object - use all setters, will test using getters below + SdlManager.Builder builder = new SdlManager.Builder(getTestContext(),appId,appName,listener); + builder.setShortAppName(appName); + builder.setAppTypes(appType); + builder.setTransportType(transport); + builder.setLanguage(Language.EN_US); + builder.setDayColorScheme(templateColorScheme); + builder.setNightColorScheme(templateColorScheme); + builder.setVrSynonyms(Test.GENERAL_VECTOR_STRING); + builder.setTtsName(Test.GENERAL_VECTOR_TTS_CHUNKS); + builder.setLockScreenConfig(lockScreenConfig); + builder.setMinimumProtocolVersion(Test.GENERAL_VERSION); + builder.setMinimumRPClVersion(Test.GENERAL_VERSION); + manager = builder.build(); + + // mock SdlProxyBase and set it manually + sdlProxyBase = mock(SdlProxyBase.class); + manager.setProxy(sdlProxyBase); + + return manager; + } + + // TESTS + + public void testNotNull(){ + assertNotNull(createSampleManager("app","123456", Test.GENERAL_LOCKSCREENCONFIG)); + } + + public void testMissingAppName() { + try { + createSampleManager(null,"123456", Test.GENERAL_LOCKSCREENCONFIG); + } catch (IllegalArgumentException ex) { + assertSame(ex.getMessage(), "You must specify an app name by calling setAppName"); + } + } + + public void testMissingAppId() { + try { + createSampleManager("app",null, Test.GENERAL_LOCKSCREENCONFIG); + } catch (IllegalArgumentException ex) { + assertSame(ex.getMessage(), "You must specify an app ID by calling setAppId"); + } + } + + public void testManagerSetters() { + assertEquals("123456", sdlManager.getAppId()); + assertEquals("heyApp", sdlManager.getAppName()); + assertEquals("heyApp", sdlManager.getShortAppName()); + assertEquals(appType, sdlManager.getAppTypes()); + assertEquals(Language.EN_US, sdlManager.getHmiLanguage()); + assertEquals(transport, sdlManager.getTransport()); + assertEquals(templateColorScheme, sdlManager.getDayColorScheme()); + assertEquals(templateColorScheme, sdlManager.getNightColorScheme()); + assertEquals(Test.GENERAL_VECTOR_STRING, sdlManager.getVrSynonyms()); + assertEquals(Test.GENERAL_VECTOR_TTS_CHUNKS, sdlManager.getTtsChunks()); + assertEquals(Test.GENERAL_LOCKSCREENCONFIG, sdlManager.getLockScreenConfig()); + assertEquals(Test.GENERAL_VERSION, sdlManager.getMinimumProtocolVersion()); + assertEquals(Test.GENERAL_VERSION, sdlManager.getMinimumRPCVersion()); + } + + public void testStartingManager(){ + listenerCalledCounter = 0; + + sdlManager.start(); + + // Create and force all sub managers to be ready manually. Because SdlManager will not start until all sub managers are ready. + // Note: SdlManager.initialize() will not be called automatically by proxy as in real life because we have mock proxy not a real one + sdlManager.initialize(); + + // Set all sub managers' states to ready + sdlManager.getPermissionManager().transitionToState(BaseSubManager.READY); + sdlManager.getFileManager().transitionToState(BaseSubManager.READY); + sdlManager.getScreenManager().transitionToState(BaseSubManager.READY); + sdlManager.getLockScreenManager().transitionToState(BaseSubManager.READY); + + // Make sure the listener is called exactly once + assertEquals("Listener was not called or called more/less frequently than expected", listenerCalledCounter, 1); + } + + public void testManagerStates() { + SdlManager sdlManager = createSampleManager("test", "00000", new LockScreenConfig()); + sdlManager.initialize(); + + + // Case 1-A: + sdlManager.getPermissionManager().transitionToState(BaseSubManager.READY); + sdlManager.getFileManager().transitionToState(BaseSubManager.READY); + sdlManager.getScreenManager().transitionToState(BaseSubManager.READY); + sdlManager.getLockScreenConfig().setEnabled(true); + sdlManager.getLockScreenManager().transitionToState(BaseSubManager.READY); + sdlManager.checkState(); + assertEquals(BaseSubManager.READY, sdlManager.getState()); + + + // Case 1-B: + sdlManager.getPermissionManager().transitionToState(BaseSubManager.READY); + sdlManager.getFileManager().transitionToState(BaseSubManager.READY); + sdlManager.getScreenManager().transitionToState(BaseSubManager.READY); + sdlManager.getLockScreenConfig().setEnabled(false); + sdlManager.getLockScreenManager().transitionToState(BaseSubManager.SETTING_UP); + sdlManager.checkState(); + assertEquals(BaseSubManager.READY, sdlManager.getState()); + + + // Case 2-A: + sdlManager.getPermissionManager().transitionToState(BaseSubManager.ERROR); + sdlManager.getFileManager().transitionToState(BaseSubManager.ERROR); + sdlManager.getScreenManager().transitionToState(BaseSubManager.ERROR); + sdlManager.getLockScreenConfig().setEnabled(true); + sdlManager.getLockScreenManager().transitionToState(BaseSubManager.ERROR); + sdlManager.checkState(); + assertEquals(BaseSubManager.ERROR, sdlManager.getState()); + + + // Case 1-B: + sdlManager.getPermissionManager().transitionToState(BaseSubManager.ERROR); + sdlManager.getFileManager().transitionToState(BaseSubManager.ERROR); + sdlManager.getScreenManager().transitionToState(BaseSubManager.ERROR); + sdlManager.getLockScreenConfig().setEnabled(false); + sdlManager.getLockScreenManager().transitionToState(BaseSubManager.SETTING_UP); + sdlManager.checkState(); + assertEquals(BaseSubManager.ERROR, sdlManager.getState()); + + + // Case 3-A: + sdlManager.getPermissionManager().transitionToState(BaseSubManager.ERROR); + sdlManager.getFileManager().transitionToState(BaseSubManager.READY); + sdlManager.getScreenManager().transitionToState(BaseSubManager.SETTING_UP); + sdlManager.getLockScreenConfig().setEnabled(true); + sdlManager.getLockScreenManager().transitionToState(BaseSubManager.LIMITED); + sdlManager.checkState(); + assertEquals(BaseSubManager.SETTING_UP, sdlManager.getState()); + + + // Case 3-B: + sdlManager.getPermissionManager().transitionToState(BaseSubManager.ERROR); + sdlManager.getFileManager().transitionToState(BaseSubManager.READY); + sdlManager.getScreenManager().transitionToState(BaseSubManager.SETTING_UP); + sdlManager.getLockScreenConfig().setEnabled(false); + sdlManager.getLockScreenManager().transitionToState(BaseSubManager.SETTING_UP); + sdlManager.checkState(); + assertEquals(BaseSubManager.SETTING_UP, sdlManager.getState()); + + + // Case 4-A: + sdlManager.getPermissionManager().transitionToState(BaseSubManager.READY); + sdlManager.getFileManager().transitionToState(BaseSubManager.ERROR); + sdlManager.getScreenManager().transitionToState(BaseSubManager.READY); + sdlManager.getLockScreenConfig().setEnabled(true); + sdlManager.getLockScreenManager().transitionToState(BaseSubManager.READY); + sdlManager.checkState(); + assertEquals(BaseSubManager.LIMITED, sdlManager.getState()); + + + // Case 4-B: + sdlManager.getPermissionManager().transitionToState(BaseSubManager.READY); + sdlManager.getFileManager().transitionToState(BaseSubManager.ERROR); + sdlManager.getScreenManager().transitionToState(BaseSubManager.READY); + sdlManager.getLockScreenConfig().setEnabled(false); + sdlManager.getLockScreenManager().transitionToState(BaseSubManager.SETTING_UP); + sdlManager.checkState(); + assertEquals(BaseSubManager.LIMITED, sdlManager.getState()); + + + // Case 5-A: + sdlManager.getPermissionManager().transitionToState(BaseSubManager.READY); + sdlManager.getFileManager().transitionToState(BaseSubManager.LIMITED); + sdlManager.getScreenManager().transitionToState(BaseSubManager.ERROR); + sdlManager.getLockScreenConfig().setEnabled(true); + sdlManager.getLockScreenManager().transitionToState(BaseSubManager.READY); + sdlManager.checkState(); + assertEquals(BaseSubManager.LIMITED, sdlManager.getState()); + + + // Case 5-B: + sdlManager.getPermissionManager().transitionToState(BaseSubManager.READY); + sdlManager.getFileManager().transitionToState(BaseSubManager.LIMITED); + sdlManager.getScreenManager().transitionToState(BaseSubManager.ERROR); + sdlManager.getLockScreenConfig().setEnabled(false); + sdlManager.getLockScreenManager().transitionToState(BaseSubManager.SETTING_UP); + sdlManager.checkState(); + assertEquals(BaseSubManager.LIMITED, sdlManager.getState()); + } + + public void testSendRPC(){ + listenerCalledCounter = 0; + + // When sdlProxyBase.sendRPCRequest() is called, create a fake success response + Answer<Void> answer = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + RPCRequest request = (RPCRequest) args[0]; + RPCResponse response = new RPCResponse(FunctionID.GET_VEHICLE_DATA.toString()); + response.setSuccess(true); + request.getOnRPCResponseListener().onResponse(0, response); + return null; + } + }; + try { + doAnswer(answer).when(sdlProxyBase).sendRPC(any(RPCMessage.class)); + } catch (SdlException e) { + e.printStackTrace(); + } + + + // Test send RPC request + final GetVehicleData request = new GetVehicleData(); + request.setGps(true); + request.setOnRPCResponseListener(new OnRPCResponseListener() { + @Override + public void onResponse(int correlationId, RPCResponse response) { + assertTrue(response.getSuccess()); + listenerCalledCounter++; + } + }); + + sdlManager.sendRPC(request); + + // Make sure the listener is called exactly once + assertEquals("Listener was not called or called more/less frequently than expected", listenerCalledCounter, 1); + } + + public void testSendRPCs(){ + testSendMultipleRPCs(false); + } + + public void testSendSequentialRPCs(){ + testSendMultipleRPCs(true); + } + + private void testSendMultipleRPCs(boolean sequentialSend){ + listenerCalledCounter = 0; + + // When sdlProxyBase.sendRPCRequests() is called, call listener.onFinished() to fake the response + final Answer<Void> answer = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + OnMultipleRequestListener listener = (OnMultipleRequestListener) args[1]; + listener.onFinished(); + return null; + } + }; + try { + if (sequentialSend){ + doAnswer(answer).when(sdlProxyBase).sendSequentialRequests(any(List.class), any(OnMultipleRequestListener.class)); + + } else { + doAnswer(answer).when(sdlProxyBase).sendRequests(any(List.class), any(OnMultipleRequestListener.class)); + } + } catch (SdlException e) { + e.printStackTrace(); + } + + + // Test send RPC requests + List<RPCMessage> rpcsList = Arrays.asList(new GetVehicleData(), new Show(), new OnAppServiceData(), new GetAppServiceDataResponse()); + OnMultipleRequestListener onMultipleRequestListener = new OnMultipleRequestListener() { + @Override + public void onUpdate(int remainingRequests) { } + + @Override + public void onFinished() { + listenerCalledCounter++; + } + + @Override + public void onError(int correlationId, Result resultCode, String info) {} + + @Override + public void onResponse(int correlationId, RPCResponse response) {} + }; + if (sequentialSend) { + sdlManager.sendSequentialRPCs(rpcsList, onMultipleRequestListener); + } else { + sdlManager.sendRPCs(rpcsList, onMultipleRequestListener); + } + + + // Make sure the listener is called exactly once + assertEquals("Listener was not called or called more/less frequently than expected", listenerCalledCounter, 1); + } + +} diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/audio/AudioStreamManagerTest.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/audio/AudioStreamManagerTest.java new file mode 100644 index 000000000..35c57a4c3 --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/audio/AudioStreamManagerTest.java @@ -0,0 +1,681 @@ +package com.smartdevicelink.managers.audio;
+
+import android.content.Context;
+import android.media.AudioFormat;
+import android.media.MediaFormat;
+import android.media.MediaPlayer;
+import android.os.Build;
+import android.support.test.InstrumentationRegistry;
+import android.util.Log;
+
+import com.smartdevicelink.SdlConnection.SdlSession;
+import com.smartdevicelink.managers.CompletionListener;
+import com.smartdevicelink.protocol.enums.SessionType;
+import com.smartdevicelink.proxy.interfaces.IAudioStreamListener;
+import com.smartdevicelink.proxy.interfaces.ISdl;
+import com.smartdevicelink.managers.audio.AudioStreamManager.SampleType;
+import com.smartdevicelink.proxy.interfaces.ISdlServiceListener;
+import com.smartdevicelink.proxy.rpc.AudioPassThruCapabilities;
+import com.smartdevicelink.proxy.rpc.enums.AudioType;
+import com.smartdevicelink.proxy.rpc.enums.BitsPerSample;
+import com.smartdevicelink.proxy.rpc.enums.SamplingRate;
+import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType;
+
+import junit.framework.TestCase;
+
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+public class AudioStreamManagerTest extends TestCase {
+ public static final String TAG = AudioStreamManagerTest.class.getSimpleName();
+ private Context mContext;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mContext = InstrumentationRegistry.getContext();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ mContext = null;
+ }
+
+ public void testCreatingAudioStreamManager() {
+ ISdl internalInterface = mock(ISdl.class);
+ AudioPassThruCapabilities audioCapabilities = new AudioPassThruCapabilities(SamplingRate._16KHZ, BitsPerSample._16_BIT, AudioType.PCM);
+ doReturn(true).when(internalInterface).isConnected();
+ doReturn(audioCapabilities).when(internalInterface).getCapability(SystemCapabilityType.PCM_STREAMING);
+
+ new AudioStreamManager(internalInterface, mContext);
+ }
+
+ public void testStartAudioStreamManager() {
+ final SdlSession mockSession = mock(SdlSession.class);
+
+ Answer<Void> audioServiceAnswer = new Answer<Void>() {
+ ISdlServiceListener serviceListener = null;
+ @Override
+ public Void answer(InvocationOnMock invocation) {
+ Method method = invocation.getMethod();
+ Object[] args = invocation.getArguments();
+
+ switch (method.getName()) {
+ case "addServiceListener":
+ // parameters (SessionType serviceType, ISdlServiceListener sdlServiceListener);
+ SessionType sessionType = (SessionType) args[0];
+ assertEquals(sessionType, SessionType.PCM);
+ serviceListener = (ISdlServiceListener) args[1];
+ break;
+ case "startAudioService":
+ // parameters (boolean encrypted, AudioStreamingCodec codec, AudioStreamingParams params);
+ Boolean encrypted = (Boolean) args[0];
+ serviceListener.onServiceStarted(mockSession, SessionType.PCM, encrypted);
+ break;
+ case "stopAudioService":
+ // parameters ()
+ serviceListener.onServiceEnded(mockSession, SessionType.PCM);
+ break;
+ }
+
+ return null;
+ }
+ };
+
+ ISdl internalInterface = mock(ISdl.class);
+ AudioPassThruCapabilities audioCapabilities = new AudioPassThruCapabilities(SamplingRate._16KHZ, BitsPerSample._16_BIT, AudioType.PCM);
+ doReturn(true).when(internalInterface).isConnected();
+ doReturn(audioCapabilities).when(internalInterface).getCapability(SystemCapabilityType.PCM_STREAMING);
+ doAnswer(audioServiceAnswer).when(internalInterface).addServiceListener(any(SessionType.class), any(ISdlServiceListener.class));
+ doAnswer(audioServiceAnswer).when(internalInterface).startAudioService(any(Boolean.class));
+ doAnswer(audioServiceAnswer).when(internalInterface).stopAudioService();
+
+ CompletionListener completionListener = new CompletionListener() {
+ @Override
+ public void onComplete(boolean success) {
+ assertEquals(true, success);
+ }
+ };
+
+ CompletionListener mockListener = spy(completionListener);
+ AudioStreamManager manager = new AudioStreamManager(internalInterface, mContext);
+
+ manager.startAudioStream(false, mockListener);
+ manager.stopAudioStream(mockListener);
+ verify(mockListener, timeout(10000).times(2)).onComplete(any(Boolean.class));
+ }
+
+ public void testWithSquareSampleAudio16BitAnd8KhzApi16() throws Exception {
+ setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 16);
+ AudioPassThruCapabilities audioPassThruCapabilities = new AudioPassThruCapabilities(SamplingRate._8KHZ, BitsPerSample._16_BIT, AudioType.PCM);
+ runFullAudioManagerDecodeFlowWithSquareSampleAudio(8000, SampleType.SIGNED_16_BIT, audioPassThruCapabilities);
+ }
+
+ public void testWithSquareSampleAudio16BitAnd16KhzApi16() throws Exception {
+ setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 16);
+ AudioPassThruCapabilities audioPassThruCapabilities = new AudioPassThruCapabilities(SamplingRate._16KHZ, BitsPerSample._16_BIT, AudioType.PCM);
+ runFullAudioManagerDecodeFlowWithSquareSampleAudio(16000, SampleType.SIGNED_16_BIT, audioPassThruCapabilities);
+ }
+
+ public void testWithSquareSampleAudio16BitAnd22KhzApi16() throws Exception {
+ setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 16);
+ AudioPassThruCapabilities audioPassThruCapabilities = new AudioPassThruCapabilities(SamplingRate._22KHZ, BitsPerSample._16_BIT, AudioType.PCM);
+ runFullAudioManagerDecodeFlowWithSquareSampleAudio(22050, SampleType.SIGNED_16_BIT, audioPassThruCapabilities);
+ }
+
+ public void testWithSquareSampleAudio16BitAnd44KhzApi16() throws Exception {
+ setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 16);
+ AudioPassThruCapabilities audioPassThruCapabilities = new AudioPassThruCapabilities(SamplingRate._44KHZ, BitsPerSample._16_BIT, AudioType.PCM);
+ runFullAudioManagerDecodeFlowWithSquareSampleAudio(44100, SampleType.SIGNED_16_BIT, audioPassThruCapabilities);
+ }
+
+ public void testWithSquareSampleAudio8BitAnd8KhzApi16() throws Exception {
+ setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 16);
+ AudioPassThruCapabilities audioPassThruCapabilities = new AudioPassThruCapabilities(SamplingRate._8KHZ, BitsPerSample._8_BIT, AudioType.PCM);
+ runFullAudioManagerDecodeFlowWithSquareSampleAudio(8000, SampleType.UNSIGNED_8_BIT, audioPassThruCapabilities);
+ }
+
+ public void testWithSquareSampleAudio8BitAnd16KhzApi16() throws Exception {
+ setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 16);
+ AudioPassThruCapabilities audioPassThruCapabilities = new AudioPassThruCapabilities(SamplingRate._16KHZ, BitsPerSample._8_BIT, AudioType.PCM);
+ runFullAudioManagerDecodeFlowWithSquareSampleAudio(16000, SampleType.UNSIGNED_8_BIT, audioPassThruCapabilities);
+ }
+
+ public void testWithSquareSampleAudio8BitAnd22KhzApi16() throws Exception {
+ setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 16);
+ AudioPassThruCapabilities audioPassThruCapabilities = new AudioPassThruCapabilities(SamplingRate._22KHZ, BitsPerSample._8_BIT, AudioType.PCM);
+ runFullAudioManagerDecodeFlowWithSquareSampleAudio(22050, SampleType.UNSIGNED_8_BIT, audioPassThruCapabilities);
+ }
+
+ public void testWithSquareSampleAudio8BitAnd44KhzApi16() throws Exception {
+ setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 16);
+ AudioPassThruCapabilities audioPassThruCapabilities = new AudioPassThruCapabilities(SamplingRate._44KHZ, BitsPerSample._8_BIT, AudioType.PCM);
+ runFullAudioManagerDecodeFlowWithSquareSampleAudio(44100, SampleType.UNSIGNED_8_BIT, audioPassThruCapabilities);
+ }
+
+ public void testWithSquareSampleAudio16BitAnd8KhzApi21() throws Exception {
+ setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 21);
+ AudioPassThruCapabilities audioPassThruCapabilities = new AudioPassThruCapabilities(SamplingRate._8KHZ, BitsPerSample._16_BIT, AudioType.PCM);
+ runFullAudioManagerDecodeFlowWithSquareSampleAudio(8000, SampleType.SIGNED_16_BIT, audioPassThruCapabilities);
+ }
+
+ public void testWithSquareSampleAudio16BitAnd16KhzApi21() throws Exception {
+ setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 21);
+ AudioPassThruCapabilities audioPassThruCapabilities = new AudioPassThruCapabilities(SamplingRate._16KHZ, BitsPerSample._16_BIT, AudioType.PCM);
+ runFullAudioManagerDecodeFlowWithSquareSampleAudio(16000, SampleType.SIGNED_16_BIT, audioPassThruCapabilities);
+ }
+
+ public void testWithSquareSampleAudio16BitAnd22KhzApi21() throws Exception {
+ setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 21);
+ AudioPassThruCapabilities audioPassThruCapabilities = new AudioPassThruCapabilities(SamplingRate._22KHZ, BitsPerSample._16_BIT, AudioType.PCM);
+ runFullAudioManagerDecodeFlowWithSquareSampleAudio(22050, SampleType.SIGNED_16_BIT, audioPassThruCapabilities);
+ }
+
+ public void testWithSquareSampleAudio16BitAnd44KhzApi21() throws Exception {
+ setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 21);
+ AudioPassThruCapabilities audioPassThruCapabilities = new AudioPassThruCapabilities(SamplingRate._44KHZ, BitsPerSample._16_BIT, AudioType.PCM);
+ runFullAudioManagerDecodeFlowWithSquareSampleAudio(44100, SampleType.SIGNED_16_BIT, audioPassThruCapabilities);
+ }
+
+ public void testWithSquareSampleAudio8BitAnd8KhzApi21() throws Exception {
+ setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 21);
+ AudioPassThruCapabilities audioPassThruCapabilities = new AudioPassThruCapabilities(SamplingRate._8KHZ, BitsPerSample._8_BIT, AudioType.PCM);
+ runFullAudioManagerDecodeFlowWithSquareSampleAudio(8000, SampleType.UNSIGNED_8_BIT, audioPassThruCapabilities);
+ }
+
+ public void testWithSquareSampleAudio8BitAnd16KhzApi21() throws Exception {
+ setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 21);
+ AudioPassThruCapabilities audioPassThruCapabilities = new AudioPassThruCapabilities(SamplingRate._16KHZ, BitsPerSample._8_BIT, AudioType.PCM);
+ runFullAudioManagerDecodeFlowWithSquareSampleAudio(16000, SampleType.UNSIGNED_8_BIT, audioPassThruCapabilities);
+ }
+
+ public void testWithSquareSampleAudio8BitAnd22KhzApi21() throws Exception {
+ setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 21);
+ AudioPassThruCapabilities audioPassThruCapabilities = new AudioPassThruCapabilities(SamplingRate._22KHZ, BitsPerSample._8_BIT, AudioType.PCM);
+ runFullAudioManagerDecodeFlowWithSquareSampleAudio(22050, SampleType.UNSIGNED_8_BIT, audioPassThruCapabilities);
+ }
+
+ public void testWithSquareSampleAudio8BitAnd44KhzApi21() throws Exception {
+ setFinalStatic(Build.VERSION.class.getField("SDK_INT"), 21);
+ AudioPassThruCapabilities audioPassThruCapabilities = new AudioPassThruCapabilities(SamplingRate._44KHZ, BitsPerSample._8_BIT, AudioType.PCM);
+ runFullAudioManagerDecodeFlowWithSquareSampleAudio(44100, SampleType.UNSIGNED_8_BIT, audioPassThruCapabilities);
+ }
+
+ private int testFullAudioManagerDecodeFlowCorrectCounter = 0;
+ private int testFullAudioManagerDecodeFlowWrongCounter = 0;
+ private void runFullAudioManagerDecodeFlowWithSquareSampleAudio(final int sampleRate, final @SampleType int sampleType, final AudioPassThruCapabilities audioCapabilities) {
+ testFullAudioManagerDecodeFlowCorrectCounter = 0;
+ testFullAudioManagerDecodeFlowWrongCounter = 0;
+
+ IAudioStreamListener audioStreamListener = new IAudioStreamListener() {
+ @Override
+ public void sendAudio(byte[] data, int offset, int length, long presentationTimeUs) throws ArrayIndexOutOfBoundsException {
+ ByteBuffer buffer = ByteBuffer.wrap(data, offset, length);
+ this.sendAudio(buffer, presentationTimeUs);
+ }
+
+ @Override
+ public void sendAudio(ByteBuffer data, long presentationTimeUs) {
+ SampleBuffer samples = SampleBuffer.wrap(data, sampleType, presentationTimeUs);
+ double timeUs = presentationTimeUs;
+ double sampleDurationUs = 1000000.0 / sampleRate;
+
+ for (int i = 0; i < samples.limit(); ++i) {
+ double sample = samples.get(i);
+ double edge = timeUs % 4000.0;
+
+ if (edge > 2000.0) {
+ // swap sample as it's negative expected
+ sample = sample * -1.0;
+ }
+
+ edge = edge % 2000.0;
+
+ // at the edge of a wave the sample can be lower than 0.7
+ if ((sample > 0.7 && sample < 0.95) || (edge < sampleDurationUs || (2000.0 - sampleDurationUs) < edge)) {
+ testFullAudioManagerDecodeFlowCorrectCounter++;
+ } else {
+ testFullAudioManagerDecodeFlowWrongCounter++;
+ }
+
+ timeUs += sampleDurationUs;
+ }
+ }
+ };
+
+ final SdlSession mockSession = mock(SdlSession.class);
+ doReturn(audioStreamListener).when(mockSession).startAudioStream();
+
+ Answer<Void> audioServiceAnswer = new Answer<Void>() {
+ ISdlServiceListener serviceListener = null;
+ @Override
+ public Void answer(InvocationOnMock invocation) {
+ Method method = invocation.getMethod();
+ Object[] args = invocation.getArguments();
+
+ switch (method.getName()) {
+ case "addServiceListener":
+ // (SessionType serviceType, ISdlServiceListener sdlServiceListener);
+ SessionType sessionType = (SessionType) args[0];
+ assertEquals(sessionType, SessionType.PCM);
+
+ serviceListener = (ISdlServiceListener) args[1];
+ break;
+ case "startAudioService":
+ //(boolean encrypted, AudioStreamingCodec codec, AudioStreamingParams params);
+ Boolean encrypted = (Boolean) args[0];
+ serviceListener.onServiceStarted(mockSession, SessionType.PCM, encrypted);
+ break;
+ case "stopAudioService":
+ // parameters ()
+ serviceListener.onServiceEnded(mockSession, SessionType.PCM);
+ break;
+ }
+
+ return null;
+ }
+ };
+
+ ISdl internalInterface = mock(ISdl.class);
+ doReturn(true).when(internalInterface).isConnected();
+ doReturn(audioCapabilities).when(internalInterface).getCapability(any(SystemCapabilityType.class));
+ doAnswer(audioServiceAnswer).when(internalInterface).addServiceListener(any(SessionType.class), any(ISdlServiceListener.class));
+ doAnswer(audioServiceAnswer).when(internalInterface).startAudioService(any(Boolean.class));
+ doAnswer(audioServiceAnswer).when(internalInterface).stopAudioService();
+
+ CompletionListener fileCompletionListener = new CompletionListener() {
+ @Override
+ public void onComplete(boolean success) {
+ assertEquals(true, success);
+
+ // not more than 2.5 percent samples must be wrong
+ double relation = 100.0 * (double)testFullAudioManagerDecodeFlowWrongCounter / (double)testFullAudioManagerDecodeFlowCorrectCounter;
+ Log.v(TAG, "Validating number of correct samples (" + Math.round(relation) + "%)");
+ if (relation > 2.5) {
+ fail("Validating raw audio failed. " + Math.round(relation) + " % wrong samples detected. Correct: " + testFullAudioManagerDecodeFlowCorrectCounter + ", Wrong: " + testFullAudioManagerDecodeFlowWrongCounter);
+ }
+ }
+ };
+
+ final CompletionListener mockFileListener = spy(fileCompletionListener);
+
+ final AudioStreamManager manager = new AudioStreamManager(internalInterface, mContext);
+ manager.startAudioStream(false, new CompletionListener() {
+ @Override
+ public void onComplete(boolean success) {
+ assertEquals(true, success);
+
+ manager.pushResource(com.smartdevicelink.test.R.raw.test_audio_square_250hz_80amp_1s, mockFileListener);
+ }
+ });
+
+ verify(mockFileListener, timeout(10000)).onComplete(any(Boolean.class));
+ }
+
+ public void testSampleAtTargetTimeReturnNull() {
+ BaseAudioDecoder mockDecoder = mock(BaseAudioDecoder.class, Mockito.CALLS_REAL_METHODS);
+ Method sampleAtTargetMethod = getSampleAtTargetMethod();
+ SampleBuffer sample = SampleBuffer.allocate(1, SampleType.SIGNED_16_BIT, ByteOrder.LITTLE_ENDIAN, 1);
+ Double result;
+ try {
+ result = (Double) sampleAtTargetMethod.invoke(mockDecoder, 1.0, sample, 1, 3, 2);
+ assertNull(result);
+ result = (Double) sampleAtTargetMethod.invoke(mockDecoder, 1.0, sample, 5, 3, 1);
+ assertNull(result);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public void testSampleAtTargetTimeReturnLastOutputSample() {
+ BaseAudioDecoder mockDecoder = mock(BaseAudioDecoder.class, Mockito.CALLS_REAL_METHODS);
+ Method sampleAtTargetMethod = getSampleAtTargetMethod();
+ SampleBuffer sample = SampleBuffer.allocate(1, SampleType.SIGNED_16_BIT, ByteOrder.LITTLE_ENDIAN, 1);
+ Double result;
+ Double lastOutputSample = 15.0;
+ try {
+ result = (Double) sampleAtTargetMethod.invoke(mockDecoder, lastOutputSample, sample, 6, 1, 5);
+ assertTrue(result.doubleValue() == lastOutputSample);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public void testSampleAtTargetTimeReturnOutputSampleGet() {
+ BaseAudioDecoder mockDecoder = mock(BaseAudioDecoder.class, Mockito.CALLS_REAL_METHODS);
+ Method sampleAtTargetMethod = getSampleAtTargetMethod();
+ SampleBuffer sample = SampleBuffer.allocate(10, SampleType.SIGNED_16_BIT, ByteOrder.LITTLE_ENDIAN, 1);
+ Double result;
+ try {
+ result = (Double) sampleAtTargetMethod.invoke(mockDecoder, 1.0, sample, 1, 1, 2);
+ assertTrue(result == sample.get(1));
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public void testSampleAtTargetTime() {
+ BaseAudioDecoder mockDecoder = mock(BaseAudioDecoder.class, Mockito.CALLS_REAL_METHODS);
+ Method sampleAtTargetMethod = getSampleAtTargetMethod();
+ SampleBuffer sample = SampleBuffer.allocate(10, SampleType.SIGNED_16_BIT, ByteOrder.LITTLE_ENDIAN, 1);
+ Double result;
+ try {
+ result = (Double) sampleAtTargetMethod.invoke(mockDecoder, 1.0, sample, 1, 3, 2);
+ assertNotNull(result);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public void testOutputFormatChanged() {
+ BaseAudioDecoder mockDecoder = mock(BaseAudioDecoder.class, Mockito.CALLS_REAL_METHODS);
+
+ try {
+ Field outputChannelCountField = BaseAudioDecoder.class.getDeclaredField("outputChannelCount");
+ Field outputSampleRateField = BaseAudioDecoder.class.getDeclaredField("outputSampleRate");
+ Field outputSampleTypeField = BaseAudioDecoder.class.getDeclaredField("outputSampleType");
+
+ outputChannelCountField.setAccessible(true);
+ outputSampleRateField.setAccessible(true);
+ outputSampleTypeField.setAccessible(true);
+
+ // channel count, sample rate, sample type
+ int key_channel_count = 0, key_sample_rate = 1, key_sample_type = 2, key_sample_type_result = 3;
+ int[][] tests = new int[][] {
+ { 47, 42000, AudioFormat.ENCODING_PCM_8BIT, SampleType.UNSIGNED_8_BIT },
+ { 2, 16000, AudioFormat.ENCODING_PCM_16BIT, SampleType.SIGNED_16_BIT },
+ { 1, 22050, AudioFormat.ENCODING_PCM_FLOAT, SampleType.FLOAT },
+ { 3, 48000, AudioFormat.ENCODING_INVALID, SampleType.SIGNED_16_BIT },
+ };
+
+ for (int[] test : tests) {
+ int channel_count = test[key_channel_count];
+ int sample_rate = test[key_sample_rate];
+ int sample_type = test[key_sample_type];
+ int sample_type_result = test[key_sample_type_result];
+
+ MediaFormat format = new MediaFormat();
+
+ format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, channel_count);
+ format.setInteger(MediaFormat.KEY_SAMPLE_RATE, sample_rate);
+ format.setInteger(MediaFormat.KEY_PCM_ENCODING, sample_type);
+
+ // in case the phone version is old the method does not take sample type into account but
+ // always expected 16 bit. See https://developer.android.com/reference/android/media/MediaFormat.html#KEY_PCM_ENCODING
+ if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.N) {
+ sample_type_result = SampleType.SIGNED_16_BIT;
+ }
+
+ mockDecoder.onOutputFormatChanged(format);
+
+ int output_channel_count = outputChannelCountField.getInt(mockDecoder);
+ int output_sample_rate = outputSampleRateField.getInt(mockDecoder);
+ int output_sample_type = outputSampleTypeField.getInt(mockDecoder);
+
+ // changing from assertEquals to if and fail so travis gives better results
+
+ if (channel_count != output_channel_count) {
+ fail("AssertEqualsFailed: channel_count == output_channel_count (" + channel_count + " == " + output_channel_count + ")");
+ }
+
+ if (sample_rate != output_sample_rate) {
+ fail("AssertEqualsFailed: sample_rate == output_sample_rate (" + sample_rate + " == " + output_sample_rate + ")");
+ }
+
+ if (sample_type_result != output_sample_type) {
+ fail("Assert: sample_type_result == output_sample_type (" + sample_type_result + " == " + output_sample_type + ")");
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public void testPlayAudioFileForManualTest() throws IOException {
+ AudioPassThruCapabilities audioCapabilities = new AudioPassThruCapabilities(SamplingRate._16KHZ, BitsPerSample._16_BIT, AudioType.PCM);
+ final int sampleType = SampleType.SIGNED_16_BIT;
+ final int sampleRate = 16000;
+
+ final File outputFile = new File(mContext.getCacheDir(), "test_audio_file.wav");
+ assertNotNull((outputFile));
+ final FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
+ assertNotNull(fileOutputStream);
+ writeWaveHeader(fileOutputStream, sampleRate, sampleType << 3);
+
+ IAudioStreamListener audioStreamListener = new IAudioStreamListener() {
+ long audioLength = 0;
+
+ @Override
+ public void sendAudio(byte[] data, int offset, int length, long presentationTimeUs) throws ArrayIndexOutOfBoundsException {
+ ByteBuffer buffer = ByteBuffer.wrap(data, offset, length);
+ this.sendAudio(buffer, presentationTimeUs);
+ }
+
+ @Override
+ public void sendAudio(ByteBuffer data, long presentationTimeUs) {
+ try {
+ long length = data.limit();
+ byte[] d = data.array();
+ fileOutputStream.write(d, 0, (int) length);
+
+ audioLength += length;
+ RandomAccessFile raf = new RandomAccessFile(outputFile, "rw");
+ updateWaveHeaderLength(raf, audioLength);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+
+ final SdlSession mockSession = mock(SdlSession.class);
+ doReturn(audioStreamListener).when(mockSession).startAudioStream();
+
+ Answer<Void> audioServiceAnswer = new Answer<Void>() {
+ ISdlServiceListener serviceListener = null;
+ @Override
+ public Void answer(InvocationOnMock invocation) {
+ Method method = invocation.getMethod();
+ Object[] args = invocation.getArguments();
+
+ switch (method.getName()) {
+ case "addServiceListener":
+ // (SessionType serviceType, ISdlServiceListener sdlServiceListener);
+ SessionType sessionType = (SessionType) args[0];
+ assertEquals(sessionType, SessionType.PCM);
+
+ serviceListener = (ISdlServiceListener) args[1];
+ break;
+ case "startAudioService":
+ //(boolean encrypted, AudioStreamingCodec codec, AudioStreamingParams params);
+ Boolean encrypted = (Boolean) args[0];
+ serviceListener.onServiceStarted(mockSession, SessionType.PCM, encrypted);
+ break;
+ case "stopAudioService":
+ // parameters ()
+ serviceListener.onServiceEnded(mockSession, SessionType.PCM);
+ break;
+ }
+
+ return null;
+ }
+ };
+
+ ISdl internalInterface = mock(ISdl.class);
+ doReturn(true).when(internalInterface).isConnected();
+ doReturn(audioCapabilities).when(internalInterface).getCapability(any(SystemCapabilityType.class));
+ doAnswer(audioServiceAnswer).when(internalInterface).addServiceListener(any(SessionType.class), any(ISdlServiceListener.class));
+ doAnswer(audioServiceAnswer).when(internalInterface).startAudioService(any(Boolean.class));
+ doAnswer(audioServiceAnswer).when(internalInterface).stopAudioService();
+
+ final MediaPlayer.OnCompletionListener mockPlayerCompletionListener = mock(MediaPlayer.OnCompletionListener.class);
+ final MediaPlayer player = new MediaPlayer();
+ player.setOnCompletionListener(mockPlayerCompletionListener);
+
+ CompletionListener fileCompletionListener = new CompletionListener() {
+ @Override
+ public void onComplete(boolean success) {
+ try {
+ fileOutputStream.flush();
+ fileOutputStream.close();
+
+ player.setDataSource(outputFile.getPath());
+ player.prepare();
+ player.start();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+
+ final CompletionListener mockFileListener = spy(fileCompletionListener);
+
+ final AudioStreamManager manager = new AudioStreamManager(internalInterface, mContext);
+ manager.startAudioStream(false, new CompletionListener() {
+ @Override
+ public void onComplete(boolean success) {
+ assertEquals(true, success);
+
+ manager.pushResource(com.smartdevicelink.test.R.raw.test_audio_square_250hz_80amp_1s, mockFileListener);
+ }
+ });
+
+ verify(mockFileListener, timeout(10000)).onComplete(any(Boolean.class));
+ verify(mockPlayerCompletionListener, timeout(10000)).onCompletion(any(MediaPlayer.class));
+ }
+
+ private Method getSampleAtTargetMethod() {
+ Method method = null;
+ try {
+ method = BaseAudioDecoder.class.getDeclaredMethod("sampleAtTargetTime",
+ double.class, SampleBuffer.class, double.class, double.class, double.class);
+ method.setAccessible(true);
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ fail();
+ }
+ return method;
+ }
+
+ private void setFinalStatic(Field field, Object newValue) throws Exception {
+ field.setAccessible(true);
+ field.set(null, newValue);
+ }
+
+ private void writeWaveHeader(OutputStream stream, long samplerate, long bitspersample) throws IOException {
+ byte[] header = new byte[44];
+ // the data header is 36 bytes large
+ long datalength = 36;
+ long audiolength = 0;
+ long format = 1; // 1 = PCM
+ long channels = 1;
+ long blockalign = (channels * bitspersample) >> 3;
+ long byterate = (samplerate * channels * bitspersample) >> 3;
+
+ // RIFF header.
+ header[0] = 'R';
+ header[1] = 'I';
+ header[2] = 'F';
+ header[3] = 'F';
+ // Total data length (UInt32).
+ header[4] = (byte)((datalength) & 0xff);
+ header[5] = (byte)((datalength >> 8) & 0xff);
+ header[6] = (byte)((datalength >> 16) & 0xff);
+ header[7] = (byte)((datalength >> 24) & 0xff);
+ // WAVE header.
+ header[8] = 'W';
+ header[9] = 'A';
+ header[10] = 'V';
+ header[11] = 'E';
+ // Format (fmt) header.
+ header[12] = 'f';
+ header[13] = 'm';
+ header[14] = 't';
+ header[15] = ' ';
+ // Format header size (UInt32).
+ header[16] = 16;
+ header[17] = 0;
+ header[18] = 0;
+ header[19] = 0;
+ // Format type (UInt16). Set 1 for PCM.
+ header[20] = (byte)((format) & 0xff);
+ header[21] = (byte)((format >> 8) & 0xff);
+ // Channels
+ header[22] = (byte)((channels) & 0xff);
+ header[23] = (byte)((channels >> 8) & 0xff);
+ // Sample rate (UInt32).
+ header[24] = (byte)((samplerate) & 0xff);
+ header[25] = (byte)((samplerate >> 8) & 0xff);
+ header[26] = (byte)((samplerate >> 16) & 0xff);
+ header[27] = (byte)((samplerate >> 24) & 0xff);
+ // Byte rate (UInt32).
+ header[28] = (byte)((byterate) & 0xff);
+ header[29] = (byte)((byterate >> 8) & 0xff);
+ header[30] = (byte)((byterate >> 16) & 0xff);
+ header[31] = (byte)((byterate >> 24) & 0xff);
+ // Block alignment (UInt16).
+ header[32] = (byte)((blockalign) & 0xff);
+ header[33] = (byte)((blockalign >> 8) & 0xff);
+ // Bits per sample (UInt16).
+ header[34] = (byte)((bitspersample) & 0xff);
+ header[35] = (byte)((bitspersample >> 8) & 0xff);
+ // Data header
+ header[36] = 'd';
+ header[37] = 'a';
+ header[38] = 't';
+ header[39] = 'a';
+ // Total audio length (UInt32).
+ header[40] = (byte)((audiolength) & 0xff);
+ header[41] = (byte)((audiolength >> 8) & 0xff);
+ header[42] = (byte)((audiolength >> 16) & 0xff);
+ header[43] = (byte)((audiolength >> 24) & 0xff);
+
+ stream.write(header, 0, header.length);
+ }
+
+ /** Updates the data length and audio length of an existing RIFF/WAVE header in the file pointed by the RandomAccessFile object. */
+ private void updateWaveHeaderLength(RandomAccessFile stream, long audiolength) throws IOException {
+ // the data header is 36 bytes large
+ long datalength = 36 + audiolength;
+
+ // Seek from the beginning to data length
+ stream.seek(4);
+ // Overwrite total data length
+ stream.write((int)((datalength) & 0xff));
+ stream.write((int)((datalength >> 8) & 0xff));
+ stream.write((int)((datalength >> 16) & 0xff));
+ stream.write((int)((datalength >> 24) & 0xff));
+ // Seek from the end of data length to audio length
+ stream.seek(40);
+ // overwrite total audio length
+ stream.write((int)((audiolength) & 0xff));
+ stream.write((int)((audiolength >> 8) & 0xff));
+ stream.write((int)((audiolength >> 16) & 0xff));
+ stream.write((int)((audiolength >> 24) & 0xff));
+ }
+}
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/file/FileManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/file/FileManagerTests.java new file mode 100644 index 000000000..b4e27f205 --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/file/FileManagerTests.java @@ -0,0 +1,507 @@ +package com.smartdevicelink.managers.file; + +import android.content.Context; +import android.net.Uri; + +import com.smartdevicelink.AndroidTestCase2; +import com.smartdevicelink.managers.BaseSubManager; +import com.smartdevicelink.managers.CompletionListener; +import com.smartdevicelink.managers.file.filetypes.SdlArtwork; +import com.smartdevicelink.managers.file.filetypes.SdlFile; +import com.smartdevicelink.proxy.RPCRequest; +import com.smartdevicelink.proxy.interfaces.ISdl; +import com.smartdevicelink.proxy.rpc.ListFiles; +import com.smartdevicelink.proxy.rpc.ListFilesResponse; +import com.smartdevicelink.proxy.rpc.PutFile; +import com.smartdevicelink.proxy.rpc.PutFileResponse; +import com.smartdevicelink.proxy.rpc.enums.FileType; +import com.smartdevicelink.proxy.rpc.enums.Result; +import com.smartdevicelink.proxy.rpc.enums.StaticIconName; +import com.smartdevicelink.proxy.rpc.listeners.OnMultipleRequestListener; +import com.smartdevicelink.test.Test; + +import junit.framework.Assert; + +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; + +/** + * This is a unit test class for the SmartDeviceLink library manager class : + * {@link FileManager} + */ +public class FileManagerTests extends AndroidTestCase2 { + public static final String TAG = "FileManagerTests"; + private FileManager fileManager; + private Context mTestContext; + private SdlFile validFile; + + // SETUP / HELPERS + + @Override + public void setUp() throws Exception{ + super.setUp(); + mTestContext = this.getContext(); + validFile = new SdlFile(); + validFile.setName(Test.GENERAL_STRING); + validFile.setFileData(Test.GENERAL_BYTE_ARRAY); + validFile.setPersistent(false); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + } + + private Answer<Void> onListFilesSuccess = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + RPCRequest message = (RPCRequest) args[0]; + if(message instanceof ListFiles){ + int correlationId = message.getCorrelationID(); + ListFilesResponse listFilesResponse = new ListFilesResponse(); + listFilesResponse.setFilenames(Test.GENERAL_STRING_LIST); + listFilesResponse.setSpaceAvailable(Test.GENERAL_INT); + listFilesResponse.setSuccess(true); + message.getOnRPCResponseListener().onResponse(correlationId, listFilesResponse); + } + return null; + } + }; + + private Answer<Void> onListFilesFailure = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + RPCRequest message = (RPCRequest) args[0]; + if(message instanceof ListFiles){ + int correlationId = message.getCorrelationID(); + ListFilesResponse listFilesResponse = new ListFilesResponse(); + listFilesResponse.setSuccess(false); + message.getOnRPCResponseListener().onResponse(correlationId, listFilesResponse); + } + return null; + } + }; + + private Answer<Void> onPutFileSuccess = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + RPCRequest message = (RPCRequest) args[0]; + if(message instanceof PutFile){ + int correlationId = message.getCorrelationID(); + PutFileResponse putFileResponse = new PutFileResponse(); + putFileResponse.setSuccess(true); + message.getOnRPCResponseListener().onResponse(correlationId, putFileResponse); + } + return null; + } + }; + + private Answer<Void> onPutFileFailure = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + RPCRequest message = (RPCRequest) args[0]; + if(message instanceof PutFile){ + int correlationId = message.getCorrelationID(); + PutFileResponse putFileResponse = new PutFileResponse(); + putFileResponse.setSuccess(false); + message.getOnRPCResponseListener().onResponse(correlationId, putFileResponse); + } + return null; + } + }; + + private Answer<Void> onSendRequestsSuccess = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + List<RPCRequest> rpcs = (List<RPCRequest>) args[0]; + OnMultipleRequestListener listener = (OnMultipleRequestListener) args[1]; + if(rpcs.get(0) instanceof PutFile){ + for(RPCRequest message : rpcs){ + int correlationId = message.getCorrelationID(); + listener.addCorrelationId(correlationId); + PutFileResponse putFileResponse = new PutFileResponse(); + putFileResponse.setSuccess(true); + listener.onResponse(correlationId, putFileResponse); + } + } + return null; + } + }; + + // TESTS + + public void testInitializationSuccess(){ + ISdl internalInterface = mock(ISdl.class); + + doAnswer(onListFilesSuccess).when(internalInterface).sendRPCRequest(any(ListFiles.class)); + + final FileManager fileManager = new FileManager(internalInterface, mTestContext); + fileManager.start(new CompletionListener() { + @Override + public void onComplete(boolean success) { + assertTrue(success); + Assert.assertEquals(fileManager.getState(), BaseSubManager.READY); + assertEquals(fileManager.getRemoteFileNames(), Test.GENERAL_STRING_LIST); + } + }); + } + + public void testInitializationFailure(){ + ISdl internalInterface = mock(ISdl.class); + + doAnswer(onListFilesFailure).when(internalInterface).sendRPCRequest(any(ListFiles.class)); + + final FileManager fileManager = new FileManager(internalInterface, mTestContext); + fileManager.start(new CompletionListener() { + @Override + public void onComplete(boolean success) { + assertFalse(success); + assertEquals(fileManager.getState(), BaseSubManager.ERROR); + } + }); + } + + public void testFileUploadSuccess(){ + ISdl internalInterface = mock(ISdl.class); + + doAnswer(onListFilesSuccess).when(internalInterface).sendRPCRequest(any(ListFiles.class)); + doAnswer(onPutFileSuccess).when(internalInterface).sendRPCRequest(any(PutFile.class)); + + final FileManager fileManager = new FileManager(internalInterface, mTestContext); + fileManager.start(new CompletionListener() { + @Override + public void onComplete(boolean success) { + assertTrue(success); + fileManager.uploadFile(validFile, new CompletionListener() { + @Override + public void onComplete(boolean success) { + assertTrue(success); + assertTrue(fileManager.getRemoteFileNames().contains(validFile.getName())); + assertTrue(fileManager.hasUploadedFile(validFile)); + } + }); + } + }); + } + + public void testFileUploadFailure(){ + ISdl internalInterface = mock(ISdl.class); + + doAnswer(onListFilesSuccess).when(internalInterface).sendRPCRequest(any(ListFiles.class)); + doAnswer(onPutFileFailure).when(internalInterface).sendRPCRequest(any(PutFile.class)); + + final FileManager fileManager = new FileManager(internalInterface, mTestContext); + fileManager.start(new CompletionListener() { + @Override + public void onComplete(boolean success) { + assertTrue(success); + fileManager.uploadFile(validFile, new CompletionListener() { + @Override + public void onComplete(boolean success) { + assertFalse(success); + assertFalse(fileManager.getRemoteFileNames().contains(validFile.getName())); + assertFalse(fileManager.hasUploadedFile(validFile)); + } + }); + } + }); + } + + public void testFileUploadForStaticIcon(){ + ISdl internalInterface = mock(ISdl.class); + + doAnswer(onListFilesSuccess).when(internalInterface).sendRPCRequest(any(ListFiles.class)); + + final FileManager fileManager = new FileManager(internalInterface, mTestContext); + fileManager.start(new CompletionListener() { + @Override + public void onComplete(boolean success) { + assertTrue(success); + SdlArtwork artwork = new SdlArtwork(StaticIconName.ALBUM); + fileManager.uploadFile(artwork, new CompletionListener() { + @Override + public void onComplete(boolean success) { + assertTrue(success); + } + }); + } + }); + } + + public void testInvalidSdlFileInput(){ + ISdl internalInterface = mock(ISdl.class); + + doAnswer(onListFilesSuccess).when(internalInterface).sendRPCRequest(any(ListFiles.class)); + + final FileManager fileManager = new FileManager(internalInterface, mTestContext); + fileManager.start(new CompletionListener() { + @Override + public void onComplete(boolean success) { + assertTrue(success); + SdlFile sdlFile = new SdlFile(); + // Don't set name + sdlFile.setFileData(Test.GENERAL_BYTE_ARRAY); + checkForUploadFailure(fileManager, sdlFile); + + sdlFile = new SdlFile(); + sdlFile.setName(Test.GENERAL_STRING); + // Don't set data + checkForUploadFailure(fileManager, sdlFile); + + sdlFile = new SdlFile(); + sdlFile.setName(Test.GENERAL_STRING); + // Give an invalid resource ID + sdlFile.setResourceId(Test.GENERAL_INT); + checkForUploadFailure(fileManager, sdlFile); + + sdlFile = new SdlFile(); + sdlFile.setName(Test.GENERAL_STRING); + // Set invalid Uri + Uri testUri = Uri.parse("http://www.google.com"); + sdlFile.setUri(testUri); + checkForUploadFailure(fileManager, sdlFile); + } + }); + } + + private void checkForUploadFailure(FileManager fileManager, SdlFile sdlFile){ + boolean error = false; + + try { + fileManager.uploadFile(sdlFile, new CompletionListener() { + @Override + public void onComplete(boolean success) {} + }); + }catch (IllegalArgumentException e){ + error = true; + } + + assertTrue(error); + } + + public void testInvalidSdlArtworkInput(){ + SdlArtwork sdlArtwork = new SdlArtwork(); + // Set invalid type + for(FileType fileType : FileType.values()){ + boolean shouldError = true, didError = false; + if(fileType.equals(FileType.GRAPHIC_BMP) || fileType.equals(FileType.GRAPHIC_PNG) + || fileType.equals(FileType.GRAPHIC_JPEG)){ + shouldError = false; + } + try{ + sdlArtwork.setType(fileType); + }catch(IllegalArgumentException e){ + didError = true; + } + assertEquals(shouldError, didError); + } + } + + public void testMultipleFileUploadThenDeleteSuccess(){ + ISdl internalInterface = mock(ISdl.class); + + doAnswer(onListFilesSuccess).when(internalInterface).sendRPCRequest(any(ListFiles.class)); + doAnswer(onSendRequestsSuccess).when(internalInterface).sendRequests(any(List.class), any(OnMultipleRequestListener.class)); + + final FileManager fileManager = new FileManager(internalInterface, mTestContext); + fileManager.start(new CompletionListener() { + @Override + public void onComplete(boolean success) { + assertTrue(success); + int fileNum = 1; + final List<SdlFile> filesToUpload = new ArrayList<>(); + SdlFile sdlFile = new SdlFile(); + sdlFile.setName("file" + fileNum++); + Uri uri = Uri.parse("android.resource://" + mTestContext.getPackageName() + "/drawable/ic_sdl"); + sdlFile.setUri(uri); + filesToUpload.add(sdlFile); + + sdlFile = new SdlFile(); + sdlFile.setName("file" + fileNum++); + sdlFile.setResourceId(com.smartdevicelink.test.R.drawable.ic_sdl); + filesToUpload.add(sdlFile); + + fileManager.uploadFiles(filesToUpload, + new MultipleFileCompletionListener() { + @Override + public void onComplete(Map<String, String> errors) { + assertNull(errors); + List <String> uploadedFileNames = fileManager.getRemoteFileNames(); + for(SdlFile file : filesToUpload){ + assertTrue(uploadedFileNames.contains(file.getName())); + } + fileManager.deleteRemoteFilesWithNames(uploadedFileNames, new MultipleFileCompletionListener() { + @Override + public void onComplete(Map<String, String> errors) { + assertNull(errors); + List <String> uploadedFileNames = fileManager.getRemoteFileNames(); + for(SdlFile file : filesToUpload){ + assertFalse(uploadedFileNames.contains(file.getName())); + } + } + }); + } + }); + } + }); + } + + public void testMultipleFileUploadPartialFailure(){ + final String failureReason = "No space available"; + + ISdl internalInterface = mock(ISdl.class); + + doAnswer(onListFilesSuccess).when(internalInterface).sendRPCRequest(any(ListFiles.class)); + + Answer<Void> onSendRequestsFailure = new Answer<Void>() { + private int responseNum = 0; + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + List<RPCRequest> rpcs = (List<RPCRequest>) args[0]; + OnMultipleRequestListener listener = (OnMultipleRequestListener) args[1]; + if(rpcs.get(0) instanceof PutFile){ + for(RPCRequest message : rpcs){ + int correlationId = message.getCorrelationID(); + listener.addCorrelationId(correlationId); + PutFileResponse putFileResponse = new PutFileResponse(); + if(responseNum++ % 2 == 0){ + listener.onError(correlationId, Result.OUT_OF_MEMORY, failureReason); + }else{ + putFileResponse.setSuccess(true); + listener.onResponse(correlationId, putFileResponse); + } + } + } + return null; + } + }; + doAnswer(onSendRequestsFailure).when(internalInterface).sendRequests(any(List.class), any(OnMultipleRequestListener.class)); + + final FileManager fileManager = new FileManager(internalInterface, mTestContext); + fileManager.start(new CompletionListener() { + @Override + public void onComplete(boolean success) { + assertTrue(success); + final String baseFileName = "file"; + int fileNum = 0; + final List<SdlFile> filesToUpload = new ArrayList<>(); + SdlFile sdlFile = new SdlFile(); + sdlFile.setName(baseFileName + fileNum++); + Uri uri = Uri.parse("android.resource://" + mTestContext.getPackageName() + "/drawable/ic_sdl"); + sdlFile.setUri(uri); + filesToUpload.add(sdlFile); + + sdlFile = new SdlFile(); + sdlFile.setName(baseFileName + fileNum++); + sdlFile.setResourceId(com.smartdevicelink.test.R.drawable.ic_sdl); + filesToUpload.add(sdlFile); + + sdlFile = new SdlFile(); + sdlFile.setName(baseFileName + fileNum++); + sdlFile.setFileData(Test.GENERAL_BYTE_ARRAY); + sdlFile.setPersistent(true); + sdlFile.setType(FileType.BINARY); + filesToUpload.add(sdlFile); + + fileManager.uploadFiles(filesToUpload, + new MultipleFileCompletionListener() { + @Override + public void onComplete(Map<String, String> errors) { + assertNotNull(errors); + for(int i = 0; i < filesToUpload.size(); i++){ + if(i % 2 == 0){ + assertTrue(errors.containsKey(filesToUpload.get(i).getName())); + assertEquals(FileManager.buildErrorString(Result.OUT_OF_MEMORY, + failureReason), errors.get(filesToUpload.get(i).getName())); + }else{ + assertFalse(errors.containsKey(filesToUpload.get(i).getName())); + } + } + List <String> uploadedFileNames = fileManager.getRemoteFileNames(); + for(int i = 0; i < filesToUpload.size(); i++){ + if(i % 2 == 0){ + assertFalse(uploadedFileNames.contains(filesToUpload.get(i).getName())); + }else{ + assertTrue(uploadedFileNames.contains(filesToUpload.get(i).getName())); + } + } + } + }); + } + }); + } + + public void testMultipleArtworkUploadSuccess(){ + ISdl internalInterface = mock(ISdl.class); + + doAnswer(onListFilesSuccess).when(internalInterface).sendRPCRequest(any(ListFiles.class)); + doAnswer(onSendRequestsSuccess).when(internalInterface).sendRequests(any(List.class), any(OnMultipleRequestListener.class)); + + final FileManager fileManager = new FileManager(internalInterface, mTestContext); + fileManager.start(new CompletionListener() { + @Override + public void onComplete(boolean success) { + assertTrue(success); + int fileNum = 1; + final List<SdlArtwork> artworkToUpload = new ArrayList<>(); + SdlArtwork sdlArtwork = new SdlArtwork(); + sdlArtwork.setName("art" + fileNum++); + Uri uri = Uri.parse("android.resource://" + mTestContext.getPackageName() + "/drawable/ic_sdl"); + sdlArtwork.setUri(uri); + sdlArtwork.setType(FileType.GRAPHIC_PNG); + artworkToUpload.add(sdlArtwork); + + sdlArtwork = new SdlArtwork(); + sdlArtwork.setName("art" + fileNum++); + uri = Uri.parse("android.resource://" + mTestContext.getPackageName() + "/drawable/sdl_tray_icon"); + sdlArtwork.setUri(uri); + sdlArtwork.setType(FileType.GRAPHIC_PNG); + artworkToUpload.add(sdlArtwork); + + fileManager.uploadFiles(artworkToUpload, + new MultipleFileCompletionListener() { + @Override + public void onComplete(Map<String, String> errors) { + assertNull(errors); + List < String > uploadedFileNames = fileManager.getRemoteFileNames(); + for(SdlArtwork artwork : artworkToUpload){ + assertTrue(uploadedFileNames.contains(artwork.getName())); + } + } + }); + } + }); + } + + public void testPersistentFileUploaded(){ + ISdl internalInterface = mock(ISdl.class); + + doAnswer(onListFilesSuccess).when(internalInterface).sendRPCRequest(any(ListFiles.class)); + + final SdlFile file = new SdlFile(); + file.setName(Test.GENERAL_STRING_LIST.get(0)); + file.setPersistent(true); + + final FileManager fileManager = new FileManager(internalInterface, mTestContext); + fileManager.start(new CompletionListener() { + @Override + public void onComplete(boolean success) { + assertTrue(fileManager.hasUploadedFile(file)); + } + }); + } +}
\ No newline at end of file diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/lockscreen/LockScreenConfigTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/lockscreen/LockScreenConfigTests.java new file mode 100644 index 000000000..c2d4066ce --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/lockscreen/LockScreenConfigTests.java @@ -0,0 +1,45 @@ +package com.smartdevicelink.managers.lockscreen; + +import com.smartdevicelink.AndroidTestCase2; +import com.smartdevicelink.test.Test; + + +/** + * This is a unit test class for the SmartDeviceLink library manager class : + * {@link com.smartdevicelink.managers.lockscreen.LockScreenConfig} + * + * We currently do not need to test null values, as each currently is a primitive + */ +public class LockScreenConfigTests extends AndroidTestCase2 { + + private LockScreenConfig lockScreenConfig; + + @Override + public void setUp() throws Exception { + super.setUp(); + + // set info for all the setters + lockScreenConfig = new LockScreenConfig(); + lockScreenConfig.setCustomView(Test.GENERAL_INT); + lockScreenConfig.setAppIcon(Test.GENERAL_INT); + lockScreenConfig.setBackgroundColor(Test.GENERAL_INT); + lockScreenConfig.showDeviceLogo(true); + lockScreenConfig.setEnabled(true); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + } + + public void testLockScreenConfig() { + + // get the info and make sure its correct + assertEquals(Test.GENERAL_INT, lockScreenConfig.getCustomView()); + assertEquals(Test.GENERAL_INT, lockScreenConfig.getAppIcon()); + assertEquals(Test.GENERAL_INT, lockScreenConfig.getBackgroundColor()); + assertEquals(true, lockScreenConfig.isEnabled()); + assertEquals(true, lockScreenConfig.isDeviceLogoEnabled()); + } + +}
\ No newline at end of file diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/lockscreen/LockScreenManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/lockscreen/LockScreenManagerTests.java new file mode 100644 index 000000000..69e0aa898 --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/lockscreen/LockScreenManagerTests.java @@ -0,0 +1,56 @@ +package com.smartdevicelink.managers.lockscreen; + +import android.content.Context; + +import com.smartdevicelink.AndroidTestCase2; +import com.smartdevicelink.proxy.interfaces.ISdl; +import com.smartdevicelink.proxy.rpc.enums.LockScreenStatus; +import com.smartdevicelink.test.Test; + +import static org.mockito.Mockito.mock; + +/** + * This is a unit test class for the SmartDeviceLink library manager class : + * {@link com.smartdevicelink.managers.lockscreen.LockScreenManager} + */ +public class LockScreenManagerTests extends AndroidTestCase2 { + + private LockScreenManager lockScreenManager; + + @Override + public void setUp() throws Exception{ + super.setUp(); + + ISdl internalInterface = mock(ISdl.class); + + Context context = getContext(); + // create config + LockScreenConfig lockScreenConfig = new LockScreenConfig(); + lockScreenConfig.setCustomView(Test.GENERAL_INT); + lockScreenConfig.setAppIcon(Test.GENERAL_INT); + lockScreenConfig.setBackgroundColor(Test.GENERAL_INT); + lockScreenConfig.showDeviceLogo(true); + lockScreenConfig.setEnabled(true); + + lockScreenManager = new LockScreenManager(lockScreenConfig, context, internalInterface); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + } + + public void testVariables() { + assertEquals(Test.GENERAL_INT, lockScreenManager.customView); + assertEquals(Test.GENERAL_INT, lockScreenManager.lockScreenIcon); + assertEquals(Test.GENERAL_INT, lockScreenManager.lockScreenColor); + assertEquals(true, lockScreenManager.deviceLogoEnabled); + assertEquals(true, lockScreenManager.lockScreenEnabled); + assertNull(lockScreenManager.deviceLogo); + } + + public void testGetLockScreenStatus(){ + assertEquals(LockScreenStatus.OFF, lockScreenManager.getLockScreenStatus()); + } + +} diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/permission/PermissionManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/permission/PermissionManagerTests.java new file mode 100644 index 000000000..6a66a3092 --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/permission/PermissionManagerTests.java @@ -0,0 +1,203 @@ +package com.smartdevicelink.managers.permission; + +import android.support.annotation.NonNull; + +import com.smartdevicelink.AndroidTestCase2; +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.proxy.interfaces.ISdl; +import com.smartdevicelink.proxy.rpc.HMIPermissions; +import com.smartdevicelink.proxy.rpc.OnHMIStatus; +import com.smartdevicelink.proxy.rpc.OnPermissionsChange; +import com.smartdevicelink.proxy.rpc.ParameterPermissions; +import com.smartdevicelink.proxy.rpc.PermissionItem; +import com.smartdevicelink.proxy.rpc.enums.HMILevel; +import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener; + +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static com.smartdevicelink.managers.permission.PermissionManager.PERMISSION_GROUP_STATUS_ALLOWED; +import static com.smartdevicelink.managers.permission.PermissionManager.PERMISSION_GROUP_STATUS_MIXED; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; + +public class PermissionManagerTests extends AndroidTestCase2 { + + private OnRPCNotificationListener onHMIStatusListener, onPermissionsChangeListener; + private PermissionManager permissionManager; + private int listenerCalledCounter; + + + @Override + protected void setUp() throws Exception { + super.setUp(); + + // Mock Isdl and its behaviour to use it for PermissionManager testing + ISdl internalInterface = mock(ISdl.class); + + + // When internalInterface.addOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, OnRPCNotificationListener) is called + // inside PermissionManager's constructor, then keep a reference to the OnRPCNotificationListener so we can trigger it later + // to emulate what Core does when it sends OnHMIStatus notification + Answer<Void> onHMIStatusAnswer = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + onHMIStatusListener = (OnRPCNotificationListener) args[1]; + return null; + } + }; + doAnswer(onHMIStatusAnswer).when(internalInterface).addOnRPCNotificationListener(eq(FunctionID.ON_HMI_STATUS), any(OnRPCNotificationListener.class)); + + + // When internalInterface.addOnRPCNotificationListener(FunctionID.ON_PERMISSIONS_CHANGE, OnRPCNotificationListener) is called + // inside PermissionManager's constructor, then keep a reference to the onPermissionsChangeListener so we can trigger it later + // to emulate what Core does when it sends OnPermissionsChange notification + Answer<Void> onPermissionsChangeAnswer = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + onPermissionsChangeListener = (OnRPCNotificationListener) args[1]; + return null; + } + }; + doAnswer(onPermissionsChangeAnswer).when(internalInterface).addOnRPCNotificationListener(eq(FunctionID.ON_PERMISSIONS_CHANGE), any(OnRPCNotificationListener.class)); + + + // Initialize PermissionManager + permissionManager = new PermissionManager(internalInterface); + } + + // Emulate what happens when Core sends OnHMIStatus notification + private void sendFakeCoreOnHMIStatusNotifications(HMILevel hmiLevel) { + if (hmiLevel != null) { + OnHMIStatus onHMIStatusFakeNotification = new OnHMIStatus(); + onHMIStatusFakeNotification.setHmiLevel(hmiLevel); + onHMIStatusListener.onNotified(onHMIStatusFakeNotification); + } + } + + // Emulate what happens when Core sends OnPermissionsChange notification + private void sendFakeCoreOnPermissionsChangeNotifications(List<PermissionItem> permissionItems) { + if (permissionItems != null) { + OnPermissionsChange onPermissionChangeFakeNotification = new OnPermissionsChange(); + onPermissionChangeFakeNotification.setPermissionItem(permissionItems); + onPermissionsChangeListener.onNotified(onPermissionChangeFakeNotification); + } + } + + // Test adding a listener to be called when ALL of the specified permissions become allowed + public void testListenersAllAllowed() { + listenerCalledCounter = 0; + + + // Test how developers can add listeners through PermissionManager + List<PermissionElement> permissionElements = new ArrayList<>(); + permissionElements.add(new PermissionElement(FunctionID.SHOW, null)); + permissionElements.add(new PermissionElement(FunctionID.GET_VEHICLE_DATA, Arrays.asList("rpm", "airbagStatus"))); + permissionManager.addListener(permissionElements, PermissionManager.PERMISSION_GROUP_TYPE_ALL_ALLOWED, new OnPermissionChangeListener() { + @Override + public void onPermissionsChange(@NonNull Map<FunctionID, PermissionStatus> allowedPermissions, @NonNull int permissionGroupStatus) { + // Make sure is the actual result matches the expected one + assertEquals(permissionGroupStatus, PERMISSION_GROUP_STATUS_ALLOWED); + assertTrue(allowedPermissions.get(FunctionID.SHOW).getIsRPCAllowed()); + assertTrue(allowedPermissions.get(FunctionID.GET_VEHICLE_DATA).getIsRPCAllowed()); + assertTrue(allowedPermissions.get(FunctionID.GET_VEHICLE_DATA).getAllowedParameters().get("rpm")); + assertTrue(allowedPermissions.get(FunctionID.GET_VEHICLE_DATA).getAllowedParameters().get("airbagStatus")); + listenerCalledCounter++; + } + }); + + + // Emulate Core's behaviour by sending OnHMIStatus notification + sendFakeCoreOnHMIStatusNotifications(HMILevel.HMI_LIMITED); + + + // Emulate Core's behaviour by sending OnPermissionsChange notification + List<PermissionItem> permissionItems = new ArrayList<>(); + PermissionItem permissionItem1 = new PermissionItem(); + permissionItem1.setRpcName(FunctionID.SHOW.toString()); + permissionItem1.setHMIPermissions(new HMIPermissions(Arrays.asList(HMILevel.HMI_BACKGROUND, HMILevel.HMI_FULL, HMILevel.HMI_LIMITED), new ArrayList<HMILevel>())); + permissionItem1.setParameterPermissions(new ParameterPermissions(new ArrayList<String>(), new ArrayList<String>())); + permissionItems.add(permissionItem1); + PermissionItem permissionItem2 = new PermissionItem(); + permissionItem2.setRpcName(FunctionID.GET_VEHICLE_DATA.toString()); + permissionItem2.setHMIPermissions(new HMIPermissions(Arrays.asList(HMILevel.HMI_BACKGROUND, HMILevel.HMI_FULL), new ArrayList<HMILevel>())); + permissionItem2.setParameterPermissions(new ParameterPermissions(Arrays.asList("rpm", "airbagStatus"), new ArrayList<String>())); + permissionItems.add(permissionItem2); + sendFakeCoreOnPermissionsChangeNotifications(permissionItems); + + + // Emulate Core's behaviour by sending OnHMIStatus notification + sendFakeCoreOnHMIStatusNotifications(HMILevel.HMI_FULL); + + + // Make sure the listener is called exactly once + assertEquals("Listener was not called or called more/less frequently than expected", listenerCalledCounter, 1); + } + + + // Test adding a listener to be called when ANY of the specified permissions become allowed + public void testListenersAnyAllowed() { + listenerCalledCounter = 0; + + // Test how developers can add listeners through PermissionManager + List<PermissionElement> permissionElements = new ArrayList<>(); + permissionElements.add(new PermissionElement(FunctionID.SHOW, null)); + permissionElements.add(new PermissionElement(FunctionID.GET_VEHICLE_DATA, Arrays.asList("rpm", "airbagStatus"))); + permissionManager.addListener(permissionElements, PermissionManager.PERMISSION_GROUP_TYPE_ANY, new OnPermissionChangeListener() { + @Override + public void onPermissionsChange(@NonNull Map<FunctionID, PermissionStatus> allowedPermissions, @NonNull int permissionGroupStatus) { + // Make sure is the actual result matches the expected one + if (listenerCalledCounter == 0) { // Listener called for the first time + assertEquals(permissionGroupStatus, PERMISSION_GROUP_STATUS_MIXED); + assertTrue(allowedPermissions.get(FunctionID.SHOW).getIsRPCAllowed()); + assertTrue(!allowedPermissions.get(FunctionID.GET_VEHICLE_DATA).getIsRPCAllowed()); + assertTrue(!allowedPermissions.get(FunctionID.GET_VEHICLE_DATA).getAllowedParameters().get("rpm")); + assertTrue(!allowedPermissions.get(FunctionID.GET_VEHICLE_DATA).getAllowedParameters().get("airbagStatus")); + } else if (listenerCalledCounter == 1) { // Listener called for the second time + assertEquals(permissionGroupStatus, PERMISSION_GROUP_STATUS_ALLOWED); + assertTrue(allowedPermissions.get(FunctionID.SHOW).getIsRPCAllowed()); + assertTrue(allowedPermissions.get(FunctionID.GET_VEHICLE_DATA).getIsRPCAllowed()); + assertTrue(allowedPermissions.get(FunctionID.GET_VEHICLE_DATA).getAllowedParameters().get("rpm")); + assertTrue(allowedPermissions.get(FunctionID.GET_VEHICLE_DATA).getAllowedParameters().get("airbagStatus")); + } + listenerCalledCounter++; + } + }); + + + // Emulate Core's behaviour by sending OnHMIStatus notification + sendFakeCoreOnHMIStatusNotifications(HMILevel.HMI_LIMITED); + + + // Emulate Core's behaviour by sending OnPermissionsChange notification + List<PermissionItem> permissionItems = new ArrayList<>(); + PermissionItem permissionItem1 = new PermissionItem(); + permissionItem1.setRpcName(FunctionID.SHOW.toString()); + permissionItem1.setHMIPermissions(new HMIPermissions(Arrays.asList(HMILevel.HMI_BACKGROUND, HMILevel.HMI_FULL, HMILevel.HMI_LIMITED), new ArrayList<HMILevel>())); + permissionItem1.setParameterPermissions(new ParameterPermissions(new ArrayList<String>(), new ArrayList<String>())); + permissionItems.add(permissionItem1); + PermissionItem permissionItem2 = new PermissionItem(); + permissionItem2.setRpcName(FunctionID.GET_VEHICLE_DATA.toString()); + permissionItem2.setHMIPermissions(new HMIPermissions(Arrays.asList(HMILevel.HMI_BACKGROUND, HMILevel.HMI_FULL), new ArrayList<HMILevel>())); + permissionItem2.setParameterPermissions(new ParameterPermissions(Arrays.asList("rpm", "airbagStatus"), new ArrayList<String>())); + permissionItems.add(permissionItem2); + sendFakeCoreOnPermissionsChangeNotifications(permissionItems); + + + // Emulate Core's behaviour by sending OnHMIStatus notification + sendFakeCoreOnHMIStatusNotifications(HMILevel.HMI_FULL); + + + // Make sure the the listener is called exactly twice + assertEquals("Listener was not called or called more/less frequently than expected", listenerCalledCounter, 2); + } +} diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/ScreenManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/ScreenManagerTests.java new file mode 100644 index 000000000..872e09b81 --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/ScreenManagerTests.java @@ -0,0 +1,135 @@ +package com.smartdevicelink.managers.screen; + +import com.smartdevicelink.AndroidTestCase2; +import com.smartdevicelink.managers.BaseSubManager; +import com.smartdevicelink.managers.file.FileManager; +import com.smartdevicelink.managers.file.filetypes.SdlArtwork; +import com.smartdevicelink.proxy.interfaces.ISdl; +import com.smartdevicelink.proxy.rpc.enums.FileType; +import com.smartdevicelink.proxy.rpc.enums.MetadataType; +import com.smartdevicelink.proxy.rpc.enums.TextAlignment; + +import java.util.Arrays; +import java.util.List; + +import static org.mockito.Mockito.mock; + +/** + * This is a unit test class for the SmartDeviceLink library manager class : + * {@link ScreenManager} + */ +public class ScreenManagerTests extends AndroidTestCase2 { + private ScreenManager screenManager; + private SdlArtwork testArtwork; + + @Override + public void setUp() throws Exception{ + super.setUp(); + + ISdl internalInterface = mock(ISdl.class); + FileManager fileManager = mock(FileManager.class); + screenManager = new ScreenManager(internalInterface, fileManager); + screenManager.start(null); + + + testArtwork = new SdlArtwork("testFile", FileType.GRAPHIC_PNG, 1, false); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + } + + public void testInstantiation(){ + assertNull(screenManager.getTextField1()); + assertNull(screenManager.getTextField2()); + assertNull(screenManager.getTextField3()); + assertNull(screenManager.getTextField4()); + assertNull(screenManager.getMediaTrackTextField()); + assertNull(screenManager.getPrimaryGraphic()); + assertNull(screenManager.getSecondaryGraphic()); + assertEquals(screenManager.getTextAlignment(), TextAlignment.CENTERED); + assertNull(screenManager.getTextField1Type()); + assertNull(screenManager.getTextField2Type()); + assertNull(screenManager.getTextField3Type()); + assertNull(screenManager.getTextField4Type()); + assertTrue(screenManager.getSoftButtonObjects().isEmpty()); + assertNull(screenManager.getSoftButtonObjectByName("test")); + assertNull(screenManager.getSoftButtonObjectById(1)); + assertEquals(screenManager.getState(), BaseSubManager.READY); + } + + public void testSetTextField() { + screenManager.setTextField1("It is"); + screenManager.setTextField2("Wednesday"); + screenManager.setTextField3("My"); + screenManager.setTextField4("Dudes"); + assertEquals(screenManager.getTextField1(), "It is"); + assertEquals(screenManager.getTextField2(), "Wednesday"); + assertEquals(screenManager.getTextField3(), "My"); + assertEquals(screenManager.getTextField4(), "Dudes"); + } + + public void testMediaTrackTextFields() { + String songTitle = "Wild For The Night"; + screenManager.setMediaTrackTextField(songTitle); + assertEquals(screenManager.getMediaTrackTextField(), songTitle); + } + + public void testSetPrimaryGraphic() { + screenManager.setPrimaryGraphic(testArtwork); + assertEquals(screenManager.getPrimaryGraphic(), testArtwork); + } + + public void testSetPrimaryGraphicWithBlankImage() { + screenManager.setPrimaryGraphic(null); + assertNotNull(screenManager.getPrimaryGraphic()); + assertEquals(screenManager.getPrimaryGraphic().getName(), "blankArtwork"); + } + + public void testSetSecondaryGraphic() { + screenManager.setSecondaryGraphic(testArtwork); + assertEquals(screenManager.getSecondaryGraphic(), testArtwork); + } + + public void testSetSecondaryGraphicWithBlankImage() { + screenManager.setSecondaryGraphic(null); + assertNotNull(screenManager.getSecondaryGraphic()); + assertEquals(screenManager.getSecondaryGraphic().getName(), "blankArtwork"); + } + + public void testAlignment() { + screenManager.setTextAlignment(TextAlignment.LEFT_ALIGNED); + assertEquals(screenManager.getTextAlignment(), TextAlignment.LEFT_ALIGNED); + } + + public void testSetTextFieldTypes() { + screenManager.setTextField1Type(MetadataType.MEDIA_TITLE); + screenManager.setTextField2Type(MetadataType.MEDIA_ALBUM); + screenManager.setTextField3Type(MetadataType.MEDIA_ARTIST); + screenManager.setTextField4Type(MetadataType.MEDIA_GENRE); + assertEquals(screenManager.getTextField1Type(), MetadataType.MEDIA_TITLE); + assertEquals(screenManager.getTextField2Type(), MetadataType.MEDIA_ALBUM); + assertEquals(screenManager.getTextField3Type(), MetadataType.MEDIA_ARTIST); + assertEquals(screenManager.getTextField4Type(), MetadataType.MEDIA_GENRE); + } + + public void testSetSoftButtonObjects(){ + // Create softButtonObject1 + SoftButtonState softButtonState1 = new SoftButtonState("object1-state1", "it is", testArtwork); + SoftButtonState softButtonState2 = new SoftButtonState("object1-state2", "Wed", testArtwork); + SoftButtonObject softButtonObject1 = new SoftButtonObject("object1", Arrays.asList(softButtonState1, softButtonState2), softButtonState1.getName(),null); + + // Create softButtonObject2 + SoftButtonState softButtonState3 = new SoftButtonState("object2-state1", "my", testArtwork); + SoftButtonState softButtonState4 = new SoftButtonState("object2-state2", "dudes!", null); + SoftButtonObject softButtonObject2 = new SoftButtonObject("object2", Arrays.asList(softButtonState3, softButtonState4), softButtonState3.getName(), null); + + List<SoftButtonObject> softButtonObjects = Arrays.asList(softButtonObject1, softButtonObject2); + screenManager.setSoftButtonObjects(Arrays.asList(softButtonObject1, softButtonObject2)); + assertEquals(screenManager.getSoftButtonObjects(), softButtonObjects); + assertEquals(screenManager.getSoftButtonObjectByName("object2"), softButtonObject2); + assertEquals(screenManager.getSoftButtonObjectById(100), softButtonObject2); + } + +} diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/SoftButtonManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/SoftButtonManagerTests.java new file mode 100644 index 000000000..144057c36 --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/SoftButtonManagerTests.java @@ -0,0 +1,242 @@ +package com.smartdevicelink.managers.screen; + + +import com.smartdevicelink.AndroidTestCase2; +import com.smartdevicelink.managers.CompletionListener; +import com.smartdevicelink.managers.file.FileManager; +import com.smartdevicelink.managers.file.MultipleFileCompletionListener; +import com.smartdevicelink.managers.file.filetypes.SdlArtwork; +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.proxy.interfaces.ISdl; +import com.smartdevicelink.proxy.rpc.Image; +import com.smartdevicelink.proxy.rpc.OnHMIStatus; +import com.smartdevicelink.proxy.rpc.Show; +import com.smartdevicelink.proxy.rpc.SoftButton; +import com.smartdevicelink.proxy.rpc.enums.FileType; +import com.smartdevicelink.proxy.rpc.enums.HMILevel; +import com.smartdevicelink.proxy.rpc.enums.ImageType; +import com.smartdevicelink.proxy.rpc.enums.SoftButtonType; +import com.smartdevicelink.proxy.rpc.enums.StaticIconName; +import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener; +import com.smartdevicelink.test.Validator; + +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.util.Arrays; +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; + +/** + * This is a unit test class for the SmartDeviceLink library manager class : + * {@link SoftButtonManager} + */ +public class SoftButtonManagerTests extends AndroidTestCase2 { + + private SoftButtonManager softButtonManager; + private boolean fileManagerUploadArtworksGotCalled; + private boolean internalInterfaceSendRPCRequestGotCalled; + private boolean softButtonMangerUpdateCompleted; + private SoftButtonObject softButtonObject1, softButtonObject2; + private SoftButtonState softButtonState1, softButtonState2, softButtonState3, softButtonState4; + + + @Override + public void setUp() throws Exception { + super.setUp(); + + // When internalInterface.addOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, OnRPCNotificationListener) is called + // inside SoftButtonManager, respond with a fake HMILevel.HMI_FULL response to let the SoftButtonManager continue working. + ISdl internalInterface = mock(ISdl.class); + Answer<Void> onHMIStatusAnswer = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + OnRPCNotificationListener onHMIStatusListener = (OnRPCNotificationListener) args[1]; + OnHMIStatus onHMIStatusFakeNotification = new OnHMIStatus(); + onHMIStatusFakeNotification.setHmiLevel(HMILevel.HMI_FULL); + onHMIStatusListener.onNotified(onHMIStatusFakeNotification); + return null; + } + }; + doAnswer(onHMIStatusAnswer).when(internalInterface).addOnRPCNotificationListener(eq(FunctionID.ON_HMI_STATUS), any(OnRPCNotificationListener.class)); + + + // When fileManager.uploadArtworks() is called inside the SoftButtonManager, respond with + // a fake onComplete() callback to let the SoftButtonManager continue working. + FileManager fileManager = mock(FileManager.class); + Answer<Void> onFileManagerUploadAnswer = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + fileManagerUploadArtworksGotCalled = true; + Object[] args = invocation.getArguments(); + MultipleFileCompletionListener multipleFileCompletionListener = (MultipleFileCompletionListener) args[1]; + multipleFileCompletionListener.onComplete(null); + return null; + } + }; + doAnswer(onFileManagerUploadAnswer).when(fileManager).uploadArtworks(any(List.class), any(MultipleFileCompletionListener.class)); + + + // Create softButtonManager + softButtonManager = new SoftButtonManager(internalInterface, fileManager); + + + // When internalInterface.sendRPCRequest() is called inside SoftButtonManager: + // 1) respond with a fake onResponse() callback to let the SoftButtonManager continue working + // 2) assert that the Show RPC values (ie: MainField1 & SoftButtons) that are created by the SoftButtonManager, match the ones that are provided by the developer + Answer<Void> onSendShowRPCAnswer = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + internalInterfaceSendRPCRequestGotCalled = true; + Object[] args = invocation.getArguments(); + Show show = (Show) args[0]; + + show.getOnRPCResponseListener().onResponse(0, null); + + assertEquals(show.getMainField1(), softButtonManager.getCurrentMainField1()); + assertEquals(show.getSoftButtons().size(), softButtonManager.createSoftButtonsForCurrentState().size()); + + return null; + } + }; + doAnswer(onSendShowRPCAnswer).when(internalInterface).sendRPCRequest(any(Show.class)); + + + // Create soft button objects + softButtonState1 = new SoftButtonState("object1-state1", "o1s1", new SdlArtwork("image1", FileType.GRAPHIC_PNG, 1, true)); + softButtonState2 = new SoftButtonState("object1-state2", "o1s2", new SdlArtwork(StaticIconName.ALBUM)); + softButtonObject1 = new SoftButtonObject("object1", Arrays.asList(softButtonState1, softButtonState2), softButtonState1.getName(), null); + softButtonState3 = new SoftButtonState("object2-state1", "o2s1", null); + softButtonState4 = new SoftButtonState("object2-state2", "o2s2", new SdlArtwork("image3", FileType.GRAPHIC_PNG, 3, true)); + softButtonObject2 = new SoftButtonObject("object2", Arrays.asList(softButtonState3, softButtonState4), softButtonState3.getName(), null); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + } + + public void testSoftButtonManagerUpdate() { + // Reset the boolean variables + fileManagerUploadArtworksGotCalled = false; + internalInterfaceSendRPCRequestGotCalled = false; + softButtonMangerUpdateCompleted = false; + + + // Test batch update + softButtonManager.setBatchUpdates(true); + List<SoftButtonObject> softButtonObjects = Arrays.asList(softButtonObject1, softButtonObject2); + softButtonManager.setSoftButtonObjects(Arrays.asList(softButtonObject1, softButtonObject2)); + softButtonManager.setBatchUpdates(false); + softButtonManager.update(new CompletionListener() { + @Override + public void onComplete(boolean success) { + softButtonMangerUpdateCompleted = true; + } + }); + + + // Test single update, setCurrentMainField1, and transitionToNextState + softButtonManager.setCurrentMainField1("It is Wednesday my dudes!"); + softButtonObject1.transitionToNextState(); + + + // Check that everything got called as expected + assertTrue("FileManager.uploadArtworks() did not get called", fileManagerUploadArtworksGotCalled); + assertTrue("InternalInterface.sendRPCRequest() did not get called", internalInterfaceSendRPCRequestGotCalled); + assertTrue("SoftButtonManger update onComplete() did not get called", softButtonMangerUpdateCompleted); + + + // Test getSoftButtonObjects + assertEquals("Returned softButtonObjects value doesn't match the expected value", softButtonObjects, softButtonManager.getSoftButtonObjects()); + } + + public void testSoftButtonManagerGetSoftButtonObject() { + softButtonManager.setSoftButtonObjects(Arrays.asList(softButtonObject1, softButtonObject2)); + + + // Test get by valid name + assertEquals("Returned SoftButtonObject doesn't match the expected value", softButtonObject2, softButtonManager.getSoftButtonObjectByName("object2")); + + + // Test get by invalid name + assertNull("Returned SoftButtonObject doesn't match the expected value", softButtonManager.getSoftButtonObjectByName("object300")); + + + // Test get by valid id + assertEquals("Returned SoftButtonObject doesn't match the expected value", softButtonObject2, softButtonManager.getSoftButtonObjectById(100)); + + + // Test get by invalid id + assertNull("Returned SoftButtonObject doesn't match the expected value", softButtonManager.getSoftButtonObjectById(500)); + } + + public void testSoftButtonState(){ + // Test SoftButtonState.getName() + String nameExpectedValue = "object1-state1"; + assertEquals("Returned state name doesn't match the expected value", nameExpectedValue, softButtonState1.getName()); + + + // Test SoftButtonState.getArtwork() + SdlArtwork artworkExpectedValue = new SdlArtwork("image1", FileType.GRAPHIC_PNG, 1, true); + assertTrue("Returned SdlArtwork doesn't match the expected value", Validator.validateSdlFile(artworkExpectedValue, softButtonState1.getArtwork())); + SdlArtwork artworkExpectedValue2 = new SdlArtwork(StaticIconName.ALBUM); + assertTrue("Returned SdlArtwork doesn't match the expected value", Validator.validateSdlFile(artworkExpectedValue2, softButtonState2.getArtwork())); + + + // Test SoftButtonState.getSoftButton() + SoftButton softButtonExpectedValue = new SoftButton(SoftButtonType.SBT_BOTH, 0); + softButtonExpectedValue.setText("o1s1"); + softButtonExpectedValue.setImage(new Image(artworkExpectedValue.getName(), ImageType.DYNAMIC)); + assertTrue("Returned SoftButton doesn't match the expected value", Validator.validateSoftButton(softButtonExpectedValue, softButtonState1.getSoftButton())); + } + + public void testSoftButtonObject(){ + // Test SoftButtonObject.getName() + assertEquals("Returned object name doesn't match the expected value", "object1", softButtonObject1.getName()); + + + // Test SoftButtonObject.getCurrentState() + assertEquals("Returned current state doesn't match the expected value", softButtonState1, softButtonObject1.getCurrentState()); + + + // Test SoftButtonObject.getCurrentStateName() + assertEquals("Returned current state name doesn't match the expected value", softButtonState1.getName(), softButtonObject1.getCurrentStateName()); + + + // Test SoftButtonObject.getButtonId() + assertEquals("Returned button Id doesn't match the expected value", 0, softButtonObject1.getButtonId()); + + + // Test SoftButtonObject.getCurrentStateSoftButton() + SoftButton softButtonExpectedValue = new SoftButton(SoftButtonType.SBT_TEXT, 0); + softButtonExpectedValue.setText("o2s1"); + assertTrue("Returned current state SoftButton doesn't match the expected value", Validator.validateSoftButton(softButtonExpectedValue, softButtonObject2.getCurrentStateSoftButton())); + + + // Test SoftButtonObject.getStates() + assertEquals("Returned object states doesn't match the expected value", Arrays.asList(softButtonState1, softButtonState2), softButtonObject1.getStates()); + + + // Test SoftButtonObject.transitionToNextState() + assertEquals(softButtonState1, softButtonObject1.getCurrentState()); + softButtonObject1.transitionToNextState(); + assertEquals(softButtonState2, softButtonObject1.getCurrentState()); + + + // Test SoftButtonObject.transitionToStateByName() - transitioning to a none existing state + boolean success = softButtonObject1.transitionToStateByName("none existing name"); + assertFalse(success); + + + // Test SoftButtonObject.transitionToStateByName() - transitioning to an existing state + success = softButtonObject1.transitionToStateByName("object1-state1"); + assertTrue(success); + assertEquals(softButtonState1, softButtonObject1.getCurrentState()); + } +} diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/TextAndGraphicManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/TextAndGraphicManagerTests.java new file mode 100644 index 000000000..d063f52e3 --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/TextAndGraphicManagerTests.java @@ -0,0 +1,546 @@ +package com.smartdevicelink.managers.screen; + +import android.content.Context; +import android.net.Uri; + +import com.smartdevicelink.AndroidTestCase2; +import com.smartdevicelink.managers.BaseSubManager; +import com.smartdevicelink.managers.file.FileManager; +import com.smartdevicelink.managers.file.filetypes.SdlArtwork; +import com.smartdevicelink.proxy.interfaces.ISdl; +import com.smartdevicelink.proxy.rpc.DisplayCapabilities; +import com.smartdevicelink.proxy.rpc.MetadataTags; +import com.smartdevicelink.proxy.rpc.Show; +import com.smartdevicelink.proxy.rpc.TextField; +import com.smartdevicelink.proxy.rpc.enums.FileType; +import com.smartdevicelink.proxy.rpc.enums.HMILevel; +import com.smartdevicelink.proxy.rpc.enums.MetadataType; +import com.smartdevicelink.proxy.rpc.enums.TextAlignment; +import com.smartdevicelink.proxy.rpc.enums.TextFieldName; + +import org.json.JSONException; + +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.Mockito.mock; + +/** + * This is a unit test class for the SmartDeviceLink library manager class : + * {@link com.smartdevicelink.managers.screen.TextAndGraphicManager} + */ +public class TextAndGraphicManagerTests extends AndroidTestCase2 { + + // SETUP / HELPERS + private TextAndGraphicManager textAndGraphicManager; + private SdlArtwork testArtwork; + + @Override + public void setUp() throws Exception{ + super.setUp(); + Context mTestContext = this.getContext(); + // mock things + ISdl internalInterface = mock(ISdl.class); + FileManager fileManager = mock(FileManager.class); + SoftButtonManager softButtonManager = mock(SoftButtonManager.class); + + testArtwork = new SdlArtwork(); + testArtwork.setName("testFile"); + Uri uri = Uri.parse("android.resource://" + mTestContext.getPackageName() + "/drawable/ic_sdl"); + testArtwork.setUri(uri); + testArtwork.setType(FileType.GRAPHIC_PNG); + + textAndGraphicManager = new TextAndGraphicManager(internalInterface, fileManager, softButtonManager); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + } + + private DisplayCapabilities getDisplayCapability(int numberOfMainFields){ + + TextField mainField1 = new TextField(); + mainField1.setName(TextFieldName.mainField1); + TextField mainField2 = new TextField(); + mainField2.setName(TextFieldName.mainField2); + TextField mainField3 = new TextField(); + mainField3.setName(TextFieldName.mainField3); + TextField mainField4 = new TextField(); + mainField4.setName(TextFieldName.mainField4); + + List<TextField> textFieldList = new ArrayList<>(); + + textFieldList.add(mainField1); + textFieldList.add(mainField2); + textFieldList.add(mainField3); + textFieldList.add(mainField4); + + List<TextField> returnList = new ArrayList<>(); + + if (numberOfMainFields > 0){ + for (int i = 0; i < numberOfMainFields; i++) { + returnList.add(textFieldList.get(i)); + } + } + + DisplayCapabilities displayCapabilities = new DisplayCapabilities(); + displayCapabilities.setTextFields(returnList); + + return displayCapabilities; + } + + public void testInstantiation(){ + + assertNull(textAndGraphicManager.getTextField1()); + assertNull(textAndGraphicManager.getTextField2()); + assertNull(textAndGraphicManager.getTextField3()); + assertNull(textAndGraphicManager.getTextField4()); + assertNull(textAndGraphicManager.getMediaTrackTextField()); + assertNull(textAndGraphicManager.getPrimaryGraphic()); + assertNull(textAndGraphicManager.getSecondaryGraphic()); + assertEquals(textAndGraphicManager.getTextAlignment(), TextAlignment.CENTERED); + assertNull(textAndGraphicManager.getTextField1Type()); + assertNull(textAndGraphicManager.getTextField2Type()); + assertNull(textAndGraphicManager.getTextField3Type()); + assertNull(textAndGraphicManager.getTextField4Type()); + + assertNotNull(textAndGraphicManager.currentScreenData); + assertNull(textAndGraphicManager.inProgressUpdate); + assertNull(textAndGraphicManager.queuedImageUpdate); + assertFalse(textAndGraphicManager.hasQueuedUpdate); + assertNull(textAndGraphicManager.displayCapabilities); + assertEquals(textAndGraphicManager.currentHMILevel, HMILevel.HMI_NONE); + assertFalse(textAndGraphicManager.isDirty); + assertEquals(textAndGraphicManager.getState(), BaseSubManager.SETTING_UP); + assertNotNull(textAndGraphicManager.getBlankArtwork()); + } + + public void testGetMainLines(){ + + // We want to test that the looping works. By default, it will return 4 if display cap is null + + // Null test + assertEquals(textAndGraphicManager.getNumberOfLines(), 4); + + // The tests.java class has an example of this, but we must build it to do what + // we need it to do. Build display cap w/ 3 main fields and test that it returns 3 + textAndGraphicManager.displayCapabilities = getDisplayCapability(3); + assertEquals(textAndGraphicManager.getNumberOfLines(), 3); + } + + public void testAssemble1Line(){ + + Show inputShow = new Show(); + + // Force it to return display with support for only 1 line of text + textAndGraphicManager.displayCapabilities = getDisplayCapability(1); + + textAndGraphicManager.setTextField1("It is"); + textAndGraphicManager.setTextField1Type(MetadataType.HUMIDITY); + + Show assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "It is"); + + // test tags (just 1) + MetadataTags tags = assembledShow.getMetadataTags(); + List<MetadataType> tagsList = new ArrayList<>(); + tagsList.add(MetadataType.HUMIDITY); + assertEquals(tags.getMainField1(), tagsList); + + textAndGraphicManager.setTextField2("Wednesday"); + + assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "It is - Wednesday"); + + textAndGraphicManager.setTextField3("My"); + + assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "It is - Wednesday - My"); + + textAndGraphicManager.setTextField4("Dudes"); + textAndGraphicManager.setTextField4Type(MetadataType.CURRENT_TEMPERATURE); + + assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "It is - Wednesday - My - Dudes"); + + // test tags + tags = assembledShow.getMetadataTags(); + tagsList = new ArrayList<>(); + tagsList.add(MetadataType.HUMIDITY); + tagsList.add(MetadataType.CURRENT_TEMPERATURE); + assertEquals(tags.getMainField1(), tagsList); + + // For some obscurity, lets try setting just fields 2 and 4 for a 1 line display + textAndGraphicManager.setTextField1(null); + textAndGraphicManager.setTextField3(null); + + assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "Wednesday - Dudes"); + } + + public void testAssemble2Lines() { + + Show inputShow = new Show(); + + // Force it to return display with support for only 2 lines of text + textAndGraphicManager.displayCapabilities = getDisplayCapability(2); + + textAndGraphicManager.setTextField1("It is"); + textAndGraphicManager.setTextField1Type(MetadataType.HUMIDITY); + + Show assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "It is"); + + // test tags + MetadataTags tags = assembledShow.getMetadataTags(); + List<MetadataType> tagsList = new ArrayList<>(); + tagsList.add(MetadataType.HUMIDITY); + assertEquals(tags.getMainField1(), tagsList); + + textAndGraphicManager.setTextField2("Wednesday"); + textAndGraphicManager.setTextField2Type(MetadataType.CURRENT_TEMPERATURE); + + assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "It is"); + assertEquals(assembledShow.getMainField2(), "Wednesday"); + + // test tags + tags = assembledShow.getMetadataTags(); + tagsList = new ArrayList<>(); + List<MetadataType> tagsList2 = new ArrayList<>(); + tagsList.add(MetadataType.HUMIDITY); + tagsList2.add(MetadataType.CURRENT_TEMPERATURE); + assertEquals(tags.getMainField1(), tagsList); + assertEquals(tags.getMainField2(), tagsList2); + + textAndGraphicManager.setTextField3("My"); + textAndGraphicManager.setTextField3Type(MetadataType.MEDIA_ALBUM); + + assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "It is - Wednesday"); + assertEquals(assembledShow.getMainField2(), "My"); + + // test tags + tags = assembledShow.getMetadataTags(); + tagsList = new ArrayList<>(); + tagsList2 = new ArrayList<>(); + tagsList.add(MetadataType.CURRENT_TEMPERATURE); + tagsList.add(MetadataType.HUMIDITY); + tagsList2.add(MetadataType.MEDIA_ALBUM); + assertEquals(tags.getMainField1(), tagsList); + assertEquals(tags.getMainField2(), tagsList2); + + textAndGraphicManager.setTextField4("Dudes"); + textAndGraphicManager.setTextField4Type(MetadataType.MEDIA_STATION); + + assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "It is - Wednesday"); + assertEquals(assembledShow.getMainField2(), "My - Dudes"); + + // test tags + tags = assembledShow.getMetadataTags(); + tagsList = new ArrayList<>(); + tagsList2 = new ArrayList<>(); + tagsList.add(MetadataType.CURRENT_TEMPERATURE); + tagsList.add(MetadataType.HUMIDITY); + tagsList2.add(MetadataType.MEDIA_STATION); + tagsList2.add(MetadataType.MEDIA_ALBUM); + assertEquals(tags.getMainField1(), tagsList); + assertEquals(tags.getMainField2(), tagsList2); + + // For some obscurity, lets try setting just fields 2 and 4 for a 2 line display + textAndGraphicManager.setTextField1(null); + textAndGraphicManager.setTextField3(null); + textAndGraphicManager.setTextField1Type(null); + textAndGraphicManager.setTextField3Type(null); + + assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "Wednesday"); + assertEquals(assembledShow.getMainField2(), "Dudes"); + + // And 3 fields without setting 1 + textAndGraphicManager.setTextField3("My"); + + assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "Wednesday"); + assertEquals(assembledShow.getMainField2(), "My - Dudes"); + + // test tags + tags = assembledShow.getMetadataTags(); + tagsList = new ArrayList<>(); + tagsList2 = new ArrayList<>(); + tagsList.add(MetadataType.CURRENT_TEMPERATURE); + tagsList2.add(MetadataType.MEDIA_STATION); + assertEquals(tags.getMainField1(), tagsList); + assertEquals(tags.getMainField2(), tagsList2); + } + + public void testAssemble3Lines() { + + Show inputShow = new Show(); + + // Force it to return display with support for only 3 lines of text + textAndGraphicManager.displayCapabilities = getDisplayCapability(3); + + textAndGraphicManager.setTextField1("It is"); + textAndGraphicManager.setTextField1Type(MetadataType.HUMIDITY); + + Show assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "It is"); + assertEquals(assembledShow.getMainField2(), ""); + assertEquals(assembledShow.getMainField3(), ""); + + // test tags + MetadataTags tags = assembledShow.getMetadataTags(); + List<MetadataType> tagsList = new ArrayList<>(); + tagsList.add(MetadataType.HUMIDITY); + assertEquals(tags.getMainField1(), tagsList); + + textAndGraphicManager.setTextField2("Wednesday"); + textAndGraphicManager.setTextField2Type(MetadataType.CURRENT_TEMPERATURE); + + assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "It is"); + assertEquals(assembledShow.getMainField2(), "Wednesday"); + assertEquals(assembledShow.getMainField3(), ""); + + // test tags + tags = assembledShow.getMetadataTags(); + tagsList = new ArrayList<>(); + List<MetadataType> tagsList2 = new ArrayList<>(); + tagsList.add(MetadataType.HUMIDITY); + tagsList2.add(MetadataType.CURRENT_TEMPERATURE); + assertEquals(tags.getMainField1(), tagsList); + assertEquals(tags.getMainField2(), tagsList2); + + textAndGraphicManager.setTextField3("My"); + textAndGraphicManager.setTextField3Type(MetadataType.MEDIA_ALBUM); + + assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "It is"); + assertEquals(assembledShow.getMainField2(), "Wednesday"); + assertEquals(assembledShow.getMainField3(), "My"); + + // test tags + tags = assembledShow.getMetadataTags(); + tagsList = new ArrayList<>(); + tagsList2 = new ArrayList<>(); + List<MetadataType> tagsList3 = new ArrayList<>(); + tagsList.add(MetadataType.HUMIDITY); + tagsList2.add(MetadataType.CURRENT_TEMPERATURE); + tagsList3.add(MetadataType.MEDIA_ALBUM); + assertEquals(tags.getMainField1(), tagsList); + assertEquals(tags.getMainField2(), tagsList2); + assertEquals(tags.getMainField3(), tagsList3); + + textAndGraphicManager.setTextField4("Dudes"); + textAndGraphicManager.setTextField4Type(MetadataType.MEDIA_STATION); + + assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "It is"); + assertEquals(assembledShow.getMainField2(), "Wednesday"); + assertEquals(assembledShow.getMainField3(), "My - Dudes"); + + // test tags + tags = assembledShow.getMetadataTags(); + tagsList = new ArrayList<>(); + tagsList2 = new ArrayList<>(); + tagsList3 = new ArrayList<>(); + tagsList.add(MetadataType.HUMIDITY); + tagsList2.add(MetadataType.CURRENT_TEMPERATURE); + tagsList3.add(MetadataType.MEDIA_ALBUM); + tagsList3.add(MetadataType.MEDIA_STATION); + assertEquals(tags.getMainField1(), tagsList); + assertEquals(tags.getMainField2(), tagsList2); + assertEquals(tags.getMainField3(), tagsList3); + + // Someone might not want to set the fields in order? We should handle that + textAndGraphicManager.setTextField1(null); + + assembledShow = textAndGraphicManager.assembleShowText(inputShow); + try { + System.out.println(assembledShow.serializeJSON().toString()); + } catch (JSONException e) { + e.printStackTrace(); + } + + assertEquals(assembledShow.getMainField2(), "Wednesday"); + assertEquals(assembledShow.getMainField3(), "My - Dudes"); + } + + public void testAssemble4Lines() { + + Show inputShow = new Show(); + + // Force it to return display with support for only 4 lines of text + textAndGraphicManager.displayCapabilities = getDisplayCapability(4); + + textAndGraphicManager.setTextField1("It is"); + textAndGraphicManager.setTextField1Type(MetadataType.HUMIDITY); + + Show assembledShow = textAndGraphicManager.assembleShowText(inputShow); + + assertEquals(assembledShow.getMainField1(), "It is"); + assertEquals(assembledShow.getMainField2(), ""); + assertEquals(assembledShow.getMainField3(), ""); + assertEquals(assembledShow.getMainField4(), ""); + + // test tags + MetadataTags tags = assembledShow.getMetadataTags(); + List<MetadataType> tagsList = new ArrayList<>(); + tagsList.add(MetadataType.HUMIDITY); + assertEquals(tags.getMainField1(), tagsList); + + textAndGraphicManager.setTextField2("Wednesday"); + textAndGraphicManager.setTextField2Type(MetadataType.CURRENT_TEMPERATURE); + + assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "It is"); + assertEquals(assembledShow.getMainField2(), "Wednesday"); + assertEquals(assembledShow.getMainField3(), ""); + assertEquals(assembledShow.getMainField4(), ""); + + // test tags + tags = assembledShow.getMetadataTags(); + tagsList = new ArrayList<>(); + List<MetadataType> tagsList2 = new ArrayList<>(); + tagsList.add(MetadataType.HUMIDITY); + tagsList2.add(MetadataType.CURRENT_TEMPERATURE); + assertEquals(tags.getMainField1(), tagsList); + assertEquals(tags.getMainField2(), tagsList2); + + textAndGraphicManager.setTextField3("My"); + textAndGraphicManager.setTextField3Type(MetadataType.MEDIA_ALBUM); + + assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "It is"); + assertEquals(assembledShow.getMainField2(), "Wednesday"); + assertEquals(assembledShow.getMainField3(), "My"); + assertEquals(assembledShow.getMainField4(), ""); + + // test tags + tags = assembledShow.getMetadataTags(); + tagsList = new ArrayList<>(); + tagsList2 = new ArrayList<>(); + List<MetadataType> tagsList3 = new ArrayList<>(); + tagsList.add(MetadataType.HUMIDITY); + tagsList2.add(MetadataType.CURRENT_TEMPERATURE); + tagsList3.add(MetadataType.MEDIA_ALBUM); + assertEquals(tags.getMainField1(), tagsList); + assertEquals(tags.getMainField2(), tagsList2); + assertEquals(tags.getMainField3(), tagsList3); + + textAndGraphicManager.setTextField4("Dudes"); + textAndGraphicManager.setTextField4Type(MetadataType.MEDIA_STATION); + + assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "It is"); + assertEquals(assembledShow.getMainField2(), "Wednesday"); + assertEquals(assembledShow.getMainField3(), "My"); + assertEquals(assembledShow.getMainField4(), "Dudes"); + + // test tags + tags = assembledShow.getMetadataTags(); + tagsList = new ArrayList<>(); + tagsList2 = new ArrayList<>(); + tagsList3 = new ArrayList<>(); + List<MetadataType> tagsList4 = new ArrayList<>(); + tagsList.add(MetadataType.HUMIDITY); + tagsList2.add(MetadataType.CURRENT_TEMPERATURE); + tagsList3.add(MetadataType.MEDIA_ALBUM); + tagsList4.add(MetadataType.MEDIA_STATION); + assertEquals(tags.getMainField1(), tagsList); + assertEquals(tags.getMainField2(), tagsList2); + assertEquals(tags.getMainField3(), tagsList3); + assertEquals(tags.getMainField4(), tagsList4); + + // try just setting line 1 and 4 + textAndGraphicManager.setTextField2(null); + textAndGraphicManager.setTextField3(null); + textAndGraphicManager.setTextField2Type(null); + textAndGraphicManager.setTextField3Type(null); + + assembledShow = textAndGraphicManager.assembleShowText(inputShow); + assertEquals(assembledShow.getMainField1(), "It is"); + assertEquals(assembledShow.getMainField2(), ""); + assertEquals(assembledShow.getMainField3(), ""); + assertEquals(assembledShow.getMainField4(), "Dudes"); + + // test tags + tags = assembledShow.getMetadataTags(); + tagsList = new ArrayList<>(); + tagsList4 = new ArrayList<>(); + tagsList.add(MetadataType.HUMIDITY); + tagsList4.add(MetadataType.MEDIA_STATION); + assertEquals(tags.getMainField1(), tagsList); + assertEquals(tags.getMainField4(), tagsList4); + } + + public void testMediaTrackTextField() { + + String songTitle = "Wild For The Night"; + textAndGraphicManager.setMediaTrackTextField(songTitle); + assertEquals(textAndGraphicManager.getMediaTrackTextField(), songTitle); + } + + public void testAlignment() { + + textAndGraphicManager.setTextAlignment(TextAlignment.LEFT_ALIGNED); + assertEquals(textAndGraphicManager.getTextAlignment(), TextAlignment.LEFT_ALIGNED); + } + + public void testExtractTextFromShow(){ + + Show mainShow = new Show(); + mainShow.setMainField1("test"); + mainShow.setMainField3("Sauce"); + mainShow.setMainField4(""); + + Show newShow = textAndGraphicManager.extractTextFromShow(mainShow); + + assertEquals(newShow.getMainField1(), "test"); + assertEquals(newShow.getMainField3(), "Sauce"); + assertEquals(newShow.getMainField4(), ""); + assertNull(newShow.getMainField2()); + } + + // TEST IMAGES + + public void testSetPrimaryGraphic() { + textAndGraphicManager.setPrimaryGraphic(testArtwork); + assertEquals(textAndGraphicManager.getPrimaryGraphic(), testArtwork); + } + + public void testSetSecondaryGraphic() { + textAndGraphicManager.setSecondaryGraphic(testArtwork); + assertEquals(textAndGraphicManager.getSecondaryGraphic(), testArtwork); + } + + // TEST DISPOSE + + public void testDispose() { + textAndGraphicManager.dispose(); + + assertNull(textAndGraphicManager.getTextField1()); + assertNull(textAndGraphicManager.getTextField2()); + assertNull(textAndGraphicManager.getTextField3()); + assertNull(textAndGraphicManager.getTextField4()); + assertNull(textAndGraphicManager.getMediaTrackTextField()); + assertNull(textAndGraphicManager.getPrimaryGraphic()); + assertNull(textAndGraphicManager.getSecondaryGraphic()); + assertNull(textAndGraphicManager.getTextAlignment()); + assertNull(textAndGraphicManager.getTextField1Type()); + assertNull(textAndGraphicManager.getTextField2Type()); + assertNull(textAndGraphicManager.getTextField3Type()); + assertNull(textAndGraphicManager.getTextField4Type()); + assertNotNull(textAndGraphicManager.getBlankArtwork()); + assertNull(textAndGraphicManager.currentScreenData); + assertNull(textAndGraphicManager.inProgressUpdate); + assertNull(textAndGraphicManager.queuedImageUpdate); + assertFalse(textAndGraphicManager.hasQueuedUpdate); + assertNull(textAndGraphicManager.displayCapabilities); + assertFalse(textAndGraphicManager.isDirty); + assertEquals(textAndGraphicManager.getState(), BaseSubManager.SHUTDOWN); + } +} diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/video/VideoStreamManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/video/VideoStreamManagerTests.java new file mode 100644 index 000000000..e0febdb51 --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/video/VideoStreamManagerTests.java @@ -0,0 +1,282 @@ +package com.smartdevicelink.managers.video; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.view.Display; +import android.view.MotionEvent; +import android.view.View; + +import com.smartdevicelink.AndroidTestCase2; +import com.smartdevicelink.managers.CompletionListener; +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.protocol.enums.SessionType; +import com.smartdevicelink.proxy.interfaces.ISdl; +import com.smartdevicelink.proxy.interfaces.ISdlServiceListener; +import com.smartdevicelink.proxy.interfaces.IVideoStreamListener; +import com.smartdevicelink.proxy.interfaces.OnSystemCapabilityListener; +import com.smartdevicelink.proxy.rpc.OnHMIStatus; +import com.smartdevicelink.proxy.rpc.OnTouchEvent; +import com.smartdevicelink.proxy.rpc.TouchEvent; +import com.smartdevicelink.proxy.rpc.enums.HMILevel; +import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType; +import com.smartdevicelink.proxy.rpc.enums.TouchType; +import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener; +import com.smartdevicelink.streaming.video.SdlRemoteDisplay; +import com.smartdevicelink.streaming.video.VideoStreamingParameters; +import com.smartdevicelink.test.Test; +import com.smartdevicelink.util.Version; + +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * This is a unit test class for the SmartDeviceLink video streaming manager class : + * {@link VideoStreamManager} + */ +public class VideoStreamManagerTests extends AndroidTestCase2 { + public static final String TAG = "VideoStreamManagerTests"; + private Context mTestContext; + private static boolean touchEventOccured = false; + + // SETUP / HELPERS + + @Override + public void setUp() throws Exception{ + super.setUp(); + mTestContext = this.getContext(); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + } + + // TEST CLASSES + + public static class TestPresentation extends SdlRemoteDisplay { + View simulatedView = new View(this.getContext()); + + public TestPresentation(Context context, Display display) { + super(context, display); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(simulatedView); + } + + @Override + public boolean onTouchEvent(@NonNull MotionEvent event) { + touchEventOccured = true; + return super.onTouchEvent(event); + } + } + + // TESTS + + public void testInitialization(){ + ISdl internalInterface = mock(ISdl.class); + when(internalInterface.getProtocolVersion()).thenReturn(new Version(5,1,0)); + + Answer<Void> onAddServiceListener = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + SessionType sessionType = (SessionType) args[0]; + ISdlServiceListener sdlServiceListener = (ISdlServiceListener) args[1]; + assertEquals(sessionType, SessionType.NAV); + assertNotNull(sdlServiceListener); + return null; + } + }; + + doAnswer(onAddServiceListener).when(internalInterface).addServiceListener(any(SessionType.class), any(ISdlServiceListener.class)); + + VideoStreamManager videoStreamManager = new VideoStreamManager(internalInterface); + videoStreamManager.start(new CompletionListener() { + @Override + public void onComplete(boolean success) { + assertTrue(success); + } + }); + } + + public void testHMILevelNotFull(){ + ISdl internalInterface = mock(ISdl.class); + + when(internalInterface.getProtocolVersion()).thenReturn((new Version(5,0,0))); + when(internalInterface.isCapabilitySupported(SystemCapabilityType.VIDEO_STREAMING)).thenReturn(true); + + final VideoStreamManager videoStreamManager = new VideoStreamManager(internalInterface); + videoStreamManager.start(new CompletionListener() { + @Override + public void onComplete(boolean success) { + assertNull(videoStreamManager.startVideoService( + new VideoStreamingParameters(), false)); + } + }); + } + + public void testRemoteDisplayStream(){ + ISdl internalInterface = mock(ISdl.class); + + final Set<Object> listenerSet = new HashSet<>(); + + when(internalInterface.getProtocolVersion()).thenReturn(new Version(5,0,0)); + when(internalInterface.isCapabilitySupported(SystemCapabilityType.VIDEO_STREAMING)).thenReturn(true); + + Answer<Void> onGetCapability = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + OnSystemCapabilityListener systemCapabilityListener = (OnSystemCapabilityListener) args[1]; + systemCapabilityListener.onCapabilityRetrieved(Test.GENERAL_VIDEOSTREAMINGCAPABILITY); + return null; + } + }; + + doAnswer(onGetCapability).when(internalInterface).getCapability(eq(SystemCapabilityType.VIDEO_STREAMING), any(OnSystemCapabilityListener.class)); + + Answer<Void> onAddServiceListener = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + listenerSet.add(args[1]); + return null; + } + }; + + doAnswer(onAddServiceListener).when(internalInterface).addServiceListener(eq(SessionType.NAV), any(ISdlServiceListener.class)); + + final OnRPCNotificationListener[] hmiListener = {null}; + + Answer<Void> onAddHMIListener = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + hmiListener[0] = (OnRPCNotificationListener) args[1]; + listenerSet.add(args[1]); + return null; + } + }; + + doAnswer(onAddHMIListener).when(internalInterface).addOnRPCNotificationListener(eq(FunctionID.ON_HMI_STATUS), any(OnRPCNotificationListener.class)); + + Answer<Void> onAddTouchListener = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + listenerSet.add(args[1]); + return null; + } + }; + + doAnswer(onAddTouchListener).when(internalInterface).addOnRPCNotificationListener(eq(FunctionID.ON_TOUCH_EVENT), any(OnRPCNotificationListener.class)); + + Answer<Void> onRemoveRPCNotificationListener = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + listenerSet.remove(args[1]); + return null; + } + }; + + doAnswer(onRemoveRPCNotificationListener).when(internalInterface).removeOnRPCNotificationListener(eq(FunctionID.ON_HMI_STATUS), any(OnRPCNotificationListener.class)); + doAnswer(onRemoveRPCNotificationListener).when(internalInterface).removeOnRPCNotificationListener(eq(FunctionID.ON_TOUCH_EVENT), any(OnRPCNotificationListener.class)); + + Answer<Void> onRemoveServiceListener = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + listenerSet.remove(args[1]); + return null; + } + }; + + doAnswer(onRemoveServiceListener).when(internalInterface).removeServiceListener(eq(SessionType.NAV), any(ISdlServiceListener.class)); + + when(internalInterface.startVideoStream(anyBoolean(), any(VideoStreamingParameters.class))).thenReturn(new IVideoStreamListener() { + @Override + public void sendFrame(byte[] data, int offset, int length, long presentationTimeUs) throws ArrayIndexOutOfBoundsException {} + @Override + public void sendFrame(ByteBuffer data, long presentationTimeUs) {} + }); + + when(internalInterface.getCapability(SystemCapabilityType.VIDEO_STREAMING)).thenReturn(Test.GENERAL_VIDEOSTREAMINGCAPABILITY); + + final VideoStreamManager videoStreamManager = new VideoStreamManager(internalInterface); + videoStreamManager.start(new CompletionListener() { + @Override + public void onComplete(boolean success) { + assertTrue(success); + assertTrue(listenerSet.size() == 3); + + OnHMIStatus fullNotification = new OnHMIStatus(); + fullNotification.setHmiLevel(HMILevel.HMI_FULL); + hmiListener[0].onNotified(fullNotification); + + videoStreamManager.startRemoteDisplayStream(mTestContext, TestPresentation.class, null, false); + + //assertTrue(touchEventOccured); + + videoStreamManager.dispose(); + assertTrue(listenerSet.isEmpty()); + } + }); + + } + + public void testConvertTouchEvent(){ + ISdl internalInterface = mock(ISdl.class); + when(internalInterface.getProtocolVersion()).thenReturn(new Version(5,1,0)); + + final VideoStreamManager videoStreamManager = new VideoStreamManager(internalInterface); + videoStreamManager.start(new CompletionListener() { + @Override + public void onComplete(boolean success) { + assertTrue(success); + OnTouchEvent testOnTouchEvent = new OnTouchEvent(); + TouchEvent touchEvent = Test.GENERAL_TOUCHEVENT; + testOnTouchEvent.setEvent(Collections.singletonList(touchEvent)); + testOnTouchEvent.setType(Test.GENERAL_TOUCHTYPE); + MotionEvent motionEvent; + + // Touch one pointer (100) + motionEvent = videoStreamManager.convertTouchEvent(testOnTouchEvent); + assertEquals(motionEvent.getAction(), MotionEvent.ACTION_DOWN); + + // Touch another pointer (101) without release + touchEvent.setId(Test.GENERAL_INT + 1); + testOnTouchEvent.setEvent(Collections.singletonList(touchEvent)); + motionEvent = videoStreamManager.convertTouchEvent(testOnTouchEvent); + assertEquals(motionEvent.getAction(), MotionEvent.ACTION_POINTER_DOWN); + + // Release one of the pointers (101) + testOnTouchEvent.setType(TouchType.END); + motionEvent = videoStreamManager.convertTouchEvent(testOnTouchEvent); + assertEquals(motionEvent.getAction(), MotionEvent.ACTION_POINTER_UP); + + // Release the other pointer (100) + touchEvent.setId(Test.GENERAL_INT); + testOnTouchEvent.setEvent(Collections.singletonList(touchEvent)); + motionEvent = videoStreamManager.convertTouchEvent(testOnTouchEvent); + assertEquals(motionEvent.getAction(), MotionEvent.ACTION_UP); + } + }); + } +} |