/** * Copyright 2017, Digi International Inc. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, you can obtain one at http://mozilla.org/MPL/2.0/. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package com.digi.xbee.api; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsEqual.equalTo; import static org.junit.Assert.assertThat; 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 org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import com.digi.xbee.api.connection.IConnectionInterface; import com.digi.xbee.api.exceptions.InterfaceNotOpenException; import com.digi.xbee.api.exceptions.InvalidOperatingModeException; import com.digi.xbee.api.exceptions.TimeoutException; import com.digi.xbee.api.exceptions.XBeeException; import com.digi.xbee.api.models.AccessPoint; import com.digi.xbee.api.models.OperatingMode; import com.digi.xbee.api.models.WiFiEncryptionType; @PrepareForTest({WiFiDevice.class, System.class}) @RunWith(PowerMockRunner.class) public class ConnectToAccessPointTest { // Constants. private static final String METHOD_SLEEP = "sleep"; // Variables. private WiFiDevice wifiDevice; private IConnectionInterface cInterfaceMock; private long currentMillis = 0; private AccessPoint mockedAccessPoint; @Before public void setUp() throws Exception { cInterfaceMock = PowerMockito.mock(IConnectionInterface.class); wifiDevice = PowerMockito.spy(new WiFiDevice(cInterfaceMock)); mockedAccessPoint = PowerMockito.mock(AccessPoint.class); PowerMockito.doReturn("").when(mockedAccessPoint).getSSID(); PowerMockito.doReturn(WiFiEncryptionType.NONE).when(mockedAccessPoint).getEncryptionType(); PowerMockito.when(wifiDevice.isOpen()).thenReturn(true); PowerMockito.when(wifiDevice.getOperatingMode()).thenReturn(OperatingMode.API); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#disconnect()}. * * <p>Verify that the Wi-Fi module cannot disconnect from the access point * if the device is not open throwing an {@code InterfaceNotOpenException}.</p> * * @throws XBeeException */ @Test(expected=InterfaceNotOpenException.class) public final void testDisconnectDeviceNotOpen() throws XBeeException { // Setup the resources for the test. PowerMockito.doThrow(new InterfaceNotOpenException()).when(wifiDevice).executeParameter(Mockito.anyString()); // Call the method under test. wifiDevice.disconnect(); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#disconnect()}. * * <p>Verify that the Wi-Fi module cannot disconnect from the access point * if the device is in AT mode throwing an {@code InvalidOperatingModeException}.</p> * * @throws XBeeException */ @Test(expected=InvalidOperatingModeException.class) public final void testDisconnectInvalidOperatingMode() throws XBeeException { // Setup the resources for the test. PowerMockito.doThrow(new InvalidOperatingModeException()).when(wifiDevice).executeParameter(Mockito.anyString()); // Call the method under test. wifiDevice.disconnect(); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#disconnect()}. * * <p>Verify that the Wi-Fi module cannot disconnect from the access point * if there is a timeout sending the NR command throwing a {@code TimeoutException}.</p> * * @throws XBeeException */ @Test(expected=TimeoutException.class) public final void testDisconnectTimeout() throws XBeeException { // Setup the resources for the test. PowerMockito.doThrow(new TimeoutException()).when(wifiDevice).executeParameter(Mockito.anyString()); // Call the method under test. wifiDevice.disconnect(); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#disconnect()}. * * <p>Verify that the Wi-Fi module cannot disconnect from the access point * if the AI status is {@code null}.</p> * * @throws Exception */ @Test public final void testDisconnectNullAIStatus() throws Exception { // Setup the resources for the test. PowerMockito.doNothing().when(wifiDevice).executeParameter("NR"); PowerMockito.doReturn(null).when(wifiDevice).getParameter("AI"); // Get the current time. currentMillis = System.currentTimeMillis(); // Configure the number of ticks (times) the sleep method should be called. int ticks = wifiDevice.getAccessPointTimeout()/100; // Prepare the System class to return our fixed currentMillis variable when requested. PowerMockito.mockStatic(System.class); PowerMockito.when(System.currentTimeMillis()).thenReturn(currentMillis); // When the sleep method is called, add 100ms to the currentMillis variable. PowerMockito.doAnswer(new Answer<Object>() { public Object answer(InvocationOnMock invocation) throws Exception { Object[] args = invocation.getArguments(); int sleepTime = (Integer)args[0]; changeMillisToReturn(sleepTime); return null; } }).when(wifiDevice, METHOD_SLEEP, Mockito.anyInt()); // Call the method under test. boolean disconnected = wifiDevice.disconnect(); // Verify the result. assertThat("Module should not have disconnected", disconnected, is(equalTo(false))); // Verify that the sleep method was called 'ticks' times. PowerMockito.verifyPrivate(wifiDevice, Mockito.times(ticks)).invoke(METHOD_SLEEP, 100); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#disconnect()}. * * <p>Verify that the Wi-Fi module cannot disconnect from the access point * if the AI status is empty.</p> * * @throws Exception */ @Test public final void testDisconnectEmptyAIStatus() throws Exception { // Setup the resources for the test. PowerMockito.doNothing().when(wifiDevice).executeParameter("NR"); PowerMockito.doReturn(new byte[0]).when(wifiDevice).getParameter("AI"); // Get the current time. currentMillis = System.currentTimeMillis(); // Configure the number of ticks (times) the sleep method should be called. int ticks = wifiDevice.getAccessPointTimeout()/100; // Prepare the System class to return our fixed currentMillis variable when requested. PowerMockito.mockStatic(System.class); PowerMockito.when(System.currentTimeMillis()).thenReturn(currentMillis); // When the sleep method is called, add 100ms to the currentMillis variable. PowerMockito.doAnswer(new Answer<Object>() { public Object answer(InvocationOnMock invocation) throws Exception { Object[] args = invocation.getArguments(); int sleepTime = (Integer)args[0]; changeMillisToReturn(sleepTime); return null; } }).when(wifiDevice, METHOD_SLEEP, Mockito.anyInt()); // Call the method under test. boolean disconnected = wifiDevice.disconnect(); // Verify the result. assertThat("Module should not have disconnected", disconnected, is(equalTo(false))); // Verify that the sleep method was called 'ticks' times. PowerMockito.verifyPrivate(wifiDevice, Mockito.times(ticks)).invoke(METHOD_SLEEP, 100); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#disconnect()}. * * <p>Verify that the Wi-Fi module cannot disconnect if the AI status is not * 0x23.</p> * * @throws Exception */ @Test public final void testDisconnectWrongAIStatus() throws Exception { // Setup the resources for the test. // Prepare the answers to the AT commands. PowerMockito.doNothing().when(wifiDevice).executeParameter("NR"); PowerMockito.doReturn(new byte[0x13]).when(wifiDevice).getParameter("AI"); // Get the current time. currentMillis = System.currentTimeMillis(); // Configure the number of ticks (times) the sleep method should be called. int ticks = wifiDevice.getAccessPointTimeout()/100; // Prepare the System class to return our fixed currentMillis variable when requested. PowerMockito.mockStatic(System.class); PowerMockito.when(System.currentTimeMillis()).thenReturn(currentMillis); // When the sleep method is called, add 100ms to the currentMillis variable. PowerMockito.doAnswer(new Answer<Object>() { public Object answer(InvocationOnMock invocation) throws Exception { Object[] args = invocation.getArguments(); int sleepTime = (Integer)args[0]; changeMillisToReturn(sleepTime); return null; } }).when(wifiDevice, METHOD_SLEEP, Mockito.anyInt()); // Call the method under test. boolean disconnected = wifiDevice.disconnect(); // Verify the result. assertThat("Module should have not disconnected", disconnected, is(equalTo(false))); // Verify that the sleep method was called 'ticks' times. PowerMockito.verifyPrivate(wifiDevice, Mockito.times(ticks)).invoke(METHOD_SLEEP, 100); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#disconnect()}. * * <p>Verify that the Wi-Fi module can disconnect from the access point * successfully.</p> * * @throws Exception */ @Test public final void testDisconnectSuccess() throws Exception { // Setup the resources for the test. PowerMockito.doNothing().when(wifiDevice).executeParameter("NR"); PowerMockito.doReturn(new byte[]{0x23}).when(wifiDevice).getParameter("AI"); // Get the current time. currentMillis = System.currentTimeMillis(); // Configure the number of ticks (times) the sleep method should be called. int ticks = 1; // Prepare the System class to return our fixed currentMillis variable when requested. PowerMockito.mockStatic(System.class); PowerMockito.when(System.currentTimeMillis()).thenReturn(currentMillis); // When the sleep method is called, add 100ms to the currentMillis variable. PowerMockito.doAnswer(new Answer<Object>() { public Object answer(InvocationOnMock invocation) throws Exception { Object[] args = invocation.getArguments(); int sleepTime = (Integer)args[0]; changeMillisToReturn(sleepTime); return null; } }).when(wifiDevice, METHOD_SLEEP, Mockito.anyInt()); // Call the method under test. boolean disconnected = wifiDevice.disconnect(); // Verify the result. assertThat("Module should have disconnected", disconnected, is(equalTo(true))); // Verify that the sleep method was called 'ticks' times. PowerMockito.verifyPrivate(wifiDevice, Mockito.times(ticks)).invoke(METHOD_SLEEP, 100); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#connect(AccessPoint, String)}. * * <p>Verify that the Wi-Fi module cannot connect to an access point if the * access point provided is {@code null} throwing a {@code NullPointerException}.</p> * * @throws XBeeException */ @Test(expected=NullPointerException.class) public final void testConnectAccessPointAPNull() throws XBeeException { // Call the method under test. wifiDevice.connect((AccessPoint)null, ""); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#connect(String, String, int)}. * * <p>Verify that the Wi-Fi module cannot connect to an access point if the * SSID provided is {@code null} throwing a {@code NullPointerException}.</p> * * @throws XBeeException */ @Test(expected=NullPointerException.class) public final void testConnectAccessPointSSIDNull() throws XBeeException { // Call the method under test. wifiDevice.connect((String)null, ""); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#connect(String, String)}. * * <p>Verify that the Wi-Fi module cannot connect to an access point if * there is not any access point with the provided SSID throwing an * {@code XBeeException}.</p> * * @throws XBeeException */ @Test(expected=XBeeException.class) public final void testConnectAccessPointSSIDNotFound() throws XBeeException { // Setup the resources for the test. String ssid = "AP SSID"; // Return a null access point when asked for one. PowerMockito.doReturn(null).when(wifiDevice).getAccessPoint(ssid); // Call the method under test. wifiDevice.connect(ssid, ""); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#connect(String, String)}. * * <p>Verify that the Wi-Fi module can connect to to an access point successfully * providing just the SSID of the access point.</p> * * @throws XBeeException */ @Test public final void testConnectSuccessSSID() throws XBeeException { // Setup the resources for the test. String ssid = "AP SSID"; String password = "password"; // Return the mocked access point when asked for one. PowerMockito.doReturn(mockedAccessPoint).when(wifiDevice).getAccessPoint(ssid); // Return true when asked to connect to an access point. PowerMockito.doReturn(true).when(wifiDevice).connect(Mockito.eq(mockedAccessPoint), Mockito.anyString()); // Call the method under test. boolean connected = wifiDevice.connect(ssid, password); // Verify the result. assertThat("Module should have connected", connected, is(equalTo(true))); // Verify that the connect method was called one time. Mockito.verify(wifiDevice, Mockito.times(1)).connect(Mockito.eq(mockedAccessPoint), Mockito.eq(password)); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#connect(AccessPoint, String)}. * * <p>Verify that the Wi-Fi module cannot connect to an access point if * device is not open throwing an {@code InterfaceNotOpenException}.</p> * * @throws XBeeException */ @Test(expected=InterfaceNotOpenException.class) public final void testConnectDeviceNotOpen() throws XBeeException { // Setup the resources for the test. // Prepare the answers to the AT commands. PowerMockito.doThrow(new InterfaceNotOpenException()).when(wifiDevice).setParameter(Mockito.anyString(), Mockito.any(byte[].class)); // Call the method under test. wifiDevice.connect(mockedAccessPoint, ""); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#connect(AccessPoint, String)}. * * <p>Verify that the Wi-Fi module cannot connect to an access point if the * device is in AT mode throwing an {@code InvalidOperatingModeException}.</p> * * @throws XBeeException */ @Test(expected=InvalidOperatingModeException.class) public final void testConnectInvalidOperatingMode() throws XBeeException { // Setup the resources for the test. // Prepare the answers to the AT commands. PowerMockito.doThrow(new InvalidOperatingModeException()).when(wifiDevice).setParameter(Mockito.anyString(), Mockito.any(byte[].class)); // Call the method under test. wifiDevice.connect(mockedAccessPoint, ""); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#connect(AccessPoint, String)}. * * <p>Verify that the Wi-Fi module cannot connect to an access point if there * is a timeout setting any connection parameter throwing a {@code TimeoutException}.</p> * * @throws XBeeException */ @Test(expected=TimeoutException.class) public final void testConnectTimeout() throws XBeeException { // Setup the resources for the test. // Prepare the answers to the AT commands. PowerMockito.doThrow(new TimeoutException()).when(wifiDevice).setParameter(Mockito.anyString(), Mockito.any(byte[].class)); // Call the method under test. wifiDevice.connect(mockedAccessPoint, ""); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#connect(AccessPoint, String)}. * * <p>Verify that the Wi-Fi module cannot connect to an access point if the AI * status is {@code null} and the password is not configured.</p> * * @throws Exception */ @Test public final void testConnectNullAIStatusNullPassword() throws Exception { // Setup the resources for the test. // Prepare the answers to the AT commands. PowerMockito.doNothing().when(wifiDevice).setParameter(Mockito.anyString(), Mockito.any(byte[].class)); PowerMockito.doReturn(null).when(wifiDevice).getParameter("AI"); // Get the current time. currentMillis = System.currentTimeMillis(); // Configure the number of ticks (times) the sleep method should be called. int ticks = wifiDevice.getAccessPointTimeout()/100; // Prepare the System class to return our fixed currentMillis variable when requested. PowerMockito.mockStatic(System.class); PowerMockito.when(System.currentTimeMillis()).thenReturn(currentMillis); // When the sleep method is called, add 100ms to the currentMillis variable. PowerMockito.doAnswer(new Answer<Object>() { public Object answer(InvocationOnMock invocation) throws Exception { Object[] args = invocation.getArguments(); int sleepTime = (Integer)args[0]; changeMillisToReturn(sleepTime); return null; } }).when(wifiDevice, METHOD_SLEEP, Mockito.anyInt()); // Call the method under test. boolean connected = wifiDevice.connect(mockedAccessPoint, null); // Verify the result. assertThat("Module should have not connected", connected, is(equalTo(false))); // Verify that the sleep method was called 'ticks' times. PowerMockito.verifyPrivate(wifiDevice, Mockito.times(ticks)).invoke(METHOD_SLEEP, 100); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#connect(AccessPoint, String)}. * * <p>Verify that the Wi-Fi module cannot connect to an access point if the AI * status is empty and the password is not configured.</p> * * @throws Exception */ @Test public final void testConnectEmptyAIStatus() throws Exception { // Setup the resources for the test. // Prepare the answers to the AT commands. PowerMockito.doNothing().when(wifiDevice).setParameter(Mockito.anyString(), Mockito.any(byte[].class)); PowerMockito.doReturn(new byte[0]).when(wifiDevice).getParameter("AI"); // Get the current time. currentMillis = System.currentTimeMillis(); // Configure the number of ticks (times) the sleep method should be called. int ticks = wifiDevice.getAccessPointTimeout()/100; // Prepare the System class to return our fixed currentMillis variable when requested. PowerMockito.mockStatic(System.class); PowerMockito.when(System.currentTimeMillis()).thenReturn(currentMillis); // When the sleep method is called, add 100ms to the currentMillis variable. PowerMockito.doAnswer(new Answer<Object>() { public Object answer(InvocationOnMock invocation) throws Exception { Object[] args = invocation.getArguments(); int sleepTime = (Integer)args[0]; changeMillisToReturn(sleepTime); return null; } }).when(wifiDevice, METHOD_SLEEP, Mockito.anyInt()); // Call the method under test. boolean connected = wifiDevice.connect(mockedAccessPoint, null); // Verify the result. assertThat("Module should have not connected", connected, is(equalTo(false))); // Verify that the sleep method was called 'ticks' times. PowerMockito.verifyPrivate(wifiDevice, Mockito.times(ticks)).invoke(METHOD_SLEEP, 100); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#connect(AccessPoint, String)}. * * <p>Verify that the Wi-Fi module cannot connect to an access point if the AI * status is not 0.</p> * * @throws Exception */ @Test public final void testConnectWrongAIStatus() throws Exception { // Setup the resources for the test. // Prepare the answers to the AT commands. PowerMockito.doNothing().when(wifiDevice).setParameter(Mockito.anyString(), Mockito.any(byte[].class)); PowerMockito.doReturn(new byte[]{0x23}).when(wifiDevice).getParameter("AI"); Mockito.doReturn(WiFiEncryptionType.NONE).when(mockedAccessPoint).getEncryptionType(); // Get the current time. currentMillis = System.currentTimeMillis(); // Configure the number of ticks (times) the sleep method should be called. int ticks = wifiDevice.getAccessPointTimeout()/100; // Prepare the System class to return our fixed currentMillis variable when requested. PowerMockito.mockStatic(System.class); PowerMockito.when(System.currentTimeMillis()).thenReturn(currentMillis); // When the sleep method is called, add 100ms to the currentMillis variable. PowerMockito.doAnswer(new Answer<Object>() { public Object answer(InvocationOnMock invocation) throws Exception { Object[] args = invocation.getArguments(); int sleepTime = (Integer)args[0]; changeMillisToReturn(sleepTime); return null; } }).when(wifiDevice, METHOD_SLEEP, Mockito.anyInt()); // Call the method under test. boolean connected = wifiDevice.connect(mockedAccessPoint, "password"); // Verify the result. assertThat("Module should have not connected", connected, is(equalTo(false))); // Verify that the sleep method was called 'ticks' times. PowerMockito.verifyPrivate(wifiDevice, Mockito.times(ticks)).invoke(METHOD_SLEEP, 100); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#connect(AccessPoint, String)}. * * <p>Verify that the Wi-Fi module can connect to to an access point successfully when * the password is null.</p> * * @throws Exception */ @Test public final void testConnectSuccessPasswordNull() throws Exception { // Setup the resources for the test. // Prepare the answers to the AT commands. PowerMockito.doNothing().when(wifiDevice).setParameter(Mockito.anyString(), Mockito.any(byte[].class)); PowerMockito.doReturn(new byte[]{0}).when(wifiDevice).getParameter("AI"); // Get the current time. currentMillis = System.currentTimeMillis(); // Prepare the System class to return our fixed currentMillis variable when requested. PowerMockito.mockStatic(System.class); PowerMockito.when(System.currentTimeMillis()).thenReturn(currentMillis); // When the sleep method is called, add 100ms to the currentMillis variable. PowerMockito.doAnswer(new Answer<Object>() { public Object answer(InvocationOnMock invocation) throws Exception { Object[] args = invocation.getArguments(); int sleepTime = (Integer)args[0]; changeMillisToReturn(sleepTime); return null; } }).when(wifiDevice, METHOD_SLEEP, Mockito.anyInt()); // Call the method under test. boolean connected = wifiDevice.connect(mockedAccessPoint, null); // Verify the result. assertThat("Module should have connected", connected, is(equalTo(true))); // Verify that the sleep method was called one time. PowerMockito.verifyPrivate(wifiDevice, Mockito.times(1)).invoke(METHOD_SLEEP, 100); } /** * Test method for {@link com.digi.xbee.api.WiFiDevice#connect(AccessPoint, String)}. * * <p>Verify that the Wi-Fi module can connect to to an access point successfully when * the password is not null.</p> * * @throws Exception */ @Test public final void testConnectSuccessPasswordNotNull() throws Exception { // Setup the resources for the test. // Prepare the answers to the AT commands. PowerMockito.doNothing().when(wifiDevice).setParameter(Mockito.anyString(), Mockito.any(byte[].class)); PowerMockito.doReturn(new byte[]{0x00}).when(wifiDevice).getParameter("AI"); Mockito.doReturn(WiFiEncryptionType.WEP).when(mockedAccessPoint).getEncryptionType(); // Get the current time. currentMillis = System.currentTimeMillis(); // Prepare the System class to return our fixed currentMillis variable when requested. PowerMockito.mockStatic(System.class); PowerMockito.when(System.currentTimeMillis()).thenReturn(currentMillis); // When the sleep method is called, add 100ms to the currentMillis variable. PowerMockito.doAnswer(new Answer<Object>() { public Object answer(InvocationOnMock invocation) throws Exception { Object[] args = invocation.getArguments(); int sleepTime = (Integer)args[0]; changeMillisToReturn(sleepTime); return null; } }).when(wifiDevice, METHOD_SLEEP, Mockito.anyInt()); // Call the method under test. boolean connected = wifiDevice.connect(mockedAccessPoint, "password"); // Verify the result. assertThat("Module should have connected", connected, is(equalTo(true))); // Verify that the sleep method was called one time. PowerMockito.verifyPrivate(wifiDevice, Mockito.times(1)).invoke(METHOD_SLEEP, 100); } /** * Helper method that changes the milliseconds to return when the System.currentMillis() * method is invoked. * * @param time The time to all to the milliseconds to return. */ public void changeMillisToReturn(int time) { currentMillis += time; // Prepare the System class to return our fixed currentMillis variable when requested. PowerMockito.when(System.currentTimeMillis()).thenReturn(currentMillis); } }