diff options
author | RHeniz <heniganr1@gmail.com> | 2021-11-02 15:10:25 -0400 |
---|---|---|
committer | RHeniz <heniganr1@gmail.com> | 2021-11-02 15:10:25 -0400 |
commit | 90f8a4a42bd7e256c7121124450277826aa7a830 (patch) | |
tree | 859aa36930b67f8a8094dfd13c0a9965cb2c1730 /android/sdl_android/src | |
parent | 316c673a5d9b4e8e144ed759d901f6ac5f8043c5 (diff) | |
parent | 0bda03437ed79d1e4890060ff9a816db3ccd5251 (diff) | |
download | sdl_android-90f8a4a42bd7e256c7121124450277826aa7a830.tar.gz |
Merge branch 'develop' into feature/android_12_fixes
Diffstat (limited to 'android/sdl_android/src')
22 files changed, 1972 insertions, 654 deletions
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 index 90bedd434..b3d489eaa 100644 --- 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 @@ -851,6 +851,42 @@ public class FileManagerTests { } /** + * Tests to make sure files are not being uploaded to head unit multiple times in a row + */ + @Test + public void testFileNotOnHmi() { + final ISdl internalInterface = createISdlMock(); + + doAnswer(onListFilesSuccess).when(internalInterface).sendRPC(any(ListFiles.class)); + doAnswer(onPutFileSuccess).when(internalInterface).sendRPC(any(PutFile.class)); + + final SdlArtwork validFile2 = new SdlArtwork(TestValues.GENERAL_STRING + "2", FileType.GRAPHIC_JPEG, TestValues.GENERAL_STRING.getBytes(), false); + + final List<SdlArtwork> list = Arrays.asList(validFile2, validFile2); + + FileManagerConfig fileManagerConfig = new FileManagerConfig(); + + final FileManager fileManager = new FileManager(internalInterface, mTestContext, fileManagerConfig); + fileManager.start(new CompletionListener() { + @Override + public void onComplete(boolean success) { + fileManager.uploadArtworks(list, new MultipleFileCompletionListener() { + @Override + public void onComplete(final Map<String, String> errors) { + assertOnMainThread(new Runnable() { + @Override + public void run() { + verify(internalInterface, times(1)).sendRPC(any(PutFile.class)); + } + }); + } + }); + } + }); + } + + + /** * Test custom overridden SdlFile equals method */ @Test diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/file/filetypes/SdlArtworkTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/file/filetypes/SdlArtworkTests.java index f4fb5e3d2..49a10ab3d 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/file/filetypes/SdlArtworkTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/file/filetypes/SdlArtworkTests.java @@ -37,6 +37,9 @@ public class SdlArtworkTests { } public static boolean equalTest(SdlArtwork original, SdlArtwork clone) { + if (original == null && clone == null) { + return true; + } assertNotNull(original); assertNotNull(clone); diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/lifecycle/SystemCapabilityManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/lifecycle/SystemCapabilityManagerTests.java index 65f9c7bb4..03854d3ee 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/lifecycle/SystemCapabilityManagerTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/lifecycle/SystemCapabilityManagerTests.java @@ -32,6 +32,7 @@ import com.smartdevicelink.proxy.rpc.SdlMsgVersion; import com.smartdevicelink.proxy.rpc.SetDisplayLayoutResponse; import com.smartdevicelink.proxy.rpc.SoftButtonCapabilities; import com.smartdevicelink.proxy.rpc.SystemCapability; +import com.smartdevicelink.proxy.rpc.TextField; import com.smartdevicelink.proxy.rpc.VideoStreamingCapability; import com.smartdevicelink.proxy.rpc.WindowCapability; import com.smartdevicelink.proxy.rpc.WindowTypeCapabilities; @@ -52,6 +53,7 @@ import com.smartdevicelink.proxy.rpc.enums.ServiceUpdateReason; import com.smartdevicelink.proxy.rpc.enums.SpeechCapabilities; import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType; import com.smartdevicelink.proxy.rpc.enums.SystemContext; +import com.smartdevicelink.proxy.rpc.enums.TextFieldName; import com.smartdevicelink.proxy.rpc.enums.WindowType; import com.smartdevicelink.proxy.rpc.listeners.OnMultipleRequestListener; import com.smartdevicelink.proxy.rpc.listeners.OnRPCListener; @@ -689,6 +691,35 @@ public class SystemCapabilityManagerTests { verify(internalInterface, times(0)).sendRPC(any(GetSystemCapability.class)); } + /** + * Test to verify that we can get null for templatesAvailable without hitting an NPE and + * test media field conversion for NON_MEDIA to NON-MEDIA for Sync bug. + */ + @Test + public void testMediaFieldConversion() { + SystemCapabilityManager systemCapabilityManager = new SystemCapabilityManager(new InternalSDLInterface()); + + RegisterAppInterfaceResponse raiResponse = new RegisterAppInterfaceResponse(); + DisplayCapabilities displayCapabilities = new DisplayCapabilities(); + displayCapabilities.setGraphicSupported(false); + TextField textField = new TextField(); + textField.setName(TextFieldName.mainField1); + displayCapabilities.setTextFields(Collections.singletonList(textField)); + raiResponse.setDisplayCapabilities(displayCapabilities); + raiResponse.setSuccess(true); + systemCapabilityManager.parseRAIResponse(raiResponse); + + WindowCapability windowCapability = systemCapabilityManager.getDefaultMainWindowCapability(); + assertNull(windowCapability.getTemplatesAvailable()); + + List<String> templates = new ArrayList<>(); + templates.add("NON_MEDIA"); + displayCapabilities.setTemplatesAvailable(templates); + systemCapabilityManager.parseRAIResponse(raiResponse); + windowCapability = systemCapabilityManager.getDefaultMainWindowCapability(); + assertTrue(windowCapability.getTemplatesAvailable().contains("NON-MEDIA")); + } + @Test public void testListConversion() { SystemCapabilityManager systemCapabilityManager = createSampleManager(); 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 index 6ccf93aeb..b5cecf26c 100644 --- 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 @@ -68,14 +68,15 @@ public class ScreenManagerTests { assertNull(screenManager.getTextField2Type()); assertNull(screenManager.getTextField3Type()); assertNull(screenManager.getTextField4Type()); - assertNull(screenManager.getMenu()); + assertTrue(screenManager.getMenu().isEmpty()); assertNull(screenManager.getVoiceCommands()); assertTrue(screenManager.getSoftButtonObjects().isEmpty()); assertNull(screenManager.getSoftButtonObjectByName("test")); assertNull(screenManager.getSoftButtonObjectById(1)); assertEquals(screenManager.getDynamicMenuUpdatesMode(), DynamicMenuUpdatesMode.ON_WITH_COMPAT_MODE); assertEquals(screenManager.getState(), BaseSubManager.READY); - assertNull(screenManager.getMenuConfiguration()); + assertNull(screenManager.getMenuConfiguration().getMenuLayout()); + assertNull(screenManager.getMenuConfiguration().getSubMenuLayout()); } @Test @@ -147,10 +148,9 @@ public class ScreenManagerTests { screenManager.setMenu(TestValues.GENERAL_MENUCELL_LIST); screenManager.setMenuConfiguration(TestValues.GENERAL_MENU_CONFIGURATION); - assertEquals(screenManager.getMenu(), TestValues.GENERAL_MENUCELL_LIST); assertEquals(screenManager.getDynamicMenuUpdatesMode(), DynamicMenuUpdatesMode.FORCE_ON); - // Should not set because of improper RAI response and improper HMI states - assertNull(screenManager.getMenuConfiguration()); + assertEquals(screenManager.getMenu(), TestValues.GENERAL_MENUCELL_LIST); + assertEquals(screenManager.getMenuConfiguration(), TestValues.GENERAL_MENU_CONFIGURATION); } @Test 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 index 9b948f808..3999e7d2c 100644 --- 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 @@ -275,6 +275,7 @@ public class TextAndGraphicManagerTests { @Test public void testOperationManagement() { + textAndGraphicManager.transactionQueue.pause(); textAndGraphicManager.isDirty = true; textAndGraphicManager.updateOperation = null; textAndGraphicManager.update(null); diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/RunScoreTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/DynamicMenuUpdateRunScoreTests.java index e92656846..69350965a 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/RunScoreTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/DynamicMenuUpdateRunScoreTests.java @@ -39,21 +39,29 @@ import com.smartdevicelink.test.TestValues; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.Arrays; +import java.util.List; + +import static com.smartdevicelink.managers.screen.menu.DynamicMenuUpdateAlgorithm.MenuCellState.ADD; +import static com.smartdevicelink.managers.screen.menu.DynamicMenuUpdateAlgorithm.MenuCellState.DELETE; +import static com.smartdevicelink.managers.screen.menu.DynamicMenuUpdateAlgorithm.MenuCellState.KEEP; import static junit.framework.TestCase.assertEquals; @RunWith(AndroidJUnit4.class) -public class RunScoreTests { +public class DynamicMenuUpdateRunScoreTests { @Test public void testSettersAndGetters() { // set everything - we only use the constructor to set variables in the Menu Manager - RunScore runScore = new RunScore(TestValues.GENERAL_INT, TestValues.GENERAL_INTEGER_LIST, TestValues.GENERAL_INTEGER_LIST); + List<DynamicMenuUpdateAlgorithm.MenuCellState> oldStatus = Arrays.asList(KEEP, DELETE); + List<DynamicMenuUpdateAlgorithm.MenuCellState> updatedStatus = Arrays.asList(KEEP, ADD); + DynamicMenuUpdateRunScore runScore = new DynamicMenuUpdateRunScore(oldStatus, updatedStatus, TestValues.GENERAL_INT); // use getters and assert equality assertEquals(runScore.getScore(), TestValues.GENERAL_INT); - assertEquals(runScore.getCurrentMenu(), TestValues.GENERAL_INTEGER_LIST); - assertEquals(runScore.getOldMenu(), TestValues.GENERAL_INTEGER_LIST); + assertEquals(runScore.getOldStatus(), oldStatus); + assertEquals(runScore.getUpdatedStatus(), updatedStatus); } } diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuCellTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuCellTests.java index b0e703e33..8088538e1 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuCellTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuCellTests.java @@ -43,13 +43,13 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import static junit.framework.TestCase.assertEquals; -import static junit.framework.TestCase.assertFalse; import static junit.framework.TestCase.assertNotNull; import static junit.framework.TestCase.assertNotSame; -import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertNotEquals; @RunWith(AndroidJUnit4.class) public class MenuCellTests { @@ -63,7 +63,6 @@ public class MenuCellTests { @Test public void testSettersAndGetters() { - // set everything MenuCell menuCell = new MenuCell(TestValues.GENERAL_STRING, null, null, menuSelectionListener); menuCell.setIcon(TestValues.GENERAL_ARTWORK); @@ -91,7 +90,6 @@ public class MenuCellTests { @Test public void testConstructors() { - // first constructor was tested in previous method, use the last two here MenuCell menuCell3 = new MenuCell(TestValues.GENERAL_STRING, TestValues.GENERAL_ARTWORK, TestValues.GENERAL_STRING_LIST, menuSelectionListener); @@ -99,20 +97,16 @@ public class MenuCellTests { assertEquals(menuCell3.getIcon(), TestValues.GENERAL_ARTWORK); assertEquals(menuCell3.getVoiceCommands(), TestValues.GENERAL_STRING_LIST); assertEquals(menuCell3.getMenuSelectionListener(), menuSelectionListener); - assertEquals(menuCell3.getUniqueTitle(), TestValues.GENERAL_STRING); MenuCell menuCell4 = new MenuCell(TestValues.GENERAL_STRING, null, null, menuSelectionListener); assertEquals(menuCell4.getTitle(), TestValues.GENERAL_STRING); assertEquals(menuCell4.getMenuSelectionListener(), menuSelectionListener); - assertEquals(menuCell4.getUniqueTitle(), TestValues.GENERAL_STRING); MenuCell menuCell5 = new MenuCell(TestValues.GENERAL_STRING, TestValues.GENERAL_MENU_LAYOUT, TestValues.GENERAL_ARTWORK, TestValues.GENERAL_MENUCELL_LIST); assertEquals(menuCell5.getTitle(), TestValues.GENERAL_STRING); assertEquals(menuCell5.getIcon(), TestValues.GENERAL_ARTWORK); assertEquals(menuCell5.getSubMenuLayout(), TestValues.GENERAL_MENU_LAYOUT); assertEquals(menuCell5.getSubCells(), TestValues.GENERAL_MENUCELL_LIST); - assertEquals(menuCell5.getUniqueTitle(), TestValues.GENERAL_STRING); - MenuCell menuCell6 = new MenuCell(TestValues.GENERAL_STRING, TestValues.GENERAL_STRING, TestValues.GENERAL_STRING, TestValues.GENERAL_ARTWORK, TestValues.GENERAL_ARTWORK, TestValues.GENERAL_STRING_LIST, menuSelectionListener); assertEquals(menuCell6.getTitle(), TestValues.GENERAL_STRING); @@ -139,36 +133,34 @@ public class MenuCellTests { @Test public void testEquality() { + MenuCell menuCell1 = new MenuCell(TestValues.GENERAL_STRING, TestValues.GENERAL_ARTWORK, TestValues.GENERAL_STRING_LIST, menuSelectionListener); + MenuCell menuCell1_1 = new MenuCell(TestValues.GENERAL_STRING, TestValues.GENERAL_ARTWORK, TestValues.GENERAL_STRING_LIST, menuSelectionListener); + menuCell1.setSubCells(Collections.singletonList(menuCell1_1)); - //We should use assertTrue (or assertFalse) because we want to use the overridden equals() method - - MenuCell menuCell = new MenuCell(TestValues.GENERAL_STRING, TestValues.GENERAL_ARTWORK, TestValues.GENERAL_STRING_LIST, menuSelectionListener); - menuCell.setSecondaryText(TestValues.GENERAL_STRING); - menuCell.setTertiaryText(TestValues.GENERAL_STRING); - menuCell.setSecondaryArtwork(TestValues.GENERAL_ARTWORK); MenuCell menuCell2 = new MenuCell(TestValues.GENERAL_STRING, TestValues.GENERAL_ARTWORK, TestValues.GENERAL_STRING_LIST, menuSelectionListener); - menuCell2.setSecondaryText(TestValues.GENERAL_STRING); - menuCell2.setTertiaryText(TestValues.GENERAL_STRING); - menuCell2.setSecondaryArtwork(TestValues.GENERAL_ARTWORK); + MenuCell menuCell2_1 = new MenuCell(TestValues.GENERAL_STRING, TestValues.GENERAL_ARTWORK, TestValues.GENERAL_STRING_LIST, menuSelectionListener); + menuCell2.setSubCells(Collections.singletonList(menuCell2_1)); // these are the same object, should be equal. - assertTrue(menuCell.equals(menuCell)); + assertEquals(menuCell1, menuCell1); // Make sure these are marked as equals, even though they are different objects - assertTrue(menuCell.equals(menuCell2)); + assertEquals(menuCell1, menuCell2); MenuCell menuCell3 = new MenuCell(TestValues.GENERAL_STRING, null, TestValues.GENERAL_STRING_LIST, menuSelectionListener); // these should be different - assertFalse(menuCell.equals(menuCell3)); + assertNotEquals(menuCell1, menuCell3); + + menuCell1_1.setTitle("new title"); + + // Make sure sub cells are not compared + assertEquals(menuCell1, menuCell2); } @Test public void testClone() { MenuCell original = new MenuCell(TestValues.GENERAL_STRING, TestValues.GENERAL_ARTWORK, TestValues.GENERAL_STRING_LIST, menuSelectionListener); - original.setSecondaryText(TestValues.GENERAL_STRING); - original.setTertiaryText(TestValues.GENERAL_STRING); - original.setSecondaryArtwork(TestValues.GENERAL_ARTWORK); MenuCell clone = original.clone(); assertNotNull(clone); @@ -208,8 +200,5 @@ public class MenuCellTests { assertNotSame(originalSubCells.get(i), cloneSubCells.get(i)); } - - } - } diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuConfigurationUpdateOperationTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuConfigurationUpdateOperationTests.java new file mode 100644 index 000000000..c52cf6186 --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuConfigurationUpdateOperationTests.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2021 Livio, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Livio Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package com.smartdevicelink.managers.screen.menu; + +import android.os.Handler; + +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.livio.taskmaster.Queue; +import com.livio.taskmaster.Taskmaster; +import com.smartdevicelink.managers.CompletionListener; +import com.smartdevicelink.managers.ISdl; +import com.smartdevicelink.proxy.RPCRequest; +import com.smartdevicelink.proxy.RPCResponse; +import com.smartdevicelink.proxy.rpc.SdlMsgVersion; +import com.smartdevicelink.proxy.rpc.SetGlobalProperties; +import com.smartdevicelink.proxy.rpc.WindowCapability; +import com.smartdevicelink.proxy.rpc.enums.MenuLayout; +import com.smartdevicelink.util.Version; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.util.ArrayList; +import java.util.Random; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(AndroidJUnit4.class) +public class MenuConfigurationUpdateOperationTests { + + private Handler mainHandler; + private Taskmaster taskmaster; + private Queue transactionQueue; + + @Before + public void setUp() throws Exception { + mainHandler = new Handler(getInstrumentation().getTargetContext().getMainLooper()); + taskmaster = new Taskmaster.Builder().build(); + taskmaster.start(); + transactionQueue = taskmaster.createQueue("MenuManager", new Random().nextInt(), false); + } + + @Test + public void testSuccess() { + final ISdl internalInterface = mock(ISdl.class); + when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(7, 0, 0))); + doAnswer(createSetGlobalPropertiesAnswer(true)).when(internalInterface).sendRPC(any(SetGlobalProperties.class)); + WindowCapability windowCapability = createWindowCapability(true, true); + MenuConfiguration menuConfiguration = new MenuConfiguration(MenuLayout.LIST, MenuLayout.LIST); + MenuConfigurationUpdateOperation operation = new MenuConfigurationUpdateOperation(internalInterface, windowCapability, menuConfiguration, new CompletionListener() { + @Override + public void onComplete(final boolean success) { + assertOnMainThread(new Runnable() { + @Override + public void run() { + assertTrue(success); + verify(internalInterface, Mockito.times(1)).sendRPC(any(SetGlobalProperties.class)); + } + }); + } + }); + transactionQueue.add(operation, false); + } + + @Test + public void testFailsRPCVersionOld() { + final ISdl internalInterface = mock(ISdl.class); + when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(5, 0, 0))); + doAnswer(createSetGlobalPropertiesAnswer(true)).when(internalInterface).sendRPC(any(SetGlobalProperties.class)); + WindowCapability windowCapability = createWindowCapability(true, true); + MenuConfiguration menuConfiguration = new MenuConfiguration(MenuLayout.LIST, MenuLayout.LIST); + MenuConfigurationUpdateOperation operation = new MenuConfigurationUpdateOperation(internalInterface, windowCapability, menuConfiguration, new CompletionListener() { + @Override + public void onComplete(final boolean success) { + assertOnMainThread(new Runnable() { + @Override + public void run() { + assertFalse(success); + verify(internalInterface, Mockito.times(0)).sendRPC(any(SetGlobalProperties.class)); + } + }); + } + }); + transactionQueue.add(operation, false); + } + + @Test + public void testFailsMenuLayoutNotSet() { + final ISdl internalInterface = mock(ISdl.class); + when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(7, 0, 0))); + doAnswer(createSetGlobalPropertiesAnswer(true)).when(internalInterface).sendRPC(any(SetGlobalProperties.class)); + WindowCapability windowCapability = createWindowCapability(true, true); + MenuConfiguration menuConfiguration = new MenuConfiguration(null, MenuLayout.LIST); + MenuConfigurationUpdateOperation operation = new MenuConfigurationUpdateOperation(internalInterface, windowCapability, menuConfiguration, new CompletionListener() { + @Override + public void onComplete(final boolean success) { + assertOnMainThread(new Runnable() { + @Override + public void run() { + assertFalse(success); + verify(internalInterface, Mockito.times(0)).sendRPC(any(SetGlobalProperties.class)); + } + }); + } + }); + transactionQueue.add(operation, false); + } + + @Test + public void testFailsMenuLayoutsAvailableEmpty() { + final ISdl internalInterface = mock(ISdl.class); + when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(7, 0, 0))); + doAnswer(createSetGlobalPropertiesAnswer(true)).when(internalInterface).sendRPC(any(SetGlobalProperties.class)); + WindowCapability windowCapability = createWindowCapability(true, true); + MenuConfiguration menuConfiguration = new MenuConfiguration(null, null); + MenuConfigurationUpdateOperation operation = new MenuConfigurationUpdateOperation(internalInterface, windowCapability, menuConfiguration, new CompletionListener() { + @Override + public void onComplete(final boolean success) { + assertOnMainThread(new Runnable() { + @Override + public void run() { + assertFalse(success); + verify(internalInterface, Mockito.times(0)).sendRPC(any(SetGlobalProperties.class)); + } + }); + } + }); + transactionQueue.add(operation, false); + } + + @Test + public void testFailsRPCNotSent() { + final ISdl internalInterface = mock(ISdl.class); + when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(7, 0, 0))); + doAnswer(createSetGlobalPropertiesAnswer(false)).when(internalInterface).sendRPC(any(SetGlobalProperties.class)); + WindowCapability windowCapability = createWindowCapability(true, true); + MenuConfiguration menuConfiguration = new MenuConfiguration(MenuLayout.LIST, MenuLayout.LIST); + MenuConfigurationUpdateOperation operation = new MenuConfigurationUpdateOperation(internalInterface, windowCapability, menuConfiguration, new CompletionListener() { + @Override + public void onComplete(final boolean success) { + assertOnMainThread(new Runnable() { + @Override + public void run() { + assertFalse(success); + verify(internalInterface, Mockito.times(1)).sendRPC(any(SetGlobalProperties.class)); + } + }); + } + }); + transactionQueue.add(operation, false); + } + + private Answer<Void> createSetGlobalPropertiesAnswer(final boolean success){ + return new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + RPCRequest request = (RPCRequest) args[0]; + RPCResponse response = new RPCResponse(request.getFunctionID().toString()); + response.setSuccess(success); + request.getOnRPCResponseListener().onResponse(request.getCorrelationID(), response); + return null; + } + }; + } + + private WindowCapability createWindowCapability (boolean supportsList, boolean supportsTile) { + WindowCapability windowCapability = new WindowCapability(); + windowCapability.setMenuLayoutsAvailable(new ArrayList<MenuLayout>()); + if (supportsList) { + windowCapability.getMenuLayoutsAvailable().add(MenuLayout.LIST); + } + if (supportsTile) { + windowCapability.getMenuLayoutsAvailable().add(MenuLayout.TILES); + } + return windowCapability; + } + + // Asserts on Taskmaster threads will fail silently so we need to do the assertions on main thread if the code is triggered from Taskmaster + private void assertOnMainThread(Runnable runnable) { + mainHandler.post(runnable); + } +} diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuManagerTests.java index e71d8295c..6f8bff69d 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuManagerTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuManagerTests.java @@ -34,6 +34,7 @@ package com.smartdevicelink.managers.screen.menu; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.livio.taskmaster.Taskmaster; import com.smartdevicelink.R; import com.smartdevicelink.managers.BaseSubManager; import com.smartdevicelink.managers.CompletionListener; @@ -41,26 +42,23 @@ import com.smartdevicelink.managers.ISdl; import com.smartdevicelink.managers.file.FileManager; import com.smartdevicelink.managers.file.filetypes.SdlArtwork; 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.rpc.ImageField; import com.smartdevicelink.proxy.rpc.OnCommand; import com.smartdevicelink.proxy.rpc.OnHMIStatus; import com.smartdevicelink.proxy.rpc.SdlMsgVersion; import com.smartdevicelink.proxy.rpc.SetGlobalProperties; -import com.smartdevicelink.proxy.rpc.TextField; import com.smartdevicelink.proxy.rpc.WindowCapability; import com.smartdevicelink.proxy.rpc.enums.FileType; import com.smartdevicelink.proxy.rpc.enums.HMILevel; -import com.smartdevicelink.proxy.rpc.enums.ImageFieldName; import com.smartdevicelink.proxy.rpc.enums.MenuLayout; import com.smartdevicelink.proxy.rpc.enums.SystemContext; -import com.smartdevicelink.proxy.rpc.enums.TextFieldName; import com.smartdevicelink.proxy.rpc.enums.TriggerSource; +import com.smartdevicelink.proxy.rpc.listeners.OnMultipleRequestListener; import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener; -import com.smartdevicelink.test.TestValues; +import com.smartdevicelink.util.Version; -import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -73,6 +71,10 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import static com.smartdevicelink.managers.screen.menu.DynamicMenuUpdateAlgorithm.MenuCellState; +import static com.smartdevicelink.managers.screen.menu.DynamicMenuUpdateAlgorithm.MenuCellState.ADD; +import static com.smartdevicelink.managers.screen.menu.DynamicMenuUpdateAlgorithm.MenuCellState.DELETE; +import static com.smartdevicelink.managers.screen.menu.DynamicMenuUpdateAlgorithm.MenuCellState.KEEP; import static junit.framework.TestCase.assertEquals; import static junit.framework.TestCase.assertFalse; import static junit.framework.TestCase.assertNotNull; @@ -81,10 +83,10 @@ import static junit.framework.TestCase.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; /** * the Algorithm specific tests are defined based on: https://github.com/smartdevicelink/sdl_evolution/blob/master/proposals/0210-mobile-dynamic-menu-cell-updating.md @@ -96,7 +98,11 @@ public class MenuManagerTests { private MenuManager menuManager; private List<MenuCell> cells; private MenuCell mainCell1, mainCell4; - final ISdl internalInterface = mock(ISdl.class); + private final MenuSelectionListener menuSelectionListenerA = mock(MenuSelectionListener.class); + private final MenuSelectionListener menuSelectionListenerB = mock(MenuSelectionListener.class); + private final MenuSelectionListener menuSelectionListenerC = mock(MenuSelectionListener.class); + private final MenuSelectionListener menuSelectionListenerD = mock(MenuSelectionListener.class); + private final MenuSelectionListener menuSelectionListenerE = mock(MenuSelectionListener.class); // SETUP / HELPERS @@ -105,8 +111,12 @@ public class MenuManagerTests { cells = createTestCells(); + final ISdl internalInterface = mock(ISdl.class); FileManager fileManager = mock(FileManager.class); + when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(6, 0, 0))); + + // When internalInterface.addOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, OnRPCNotificationListener) is called // inside MenuManager'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 @@ -130,7 +140,29 @@ public class MenuManagerTests { }; doAnswer(onCommandAnswer).when(internalInterface).addOnRPCNotificationListener(eq(FunctionID.ON_COMMAND), any(OnRPCNotificationListener.class)); - Answer<Void> answer = new Answer<Void>() { + // When internalInterface.sendRPCs() 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(); + List<RPCMessage> rpcs = (List<RPCMessage>) args[0]; + OnMultipleRequestListener listener = (OnMultipleRequestListener) args[1]; + + for (RPCMessage rpcMessage : rpcs) { + RPCRequest request = (RPCRequest) rpcMessage; + RPCResponse response = new RPCResponse(request.getFunctionID().toString()); + response.setCorrelationID(request.getCorrelationID()); + response.setSuccess(true); + listener.onResponse(request.getCorrelationID(), response); + } + + listener.onFinished(); + return null; + } + }; + doAnswer(answer).when(internalInterface).sendRPCs(any(List.class), any(OnMultipleRequestListener.class)); + + Answer<Void> setGlobalPropertiesAnswer = new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) { Object[] args = invocation.getArguments(); @@ -141,110 +173,107 @@ public class MenuManagerTests { return null; } }; - doAnswer(answer).when(internalInterface).sendRPC(any(SetGlobalProperties.class)); - - SdlMsgVersion version = new SdlMsgVersion(); - version.setMajorVersion(7); - version.setMinorVersion(0); - doReturn(version).when(internalInterface).getSdlMsgVersion(); + doAnswer(setGlobalPropertiesAnswer).when(internalInterface).sendRPC(any(SetGlobalProperties.class)); + // Create MenuManager + Taskmaster taskmaster = new Taskmaster.Builder().build(); + taskmaster.start(); + when(internalInterface.getTaskmaster()).thenReturn(taskmaster); menuManager = new MenuManager(internalInterface, fileManager); // Check some stuff during setup - assertEquals(menuManager.currentHMILevel, HMILevel.HMI_NONE); - assertEquals(menuManager.getState(), BaseSubManager.SETTING_UP); - assertEquals(menuManager.currentSystemContext, SystemContext.SYSCTXT_MAIN); - assertEquals(menuManager.dynamicMenuUpdatesMode, DynamicMenuUpdatesMode.ON_WITH_COMPAT_MODE); - assertEquals(menuManager.lastMenuId, 1); - assertNull(menuManager.menuCells); - assertNull(menuManager.waitingUpdateMenuCells); - assertNull(menuManager.oldMenuCells); - assertNull(menuManager.inProgressUpdate); - assertNull(menuManager.keepsNew); - assertNull(menuManager.keepsOld); - assertNull(menuManager.menuConfiguration); + assertEquals(HMILevel.HMI_NONE, menuManager.currentHMILevel); + assertEquals(BaseSubManager.SETTING_UP, menuManager.getState()); + assertEquals(SystemContext.SYSCTXT_MAIN, menuManager.currentSystemContext); + assertEquals(DynamicMenuUpdatesMode.ON_WITH_COMPAT_MODE, menuManager.dynamicMenuUpdatesMode); + assertTrue(menuManager.menuCells.isEmpty()); + assertTrue(menuManager.currentMenuCells.isEmpty()); + assertNull(menuManager.menuConfiguration.getMenuLayout()); + assertNull(menuManager.menuConfiguration.getSubMenuLayout()); assertNotNull(menuManager.hmiListener); assertNotNull(menuManager.commandListener); assertNotNull(menuManager.onDisplaysCapabilityListener); - - } - - @After - public void tearDown() throws Exception { - - menuManager.dispose(); - - assertEquals(menuManager.currentSystemContext, SystemContext.SYSCTXT_MAIN); - assertEquals(menuManager.dynamicMenuUpdatesMode, DynamicMenuUpdatesMode.ON_WITH_COMPAT_MODE); - assertEquals(menuManager.lastMenuId, 1); - assertNull(menuManager.menuCells); - assertNull(menuManager.oldMenuCells); - assertNull(menuManager.currentHMILevel); - assertNull(menuManager.defaultMainWindowCapability); - assertNull(menuManager.inProgressUpdate); - assertNull(menuManager.waitingUpdateMenuCells); - assertNull(menuManager.keepsNew); - assertNull(menuManager.keepsOld); - assertNull(menuManager.menuConfiguration); - - // after everything, make sure we are in the correct state - assertEquals(menuManager.getState(), BaseSubManager.SHUTDOWN); - } @Test public void testStartMenuManager() { - menuManager.start(new CompletionListener() { @Override public void onComplete(boolean success) { assertTrue(success); // Make sure the state has changed, as the Screen Manager is dependant on it - assertEquals(menuManager.getState(), BaseSubManager.READY); + assertEquals(BaseSubManager.READY, menuManager.getState()); } }); } @Test public void testHMINotReady() { - - menuManager.currentHMILevel = HMILevel.HMI_NONE; menuManager.setMenuCells(cells); + assertEquals(HMILevel.HMI_NONE, menuManager.currentHMILevel); + assertTrue(menuManager.currentMenuCells.isEmpty()); - // updating voice commands before HMI is ready - assertTrue(menuManager.waitingOnHMIUpdate); - // these are the 2 commands we have waiting - assertEquals(menuManager.waitingUpdateMenuCells.size(), 4); - assertEquals(menuManager.currentHMILevel, HMILevel.HMI_NONE); // The Menu Manager should send new menu once HMI full occurs sendFakeCoreOnHMIFullNotifications(); + // Listener should be triggered - which sets new HMI level and should proceed to send our pending update - assertEquals(menuManager.currentHMILevel, HMILevel.HMI_FULL); - // This being false means it received the hmi notification and sent the pending commands - assertFalse(menuManager.waitingOnHMIUpdate); + assertEquals(HMILevel.HMI_FULL, menuManager.currentHMILevel); + + // Sleep to give time to Taskmaster to run the operations + sleep(); + + assertEquals(cells, menuManager.currentMenuCells); } @Test - public void testUpdatingOldWay() { + public void testSettingNullMenu() { + menuManager.setMenuCells(null); + assertEquals(HMILevel.HMI_NONE, menuManager.currentHMILevel); + assertTrue(menuManager.currentMenuCells.isEmpty()); + + // The Menu Manager should send new menu once HMI full occurs + sendFakeCoreOnHMIFullNotifications(); + // Listener should be triggered - which sets new HMI level and should proceed to send our pending update + assertEquals(HMILevel.HMI_FULL, menuManager.currentHMILevel); + + assertTrue(menuManager.currentMenuCells.isEmpty()); + } + + @Test + public void testSettingNonUniqueCells() { + MenuSelectionListener listener = null; + MenuCell cell1 = new MenuCell("cell", null, null, listener); + MenuCell cell2 = new MenuCell("cell", null, null, listener); + + menuManager.setMenuCells(Arrays.asList(cell1, cell2)); + assertEquals(HMILevel.HMI_NONE, menuManager.currentHMILevel); + assertTrue(menuManager.currentMenuCells.isEmpty()); + + // The Menu Manager should send new menu once HMI full occurs + sendFakeCoreOnHMIFullNotifications(); + + // Listener should be triggered - which sets new HMI level and should proceed to send our pending update + assertEquals(HMILevel.HMI_FULL, menuManager.currentHMILevel); + + assertTrue(menuManager.transactionQueue.getTasksAsList().isEmpty()); + } + + @Test + public void testUpdatingOldWay() { // Force Menu Manager to use the old way of deleting / sending all menuManager.setDynamicUpdatesMode(DynamicMenuUpdatesMode.FORCE_OFF); assertEquals(menuManager.dynamicMenuUpdatesMode, DynamicMenuUpdatesMode.FORCE_OFF); // when we only send one command to update, we should only be returned one add command List<MenuCell> newArray = Arrays.asList(mainCell1, mainCell4); - assertEquals(menuManager.allCommandsForCells(newArray, false).size(), 4); // 1 root cells, 1 sub menu root cell, 2 sub menu cells + assertEquals(MenuReplaceUtilities.allCommandsForCells(newArray, menuManager.fileManager.get(), menuManager.windowCapability, MenuLayout.LIST).size(), 4); // 1 root cells, 1 sub menu root cell, 2 sub menu cells menuManager.currentHMILevel = HMILevel.HMI_FULL; menuManager.setMenuCells(newArray); - // Algorithm should NOT have run - assertNull(menuManager.keepsNew); - assertNull(menuManager.keepsOld); - - // Unlike voice commands, the Menu Manager dynamically assigns Cell ID's. Because of this, we need to get the updated - // cell list after setting it and then test the listeners, as they use the newly assigned cell ID's. - List<MenuCell> updatedCells = menuManager.getMenuCells(); - for (MenuCell cell : updatedCells) { + // Sleep to give time to Taskmaster to run the operations + sleep(); + for (MenuCell cell : menuManager.currentMenuCells) { // grab 2 of our newly updated cells - 1 root and 1 sub cell, and make sure they can get triggered if (cell.getTitle().equalsIgnoreCase("Test Cell 1")) { // Fake onCommand - we want to make sure that we can pass back onCommand events to our root Menu Cell @@ -272,39 +301,46 @@ public class MenuManagerTests { @Test public void testAlgorithmTest1() { - // Force Menu Manager to use the new way menuManager.setDynamicUpdatesMode(DynamicMenuUpdatesMode.FORCE_ON); assertEquals(menuManager.dynamicMenuUpdatesMode, DynamicMenuUpdatesMode.FORCE_ON); // start fresh - menuManager.oldMenuCells = null; - menuManager.menuCells = null; - menuManager.inProgressUpdate = null; - menuManager.waitingUpdateMenuCells = null; - menuManager.waitingOnHMIUpdate = false; + menuManager.currentMenuCells = new ArrayList<>(); + menuManager.menuCells = new ArrayList<>(); + + sendFakeCoreOnHMIFullNotifications(); - menuManager.currentHMILevel = HMILevel.HMI_FULL; // send new cells. They should set the old way List<MenuCell> oldMenu = createDynamicMenu1(); List<MenuCell> newMenu = createDynamicMenu1New(); menuManager.setMenuCells(oldMenu); - assertEquals(menuManager.menuCells.size(), 4); + + // Sleep to give time to Taskmaster to run the operations + sleep(); + + assertEquals(menuManager.currentMenuCells.size(), 4); + + menuManager.setMenuCells(newMenu); + + // Sleep to give time to Taskmaster to run the operations + sleep(); // this happens in the menu manager but lets make sure its behaving - RunScore runScore = menuManager.runMenuCompareAlgorithm(oldMenu, newMenu); + DynamicMenuUpdateRunScore runScore = DynamicMenuUpdateAlgorithm.dynamicRunScoreOldMenuCells(oldMenu, newMenu); - List<Integer> oldMenuScore = Arrays.asList(0, 0, 0, 0); - List<Integer> newMenuScore = Arrays.asList(0, 0, 0, 0, 1); + List<MenuCellState> oldMenuStatus = Arrays.asList(KEEP, KEEP, KEEP, KEEP); + List<MenuCellState> newMenuStatus = Arrays.asList(KEEP, KEEP, KEEP, KEEP, ADD); - assertEquals(runScore.getScore(), 1); - assertEquals(runScore.getOldMenu(), oldMenuScore); - assertEquals(runScore.getCurrentMenu(), newMenuScore); + assertEquals(1, runScore.getScore()); + assertEquals(runScore.getOldStatus(), oldMenuStatus); + assertEquals(runScore.getUpdatedStatus(), newMenuStatus); - menuManager.setMenuCells(newMenu); - assertEquals(menuManager.menuCells.size(), 5); - assertEquals(menuManager.keepsNew.size(), 4); - assertEquals(menuManager.keepsOld.size(), 4); + assertEquals(5, menuManager.currentMenuCells.size()); + List<MenuCell> oldKeeps = filterMenuCellsWithStatusList(menuManager.currentMenuCells, runScore.getOldStatus(), KEEP); + List<MenuCell> newKeeps = filterMenuCellsWithStatusList(menuManager.currentMenuCells, runScore.getUpdatedStatus(), KEEP); + assertEquals(4, oldKeeps.size()); + assertEquals(4, newKeeps.size()); } @Test @@ -315,33 +351,41 @@ public class MenuManagerTests { assertEquals(menuManager.dynamicMenuUpdatesMode, DynamicMenuUpdatesMode.FORCE_ON); // start fresh - menuManager.oldMenuCells = null; - menuManager.menuCells = null; - menuManager.inProgressUpdate = null; - menuManager.waitingUpdateMenuCells = null; - menuManager.waitingOnHMIUpdate = false; + menuManager.currentMenuCells = new ArrayList<>(); + menuManager.menuCells = new ArrayList<>(); + + sendFakeCoreOnHMIFullNotifications(); - menuManager.currentHMILevel = HMILevel.HMI_FULL; // send new cells. They should set the old way List<MenuCell> oldMenu = createDynamicMenu2(); List<MenuCell> newMenu = createDynamicMenu2New(); menuManager.setMenuCells(oldMenu); - assertEquals(menuManager.menuCells.size(), 4); + + // Sleep to give time to Taskmaster to run the operations + sleep(); + + assertEquals(4, menuManager.currentMenuCells.size()); + + menuManager.setMenuCells(newMenu); + + // Sleep to give time to Taskmaster to run the operations + sleep(); // this happens in the menu manager but lets make sure its behaving - RunScore runScore = menuManager.runMenuCompareAlgorithm(oldMenu, newMenu); + DynamicMenuUpdateRunScore runScore = DynamicMenuUpdateAlgorithm.dynamicRunScoreOldMenuCells(oldMenu, newMenu); - List<Integer> oldMenuScore = Arrays.asList(0, 0, 0, 2); - List<Integer> newMenuScore = Arrays.asList(0, 0, 0); + List<MenuCellState> oldMenuScore = Arrays.asList(KEEP, KEEP, KEEP, DELETE); + List<MenuCellState> newMenuScore = Arrays.asList(KEEP, KEEP, KEEP); assertEquals(runScore.getScore(), 0); - assertEquals(runScore.getOldMenu(), oldMenuScore); - assertEquals(runScore.getCurrentMenu(), newMenuScore); + assertEquals(runScore.getOldStatus(), oldMenuScore); + assertEquals(runScore.getUpdatedStatus(), newMenuScore); - menuManager.setMenuCells(newMenu); - assertEquals(menuManager.menuCells.size(), 3); - assertEquals(menuManager.keepsNew.size(), 3); - assertEquals(menuManager.keepsOld.size(), 3); + assertEquals(3, menuManager.currentMenuCells.size()); + List<MenuCell> oldKeeps = filterMenuCellsWithStatusList(menuManager.currentMenuCells, runScore.getOldStatus(), KEEP); + List<MenuCell> newKeeps = filterMenuCellsWithStatusList(menuManager.currentMenuCells, runScore.getUpdatedStatus(), KEEP); + assertEquals(3, oldKeeps.size()); + assertEquals(3, newKeeps.size()); } @Test @@ -352,33 +396,41 @@ public class MenuManagerTests { assertEquals(menuManager.dynamicMenuUpdatesMode, DynamicMenuUpdatesMode.FORCE_ON); // start fresh - menuManager.oldMenuCells = null; - menuManager.menuCells = null; - menuManager.inProgressUpdate = null; - menuManager.waitingUpdateMenuCells = null; - menuManager.waitingOnHMIUpdate = false; + menuManager.currentMenuCells = new ArrayList<>(); + menuManager.menuCells = new ArrayList<>(); + + sendFakeCoreOnHMIFullNotifications(); - menuManager.currentHMILevel = HMILevel.HMI_FULL; // send new cells. They should set the old way List<MenuCell> oldMenu = createDynamicMenu3(); List<MenuCell> newMenu = createDynamicMenu3New(); menuManager.setMenuCells(oldMenu); - assertEquals(menuManager.menuCells.size(), 3); + + // Sleep to give time to Taskmaster to run the operations + sleep(); + + assertEquals(menuManager.currentMenuCells.size(), 3); + + menuManager.setMenuCells(newMenu); + + // Sleep to give time to Taskmaster to run the operations + sleep(); // this happens in the menu manager but lets make sure its behaving - RunScore runScore = menuManager.runMenuCompareAlgorithm(oldMenu, newMenu); + DynamicMenuUpdateRunScore runScore = DynamicMenuUpdateAlgorithm.dynamicRunScoreOldMenuCells(oldMenu, newMenu); - List<Integer> oldMenuScore = Arrays.asList(2, 2, 2); - List<Integer> newMenuScore = Arrays.asList(1, 1, 1); + List<MenuCellState> oldMenuStatus = Arrays.asList(DELETE, DELETE, DELETE); + List<MenuCellState> newMenuStatus = Arrays.asList(ADD, ADD, ADD); assertEquals(runScore.getScore(), 3); - assertEquals(runScore.getOldMenu(), oldMenuScore); - assertEquals(runScore.getCurrentMenu(), newMenuScore); + assertEquals(runScore.getOldStatus(), oldMenuStatus); + assertEquals(runScore.getUpdatedStatus(), newMenuStatus); - menuManager.setMenuCells(newMenu); - assertEquals(menuManager.menuCells.size(), 3); - assertEquals(menuManager.keepsNew.size(), 0); - assertEquals(menuManager.keepsOld.size(), 0); + assertEquals(menuManager.currentMenuCells.size(), 3); + List<MenuCell> oldKeeps = filterMenuCellsWithStatusList(menuManager.currentMenuCells, runScore.getOldStatus(), KEEP); + List<MenuCell> newKeeps = filterMenuCellsWithStatusList(menuManager.currentMenuCells, runScore.getUpdatedStatus(), KEEP); + assertEquals(0, newKeeps.size()); + assertEquals(0, oldKeeps.size()); } @Test @@ -389,33 +441,41 @@ public class MenuManagerTests { assertEquals(menuManager.dynamicMenuUpdatesMode, DynamicMenuUpdatesMode.FORCE_ON); // start fresh - menuManager.oldMenuCells = null; - menuManager.menuCells = null; - menuManager.inProgressUpdate = null; - menuManager.waitingUpdateMenuCells = null; - menuManager.waitingOnHMIUpdate = false; + menuManager.currentMenuCells = new ArrayList<>(); + menuManager.menuCells = new ArrayList<>(); + + sendFakeCoreOnHMIFullNotifications(); - menuManager.currentHMILevel = HMILevel.HMI_FULL; // send new cells. They should set the old way List<MenuCell> oldMenu = createDynamicMenu4(); List<MenuCell> newMenu = createDynamicMenu4New(); menuManager.setMenuCells(oldMenu); - assertEquals(menuManager.menuCells.size(), 4); + + // Sleep to give time to Taskmaster to run the operations + sleep(); + + assertEquals(menuManager.currentMenuCells.size(), 4); + + menuManager.setMenuCells(newMenu); + + // Sleep to give time to Taskmaster to run the operations + sleep(); // this happens in the menu manager but lets make sure its behaving - RunScore runScore = menuManager.runMenuCompareAlgorithm(oldMenu, newMenu); + DynamicMenuUpdateRunScore runScore = DynamicMenuUpdateAlgorithm.dynamicRunScoreOldMenuCells(oldMenu, newMenu); - List<Integer> oldMenuScore = Arrays.asList(0, 2, 0, 2); - List<Integer> newMenuScore = Arrays.asList(1, 0, 1, 0); + List<MenuCellState> oldMenuStatus = Arrays.asList(KEEP, DELETE, KEEP, DELETE); + List<MenuCellState> newMenuStatus = Arrays.asList(ADD, KEEP, ADD, KEEP); assertEquals(runScore.getScore(), 2); - assertEquals(runScore.getOldMenu(), oldMenuScore); - assertEquals(runScore.getCurrentMenu(), newMenuScore); + assertEquals(runScore.getOldStatus(), oldMenuStatus); + assertEquals(runScore.getUpdatedStatus(), newMenuStatus); - menuManager.setMenuCells(newMenu); - assertEquals(menuManager.menuCells.size(), 4); - assertEquals(menuManager.keepsNew.size(), 2); - assertEquals(menuManager.keepsOld.size(), 2); + assertEquals(menuManager.currentMenuCells.size(), 4); + List<MenuCell> oldKeeps = filterMenuCellsWithStatusList(menuManager.currentMenuCells, runScore.getOldStatus(), KEEP); + List<MenuCell> newKeeps = filterMenuCellsWithStatusList(menuManager.currentMenuCells, runScore.getUpdatedStatus(), KEEP); + assertEquals(2, newKeeps.size()); + assertEquals(2, oldKeeps.size()); } @Test @@ -426,77 +486,68 @@ public class MenuManagerTests { assertEquals(menuManager.dynamicMenuUpdatesMode, DynamicMenuUpdatesMode.FORCE_ON); // start fresh - menuManager.oldMenuCells = null; - menuManager.menuCells = null; - menuManager.inProgressUpdate = null; - menuManager.waitingUpdateMenuCells = null; - menuManager.waitingOnHMIUpdate = false; + menuManager.currentMenuCells = new ArrayList<>(); + menuManager.menuCells = new ArrayList<>(); + + sendFakeCoreOnHMIFullNotifications(); - menuManager.currentHMILevel = HMILevel.HMI_FULL; // send new cells. They should set the old way List<MenuCell> oldMenu = createDynamicMenu5(); List<MenuCell> newMenu = createDynamicMenu5New(); menuManager.setMenuCells(oldMenu); - assertEquals(menuManager.menuCells.size(), 4); - // this happens in the menu manager but lets make sure its behaving - RunScore runScore = menuManager.runMenuCompareAlgorithm(oldMenu, newMenu); + // Sleep to give time to Taskmaster to run the operations + sleep(); - List<Integer> oldMenuScore = Arrays.asList(2, 0, 0, 0); - List<Integer> newMenuScore = Arrays.asList(0, 0, 0, 1); - - assertEquals(runScore.getScore(), 1); - assertEquals(runScore.getOldMenu(), oldMenuScore); - assertEquals(runScore.getCurrentMenu(), newMenuScore); + assertEquals(menuManager.currentMenuCells.size(), 4); menuManager.setMenuCells(newMenu); - assertEquals(menuManager.menuCells.size(), 4); - assertEquals(menuManager.keepsNew.size(), 3); - assertEquals(menuManager.keepsOld.size(), 3); - } - @Test - public void testSettingNullMenu() { + // Sleep to give time to Taskmaster to run the operations + sleep(); - // Make sure we can send an empty menu with no issues - // start fresh - menuManager.oldMenuCells = null; - menuManager.menuCells = null; - menuManager.inProgressUpdate = null; - menuManager.waitingUpdateMenuCells = null; - menuManager.waitingOnHMIUpdate = false; + // this happens in the menu manager but lets make sure its behaving + DynamicMenuUpdateRunScore runScore = DynamicMenuUpdateAlgorithm.dynamicRunScoreOldMenuCells(oldMenu, newMenu); - menuManager.currentHMILevel = HMILevel.HMI_FULL; - // send new cells. They should set the old way - List<MenuCell> oldMenu = createDynamicMenu1(); - List<MenuCell> newMenu = null; - menuManager.setMenuCells(oldMenu); - assertEquals(menuManager.menuCells.size(), 4); + List<MenuCellState> oldMenuStatus = Arrays.asList(DELETE, KEEP, KEEP, KEEP); + List<MenuCellState> newMenuStatus = Arrays.asList(KEEP, KEEP, KEEP, ADD); - menuManager.setMenuCells(newMenu); - assertEquals(menuManager.menuCells.size(), 0); + assertEquals(runScore.getScore(), 1); + assertEquals(runScore.getOldStatus(), oldMenuStatus); + assertEquals(runScore.getUpdatedStatus(), newMenuStatus); + + assertEquals(menuManager.currentMenuCells.size(), 4); + List<MenuCell> oldKeeps = filterMenuCellsWithStatusList(menuManager.currentMenuCells, runScore.getOldStatus(), KEEP); + List<MenuCell> newKeeps = filterMenuCellsWithStatusList(menuManager.currentMenuCells, runScore.getUpdatedStatus(), KEEP); + assertEquals(3, newKeeps.size()); + assertEquals(3, oldKeeps.size()); } @Test public void testClearingMenu() { - // Make sure we can send an empty menu with no issues // start fresh - menuManager.oldMenuCells = null; - menuManager.menuCells = null; - menuManager.inProgressUpdate = null; - menuManager.waitingUpdateMenuCells = null; - menuManager.waitingOnHMIUpdate = false; + menuManager.currentMenuCells = new ArrayList<>(); + menuManager.menuCells = new ArrayList<>(); + + sendFakeCoreOnHMIFullNotifications(); - menuManager.currentHMILevel = HMILevel.HMI_FULL; // send new cells. They should set the old way List<MenuCell> oldMenu = createDynamicMenu1(); List<MenuCell> newMenu = Collections.emptyList(); menuManager.setMenuCells(oldMenu); - assertEquals(menuManager.menuCells.size(), 4); + + // Sleep to give time to Taskmaster to run the operations + sleep(); + + assertEquals(4, menuManager.currentMenuCells.size()); menuManager.setMenuCells(newMenu); - assertEquals(menuManager.menuCells.size(), 0); + + // Sleep to give time to Taskmaster to run the operations + sleep(); + + assertEquals(0 , menuManager.currentMenuCells.size()); } @Test @@ -512,7 +563,7 @@ public class MenuManagerTests { // call open Menu MenuManager mockMenuManager = mock(MenuManager.class); MenuCell cell = mock(MenuCell.class); - mockMenuManager.oldMenuCells = null; + mockMenuManager.currentMenuCells = null; assertFalse(mockMenuManager.openSubMenu(cell)); } @@ -520,201 +571,40 @@ public class MenuManagerTests { public void testOpeningSubMenu() { // call open Menu List<MenuCell> testCells = createTestCells(); - menuManager.oldMenuCells = testCells; - menuManager.sdlMsgVersion = new SdlMsgVersion(6, 0); - // has to get success response to be true - assertTrue(menuManager.openSubMenu(testCells.get(3))); - } - - @Test - public void testSetMenuConfiguration() { - menuManager.currentHMILevel = HMILevel.HMI_FULL; - menuManager.currentSystemContext = SystemContext.SYSCTXT_MAIN; - menuManager.sdlMsgVersion = new SdlMsgVersion(6, 0); - menuManager.defaultMainWindowCapability = new WindowCapability(); - - List<MenuLayout> menuLayouts = Arrays.asList(MenuLayout.LIST, MenuLayout.TILES); - menuManager.defaultMainWindowCapability.setMenuLayoutsAvailable(menuLayouts); - - MenuConfiguration menuConfigurationTest = new MenuConfiguration(MenuLayout.LIST, MenuLayout.LIST); - menuManager.setMenuConfiguration(menuConfigurationTest); - assertEquals(menuManager.menuConfiguration, menuConfigurationTest); + menuManager.setMenuCells(testCells); - } - - @Test - public void testSettingUniqueMenuNames() { - //Testing using SDLMsgVersion 7.0, at this version uniqueTitles will be set - - // Make sure we can send an empty menu with no issues - // start fresh - menuManager.oldMenuCells = null; - menuManager.menuCells = null; - menuManager.inProgressUpdate = null; - menuManager.waitingUpdateMenuCells = null; - menuManager.waitingOnHMIUpdate = false; - - menuManager.currentHMILevel = HMILevel.HMI_FULL; - // send new cells. They should set the old way - List<MenuCell> oldMenu = createDynamicMenu6_forUniqueNamesTest(); - menuManager.setMenuCells(oldMenu); - assertEquals(menuManager.menuCells.size(), 4); - assertEquals(menuManager.menuCells.get(0).getUniqueTitle(), "A"); - assertEquals(menuManager.menuCells.get(1).getUniqueTitle(), "A (2)"); - assertEquals(menuManager.menuCells.get(2).getUniqueTitle(), "A (3)"); - assertEquals(menuManager.menuCells.get(3).getUniqueTitle(), "A (4)"); - - assertEquals((menuManager.menuCells.get(3).getSubCells().size()), 4); - assertEquals(menuManager.menuCells.get(3).getSubCells().get(0).getUniqueTitle(), "A"); - assertEquals(menuManager.menuCells.get(3).getSubCells().get(1).getUniqueTitle(), "A (2)"); - assertEquals(menuManager.menuCells.get(3).getSubCells().get(2).getUniqueTitle(), "A (3)"); - assertEquals(menuManager.menuCells.get(3).getSubCells().get(3).getUniqueTitle(), "A (4)"); - } - - @Test - public void testAllowingNonUniqueTitles() { - //Testing using SDLMsgVersion 7.1, at this version uniqueTitles will be set - SdlMsgVersion version = new SdlMsgVersion(); - version.setMajorVersion(7); - version.setMinorVersion(1); - doReturn(version).when(internalInterface).getSdlMsgVersion(); + sendFakeCoreOnHMIFullNotifications(); - // Make sure we can send an empty menu with no issues - // start fresh - menuManager.oldMenuCells = null; - menuManager.menuCells = null; - menuManager.inProgressUpdate = null; - menuManager.waitingUpdateMenuCells = null; - menuManager.waitingOnHMIUpdate = false; + // Sleep to give time to Taskmaster to run the operations + sleep(); - menuManager.currentHMILevel = HMILevel.HMI_FULL; - // send new cells. They should set the old way - List<MenuCell> oldMenu = createDynamicMenu6_forUniqueNamesTest(); - menuManager.setMenuCells(oldMenu); - assertEquals(menuManager.menuCells.size(), 4); - assertEquals(menuManager.menuCells.get(0).getUniqueTitle(), "A"); - assertEquals(menuManager.menuCells.get(1).getUniqueTitle(), "A"); - assertEquals(menuManager.menuCells.get(2).getUniqueTitle(), "A"); - assertEquals(menuManager.menuCells.get(3).getUniqueTitle(), "A"); - - assertEquals((menuManager.menuCells.get(3).getSubCells().size()), 4); - assertEquals(menuManager.menuCells.get(3).getSubCells().get(0).getUniqueTitle(), "A"); - assertEquals(menuManager.menuCells.get(3).getSubCells().get(1).getUniqueTitle(), "A"); - assertEquals(menuManager.menuCells.get(3).getSubCells().get(2).getUniqueTitle(), "A"); - assertEquals(menuManager.menuCells.get(3).getSubCells().get(3).getUniqueTitle(), "A"); + // Has to get success response to be true + MenuCell submenu = testCells.get(3); + assertTrue(menuManager.openSubMenu(submenu)); } @Test - public void testUniquenessForAvailableFields() { - WindowCapability windowCapability = new WindowCapability(); - TextField menuSubMenuSecondaryText = new TextField(); - menuSubMenuSecondaryText.setName(TextFieldName.menuSubMenuSecondaryText); - TextField menuSubMenuTertiaryText = new TextField(); - menuSubMenuTertiaryText.setName(TextFieldName.menuSubMenuTertiaryText); - TextField menuCommandSecondaryText = new TextField(); - menuCommandSecondaryText.setName(TextFieldName.menuCommandSecondaryText); - TextField menuCommandTertiaryText = new TextField(); - menuCommandTertiaryText.setName(TextFieldName.menuCommandTertiaryText); - List<TextField> textFields = new ArrayList<>(); - textFields.add(menuSubMenuSecondaryText); - textFields.add(menuSubMenuTertiaryText); - textFields.add(menuCommandSecondaryText); - textFields.add(menuCommandTertiaryText); - windowCapability.setTextFields(textFields); - - ImageField cmdIcon = new ImageField(); - cmdIcon.setName(ImageFieldName.cmdIcon); - ImageField menuSubMenuSecondaryImage = new ImageField(); - menuSubMenuSecondaryImage.setName(ImageFieldName.menuSubMenuSecondaryImage); - ImageField menuCommandSecondaryImage = new ImageField(); - menuCommandSecondaryImage.setName(ImageFieldName.menuCommandSecondaryImage); - List<ImageField> imageFieldList = new ArrayList<>(); - imageFieldList.add(cmdIcon); - imageFieldList.add(menuSubMenuSecondaryImage); - imageFieldList.add(menuCommandSecondaryImage); - windowCapability.setImageFields(imageFieldList); - menuManager.defaultMainWindowCapability = windowCapability; - - assertNull(menuManager.removeUnusedProperties(null)); - - MenuCell cell1 = new MenuCell("Text1", "SecondaryText", "TText", TestValues.GENERAL_ARTWORK, TestValues.GENERAL_ARTWORK, null, new MenuSelectionListener() { - @Override - public void onTriggered(TriggerSource trigger) { - - } - }); - - MenuCell cell2 = new MenuCell("Text1", "SecondaryText2", "TText2", null, null, null, new MenuSelectionListener() { - @Override - public void onTriggered(TriggerSource trigger) { - - } - }); - - MenuCell subCell1 = new MenuCell("SubCell1", "Secondary Text", "TText", TestValues.GENERAL_ARTWORK, TestValues.GENERAL_ARTWORK, null, new MenuSelectionListener() { - @Override - public void onTriggered(TriggerSource trigger) { - } - }); - - MenuCell subCell2 = new MenuCell("SubCell1", "Secondary Text2", "TText2", null, null, null, new MenuSelectionListener() { - @Override - public void onTriggered(TriggerSource trigger) { - } - }); - - List<MenuCell> subCellList = new ArrayList<>(); - subCellList.add(subCell1); - subCellList.add(subCell2); - - - MenuCell cell3 = new MenuCell("Test Cell 3 (sub menu)", "SecondaryText", "TText", MenuLayout.LIST, TestValues.GENERAL_ARTWORK, TestValues.GENERAL_ARTWORK, subCellList); - MenuCell cell4 = new MenuCell("Test Cell 3 (sub menu)", null, null, MenuLayout.LIST, null, null, subCellList); - - List<MenuCell> menuCellList = new ArrayList<>(); - menuCellList.add(cell1); - menuCellList.add(cell2); - menuCellList.add(cell3); - menuCellList.add(cell4); - - List<MenuCell> removedProperties = menuManager.removeUnusedProperties(menuCellList); - assertNotNull(removedProperties.get(0).getSecondaryText()); - menuManager.addUniqueNamesBasedOnStrippedCells(removedProperties, menuCellList); - assertEquals(menuCellList.get(1).getUniqueTitle(), "Text1"); - - // Remove menuCommandSecondaryText as a supported TextField - textFields.remove(menuCommandSecondaryText); - textFields.remove(menuCommandTertiaryText); - imageFieldList.remove(cmdIcon); - imageFieldList.remove(menuCommandSecondaryImage); - imageFieldList.remove(menuSubMenuSecondaryImage); - textFields.remove(menuSubMenuSecondaryText); - textFields.remove(menuSubMenuTertiaryText); - textFields.remove(menuSubMenuSecondaryImage); - - // Test removeUnusedProperties - removedProperties = menuManager.removeUnusedProperties(menuCellList); - assertNull(removedProperties.get(0).getSecondaryText()); - assertNull(removedProperties.get(0).getTertiaryText()); - - menuManager.addUniqueNamesBasedOnStrippedCells(removedProperties, menuCellList); - assertEquals(menuCellList.get(1).getUniqueTitle(), "Text1 (2)"); + public void testSetMenuConfiguration() { + sendFakeCoreOnHMIFullNotifications(); + menuManager.windowCapability = new WindowCapability(); + menuManager.windowCapability.setMenuLayoutsAvailable(Arrays.asList(MenuLayout.LIST, MenuLayout.TILES)); - // SubCell test - assertEquals(menuCellList.get(3).getUniqueTitle(), "Test Cell 3 (sub menu) (2)"); - assertEquals(menuCellList.get(2).getSubCells().get(1).getUniqueTitle(), "SubCell1 (2)"); + MenuConfiguration menuConfigurationTest = new MenuConfiguration(MenuLayout.LIST, MenuLayout.LIST); + menuManager.setMenuConfiguration(menuConfigurationTest); + // Sleep to give time to Taskmaster to run the operations + sleep(); + assertEquals(menuManager.menuConfiguration, menuConfigurationTest); } - - // HELPERS // Emulate what happens when Core sends OnHMIStatus notification private void sendFakeCoreOnHMIFullNotifications() { OnHMIStatus onHMIStatusFakeNotification = new OnHMIStatus(); onHMIStatusFakeNotification.setHmiLevel(HMILevel.HMI_FULL); + onHMIStatusFakeNotification.setSystemContext(SystemContext.SYSCTXT_MAIN); onHMIStatusListener.onNotified(onHMIStatusFakeNotification); } @@ -750,12 +640,6 @@ public class MenuManagerTests { } private List<MenuCell> createDynamicMenu1() { - - MenuSelectionListener menuSelectionListenerA = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerB = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerC = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerD = mock(MenuSelectionListener.class); - MenuCell A = new MenuCell("A", null, null, menuSelectionListenerA); MenuCell B = new MenuCell("B", null, null, menuSelectionListenerB); @@ -769,13 +653,6 @@ public class MenuManagerTests { } private List<MenuCell> createDynamicMenu1New() { - - MenuSelectionListener menuSelectionListenerA = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerB = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerC = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerD = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerE = mock(MenuSelectionListener.class); - MenuCell A = new MenuCell("A", null, null, menuSelectionListenerA); MenuCell B = new MenuCell("B", null, null, menuSelectionListenerB); @@ -791,12 +668,6 @@ public class MenuManagerTests { } private List<MenuCell> createDynamicMenu2() { - - MenuSelectionListener menuSelectionListenerA = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerB = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerC = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerD = mock(MenuSelectionListener.class); - MenuCell A = new MenuCell("A", null, null, menuSelectionListenerA); MenuCell B = new MenuCell("B", null, null, menuSelectionListenerB); @@ -810,11 +681,6 @@ public class MenuManagerTests { } private List<MenuCell> createDynamicMenu2New() { - - MenuSelectionListener menuSelectionListenerA = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerB = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerC = mock(MenuSelectionListener.class); - MenuCell A = new MenuCell("A", null, null, menuSelectionListenerA); MenuCell B = new MenuCell("B", null, null, menuSelectionListenerB); @@ -826,11 +692,6 @@ public class MenuManagerTests { } private List<MenuCell> createDynamicMenu3() { - - MenuSelectionListener menuSelectionListenerA = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerB = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerC = mock(MenuSelectionListener.class); - MenuCell A = new MenuCell("A", null, null, menuSelectionListenerA); MenuCell B = new MenuCell("B", null, null, menuSelectionListenerB); @@ -858,12 +719,6 @@ public class MenuManagerTests { } private List<MenuCell> createDynamicMenu4() { - - MenuSelectionListener menuSelectionListenerA = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerB = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerC = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerD = mock(MenuSelectionListener.class); - MenuCell A = new MenuCell("A", null, null, menuSelectionListenerA); MenuCell B = new MenuCell("B", null, null, menuSelectionListenerB); @@ -877,12 +732,6 @@ public class MenuManagerTests { } private List<MenuCell> createDynamicMenu4New() { - - MenuSelectionListener menuSelectionListenerA = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerB = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerC = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerD = mock(MenuSelectionListener.class); - MenuCell A = new MenuCell("A", null, null, menuSelectionListenerA); MenuCell B = new MenuCell("B", null, null, menuSelectionListenerB); @@ -896,12 +745,6 @@ public class MenuManagerTests { } private List<MenuCell> createDynamicMenu5() { - - MenuSelectionListener menuSelectionListenerA = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerB = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerC = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerD = mock(MenuSelectionListener.class); - MenuCell A = new MenuCell("A", null, null, menuSelectionListenerA); MenuCell B = new MenuCell("B", null, null, menuSelectionListenerB); @@ -915,12 +758,6 @@ public class MenuManagerTests { } private List<MenuCell> createDynamicMenu5New() { - - MenuSelectionListener menuSelectionListenerA = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerB = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerC = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerD = mock(MenuSelectionListener.class); - MenuCell A = new MenuCell("A", null, null, menuSelectionListenerA); MenuCell B = new MenuCell("B", null, null, menuSelectionListenerB); @@ -933,32 +770,21 @@ public class MenuManagerTests { } - private List<MenuCell> createDynamicMenu6_forUniqueNamesTest() { - MenuSelectionListener menuSelectionListenerA = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerB = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerC = mock(MenuSelectionListener.class); - MenuSelectionListener menuSelectionListenerD = mock(MenuSelectionListener.class); - - SdlArtwork icon1 = new SdlArtwork("livio", FileType.GRAPHIC_PNG, R.drawable.sdl_lockscreen_icon, false); - SdlArtwork icon2 = new SdlArtwork("livio2", FileType.GRAPHIC_PNG, R.drawable.ic_sdl, false); - SdlArtwork icon3 = new SdlArtwork("livio3", FileType.GRAPHIC_PNG, R.drawable.sdl_tray_icon, false); - SdlArtwork icon4 = new SdlArtwork("livio4", FileType.GRAPHIC_PNG, R.drawable.spp_error, false); - - MenuCell A = new MenuCell("A", icon1, null, menuSelectionListenerA); - - MenuCell B = new MenuCell("A", icon2, null, menuSelectionListenerB); - - MenuCell C = new MenuCell("A", icon3, null, menuSelectionListenerC); - - MenuCell subA = new MenuCell("A", icon1, null, menuSelectionListenerA); - MenuCell subB = new MenuCell("A", icon2, null, menuSelectionListenerB); - MenuCell subC = new MenuCell("A", icon3, null, menuSelectionListenerC); - MenuCell subD = new MenuCell("A", icon4, null, menuSelectionListenerD); - - MenuCell D = new MenuCell("A", MenuLayout.LIST, icon4, Arrays.asList(subA, subB, subC, subD)); - - return Arrays.asList(A, B, C, D); + private List<MenuCell> filterMenuCellsWithStatusList(List<MenuCell> menuCells, List<DynamicMenuUpdateAlgorithm.MenuCellState> statusList, DynamicMenuUpdateAlgorithm.MenuCellState menuCellState) { + List<MenuCell> filteredCells = new ArrayList<>(); + for (int index = 0; index < statusList.size(); index++) { + if (statusList.get(index).equals(menuCellState)) { + filteredCells.add(menuCells.get(index)); + } + } + return filteredCells; } - + private void sleep() { + try { + Thread.sleep(250); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuReplaceOperationTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuReplaceOperationTests.java new file mode 100644 index 000000000..284f1efd5 --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuReplaceOperationTests.java @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2021 Livio, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Livio Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package com.smartdevicelink.managers.screen.menu; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; +import static com.smartdevicelink.managers.screen.menu.MenuReplaceUtilities.cloneMenuCellsList; +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.os.Handler; + +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.livio.taskmaster.Queue; +import com.livio.taskmaster.Taskmaster; +import com.smartdevicelink.managers.ISdl; +import com.smartdevicelink.managers.file.FileManager; +import com.smartdevicelink.managers.file.MultipleFileCompletionListener; +import com.smartdevicelink.managers.file.filetypes.SdlArtwork; +import com.smartdevicelink.proxy.RPCMessage; +import com.smartdevicelink.proxy.RPCRequest; +import com.smartdevicelink.proxy.RPCResponse; +import com.smartdevicelink.proxy.rpc.SdlMsgVersion; +import com.smartdevicelink.proxy.rpc.TextField; +import com.smartdevicelink.proxy.rpc.WindowCapability; +import com.smartdevicelink.proxy.rpc.enums.MenuLayout; +import com.smartdevicelink.proxy.rpc.enums.TriggerSource; +import com.smartdevicelink.proxy.rpc.listeners.OnMultipleRequestListener; +import com.smartdevicelink.test.TestValues; +import com.smartdevicelink.util.Version; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +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.Random; + +@RunWith(AndroidJUnit4.class) +public class MenuReplaceOperationTests { + private Handler mainHandler; + private Taskmaster taskmaster; + private Queue transactionQueue; + + @Before + public void setUp() throws Exception { + mainHandler = new Handler(getInstrumentation().getTargetContext().getMainLooper()); + taskmaster = new Taskmaster.Builder().build(); + taskmaster.start(); + transactionQueue = taskmaster.createQueue("MenuManager", new Random().nextInt(), false); + } + + @Test + public void testSuccess() { + final ISdl internalInterface = createISdlMock(); + FileManager fileManager = createFileManagerMock(); + WindowCapability windowCapability = createWindowCapability(true, true, new ArrayList<TextField>()); + MenuConfiguration menuConfiguration = new MenuConfiguration(MenuLayout.LIST, MenuLayout.LIST); + + MenuCell menuCell1_1 = new MenuCell("cell 1_1", TestValues.GENERAL_ARTWORK, null, null); + MenuCell menuCell1 = new MenuCell("cell 1", null, TestValues.GENERAL_ARTWORK, Arrays.asList(menuCell1_1)); + MenuCell menuCell2 = new MenuCell("cell 2", TestValues.GENERAL_ARTWORK, null, null); + + final List<MenuCell> currentMenu = new ArrayList<>(); + final List<MenuCell> updatedMenu = cloneMenuCellsList(Arrays.asList(menuCell1, menuCell2)); + MenuReplaceOperation operation = new MenuReplaceOperation(internalInterface, fileManager, windowCapability, menuConfiguration, currentMenu, updatedMenu, true, new MenuManagerCompletionListener() { + @Override + public void onComplete(final boolean success, final List<MenuCell> currentMenuCells) { + assertOnMainThread(new Runnable() { + @Override + public void run() { + assertTrue(success); + assertEquals(currentMenuCells, updatedMenu); + verify(internalInterface, Mockito.times(2)).sendRPCs(any(List.class), any(OnMultipleRequestListener.class)); + } + }); + } + }); + transactionQueue.add(operation, false); + } + + @Test + public void testSwitchingCellsOrder() { + // This unit test is for this bug https://github.com/smartdevicelink/sdl_java_suite/issues/1723 + final ISdl internalInterface = createISdlMock(); + final FileManager fileManager = createFileManagerMock(); + final WindowCapability windowCapability = createWindowCapability(true, true, new ArrayList<TextField>()); + final MenuConfiguration menuConfiguration = new MenuConfiguration(MenuLayout.LIST, MenuLayout.LIST); + + MenuSelectionListener listener = null; + final MenuCell menuCell1 = new MenuCell("A", "SecondaryText", null, null, null, null, listener); + final MenuCell menuCell2 = new MenuCell("A", null, null, null, null, null, listener); + final MenuCell menuCell3 = new MenuCell("C", null, null, null, null, null, listener); + + MenuReplaceOperation operation = new MenuReplaceOperation(internalInterface, fileManager, windowCapability, menuConfiguration, new ArrayList<MenuCell>(), cloneMenuCellsList(Arrays.asList(menuCell1, menuCell2, menuCell3)), true, new MenuManagerCompletionListener() { + @Override + public void onComplete(final boolean success, final List<MenuCell> currentMenuCells1) { + assertOnMainThread(new Runnable() { + @Override + public void run() { + assertTrue(success); + assertEquals(3, currentMenuCells1.size()); + assertEquals("A", currentMenuCells1.get(0).getUniqueTitle()); + assertEquals("A (2)", currentMenuCells1.get(1).getUniqueTitle()); + assertEquals("C", currentMenuCells1.get(2).getUniqueTitle()); + + verify(internalInterface, Mockito.times(1)).sendRPCs(any(List.class), any(OnMultipleRequestListener.class)); + + MenuReplaceOperation operation = new MenuReplaceOperation(internalInterface, fileManager, windowCapability, menuConfiguration, currentMenuCells1, cloneMenuCellsList(Arrays.asList(menuCell2, menuCell1)), true, new MenuManagerCompletionListener() { + @Override + public void onComplete(final boolean success, final List<MenuCell> currentMenuCells2) { + assertOnMainThread(new Runnable() { + @Override + public void run() { + assertTrue(success); + assertEquals(2, currentMenuCells2.size()); + assertEquals("A", currentMenuCells2.get(0).getUniqueTitle()); + assertEquals("A (2)", currentMenuCells2.get(1).getUniqueTitle()); + verify(internalInterface, Mockito.times(2)).sendRPCs(any(List.class), any(OnMultipleRequestListener.class)); + } + }); + } + }); + transactionQueue.add(operation, false); + } + }); + } + }); + transactionQueue.add(operation, false); + } + + @Test + public void testResendingSameCellWithDifferentListener() { + final ISdl internalInterface = createISdlMock(); + final FileManager fileManager = createFileManagerMock(); + final WindowCapability windowCapability = createWindowCapability(true, true, new ArrayList<TextField>()); + final MenuConfiguration menuConfiguration = new MenuConfiguration(MenuLayout.LIST, MenuLayout.LIST); + + final MenuSelectionListener listener1 = new MenuSelectionListener() { + @Override + public void onTriggered(TriggerSource trigger) {} + }; + final MenuSelectionListener listener2 = new MenuSelectionListener() { + @Override + public void onTriggered(TriggerSource trigger) {} + }; + final MenuCell menuCell1 = new MenuCell("A", null, null, null, null, null, listener1); + final MenuCell menuCell2 = new MenuCell("A", null, null, null, null, null, listener2); + + MenuReplaceOperation operation = new MenuReplaceOperation(internalInterface, fileManager, windowCapability, menuConfiguration, new ArrayList<MenuCell>(), cloneMenuCellsList(Arrays.asList(menuCell1)), true, new MenuManagerCompletionListener() { + @Override + public void onComplete(final boolean success, final List<MenuCell> currentMenuCells1) { + assertOnMainThread(new Runnable() { + @Override + public void run() { + assertTrue(success); + assertEquals(1, currentMenuCells1.size()); + assertEquals(listener1, currentMenuCells1.get(0).getMenuSelectionListener()); + verify(internalInterface, Mockito.times(1)).sendRPCs(any(List.class), any(OnMultipleRequestListener.class)); + + MenuReplaceOperation operation = new MenuReplaceOperation(internalInterface, fileManager, windowCapability, menuConfiguration, currentMenuCells1, cloneMenuCellsList(Arrays.asList(menuCell2)), true, new MenuManagerCompletionListener() { + @Override + public void onComplete(final boolean success, final List<MenuCell> currentMenuCells2) { + assertOnMainThread(new Runnable() { + @Override + public void run() { + assertTrue(success); + assertEquals(1, currentMenuCells2.size()); + assertEquals(listener2, currentMenuCells2.get(0).getMenuSelectionListener()); + verify(internalInterface, Mockito.times(1)).sendRPCs(any(List.class), any(OnMultipleRequestListener.class)); + } + }); + } + }); + transactionQueue.add(operation, false); + } + }); + } + }); + transactionQueue.add(operation, false); + } + + private ISdl createISdlMock() { + final ISdl internalInterface = mock(ISdl.class); + + // When internalInterface.sendRPCs() 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(); + List<RPCMessage> rpcs = (List<RPCMessage>) args[0]; + OnMultipleRequestListener listener = (OnMultipleRequestListener) args[1]; + + for (RPCMessage rpcMessage : rpcs) { + RPCRequest request = (RPCRequest) rpcMessage; + RPCResponse response = new RPCResponse(request.getFunctionID().toString()); + response.setCorrelationID(request.getCorrelationID()); + response.setSuccess(true); + listener.onResponse(request.getCorrelationID(), response); + } + + listener.onFinished(); + return null; + } + }; + doAnswer(answer).when(internalInterface).sendRPCs(any(List.class), any(OnMultipleRequestListener.class)); + when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(7, 1, 0))); + + return internalInterface; + } + + private FileManager createFileManagerMock() { + FileManager fileManager = mock(FileManager.class); + + when(fileManager.hasUploadedFile(any(SdlArtwork.class))).thenReturn(true); + + Answer<Void> onFileManagerUploadAnswer = new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + 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)); + return fileManager; + } + + private WindowCapability createWindowCapability(boolean supportsList, boolean supportsTile, ArrayList<TextField> supportedTextFields) { + WindowCapability windowCapability = new WindowCapability(); + windowCapability.setTextFields(supportedTextFields); + windowCapability.setMenuLayoutsAvailable(new ArrayList<MenuLayout>()); + if (supportsList) { + windowCapability.getMenuLayoutsAvailable().add(MenuLayout.LIST); + } + if (supportsTile) { + windowCapability.getMenuLayoutsAvailable().add(MenuLayout.TILES); + } + return windowCapability; + } + + // Asserts on Taskmaster threads will fail silently so we need to do the assertions on main thread if the code is triggered from Taskmaster + private void assertOnMainThread(Runnable runnable) { + mainHandler.post(runnable); + } +} diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuReplaceUtilitiesTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuReplaceUtilitiesTests.java new file mode 100644 index 000000000..61587dbdc --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuReplaceUtilitiesTests.java @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2021 Livio, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Livio Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package com.smartdevicelink.managers.screen.menu; + +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.smartdevicelink.managers.file.FileManager; +import com.smartdevicelink.managers.file.filetypes.SdlArtwork; +import com.smartdevicelink.proxy.rpc.ImageField; +import com.smartdevicelink.proxy.rpc.WindowCapability; +import com.smartdevicelink.proxy.rpc.enums.ImageFieldName; +import com.smartdevicelink.proxy.rpc.enums.MenuLayout; +import com.smartdevicelink.test.TestValues; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static com.smartdevicelink.managers.screen.menu.BaseMenuManager.parentIdNotFound; +import static com.smartdevicelink.managers.screen.menu.MenuReplaceUtilities.addIdsToMenuCells; +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Created by Bilal Alsharifi on 2/4/21. + */ +@RunWith(AndroidJUnit4.class) +public class MenuReplaceUtilitiesTests { + @Before + public void setUp() throws Exception { + } + + @Test + public void testRemoveMenuCellFromList() { + MenuCell menuCellToDelete; + boolean cellRemoved; + List<MenuCell> actualMenuCellList = createMenuCellList(); + List<MenuCell> expectedMenuCellList = createMenuCellList(); + + // Delete cell c4 + menuCellToDelete = actualMenuCellList.get(3); + cellRemoved = MenuReplaceUtilities.removeCellFromList(actualMenuCellList, menuCellToDelete.getCellId()); + assertTrue(cellRemoved); + expectedMenuCellList.remove(3); + assertEquals(expectedMenuCellList, actualMenuCellList); + assertEquals(3, actualMenuCellList.size()); + + // Delete cell c4 again - removal should fail and list should not change + cellRemoved = MenuReplaceUtilities.removeCellFromList(actualMenuCellList, menuCellToDelete.getCellId()); + assertFalse(cellRemoved); + assertEquals(expectedMenuCellList, actualMenuCellList); + assertEquals(3, actualMenuCellList.size()); + + // Delete cell c3 + menuCellToDelete = actualMenuCellList.get(2); + cellRemoved = MenuReplaceUtilities.removeCellFromList(actualMenuCellList, menuCellToDelete.getCellId()); + assertTrue(cellRemoved); + expectedMenuCellList.remove(2); + assertEquals(expectedMenuCellList, actualMenuCellList); + assertEquals(2, actualMenuCellList.size()); + + // Delete cell c2-2-2 + menuCellToDelete = actualMenuCellList.get(1).getSubCells().get(1).getSubCells().get(1); + cellRemoved = MenuReplaceUtilities.removeCellFromList(actualMenuCellList, menuCellToDelete.getCellId()); + assertTrue(cellRemoved); + expectedMenuCellList.get(1).getSubCells().get(1).getSubCells().remove(1); + assertEquals(expectedMenuCellList, actualMenuCellList); + assertEquals(2, actualMenuCellList.size()); + assertEquals(1, actualMenuCellList.get(1).getSubCells().get(1).getSubCells().size()); + + // Delete cell c2-2-1 + menuCellToDelete = actualMenuCellList.get(1).getSubCells().get(1).getSubCells().get(0); + cellRemoved = MenuReplaceUtilities.removeCellFromList(actualMenuCellList, menuCellToDelete.getCellId()); + assertTrue(cellRemoved); + expectedMenuCellList.get(1).getSubCells().get(1).getSubCells().remove(0); + assertEquals(expectedMenuCellList, actualMenuCellList); + assertEquals(2, actualMenuCellList.size()); + assertEquals(0, actualMenuCellList.get(1).getSubCells().get(1).getSubCells().size()); + + // Delete cell c2-2 + menuCellToDelete = actualMenuCellList.get(1).getSubCells().get(1); + cellRemoved = MenuReplaceUtilities.removeCellFromList(actualMenuCellList, menuCellToDelete.getCellId()); + assertTrue(cellRemoved); + expectedMenuCellList.get(1).getSubCells().remove(1); + assertEquals(expectedMenuCellList, actualMenuCellList); + assertEquals(2, actualMenuCellList.size()); + assertEquals(1, actualMenuCellList.get(1).getSubCells().size()); + + // Delete cell c2-1 + menuCellToDelete = actualMenuCellList.get(1).getSubCells().get(0); + cellRemoved = MenuReplaceUtilities.removeCellFromList(actualMenuCellList, menuCellToDelete.getCellId()); + assertTrue(cellRemoved); + expectedMenuCellList.get(1).getSubCells().remove(0); + assertEquals(expectedMenuCellList, actualMenuCellList); + assertEquals(2, actualMenuCellList.size()); + assertEquals(0, actualMenuCellList.get(1).getSubCells().size()); + + // Delete cell c2 + menuCellToDelete = actualMenuCellList.get(1); + cellRemoved = MenuReplaceUtilities.removeCellFromList(actualMenuCellList, menuCellToDelete.getCellId()); + assertTrue(cellRemoved); + expectedMenuCellList.remove(1); + assertEquals(expectedMenuCellList, actualMenuCellList); + assertEquals(1, actualMenuCellList.size()); + + // Delete cell c1 + menuCellToDelete = actualMenuCellList.get(0); + cellRemoved = MenuReplaceUtilities.removeCellFromList(actualMenuCellList, menuCellToDelete.getCellId()); + assertTrue(cellRemoved); + expectedMenuCellList.remove(0); + assertEquals(expectedMenuCellList, actualMenuCellList); + assertEquals(0, actualMenuCellList.size()); + } + + @Test + public void testAddMenuRequestWithCommandId() { + MenuCell menuCellToAdd; + boolean cellAdded; + List<MenuCell> actualMenuCellList = createMenuCellList(); + List<MenuCell> expectedMenuCellList = createMenuCellList(); + List<MenuCell> newMenuList = createNewMenuList(); + + // Add cell c5 + menuCellToAdd = newMenuList.get(0); + cellAdded = MenuReplaceUtilities.addCellWithCellId(menuCellToAdd.getCellId(), 4, newMenuList, actualMenuCellList); + assertTrue(cellAdded); + expectedMenuCellList.add(4, cloneMenuCellAndRemoveSubCells(menuCellToAdd)); + assertEquals(expectedMenuCellList, actualMenuCellList); + assertEquals(5, actualMenuCellList.size()); + assertEquals(0, actualMenuCellList.get(4).getSubCells().size()); + + // Add cell c5-1 + menuCellToAdd = newMenuList.get(0).getSubCells().get(0); + cellAdded = MenuReplaceUtilities.addCellWithCellId(menuCellToAdd.getCellId(), 0, newMenuList, actualMenuCellList); + assertTrue(cellAdded); + expectedMenuCellList.get(4).getSubCells().add(0, cloneMenuCellAndRemoveSubCells(menuCellToAdd)); + assertEquals(expectedMenuCellList, actualMenuCellList); + assertEquals(5, actualMenuCellList.size()); + assertEquals(1, actualMenuCellList.get(4).getSubCells().size()); + + // Add cell c5-1-1 + menuCellToAdd = newMenuList.get(0).getSubCells().get(0).getSubCells().get(0); + cellAdded = MenuReplaceUtilities.addCellWithCellId(menuCellToAdd.getCellId(), 0, newMenuList, actualMenuCellList); + assertTrue(cellAdded); + expectedMenuCellList.get(4).getSubCells().get(0).getSubCells().add(0, cloneMenuCellAndRemoveSubCells(menuCellToAdd)); + assertEquals(expectedMenuCellList, actualMenuCellList); + assertEquals(5, actualMenuCellList.size()); + assertEquals(1, actualMenuCellList.get(4).getSubCells().size()); + assertEquals(1, actualMenuCellList.get(4).getSubCells().get(0).getSubCells().size()); + + // Add cell c5-2 + menuCellToAdd = newMenuList.get(0).getSubCells().get(1); + cellAdded = MenuReplaceUtilities.addCellWithCellId(menuCellToAdd.getCellId(), 1, newMenuList, actualMenuCellList); + assertTrue(cellAdded); + expectedMenuCellList.get(4).getSubCells().add(1, cloneMenuCellAndRemoveSubCells(menuCellToAdd)); + assertEquals(expectedMenuCellList, actualMenuCellList); + assertEquals(5, actualMenuCellList.size()); + assertEquals(2, actualMenuCellList.get(4).getSubCells().size()); + assertEquals(1, actualMenuCellList.get(4).getSubCells().get(0).getSubCells().size()); + assertEquals(0, actualMenuCellList.get(4).getSubCells().get(1).getSubCells().size()); + + // Add cell c5-2-1 + menuCellToAdd = newMenuList.get(0).getSubCells().get(1).getSubCells().get(0); + cellAdded = MenuReplaceUtilities.addCellWithCellId(menuCellToAdd.getCellId(), 0, newMenuList, actualMenuCellList); + assertTrue(cellAdded); + expectedMenuCellList.get(4).getSubCells().get(1).getSubCells().add(0, cloneMenuCellAndRemoveSubCells(menuCellToAdd)); + assertEquals(expectedMenuCellList, actualMenuCellList); + assertEquals(5, actualMenuCellList.size()); + assertEquals(2, actualMenuCellList.get(4).getSubCells().size()); + assertEquals(1, actualMenuCellList.get(4).getSubCells().get(0).getSubCells().size()); + assertEquals(1, actualMenuCellList.get(4).getSubCells().get(1).getSubCells().size()); + } + + @Test + public void testShouldCellIncludeImage() { + MenuCell menuCell; + WindowCapability windowCapability; + FileManager fileManager; + List<String> voiceCommands = null; + + // Case 1 + menuCell = new MenuCell(TestValues.GENERAL_STRING, TestValues.GENERAL_ARTWORK, voiceCommands, null); + windowCapability = createWindowCapability(true, true); + fileManager = createMockFileManager(true); + assertTrue(MenuReplaceUtilities.shouldCellIncludePrimaryImageFromCell(menuCell, fileManager, windowCapability)); + + // Case 2 - Image are not supported + menuCell = new MenuCell(TestValues.GENERAL_STRING, TestValues.GENERAL_ARTWORK, voiceCommands, null); + windowCapability = createWindowCapability(false, false); + fileManager = createMockFileManager(true); + assertFalse(MenuReplaceUtilities.shouldCellIncludePrimaryImageFromCell(menuCell, fileManager, windowCapability)); + + // Case 3 - Artwork is null + menuCell = new MenuCell(TestValues.GENERAL_STRING, null, voiceCommands, null); + windowCapability = createWindowCapability(true, true); + fileManager = createMockFileManager(true); + assertFalse(MenuReplaceUtilities.shouldCellIncludePrimaryImageFromCell(menuCell, fileManager, windowCapability)); + + // Case 4 - Artwork has not been uploaded + menuCell = new MenuCell(TestValues.GENERAL_STRING, TestValues.GENERAL_ARTWORK, voiceCommands, null); + windowCapability = createWindowCapability(true, true); + fileManager = createMockFileManager(false); + assertFalse(MenuReplaceUtilities.shouldCellIncludePrimaryImageFromCell(menuCell, fileManager, windowCapability)); + + // Case 5 - Artwork is static icon + menuCell = new MenuCell(TestValues.GENERAL_STRING, TestValues.GENERAL_ARTWORK_STATIC, voiceCommands, null); + windowCapability = createWindowCapability(true, true); + fileManager = createMockFileManager(false); + assertTrue(MenuReplaceUtilities.shouldCellIncludePrimaryImageFromCell(menuCell, fileManager, windowCapability)); + } + + private WindowCapability createWindowCapability (boolean supportsCmdIcon, boolean supportsSubMenuIcon) { + WindowCapability windowCapability = new WindowCapability(); + windowCapability.setImageFields(new ArrayList<ImageField>()); + if (supportsCmdIcon) { + windowCapability.getImageFields().add(new ImageField(ImageFieldName.cmdIcon, null)); + } + if (supportsSubMenuIcon) { + windowCapability.getImageFields().add(new ImageField(ImageFieldName.subMenuIcon, null)); + } + return windowCapability; + } + + private FileManager createMockFileManager (boolean hasUploadedFile) { + FileManager fileManager = mock(FileManager.class); + when(fileManager.hasUploadedFile(any(SdlArtwork.class))).thenReturn(hasUploadedFile); + return fileManager; + } + + private MenuCell cloneMenuCellAndRemoveSubCells(MenuCell menuCell) { + MenuCell clonedCell = menuCell.clone(); + if (clonedCell.getSubCells() != null) { + clonedCell.getSubCells().clear(); + } + return clonedCell; + } + + private List<MenuCell> createMenuCellList() { + /* + + c1 c2 c3 c4 + / \ / \ + / \ / \ + c2-1 c2-2 c4-1 c4-2 + / \ + / \ + c2-2-1 c2-2-2 + + */ + + SdlArtwork sdlArtwork = null; + List<String> voiceCommands = null; + MenuSelectionListener listener = null; + MenuLayout subMenuLayout = null; + + MenuCell menuCell1 = new MenuCell("c1", sdlArtwork, voiceCommands, listener); + + MenuCell menuCell2_1 = new MenuCell("c2_1", sdlArtwork, voiceCommands, listener); + MenuCell menuCell2_2_1 = new MenuCell("c2_2_1", sdlArtwork, voiceCommands, listener); + MenuCell menuCell2_2_2 = new MenuCell("c2_2_2", sdlArtwork, voiceCommands, listener); + MenuCell menuCell2_2 = new MenuCell("c2_2", subMenuLayout, sdlArtwork, new ArrayList<>(Arrays.asList(menuCell2_2_1, menuCell2_2_2))); + MenuCell menuCell2 = new MenuCell("c2", subMenuLayout, sdlArtwork, new ArrayList<>(Arrays.asList(menuCell2_1, menuCell2_2))); + + MenuCell menuCell3 = new MenuCell("c3", sdlArtwork, voiceCommands, listener); + + MenuCell menuCell4_1 = new MenuCell("c4_1", sdlArtwork, voiceCommands, listener); + MenuCell menuCell4_2 = new MenuCell("c4_2", sdlArtwork, voiceCommands, listener); + MenuCell menuCell4 = new MenuCell("c4", subMenuLayout, sdlArtwork, new ArrayList<>(Arrays.asList(menuCell4_1, menuCell4_2))); + + List<MenuCell> menuCellList = new ArrayList<>(Arrays.asList(menuCell1, menuCell2, menuCell3, menuCell4)); + addIdsToMenuCells(menuCellList, parentIdNotFound); + + return menuCellList ; + } + + private List<MenuCell> createNewMenuList() { + /* + + c5 + / \ + / \ + c5-1 c5-2 + / / + / / + c5-1-1 c5-2-1 + + */ + + SdlArtwork sdlArtwork = null; + List<String> voiceCommands = null; + MenuSelectionListener listener = null; + MenuLayout subMenuLayout = null; + + MenuCell menuCell5_1_1 = new MenuCell("c5_1_1", sdlArtwork, voiceCommands, listener); + MenuCell menuCell5_1 = new MenuCell("c5_1", subMenuLayout, sdlArtwork, new ArrayList<>(Arrays.asList(menuCell5_1_1))); + MenuCell menuCell5_2_1 = new MenuCell("c5_2_1", sdlArtwork, voiceCommands, listener); + MenuCell menuCell5_2 = new MenuCell("c5_2", subMenuLayout, sdlArtwork, new ArrayList<>(Arrays.asList(menuCell5_2_1))); + MenuCell menuCell5 = new MenuCell("c5", subMenuLayout, sdlArtwork, new ArrayList<>(Arrays.asList(menuCell5_1, menuCell5_2))); + + List<MenuCell> newMenuList = new ArrayList<>(Arrays.asList(menuCell5)); + addIdsToMenuCells(newMenuList, parentIdNotFound); + + return newMenuList ; + } +} diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuShowOperationTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuShowOperationTests.java new file mode 100644 index 000000000..ee90cee49 --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuShowOperationTests.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2021 Livio, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Livio Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package com.smartdevicelink.managers.screen.menu; + +import android.os.Handler; + +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.livio.taskmaster.Queue; +import com.livio.taskmaster.Taskmaster; +import com.smartdevicelink.managers.ISdl; +import com.smartdevicelink.proxy.RPCRequest; +import com.smartdevicelink.proxy.RPCResponse; +import com.smartdevicelink.proxy.rpc.ShowAppMenu; +import com.smartdevicelink.proxy.rpc.enums.MenuLayout; +import com.smartdevicelink.test.TestValues; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.util.Random; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +@RunWith(AndroidJUnit4.class) +public class MenuShowOperationTests { + private Handler mainHandler; + private Taskmaster taskmaster; + private Queue transactionQueue; + + @Before + public void setUp() throws Exception { + mainHandler = new Handler(getInstrumentation().getTargetContext().getMainLooper()); + taskmaster = new Taskmaster.Builder().build(); + taskmaster.start(); + transactionQueue = taskmaster.createQueue("MenuManager", new Random().nextInt(), false); + } + + @Test + public void testOpenMainMenu() { + final ISdl internalInterface = mock(ISdl.class); + MenuCell menuCell = null; + Integer menuIdToAssert = menuCell != null ? menuCell.getCellId() : null; + Answer<Void> showAppMenuAnswer = createShowAppMenuAnswer(true, menuIdToAssert); + doAnswer(showAppMenuAnswer).when(internalInterface).sendRPC(any(ShowAppMenu.class)); + MenuShowOperation operation = new MenuShowOperation(internalInterface, menuCell); + transactionQueue.add(operation, false); + + // Sleep to give time to Taskmaster to run the operations + sleep(); + + verify(internalInterface, Mockito.times(1)).sendRPC(any(ShowAppMenu.class)); + } + + @Test + public void testOpenSubMenu() { + final ISdl internalInterface = mock(ISdl.class); + MenuCell menuCell = new MenuCell(TestValues.GENERAL_STRING, MenuLayout.TILES, null, null); + menuCell.setCellId(TestValues.GENERAL_INT); + Integer menuIdToAssert = menuCell != null ? menuCell.getCellId() : null; + Answer<Void> showAppMenuAnswer = createShowAppMenuAnswer(true, menuIdToAssert); + doAnswer(showAppMenuAnswer).when(internalInterface).sendRPC(any(ShowAppMenu.class)); + MenuShowOperation operation = new MenuShowOperation(internalInterface, menuCell); + transactionQueue.add(operation, false); + + // Sleep to give time to Taskmaster to run the operations + sleep(); + + verify(internalInterface, Mockito.times(1)).sendRPC(any(ShowAppMenu.class)); + } + + private Answer<Void> createShowAppMenuAnswer(final boolean success, final Integer menuIdToAssert){ + return new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + final RPCRequest request = (RPCRequest) args[0]; + assertOnMainThread(new Runnable() { + @Override + public void run() { + ShowAppMenu showAppMenu = (ShowAppMenu) request; + assertEquals(showAppMenu.getMenuID(), menuIdToAssert); + } + }); + RPCResponse response = new RPCResponse(request.getFunctionID().toString()); + response.setSuccess(success); + request.getOnRPCResponseListener().onResponse(request.getCorrelationID(), response); + return null; + } + }; + } + + private void sleep() { + try { + Thread.sleep(250); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + // Asserts on Taskmaster threads will fail silently so we need to do the assertions on main thread if the code is triggered from Taskmaster + private void assertOnMainThread(Runnable runnable) { + mainHandler.post(runnable); + } +} diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/SubCellCommandListTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/SubCellCommandListTests.java deleted file mode 100644 index 03afc5348..000000000 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/SubCellCommandListTests.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2019 Livio, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the - * distribution. - * - * Neither the name of the Livio Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package com.smartdevicelink.managers.screen.menu; - -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import com.smartdevicelink.test.TestValues; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static junit.framework.TestCase.assertEquals; - -@RunWith(AndroidJUnit4.class) -public class SubCellCommandListTests { - - @Test - public void testSettersAndGetters() { - - RunScore runScore = new RunScore(TestValues.GENERAL_INT, TestValues.GENERAL_INTEGER_LIST, TestValues.GENERAL_INTEGER_LIST); - - // set everything - SubCellCommandList subCellCommandList = new SubCellCommandList(TestValues.GENERAL_STRING, TestValues.GENERAL_INTEGER, runScore, TestValues.GENERAL_MENUCELL_LIST, TestValues.GENERAL_MENUCELL_LIST); - - // use getters and assert equality - assertEquals(subCellCommandList.getMenuTitle(), TestValues.GENERAL_STRING); - assertEquals(subCellCommandList.getParentId(), TestValues.GENERAL_INTEGER); - assertEquals(runScore, runScore); - assertEquals(subCellCommandList.getNewList(), TestValues.GENERAL_MENUCELL_LIST); - assertEquals(subCellCommandList.getOldList(), TestValues.GENERAL_MENUCELL_LIST); - - } -} diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/TestValues.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/TestValues.java index 713770984..da3bb5846 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/TestValues.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/TestValues.java @@ -18,106 +18,7 @@ import com.smartdevicelink.protocol.SdlProtocol; import com.smartdevicelink.protocol.enums.FunctionID; import com.smartdevicelink.proxy.rpc.AppCapability; import com.smartdevicelink.proxy.rpc.*; -import com.smartdevicelink.proxy.rpc.enums.AmbientLightStatus; -import com.smartdevicelink.proxy.rpc.enums.AppCapabilityType; -import com.smartdevicelink.proxy.rpc.enums.AppHMIType; -import com.smartdevicelink.proxy.rpc.enums.AppInterfaceUnregisteredReason; -import com.smartdevicelink.proxy.rpc.enums.AppServiceType; -import com.smartdevicelink.proxy.rpc.enums.AudioStreamingIndicator; -import com.smartdevicelink.proxy.rpc.enums.AudioStreamingState; -import com.smartdevicelink.proxy.rpc.enums.AudioType; -import com.smartdevicelink.proxy.rpc.enums.BitsPerSample; -import com.smartdevicelink.proxy.rpc.enums.ButtonEventMode; -import com.smartdevicelink.proxy.rpc.enums.ButtonName; -import com.smartdevicelink.proxy.rpc.enums.ButtonPressMode; -import com.smartdevicelink.proxy.rpc.enums.CapacityUnit; -import com.smartdevicelink.proxy.rpc.enums.CarModeStatus; -import com.smartdevicelink.proxy.rpc.enums.CharacterSet; -import com.smartdevicelink.proxy.rpc.enums.CompassDirection; -import com.smartdevicelink.proxy.rpc.enums.ComponentVolumeStatus; -import com.smartdevicelink.proxy.rpc.enums.DefrostZone; -import com.smartdevicelink.proxy.rpc.enums.DeviceLevelStatus; -import com.smartdevicelink.proxy.rpc.enums.Dimension; -import com.smartdevicelink.proxy.rpc.enums.Direction; -import com.smartdevicelink.proxy.rpc.enums.DisplayMode; -import com.smartdevicelink.proxy.rpc.enums.DisplayType; -import com.smartdevicelink.proxy.rpc.enums.DistanceUnit; -import com.smartdevicelink.proxy.rpc.enums.DoorStatusType; -import com.smartdevicelink.proxy.rpc.enums.DriverDistractionState; -import com.smartdevicelink.proxy.rpc.enums.ECallConfirmationStatus; -import com.smartdevicelink.proxy.rpc.enums.EmergencyEventType; -import com.smartdevicelink.proxy.rpc.enums.FileType; -import com.smartdevicelink.proxy.rpc.enums.FuelCutoffStatus; -import com.smartdevicelink.proxy.rpc.enums.FuelType; -import com.smartdevicelink.proxy.rpc.enums.GlobalProperty; -import com.smartdevicelink.proxy.rpc.enums.HMILevel; -import com.smartdevicelink.proxy.rpc.enums.HmiZoneCapabilities; -import com.smartdevicelink.proxy.rpc.enums.HybridAppPreference; -import com.smartdevicelink.proxy.rpc.enums.IgnitionStableStatus; -import com.smartdevicelink.proxy.rpc.enums.IgnitionStatus; -import com.smartdevicelink.proxy.rpc.enums.ImageFieldName; -import com.smartdevicelink.proxy.rpc.enums.ImageType; -import com.smartdevicelink.proxy.rpc.enums.InteractionMode; -import com.smartdevicelink.proxy.rpc.enums.KeyboardEvent; -import com.smartdevicelink.proxy.rpc.enums.KeyboardInputMask; -import com.smartdevicelink.proxy.rpc.enums.KeyboardLayout; -import com.smartdevicelink.proxy.rpc.enums.KeypressMode; -import com.smartdevicelink.proxy.rpc.enums.Language; -import com.smartdevicelink.proxy.rpc.enums.LayoutMode; -import com.smartdevicelink.proxy.rpc.enums.LightName; -import com.smartdevicelink.proxy.rpc.enums.LightStatus; -import com.smartdevicelink.proxy.rpc.enums.LockScreenStatus; -import com.smartdevicelink.proxy.rpc.enums.MassageCushion; -import com.smartdevicelink.proxy.rpc.enums.MassageMode; -import com.smartdevicelink.proxy.rpc.enums.MassageZone; -import com.smartdevicelink.proxy.rpc.enums.MediaClockFormat; -import com.smartdevicelink.proxy.rpc.enums.MediaType; -import com.smartdevicelink.proxy.rpc.enums.MenuLayout; -import com.smartdevicelink.proxy.rpc.enums.MetadataType; -import com.smartdevicelink.proxy.rpc.enums.ModuleType; -import com.smartdevicelink.proxy.rpc.enums.NavigationAction; -import com.smartdevicelink.proxy.rpc.enums.NavigationJunction; -import com.smartdevicelink.proxy.rpc.enums.PRNDL; -import com.smartdevicelink.proxy.rpc.enums.PowerModeQualificationStatus; -import com.smartdevicelink.proxy.rpc.enums.PowerModeStatus; -import com.smartdevicelink.proxy.rpc.enums.PrerecordedSpeech; -import com.smartdevicelink.proxy.rpc.enums.PrimaryAudioSource; -import com.smartdevicelink.proxy.rpc.enums.RadioBand; -import com.smartdevicelink.proxy.rpc.enums.RadioState; -import com.smartdevicelink.proxy.rpc.enums.RequestType; -import com.smartdevicelink.proxy.rpc.enums.Result; -import com.smartdevicelink.proxy.rpc.enums.SamplingRate; -import com.smartdevicelink.proxy.rpc.enums.SeatMemoryActionType; -import com.smartdevicelink.proxy.rpc.enums.SeekIndicatorType; -import com.smartdevicelink.proxy.rpc.enums.ServiceUpdateReason; -import com.smartdevicelink.proxy.rpc.enums.SoftButtonType; -import com.smartdevicelink.proxy.rpc.enums.SpeechCapabilities; -import com.smartdevicelink.proxy.rpc.enums.SupportedSeat; -import com.smartdevicelink.proxy.rpc.enums.SystemAction; -import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType; -import com.smartdevicelink.proxy.rpc.enums.SystemContext; -import com.smartdevicelink.proxy.rpc.enums.TBTState; -import com.smartdevicelink.proxy.rpc.enums.TPMS; -import com.smartdevicelink.proxy.rpc.enums.TemperatureUnit; -import com.smartdevicelink.proxy.rpc.enums.TextAlignment; -import com.smartdevicelink.proxy.rpc.enums.TextFieldName; -import com.smartdevicelink.proxy.rpc.enums.TouchType; -import com.smartdevicelink.proxy.rpc.enums.TransmissionType; -import com.smartdevicelink.proxy.rpc.enums.TriggerSource; -import com.smartdevicelink.proxy.rpc.enums.UpdateMode; -import com.smartdevicelink.proxy.rpc.enums.VehicleDataEventStatus; -import com.smartdevicelink.proxy.rpc.enums.VehicleDataNotificationStatus; -import com.smartdevicelink.proxy.rpc.enums.VehicleDataResultCode; -import com.smartdevicelink.proxy.rpc.enums.VehicleDataStatus; -import com.smartdevicelink.proxy.rpc.enums.VehicleDataType; -import com.smartdevicelink.proxy.rpc.enums.VentilationMode; -import com.smartdevicelink.proxy.rpc.enums.VideoStreamingCodec; -import com.smartdevicelink.proxy.rpc.enums.VideoStreamingProtocol; -import com.smartdevicelink.proxy.rpc.enums.VideoStreamingState; -import com.smartdevicelink.proxy.rpc.enums.VrCapabilities; -import com.smartdevicelink.proxy.rpc.enums.WarningLightStatus; -import com.smartdevicelink.proxy.rpc.enums.WayPointType; -import com.smartdevicelink.proxy.rpc.enums.WindowType; +import com.smartdevicelink.proxy.rpc.enums.*; import com.smartdevicelink.util.Version; import org.json.JSONArray; @@ -365,6 +266,7 @@ public class TestValues { public static final DisplayCapability GENERAL_DISPLAY_CAPABILITY = new DisplayCapability(); public static final SdlArtwork GENERAL_ARTWORK = new SdlArtwork("sdl", FileType.GRAPHIC_PNG, R.drawable.ic_sdl, false); + public static final SdlArtwork GENERAL_ARTWORK_STATIC = new SdlArtwork(StaticIconName.BACK); public static final MenuLayout GENERAL_MENU_LAYOUT = MenuLayout.LIST; public static final MenuConfiguration GENERAL_MENU_CONFIGURATION = new MenuConfiguration(GENERAL_MENU_LAYOUT, GENERAL_MENU_LAYOUT); diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/Validator.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/Validator.java index e8d89c818..094b29794 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/Validator.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/Validator.java @@ -3,6 +3,9 @@ package com.smartdevicelink.test; import com.smartdevicelink.managers.file.filetypes.SdlFile; import com.smartdevicelink.protocol.enums.FrameDataControlFrameType; import com.smartdevicelink.protocol.enums.FrameType; +import com.smartdevicelink.protocol.enums.SecurityQueryErrorCode; +import com.smartdevicelink.protocol.enums.SecurityQueryID; +import com.smartdevicelink.protocol.enums.SecurityQueryType; import com.smartdevicelink.protocol.enums.SessionType; import com.smartdevicelink.proxy.rpc.*; import com.smartdevicelink.proxy.rpc.enums.AppServiceType; @@ -10,7 +13,6 @@ import com.smartdevicelink.proxy.rpc.enums.DefrostZone; import com.smartdevicelink.proxy.rpc.enums.FileType; import com.smartdevicelink.proxy.rpc.enums.HMILevel; import com.smartdevicelink.proxy.rpc.enums.HmiZoneCapabilities; -import com.smartdevicelink.proxy.rpc.enums.KeyboardLayout; import com.smartdevicelink.proxy.rpc.enums.PRNDL; import com.smartdevicelink.proxy.rpc.enums.PrerecordedSpeech; import com.smartdevicelink.proxy.rpc.enums.SpeechCapabilities; @@ -126,6 +128,75 @@ public class Validator { return true; } + public static boolean validateQueryTypeArray(SecurityQueryType[] array1, SecurityQueryType[] array2) { + + if (array1 == null) { + return (array2 == null); + } + + if (array2 == null) { + return (array1 == null); + } + + if (array1.length != array2.length) { + return false; + } + + for (int i = 0; i < array1.length; i++) { + if (array1[i] != array2[i]) { + return false; + } + } + + return true; + } + + public static boolean validateQueryIDArray(SecurityQueryID[] array1, SecurityQueryID[] array2) { + + if (array1 == null) { + return (array2 == null); + } + + if (array2 == null) { + return (array1 == null); + } + + if (array1.length != array2.length) { + return false; + } + + for (int i = 0; i < array1.length; i++) { + if (array1[i] != array2[i]) { + return false; + } + } + + return true; + } + + public static boolean validateQueryErrorCodeArray(SecurityQueryErrorCode[] array1, SecurityQueryErrorCode[] array2) { + + if (array1 == null) { + return (array2 == null); + } + + if (array2 == null) { + return (array1 == null); + } + + if (array1.length != array2.length) { + return false; + } + + for (int i = 0; i < array1.length; i++) { + if (array1[i] != array2[i]) { + return false; + } + } + + return true; + } + public static boolean validateFrameDataControlFrameTypeArray(FrameDataControlFrameType[] array1, FrameDataControlFrameType[] array2) { if (array1 == null) { diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/SecurityQueryPayloadTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/SecurityQueryPayloadTests.java new file mode 100644 index 000000000..8c0c36041 --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/SecurityQueryPayloadTests.java @@ -0,0 +1,126 @@ +package com.smartdevicelink.test.protocol; + +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.smartdevicelink.protocol.SecurityQueryPayload; +import com.smartdevicelink.protocol.enums.SecurityQueryID; +import com.smartdevicelink.protocol.enums.SecurityQueryType; +import com.smartdevicelink.util.BitConverter; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +@RunWith(AndroidJUnit4.class) +public class SecurityQueryPayloadTests { + + public static SecurityQueryPayload createDummyBqh() { + SecurityQueryPayload bqh = new SecurityQueryPayload(); + bqh.setCorrelationID(123); + bqh.setQueryID(SecurityQueryID.SEND_HANDSHAKE_DATA); + bqh.setQueryType(SecurityQueryType.REQUEST); + bqh.setBulkData(null); + bqh.setJsonSize(0); + return bqh; + } + + public SecurityQueryPayload safeParse(byte[] array) { + try { + return SecurityQueryPayload.parseBinaryQueryHeader(array); + } catch (Exception e) { + return null; + } + } + + @Test + public void testCorrectParsing() { + byte[] array = new byte[12]; + array[0] = 0; + array[1] = 0; + array[2] = 0; + array[3] = 2; + array[4] = 0; + array[5] = 0; + array[6] = 0; + array[7] = 3; + array[8] = 0; + array[9] = 0; + array[10] = 0; + array[11] = 0; + + SecurityQueryPayload parsedBqh = SecurityQueryPayload.parseBinaryQueryHeader(array); + assertEquals(parsedBqh.getQueryType(), SecurityQueryType.REQUEST); + assertEquals(parsedBqh.getQueryID(), SecurityQueryID.SEND_INTERNAL_ERROR); + assertEquals(parsedBqh.getCorrelationID(), 3); + assertEquals(parsedBqh.getJsonSize(), 0); + } + + @Test + public void testCorrectHeaderAssembly() { + SecurityQueryPayload dummyBqh = new SecurityQueryPayload(); + dummyBqh.setQueryType(SecurityQueryType.REQUEST); + dummyBqh.setQueryID(SecurityQueryID.SEND_HANDSHAKE_DATA); + dummyBqh.setCorrelationID(3); + dummyBqh.setJsonSize(0); + + byte[] assembledHeader = dummyBqh.assembleHeaderBytes(); + assertEquals(dummyBqh.getQueryType(), SecurityQueryType.valueOf(assembledHeader[0])); + byte[] queryIDFromHeader = new byte[3]; + System.arraycopy(assembledHeader, 1, queryIDFromHeader, 0, 3); + assertEquals(dummyBqh.getQueryID(), SecurityQueryID.valueOf(queryIDFromHeader)); + assertEquals(dummyBqh.getCorrelationID(), BitConverter.intFromByteArray(assembledHeader, 4)); + assertEquals(dummyBqh.getJsonSize(), BitConverter.intFromByteArray(assembledHeader, 8)); + } + + @Test + public void testAssemblyAndParse() { + SecurityQueryPayload bqh = createDummyBqh(); + + byte[] bqhBytes = bqh.assembleHeaderBytes(); + assertNotNull(bqhBytes); + + SecurityQueryPayload parsedBqh = SecurityQueryPayload.parseBinaryQueryHeader(bqhBytes); + assertNotNull(parsedBqh); + + assertEquals(bqh.getCorrelationID(), parsedBqh.getCorrelationID()); + assertEquals(bqh.getQueryID(), parsedBqh.getQueryID()); + assertEquals(bqh.getQueryType(), parsedBqh.getQueryType()); + assertEquals(bqh.getBulkData(), parsedBqh.getBulkData()); + assertEquals(bqh.getJsonData(), parsedBqh.getJsonData()); + assertEquals(bqh.getJsonSize(), parsedBqh.getJsonSize()); + } + + @Test + public void testCorruptHeader() { + SecurityQueryPayload bqh = createDummyBqh(); + + byte[] bqhBytes = bqh.assembleHeaderBytes(); + + assertNotNull(safeParse(bqhBytes)); + + int size = bqhBytes.length; + for (int i = 0; i < size; i++) { + bqhBytes[i] = (byte) 0x99; + } + + assertNull(safeParse(bqhBytes)); + SecurityQueryPayload head = SecurityQueryPayload.parseBinaryQueryHeader(bqhBytes); + assertNull(head); + } + + @Test + public void testJsonSetException() { + try { + SecurityQueryPayload bqh = createDummyBqh(); + bqh.setJsonData(null); + fail("Setting JSON data to null should have thrown an exception"); + } catch (Exception e) { + //Pass + } + } +} diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryErrorCodeTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryErrorCodeTests.java new file mode 100644 index 000000000..0b6cd3f61 --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryErrorCodeTests.java @@ -0,0 +1,189 @@ +package com.smartdevicelink.test.protocol.enums; + +import com.smartdevicelink.protocol.enums.SecurityQueryErrorCode; +import com.smartdevicelink.test.Validator; + +import junit.framework.TestCase; + +import java.util.Vector; + +public class SecurityQueryErrorCodeTests extends TestCase { + + private Vector<SecurityQueryErrorCode> list = SecurityQueryErrorCode.getList(); + + public void testValidEnums() { + final byte ERROR_SUCCESS_BYTE = (byte) 0x00; + final String ERROR_SUCCESS_STRING = "ERROR_SUCCESS"; + + final byte ERROR_INVALID_QUERY_SIZE_BYTE = (byte) 0x01; + final String ERROR_INVALID_QUERY_SIZE_STRING = "ERROR_INVALID_QUERY_SIZE"; + + final byte ERROR_INVALID_QUERY_ID_BYTE = (byte) 0x02; + final String ERROR_INVALID_QUERY_ID_STRING = "ERROR_INVALID_QUERY_ID"; + + final byte ERROR_NOT_SUPPORTED_BYTE = (byte) 0x03; + final String ERROR_NOT_SUPPORTED_STRING = "ERROR_NOT_SUPPORTED"; + + final byte ERROR_SERVICE_ALREADY_PROTECTED_BYTE = (byte) 0x04; + final String ERROR_SERVICE_ALREADY_PROTECTED_STRING = "ERROR_SERVICE_ALREADY_PROTECTED"; + + final byte ERROR_SERVICE_NOT_PROTECTED_BYTE = (byte) 0x05; + final String ERROR_SERVICE_NOT_PROTECTED_STRING = "ERROR_SERVICE_NOT_PROTECTED"; + + final byte ERROR_DECRYPTION_FAILED_BYTE = (byte) 0x06; + final String ERROR_DECRYPTION_FAILED_STRING = "ERROR_DECRYPTION_FAILED"; + + final byte ERROR_ENCRYPTION_FAILED_BYTE = (byte) 0x07; + final String ERROR_ENCRYPTION_FAILED_STRING = "ERROR_ENCRYPTION_FAILED"; + + final byte ERROR_SSL_INVALID_DATA_BYTE = (byte) 0x08; + final String ERROR_SSL_INVALID_DATA_STRING = "ERROR_SSL_INVALID_DATA"; + + final byte ERROR_HANDSHAKE_FAILED_BYTE = (byte) 0x09; + final String ERROR_HANDSHAKE_FAILED_STRING = "ERROR_HANDSHAKE_FAILED"; + + final byte INVALID_CERT_BYTE = (byte) 0x0A; + final String INVALID_CERT_STRING = "INVALID_CERT"; + + final byte EXPIRED_CERT_BYTE = (byte) 0x0B; + final String EXPIRED_CERT_STRING = "EXPIRED_CERT"; + + final byte ERROR_INTERNAL_BYTE = (byte) 0xFF; + final String ERROR_INTERNAL_STRING = "ERROR_INTERNAL"; + + final byte ERROR_UNKNOWN_INTERNAL_ERROR_BYTE = (byte) 0xFE; + final String ERROR_UNKNOWN_INTERNAL_ERROR_STRING = "ERROR_UNKNOWN_INTERNAL_ERROR"; + + try { + assertNotNull("QueryErrorCode list returned null", list); + + SecurityQueryErrorCode enumSuccess = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_SUCCESS_BYTE); + SecurityQueryErrorCode enumInvalidQuerySize = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_INVALID_QUERY_SIZE_BYTE); + SecurityQueryErrorCode enumInvalidQueryID = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_INVALID_QUERY_ID_BYTE); + SecurityQueryErrorCode enumNotSupported = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_NOT_SUPPORTED_BYTE); + SecurityQueryErrorCode enumServiceAlreadyProtected = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_SERVICE_ALREADY_PROTECTED_BYTE); + SecurityQueryErrorCode enumServiceNotProtected = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_SERVICE_NOT_PROTECTED_BYTE); + SecurityQueryErrorCode enumDecryptionFailed = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_DECRYPTION_FAILED_BYTE); + SecurityQueryErrorCode enumEncryptionFailed = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_ENCRYPTION_FAILED_BYTE); + SecurityQueryErrorCode enumSSLInvalidData = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_SSL_INVALID_DATA_BYTE); + SecurityQueryErrorCode enumHandshakeFailed = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_HANDSHAKE_FAILED_BYTE); + SecurityQueryErrorCode enumInvalidCert = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, INVALID_CERT_BYTE); + SecurityQueryErrorCode enumExpiredCert = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, EXPIRED_CERT_BYTE); + SecurityQueryErrorCode enumInternal = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_INTERNAL_BYTE); + SecurityQueryErrorCode enumUnknownInternalError = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_UNKNOWN_INTERNAL_ERROR_BYTE); + + assertNotNull("Success byte match returned null", enumSuccess); + assertNotNull("Invalid Query Size byte match returned null", enumInvalidQuerySize); + assertNotNull("Invalid Query ID byte match returned null", enumInvalidQueryID); + assertNotNull("Not Supported byte match returned null", enumNotSupported); + assertNotNull("Service Already Protected byte match returned null", enumServiceAlreadyProtected); + assertNotNull("Service Not Protected byte match returned null", enumServiceNotProtected); + assertNotNull("Decryption Failed byte match returned null", enumDecryptionFailed); + assertNotNull("Encryption Failed byte match returned null", enumEncryptionFailed); + assertNotNull("SSL Invalid Data byte match returned null", enumSSLInvalidData); + assertNotNull("Handshake Failed byte match returned null", enumHandshakeFailed); + assertNotNull("Invalid Cert byte match returned null", enumInvalidCert); + assertNotNull("Expired Cert byte match returned null", enumExpiredCert); + assertNotNull("Internal byte match returned null", enumInternal); + assertNotNull("Unknown Internal byte match returned null", enumUnknownInternalError); + + enumSuccess = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_SUCCESS_STRING); + enumInvalidQuerySize = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_INVALID_QUERY_SIZE_STRING); + enumInvalidQueryID = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_INVALID_QUERY_ID_STRING); + enumNotSupported = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_NOT_SUPPORTED_STRING); + enumServiceAlreadyProtected = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_SERVICE_ALREADY_PROTECTED_STRING); + enumServiceNotProtected = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_SERVICE_NOT_PROTECTED_STRING); + enumDecryptionFailed = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_DECRYPTION_FAILED_STRING); + enumEncryptionFailed = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_ENCRYPTION_FAILED_STRING); + enumSSLInvalidData = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_SSL_INVALID_DATA_STRING); + enumHandshakeFailed = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_HANDSHAKE_FAILED_STRING); + enumInvalidCert = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, INVALID_CERT_STRING); + enumExpiredCert = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, EXPIRED_CERT_STRING); + enumInternal = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_INTERNAL_STRING); + enumUnknownInternalError = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, ERROR_UNKNOWN_INTERNAL_ERROR_STRING); + + assertNotNull("Success string match returned null", enumSuccess); + assertNotNull("Invalid Query Size string match returned null", enumInvalidQuerySize); + assertNotNull("Invalid Query ID string match returned null", enumInvalidQueryID); + assertNotNull("Not Supported string match returned null", enumNotSupported); + assertNotNull("Service Already Protected string match returned null", enumServiceAlreadyProtected); + assertNotNull("Service Not Protected string match returned null", enumServiceNotProtected); + assertNotNull("Decryption Failed string match returned null", enumDecryptionFailed); + assertNotNull("Encryption Failed string match returned null", enumEncryptionFailed); + assertNotNull("SSL Invalid Data string match returned null", enumSSLInvalidData); + assertNotNull("Handshake Failed string match returned null", enumHandshakeFailed); + assertNotNull("Invalid Cert string match returned null", enumInvalidCert); + assertNotNull("Expired Cert string match returned null", enumExpiredCert); + assertNotNull("Internal string match returned null", enumInternal); + assertNotNull("Unknown Internal string match returned null", enumUnknownInternalError); + } catch (NullPointerException exception) { + fail("Null enum list throws NullPointerException."); + } + } + + public void testInvalidEnum() { + final byte INVALID_BYTE = (byte) 0xAB; + final String INVALID_STRING = "Invalid"; + + try { + SecurityQueryErrorCode enumInvalid = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, INVALID_BYTE); + assertNull("Invalid byte match didn't return null", enumInvalid); + + enumInvalid = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, INVALID_STRING); + assertNull("Invalid byte match didn't return null", enumInvalid); + } catch (IllegalArgumentException exception) { + fail("Invalid enum throws IllegalArgumentException."); + } + } + + public void testNullEnum() { + try { + SecurityQueryErrorCode enumNull = (SecurityQueryErrorCode) SecurityQueryErrorCode.get(list, null); + assertNull("Null lookup returns a value", enumNull); + } catch (NullPointerException exception) { + fail("Null string throws NullPointerException."); + } + } + + public void testListEnum() { + Vector<SecurityQueryErrorCode> enumTestList = new Vector<>(); + enumTestList.add(SecurityQueryErrorCode.ERROR_SUCCESS); + enumTestList.add(SecurityQueryErrorCode.ERROR_INVALID_QUERY_SIZE); + enumTestList.add(SecurityQueryErrorCode.ERROR_INVALID_QUERY_ID); + enumTestList.add(SecurityQueryErrorCode.ERROR_NOT_SUPPORTED); + enumTestList.add(SecurityQueryErrorCode.ERROR_SERVICE_ALREADY_PROTECTED); + enumTestList.add(SecurityQueryErrorCode.ERROR_SERVICE_NOT_PROTECTED); + enumTestList.add(SecurityQueryErrorCode.ERROR_DECRYPTION_FAILED); + enumTestList.add(SecurityQueryErrorCode.ERROR_ENCRYPTION_FAILED); + enumTestList.add(SecurityQueryErrorCode.ERROR_SSL_INVALID_DATA); + enumTestList.add(SecurityQueryErrorCode.ERROR_HANDSHAKE_FAILED); + enumTestList.add(SecurityQueryErrorCode.INVALID_CERT); + enumTestList.add(SecurityQueryErrorCode.EXPIRED_CERT); + enumTestList.add(SecurityQueryErrorCode.ERROR_INTERNAL); + enumTestList.add(SecurityQueryErrorCode.ERROR_UNKNOWN_INTERNAL_ERROR); + + assertTrue("List does not match enum test list.", + list.containsAll(enumTestList) && + enumTestList.containsAll(list)); + + SecurityQueryErrorCode[] enumValueArray = SecurityQueryErrorCode.values(); + SecurityQueryErrorCode[] enumTestArray = { + SecurityQueryErrorCode.ERROR_SUCCESS, + SecurityQueryErrorCode.ERROR_INVALID_QUERY_SIZE, + SecurityQueryErrorCode.ERROR_INVALID_QUERY_ID, + SecurityQueryErrorCode.ERROR_NOT_SUPPORTED, + SecurityQueryErrorCode.ERROR_SERVICE_ALREADY_PROTECTED, + SecurityQueryErrorCode.ERROR_SERVICE_NOT_PROTECTED, + SecurityQueryErrorCode.ERROR_DECRYPTION_FAILED, + SecurityQueryErrorCode.ERROR_ENCRYPTION_FAILED, + SecurityQueryErrorCode.ERROR_SSL_INVALID_DATA, + SecurityQueryErrorCode.ERROR_HANDSHAKE_FAILED, + SecurityQueryErrorCode.INVALID_CERT, + SecurityQueryErrorCode.EXPIRED_CERT, + SecurityQueryErrorCode.ERROR_INTERNAL, + SecurityQueryErrorCode.ERROR_UNKNOWN_INTERNAL_ERROR + }; + assertTrue("Array does not match enum values array.", + Validator.validateQueryErrorCodeArray(enumValueArray, enumTestArray)); + } +} diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryIDTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryIDTests.java new file mode 100644 index 000000000..4f73f8139 --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryIDTests.java @@ -0,0 +1,91 @@ +package com.smartdevicelink.test.protocol.enums; + +import com.smartdevicelink.protocol.enums.SecurityQueryID; +import com.smartdevicelink.test.Validator; + +import junit.framework.TestCase; + +import java.util.Vector; + +public class SecurityQueryIDTests extends TestCase { + + private Vector<SecurityQueryID> list = SecurityQueryID.getList(); + + public void testValidEnums() { + final byte[] SEND_HANDSHAKE_DATA_BYTES = {(byte) 0x00, (byte) 0x00, (byte) 0x01}; + final String SEND_HANDSHAKE_DATA_STRING = "SEND_HANDSHAKE_DATA"; + + final byte[] SEND_INTERNAL_ERROR_BYTES = {(byte) 0x00, (byte) 0x00, (byte) 0x02}; + final String SEND_INTERNAL_ERROR_STRING = "SEND_INTERNAL_ERROR"; + + final byte[] INVALID_QUERY_ID_BYTES = {(byte) 0xFF, (byte) 0xFF, (byte) 0xFF}; + final String INVALID_QUERY_ID_STRING = "INVALID_QUERY_ID"; + + try { + assertNotNull("QueryID list returned null", list); + + SecurityQueryID enumHandshakeData = (SecurityQueryID) SecurityQueryID.get(list, SEND_HANDSHAKE_DATA_BYTES); + SecurityQueryID enumInternalError = (SecurityQueryID) SecurityQueryID.get(list, SEND_INTERNAL_ERROR_BYTES); + SecurityQueryID enumInvalidSecurityQueryId = (SecurityQueryID) SecurityQueryID.get(list, INVALID_QUERY_ID_BYTES); + + assertNotNull("Send Handshake Data byte match returned null", enumHandshakeData); + assertNotNull("Send Internal Error byte match returned null", enumInternalError); + assertNotNull("Send Invalid QueryID byte match returned null", enumInvalidSecurityQueryId); + + enumHandshakeData = (SecurityQueryID) SecurityQueryID.get(list, SEND_HANDSHAKE_DATA_STRING); + enumInternalError = (SecurityQueryID) SecurityQueryID.get(list, SEND_INTERNAL_ERROR_STRING); + enumInvalidSecurityQueryId = (SecurityQueryID) SecurityQueryID.get(list, INVALID_QUERY_ID_STRING); + + assertNotNull("Send Handshake Data string match returned null", enumHandshakeData); + assertNotNull("Send Internal Error string match returned null", enumInternalError); + assertNotNull("Send Invalid QueryID string match returned null", enumInvalidSecurityQueryId); + } catch(NullPointerException exception) { + fail("Null enum list throws NullPointerException."); + } + } + + public void testInvalidEnum() { + + final byte[] INVALID_BYTE_ARRAY = {(byte) 0xAB, (byte) 0xAB, (byte) 0xAB}; + final String INVALID_STRING = "Invalid"; + + try { + SecurityQueryID enumInvalid = (SecurityQueryID) SecurityQueryID.get(list, INVALID_BYTE_ARRAY); + assertNull("Invalid byte[] match didn't return null", enumInvalid); + + enumInvalid = (SecurityQueryID) SecurityQueryID.get(list, INVALID_STRING); + assertNull("Invalid string match didn't return null", enumInvalid); + } catch (IllegalArgumentException exception) { + fail("Invalid enum throws IllegalArgumentException."); + } + } + + public void testNullEnum() { + try { + SecurityQueryID enumNull = (SecurityQueryID) SecurityQueryID.get(list, (String) null); + assertNull("Null lookup returns a null string value", enumNull); + + enumNull = (SecurityQueryID) SecurityQueryID.get(list, (byte[]) null); + assertNull("Null lookup returns a null byte[] value", enumNull); + }catch (NullPointerException exception) { + fail("Null string throws NullPointerException."); + } + } + + public void testListEnum() { + Vector<SecurityQueryID> enumTestList = new Vector<>(); + enumTestList.add(SecurityQueryID.SEND_HANDSHAKE_DATA); + enumTestList.add(SecurityQueryID.SEND_INTERNAL_ERROR); + enumTestList.add(SecurityQueryID.INVALID_QUERY_ID); + + assertTrue("List does not match enum test list.", + list.containsAll(enumTestList) && + enumTestList.containsAll(list)); + + SecurityQueryID[] enumValueArray = SecurityQueryID.values(); + SecurityQueryID[] enumTestArray = {SecurityQueryID.SEND_HANDSHAKE_DATA, SecurityQueryID.SEND_INTERNAL_ERROR, SecurityQueryID.INVALID_QUERY_ID}; + assertTrue("Array does not match enum values array.", + Validator.validateQueryIDArray(enumValueArray, enumTestArray)); + } + +} diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryTypeTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryTypeTests.java new file mode 100644 index 000000000..6835da946 --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryTypeTests.java @@ -0,0 +1,97 @@ +package com.smartdevicelink.test.protocol.enums; + +import com.smartdevicelink.protocol.enums.SecurityQueryType; +import com.smartdevicelink.test.Validator; + +import junit.framework.TestCase; + +import java.util.Vector; + +public class SecurityQueryTypeTests extends TestCase { + + private Vector<SecurityQueryType> list = SecurityQueryType.getList(); + + public void testValidEnums() { + final byte REQUEST_BYTE = (byte) 0x00; + final String REQUEST_STRING = "REQUEST"; + + final byte RESPONSE_BYTE = (byte) 0x10; + final String RESPONSE_STRING = "RESPONSE"; + + final byte NOTIFICATION_BYTE = (byte) 0x20; + final String NOTIFICATION_STRING = "NOTIFICATION"; + + final byte INVALID_QUERY_TYPE_BYTE = (byte) 0xFF; + final String INVALID_QUERY_TYPE_STRING = "INVALID_QUERY_TYPE"; + + try { + assertNotNull("QueryType list returned null", list); + + SecurityQueryType enumRequest = (SecurityQueryType) SecurityQueryType.get(list, REQUEST_BYTE); + SecurityQueryType enumResponse = (SecurityQueryType) SecurityQueryType.get(list, RESPONSE_BYTE); + SecurityQueryType enumNotification = (SecurityQueryType) SecurityQueryType.get(list, NOTIFICATION_BYTE); + SecurityQueryType enumInvalidSecurityQueryType = (SecurityQueryType) SecurityQueryType.get(list, INVALID_QUERY_TYPE_BYTE); + + assertNotNull("Request byte match returned null", enumRequest); + assertNotNull("Response byte match returned null", enumResponse); + assertNotNull("Notification byte match returned null", enumNotification); + assertNotNull("Invalid Query Type byte match returned null", enumInvalidSecurityQueryType); + + enumRequest = (SecurityQueryType) SecurityQueryType.get(list, REQUEST_STRING); + enumResponse = (SecurityQueryType) SecurityQueryType.get(list, RESPONSE_STRING); + enumNotification = (SecurityQueryType) SecurityQueryType.get(list, NOTIFICATION_STRING); + enumInvalidSecurityQueryType = (SecurityQueryType) SecurityQueryType.get(list, INVALID_QUERY_TYPE_STRING); + + assertNotNull("Request string match returned null", enumRequest); + assertNotNull("Response string match returned null", enumResponse); + assertNotNull("Notification string match returned null", enumNotification); + assertNotNull("Invalid Query string byte match returned null", enumInvalidSecurityQueryType); + + + }catch (NullPointerException exception) { + fail("Null enum list throws NullPointerException."); + } + } + + public void testInvalidEnum() { + + final byte INVALID_BYTE = (byte) 0xAB; + final String INVALID_STRING = "Invalid"; + + try { + SecurityQueryType enumInvalid = (SecurityQueryType) SecurityQueryType.get(list, INVALID_BYTE); + assertNull("Invalid byte match didn't return null", enumInvalid); + + enumInvalid = (SecurityQueryType) SecurityQueryType.get(list, INVALID_STRING); + assertNull("Invalid string match didn't return null", enumInvalid); + } catch (IllegalArgumentException exception) { + fail("Invalid enum throws IllegalArgumentException."); + } + } + + public void testNullEnum() { + try { + SecurityQueryType enumNull = (SecurityQueryType) SecurityQueryType.get(list, null); + assertNull("Null lookup returns a value", enumNull); + } catch (NullPointerException exception) { + fail("Null string throws NullPointerException."); + } + } + + public void testListEnum() { + Vector<SecurityQueryType> enumTestList = new Vector<>(); + enumTestList.add(SecurityQueryType.REQUEST); + enumTestList.add(SecurityQueryType.RESPONSE); + enumTestList.add(SecurityQueryType.NOTIFICATION); + enumTestList.add(SecurityQueryType.INVALID_QUERY_TYPE); + + assertTrue("List does not match enum test list.", + list.containsAll(enumTestList) && + enumTestList.containsAll(list)); + + SecurityQueryType[] enumValueArray = SecurityQueryType.values(); + SecurityQueryType[] enumTestArray = {SecurityQueryType.REQUEST, SecurityQueryType.RESPONSE, SecurityQueryType.NOTIFICATION, SecurityQueryType.INVALID_QUERY_TYPE}; + assertTrue("Array does not match enum values array.", + Validator.validateQueryTypeArray(enumValueArray, enumTestArray)); + } +} diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/file/filetypes/SdlArtwork.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/file/filetypes/SdlArtwork.java index c8887d4e1..b46745917 100644 --- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/file/filetypes/SdlArtwork.java +++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/file/filetypes/SdlArtwork.java @@ -40,7 +40,6 @@ import com.smartdevicelink.proxy.rpc.Image; import com.smartdevicelink.proxy.rpc.enums.FileType; import com.smartdevicelink.proxy.rpc.enums.ImageType; import com.smartdevicelink.proxy.rpc.enums.StaticIconName; -import com.smartdevicelink.util.DebugTool; /** * A class that extends SdlFile, representing artwork (JPEG, PNG, or BMP) to be uploaded to core @@ -159,16 +158,10 @@ public class SdlArtwork extends SdlFile implements Cloneable { */ @Override public SdlArtwork clone() { - try { - SdlArtwork artwork = (SdlArtwork) super.clone(); - if (artwork != null) { - artwork.imageRPC = artwork.createImageRPC(); - } + SdlArtwork artwork = (SdlArtwork) super.clone(); + if (artwork != null) { + artwork.imageRPC = artwork.createImageRPC(); return artwork; - } catch (CloneNotSupportedException e) { - if (DebugTool.isDebugEnabled()) { - throw new RuntimeException("Clone not supported by super class"); - } } return null; } diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/file/filetypes/SdlFile.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/file/filetypes/SdlFile.java index 13c7d3119..a0c0d9369 100644 --- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/file/filetypes/SdlFile.java +++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/file/filetypes/SdlFile.java @@ -38,6 +38,7 @@ import androidx.annotation.NonNull; import com.smartdevicelink.proxy.rpc.enums.FileType; import com.smartdevicelink.proxy.rpc.enums.StaticIconName; +import com.smartdevicelink.util.DebugTool; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -46,7 +47,7 @@ import java.util.Arrays; /** * A class representing data to be uploaded to core */ -public class SdlFile { +public class SdlFile implements Cloneable { private String fileName; private int id = -1; private Uri uri; @@ -368,4 +369,22 @@ public class SdlFile { // return comparison return hashCode() == o.hashCode(); } + + /** + * Creates a deep copy of the object + * + * @return deep copy of the object, null if an exception occurred + */ + @Override + public SdlFile clone() { + try { + SdlFile fileClone = (SdlFile) super.clone(); + return fileClone; + } catch (CloneNotSupportedException e) { + if (DebugTool.isDebugEnabled()) { + throw new RuntimeException("Clone not supported by super class"); + } + } + return null; + } } diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java b/android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java index 0aa28bb4a..0347e09ac 100644 --- a/android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java +++ b/android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java @@ -2476,7 +2476,7 @@ public class SdlRouterService extends Service { /** * Set the connection establishment status of the particular device * - * @param address address of the device in quesiton + * @param address address of the device in question * @param hasSDLConnected true if a connection has been established, false if not */ protected void setSDLConnectedStatus(String address, boolean hasSDLConnected) { @@ -3341,7 +3341,7 @@ public class SdlRouterService extends Service { try { List<TransportType> transportTypes = (List<TransportType>) obj; if (transportTypes != null) { - if (transportTypes.get(0) != null) { + if (transportTypes.size() > 0 && transportTypes.get(0) != null) { return transportTypes.get(0); } } |