/** * UPnP PortMapper - A tool for managing port forwardings via UPnP * Copyright (C) 2015 Christoph Pirkl <christoph at users.sourceforge.net> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.chris.portmapper.router.sbbi; import static java.util.Arrays.*; import static org.junit.Assert.*; import static org.mockito.ArgumentMatchers.*; import java.io.IOException; import java.util.HashSet; import org.chris.portmapper.model.PortMapping; import org.chris.portmapper.router.RouterException; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.slf4j.Logger; import static org.mockito.Mockito.*; import net.sbbi.upnp.impls.InternetGatewayDevice; import net.sbbi.upnp.messages.ActionResponse; import net.sbbi.upnp.messages.UPNPResponseException; /** * Unit tests for {@link SBBIPortMappingExtractor}. */ public class TestPortMappingExtractor { @Mock private InternetGatewayDevice routerMock; @Mock private Logger loggerMock; private SBBIPortMappingExtractor portMappingExtractor; @Before public void setUp() { MockitoAnnotations.initMocks(this); portMappingExtractor = new SBBIPortMappingExtractor(routerMock, 5, loggerMock); } @Test public void allMappingsNull() throws RouterException, IOException, UPNPResponseException { simulateUPNPException(5, 713); assertEquals(0, portMappingExtractor.getPortMappings().size()); verify(loggerMock, times(1)).warn(anyString(), anyInt()); verify(loggerMock, never()).error(anyString()); assertNumMappingsFound(0, 5); } @Test public void allMappingsNullMaxNumReached() throws RouterException { assertEquals(0, portMappingExtractor.getPortMappings().size()); verify(loggerMock, times(1)).warn(anyString(), anyInt()); verify(loggerMock, never()).error(anyString()); assertNumMappingsFound(0, 5); } @Test public void noMapping() throws RouterException, IOException, UPNPResponseException { simulateUPNPException(0, 713); assertEquals(0, portMappingExtractor.getPortMappings().size()); assertNoWarningOrErrorLogged(); assertNumMappingsFound(0, 0); } @Test public void wrongErrorCode() throws RouterException, IOException, UPNPResponseException { simulateUPNPException(0, 42); assertEquals(0, portMappingExtractor.getPortMappings().size()); verify(loggerMock, never()).warn(anyString()); verify(loggerMock, never()).error(anyString()); verify(loggerMock, never()).warn(anyString(), any(Throwable.class)); verify(loggerMock).error(anyString(), any(Throwable.class)); assertNumMappingsFound(0, 0); } @Test public void oneMapping() throws RouterException, IOException, UPNPResponseException { simulateMapping(0); simulateUPNPException(1, 713); assertEquals(1, portMappingExtractor.getPortMappings().size()); assertNoWarningOrErrorLogged(); assertNumMappingsFound(1, 0); } private void assertNumMappingsFound(final int numFound, final int numNull) { verify(loggerMock).debug("Found {} mappings, {} mappings returned as null.", numFound, numNull); } private void assertNoWarningOrErrorLogged() { verify(loggerMock, never()).warn(anyString()); verify(loggerMock, never()).error(anyString()); verify(loggerMock, never()).warn(anyString(), any(Throwable.class)); verify(loggerMock, never()).error(anyString(), any(Throwable.class)); } private void simulateMapping(final int mappingEntry) throws IOException, UPNPResponseException { final ActionResponse response = mock(ActionResponse.class); when(response.getOutActionArgumentNames()).thenReturn( new HashSet<Object>(asList(PortMapping.MAPPING_ENTRY_ENABLED, PortMapping.MAPPING_ENTRY_EXTERNAL_PORT, PortMapping.MAPPING_ENTRY_INTERNAL_CLIENT, PortMapping.MAPPING_ENTRY_INTERNAL_PORT, PortMapping.MAPPING_ENTRY_LEASE_DURATION, PortMapping.MAPPING_ENTRY_PORT_MAPPING_DESCRIPTION, PortMapping.MAPPING_ENTRY_PROTOCOL, PortMapping.MAPPING_ENTRY_REMOTE_HOST))); when(response.getOutActionArgumentValue(PortMapping.MAPPING_ENTRY_ENABLED)).thenReturn("1"); when(response.getOutActionArgumentValue(PortMapping.MAPPING_ENTRY_EXTERNAL_PORT)).thenReturn("2"); when(response.getOutActionArgumentValue(PortMapping.MAPPING_ENTRY_INTERNAL_CLIENT)).thenReturn("internal"); when(response.getOutActionArgumentValue(PortMapping.MAPPING_ENTRY_INTERNAL_PORT)).thenReturn("3"); when(response.getOutActionArgumentValue(PortMapping.MAPPING_ENTRY_LEASE_DURATION)).thenReturn("4"); when(response.getOutActionArgumentValue(PortMapping.MAPPING_ENTRY_PORT_MAPPING_DESCRIPTION)) .thenReturn("description"); when(response.getOutActionArgumentValue(PortMapping.MAPPING_ENTRY_PROTOCOL)).thenReturn("TCP"); when(response.getOutActionArgumentValue(PortMapping.MAPPING_ENTRY_REMOTE_HOST)).thenReturn("remote"); when(routerMock.getGenericPortMappingEntry(mappingEntry)).thenReturn(response); } private void simulateUPNPException(final int mappingEntry, final int errorCode) throws IOException, UPNPResponseException { when(routerMock.getGenericPortMappingEntry(mappingEntry)).thenThrow(new UPNPResponseException(errorCode, "exception for entry " + mappingEntry + ", error code " + errorCode)); } }