/* ================================================================== * ChargePointService_v15Tests.java - 26/03/2017 8:19:32 AM * * Copyright 2007-2017 SolarNetwork.net Dev Team * * 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 2 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA * ================================================================== */ package net.solarnetwork.node.ocpp.web.test; import static org.easymock.EasyMock.expect; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import org.easymock.Capture; import org.easymock.EasyMock; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.context.MessageSource; import net.solarnetwork.node.SystemService; import net.solarnetwork.node.ocpp.ChargeConfigurationDao; import net.solarnetwork.node.ocpp.ChargeSession; import net.solarnetwork.node.ocpp.ChargeSessionManager; import net.solarnetwork.node.ocpp.support.SimpleChargeConfiguration; import net.solarnetwork.node.ocpp.web.ChargePointService_v15; import net.solarnetwork.util.StaticOptionalService; import ocpp.v15.cp.AvailabilityStatus; import ocpp.v15.cp.AvailabilityType; import ocpp.v15.cp.ChangeAvailabilityRequest; import ocpp.v15.cp.ChangeAvailabilityResponse; import ocpp.v15.cp.ChangeConfigurationRequest; import ocpp.v15.cp.ChangeConfigurationResponse; import ocpp.v15.cp.ConfigurationStatus; import ocpp.v15.cp.GetConfigurationRequest; import ocpp.v15.cp.GetConfigurationResponse; import ocpp.v15.cp.KeyValue; import ocpp.v15.cp.RemoteStartStopStatus; import ocpp.v15.cp.RemoteStartTransactionRequest; import ocpp.v15.cp.RemoteStartTransactionResponse; import ocpp.v15.cp.RemoteStopTransactionRequest; import ocpp.v15.cp.RemoteStopTransactionResponse; import ocpp.v15.cp.ResetRequest; import ocpp.v15.cp.ResetResponse; import ocpp.v15.cp.ResetStatus; import ocpp.v15.cp.ResetType; import ocpp.v15.cp.UnlockConnectorRequest; import ocpp.v15.cp.UnlockConnectorResponse; import ocpp.v15.cp.UnlockStatus; import ocpp.v15.support.ConfigurationKeys; /** * Unit tests for the {@link ChargePointService_v15} class. * * @author matt * @version 1.0 */ public class ChargePointService_v15Tests { private static final String TEST_CHARGE_BOX_ID = "test.id"; private static final String TEST_ID_TAG = "id.tag"; private static final String TEST_SOCKET_ID = "/test/socket"; private static final String TEST_SESSION_ID = "123abc"; private static final int TEST_CONNECTOR_ID = 123; private static final int TEST_TRANSACTION_ID = 321; private ChargePointService_v15 service; private ChargeConfigurationDao chargeConfigurationDao; private SystemService systemService; private ChargeSessionManager chargeSessionManager; private MessageSource messageSource; @Before public void setup() { chargeConfigurationDao = EasyMock.createMock(ChargeConfigurationDao.class); chargeSessionManager = EasyMock.createMock(ChargeSessionManager.class); messageSource = EasyMock.createMock(MessageSource.class); systemService = EasyMock.createMock(SystemService.class); service = new ChargePointService_v15(); service.setChargeConfigurationDao(chargeConfigurationDao); service.setChargeSessionManager(chargeSessionManager); service.setSystemService(new StaticOptionalService<SystemService>(systemService)); service.setMessageSource(messageSource); } @After public void finished() { EasyMock.verify(chargeConfigurationDao, chargeSessionManager, messageSource, systemService); } private void replayAll() { EasyMock.replay(chargeConfigurationDao, chargeSessionManager, messageSource, systemService); } @Test public void getAllConfigurationValues() { SimpleChargeConfiguration config = new SimpleChargeConfiguration(); config.setHeartBeatInterval(1); config.setMeterValueSampleInterval(2); expect(chargeConfigurationDao.getChargeConfiguration()).andReturn(config); replayAll(); GetConfigurationRequest req = new GetConfigurationRequest(); GetConfigurationResponse resp = service.getConfiguration(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("All keys returned", 2, resp.getConfigurationKey().size()); assertEquals("No unknown keys returned", 0, resp.getUnknownKey().size()); Map<String, String> props = getConfigurationProperties(resp); assertEquals("HeartBeatInterval", "1", props.get(ConfigurationKeys.HeartBeatInterval.getKey())); assertEquals("MeterValueSampleInterval", "2", props.get(ConfigurationKeys.MeterValueSampleInterval.getKey())); } private Map<String, String> getConfigurationProperties(GetConfigurationResponse resp) { Map<String, String> props = new LinkedHashMap<String, String>(resp.getConfigurationKey().size()); for ( KeyValue kv : resp.getConfigurationKey() ) { props.put(kv.getKey(), kv.getValue()); } return props; } @Test public void getOneConfigurationValue() { SimpleChargeConfiguration config = new SimpleChargeConfiguration(); config.setHeartBeatInterval(1); config.setMeterValueSampleInterval(2); expect(chargeConfigurationDao.getChargeConfiguration()).andReturn(config); replayAll(); GetConfigurationRequest req = new GetConfigurationRequest(); req.getKey().add(ConfigurationKeys.MeterValueSampleInterval.getKey()); GetConfigurationResponse resp = service.getConfiguration(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("All keys returned", 1, resp.getConfigurationKey().size()); assertEquals("No unknown keys returned", 0, resp.getUnknownKey().size()); Map<String, String> props = getConfigurationProperties(resp); assertEquals("MeterValueSampleInterval", "2", props.get(ConfigurationKeys.MeterValueSampleInterval.getKey())); } @Test public void changeMeterValueSampleInterval() { SimpleChargeConfiguration config = new SimpleChargeConfiguration(); config.setHeartBeatInterval(0); config.setMeterValueSampleInterval(0); expect(chargeConfigurationDao.getChargeConfiguration()).andReturn(config); // update Capture<SimpleChargeConfiguration> configCapture = new Capture<SimpleChargeConfiguration>(); chargeConfigurationDao.storeChargeConfiguration(EasyMock.capture(configCapture)); replayAll(); ChangeConfigurationRequest req = new ChangeConfigurationRequest(); req.setKey(ConfigurationKeys.MeterValueSampleInterval.getKey()); req.setValue("100"); ChangeConfigurationResponse resp = service.changeConfiguration(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", ConfigurationStatus.ACCEPTED, resp.getStatus()); // verify updated config assertNotNull("Updated config", configCapture.getValue()); SimpleChargeConfiguration updatedConfig = configCapture.getValue(); assertEquals("HeartBeatInterval unchanged", 0, updatedConfig.getHeartBeatInterval()); assertEquals("MeterValueSampleInterval", 100, updatedConfig.getMeterValueSampleInterval()); } @Test public void changeMeterValueSampleIntervalInvalid() { SimpleChargeConfiguration config = new SimpleChargeConfiguration(); config.setHeartBeatInterval(0); config.setMeterValueSampleInterval(0); expect(chargeConfigurationDao.getChargeConfiguration()).andReturn(config); replayAll(); ChangeConfigurationRequest req = new ChangeConfigurationRequest(); req.setKey(ConfigurationKeys.MeterValueSampleInterval.getKey()); req.setValue("ABC"); ChangeConfigurationResponse resp = service.changeConfiguration(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", ConfigurationStatus.REJECTED, resp.getStatus()); } @Test public void changeHeartBeatInterval() { SimpleChargeConfiguration config = new SimpleChargeConfiguration(); config.setHeartBeatInterval(0); config.setMeterValueSampleInterval(0); expect(chargeConfigurationDao.getChargeConfiguration()).andReturn(config); // update Capture<SimpleChargeConfiguration> configCapture = new Capture<SimpleChargeConfiguration>(); chargeConfigurationDao.storeChargeConfiguration(EasyMock.capture(configCapture)); replayAll(); ChangeConfigurationRequest req = new ChangeConfigurationRequest(); req.setKey(ConfigurationKeys.HeartBeatInterval.getKey()); req.setValue("100"); ChangeConfigurationResponse resp = service.changeConfiguration(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", ConfigurationStatus.ACCEPTED, resp.getStatus()); // verify updated config assertNotNull("Updated config", configCapture.getValue()); SimpleChargeConfiguration updatedConfig = configCapture.getValue(); assertEquals("HeartBeatInterval", 100, updatedConfig.getHeartBeatInterval()); assertEquals("MeterValueSampleInterval unchanged", 0, updatedConfig.getMeterValueSampleInterval()); } @Test public void changeHeartBeatIntervalInvalid() { SimpleChargeConfiguration config = new SimpleChargeConfiguration(); config.setHeartBeatInterval(0); config.setMeterValueSampleInterval(0); expect(chargeConfigurationDao.getChargeConfiguration()).andReturn(config); replayAll(); ChangeConfigurationRequest req = new ChangeConfigurationRequest(); req.setKey(ConfigurationKeys.HeartBeatInterval.getKey()); req.setValue("ABC"); ChangeConfigurationResponse resp = service.changeConfiguration(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", ConfigurationStatus.REJECTED, resp.getStatus()); } @Test public void changeAvailabilityAllDisabled() { // because passing connector ID 0, must change all sockets Set<String> availableSocketIds = new LinkedHashSet<String>(Arrays.asList(TEST_SOCKET_ID)); expect(chargeSessionManager.availableSocketIds()).andReturn(availableSocketIds); // disable the socket chargeSessionManager.configureSocketEnabledState(availableSocketIds, false); replayAll(); ChangeAvailabilityRequest req = new ChangeAvailabilityRequest(); req.setConnectorId(0); req.setType(AvailabilityType.INOPERATIVE); ChangeAvailabilityResponse resp = service.changeAvailability(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", AvailabilityStatus.ACCEPTED, resp.getStatus()); } @Test public void changeAvailabilityAllEnabled() { // because passing connector ID 0, must change all sockets Set<String> availableSocketIds = new LinkedHashSet<String>(Arrays.asList(TEST_SOCKET_ID)); expect(chargeSessionManager.availableSocketIds()).andReturn(availableSocketIds); // disable the socket chargeSessionManager.configureSocketEnabledState(availableSocketIds, true); replayAll(); ChangeAvailabilityRequest req = new ChangeAvailabilityRequest(); req.setConnectorId(0); req.setType(AvailabilityType.OPERATIVE); ChangeAvailabilityResponse resp = service.changeAvailability(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", AvailabilityStatus.ACCEPTED, resp.getStatus()); } @Test public void changeAvailabilitySingleConnectorDisabled() { expect(chargeSessionManager.socketIdForConnectorId(TEST_CONNECTOR_ID)).andReturn(TEST_SOCKET_ID); Capture<Collection<String>> socketIdsCapture = new Capture<Collection<String>>(); chargeSessionManager.configureSocketEnabledState(EasyMock.capture(socketIdsCapture), EasyMock.eq(false)); replayAll(); ChangeAvailabilityRequest req = new ChangeAvailabilityRequest(); req.setConnectorId(TEST_CONNECTOR_ID); req.setType(AvailabilityType.INOPERATIVE); ChangeAvailabilityResponse resp = service.changeAvailability(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", AvailabilityStatus.ACCEPTED, resp.getStatus()); // verify captured socket Collection<String> socketIds = socketIdsCapture.getValue(); assertNotNull("Changed socket IDs", socketIds); assertEquals("Changed socket IDs count", 1, socketIds.size()); assertEquals("Changed socket ID", TEST_SOCKET_ID, socketIds.iterator().next()); } @Test public void changeAvailabilityUnknownConnectorDisabled() { expect(chargeSessionManager.socketIdForConnectorId(1)).andReturn(null); replayAll(); ChangeAvailabilityRequest req = new ChangeAvailabilityRequest(); req.setConnectorId(1); req.setType(AvailabilityType.INOPERATIVE); ChangeAvailabilityResponse resp = service.changeAvailability(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", AvailabilityStatus.REJECTED, resp.getStatus()); } @Test public void unlockConnectorNoSession() { // get the socket ID expect(chargeSessionManager.socketIdForConnectorId(TEST_CONNECTOR_ID)).andReturn(TEST_SOCKET_ID); // check for active session on socket (and indicate there isn't) expect(chargeSessionManager.activeChargeSession(TEST_SOCKET_ID)).andReturn(null); Capture<Collection<String>> socketIdsCapture = new Capture<Collection<String>>(); chargeSessionManager.configureSocketEnabledState(EasyMock.capture(socketIdsCapture), EasyMock.eq(true)); replayAll(); UnlockConnectorRequest req = new UnlockConnectorRequest(); req.setConnectorId(TEST_CONNECTOR_ID); UnlockConnectorResponse resp = service.unlockConnector(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", UnlockStatus.ACCEPTED, resp.getStatus()); // verify captured socket Collection<String> socketIds = socketIdsCapture.getValue(); assertNotNull("Changed socket IDs", socketIds); assertEquals("Changed socket IDs count", 1, socketIds.size()); assertEquals("Changed socket ID", TEST_SOCKET_ID, socketIds.iterator().next()); } @Test public void unlockConnectorWithSession() { // get the socket ID expect(chargeSessionManager.socketIdForConnectorId(TEST_CONNECTOR_ID)).andReturn(TEST_SOCKET_ID); // check for active session on socket (and return session) final ChargeSession session = new ChargeSession(); session.setSessionId(TEST_SESSION_ID); session.setIdTag(TEST_ID_TAG); expect(chargeSessionManager.activeChargeSession(TEST_SOCKET_ID)).andReturn(session); // complete session chargeSessionManager.completeChargeSession(TEST_ID_TAG, TEST_SESSION_ID); Capture<Collection<String>> socketIdsCapture = new Capture<Collection<String>>(); chargeSessionManager.configureSocketEnabledState(EasyMock.capture(socketIdsCapture), EasyMock.eq(true)); replayAll(); UnlockConnectorRequest req = new UnlockConnectorRequest(); req.setConnectorId(TEST_CONNECTOR_ID); UnlockConnectorResponse resp = service.unlockConnector(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", UnlockStatus.ACCEPTED, resp.getStatus()); // verify captured socket Collection<String> socketIds = socketIdsCapture.getValue(); assertNotNull("Changed socket IDs", socketIds); assertEquals("Changed socket IDs count", 1, socketIds.size()); assertEquals("Changed socket ID", TEST_SOCKET_ID, socketIds.iterator().next()); } @Test public void remoteStartTransactionWithConnector() { // get the socket ID expect(chargeSessionManager.socketIdForConnectorId(TEST_CONNECTOR_ID)).andReturn(TEST_SOCKET_ID); // start the session expect(chargeSessionManager.initiateChargeSession(TEST_ID_TAG, TEST_SOCKET_ID, null)) .andReturn(TEST_SESSION_ID); replayAll(); RemoteStartTransactionRequest req = new RemoteStartTransactionRequest(); req.setIdTag(TEST_ID_TAG); req.setConnectorId(TEST_CONNECTOR_ID); RemoteStartTransactionResponse resp = service.remoteStartTransaction(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", RemoteStartStopStatus.ACCEPTED, resp.getStatus()); } @Test public void remoteStartTransactionUnspecifiedConnector() { // get the first available socket ID Set<String> availableSocketIds = new LinkedHashSet<String>( Arrays.asList(TEST_SOCKET_ID, "/another/socket")); expect(chargeSessionManager.availableSocketIds()).andReturn(availableSocketIds); // start the session expect(chargeSessionManager.initiateChargeSession(TEST_ID_TAG, TEST_SOCKET_ID, null)) .andReturn(TEST_SESSION_ID); replayAll(); RemoteStartTransactionRequest req = new RemoteStartTransactionRequest(); req.setIdTag(TEST_ID_TAG); RemoteStartTransactionResponse resp = service.remoteStartTransaction(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", RemoteStartStopStatus.ACCEPTED, resp.getStatus()); } @Test public void remoteStopTransaction() { // get active session for transaction final ChargeSession session = new ChargeSession(); session.setSessionId(TEST_SESSION_ID); session.setTransactionId(TEST_TRANSACTION_ID); session.setIdTag(TEST_ID_TAG); expect(chargeSessionManager.activeChargeSession(TEST_TRANSACTION_ID)).andReturn(session); // end the session chargeSessionManager.completeChargeSession(TEST_ID_TAG, TEST_SESSION_ID); replayAll(); RemoteStopTransactionRequest req = new RemoteStopTransactionRequest(); req.setTransactionId(TEST_TRANSACTION_ID); RemoteStopTransactionResponse resp = service.remoteStopTransaction(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", RemoteStartStopStatus.ACCEPTED, resp.getStatus()); } @Test public void remoteStopTransactionNoSession() { // get active session for transaction (not finding) expect(chargeSessionManager.activeChargeSession(TEST_TRANSACTION_ID)).andReturn(null); replayAll(); RemoteStopTransactionRequest req = new RemoteStopTransactionRequest(); req.setTransactionId(TEST_TRANSACTION_ID); RemoteStopTransactionResponse resp = service.remoteStopTransaction(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", RemoteStartStopStatus.REJECTED, resp.getStatus()); } @Test public void resetNoSessionsSoft() { // get the available socket IDs to look for sessions to stop Set<String> availableSocketIds = new LinkedHashSet<String>(Arrays.asList(TEST_SOCKET_ID)); expect(chargeSessionManager.availableSocketIds()).andReturn(availableSocketIds); // look for active charge session on socket (not found) expect(chargeSessionManager.activeChargeSession(TEST_SOCKET_ID)).andReturn(null); replayAll(); ResetRequest req = new ResetRequest(); req.setType(ResetType.SOFT); ResetResponse resp = service.reset(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", ResetStatus.ACCEPTED, resp.getStatus()); } @Test public void resetNoSessionsHard() { // get the available socket IDs to look for sessions to stop Set<String> availableSocketIds = new LinkedHashSet<String>(Arrays.asList(TEST_SOCKET_ID)); expect(chargeSessionManager.availableSocketIds()).andReturn(availableSocketIds); // look for active charge session on socket (not found) expect(chargeSessionManager.activeChargeSession(TEST_SOCKET_ID)).andReturn(null); // reboot systemService.reboot(); replayAll(); ResetRequest req = new ResetRequest(); req.setType(ResetType.HARD); ResetResponse resp = service.reset(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", ResetStatus.ACCEPTED, resp.getStatus()); } @Test public void resetWithActiveSessionsSoft() { // get the available socket IDs to look for sessions to stop Set<String> availableSocketIds = new LinkedHashSet<String>(Arrays.asList(TEST_SOCKET_ID)); expect(chargeSessionManager.availableSocketIds()).andReturn(availableSocketIds); // look for active charge session on socket final ChargeSession session = new ChargeSession(); session.setSessionId(TEST_SESSION_ID); session.setTransactionId(TEST_TRANSACTION_ID); session.setIdTag(TEST_ID_TAG); expect(chargeSessionManager.activeChargeSession(TEST_SOCKET_ID)).andReturn(session); // end session chargeSessionManager.completeChargeSession(TEST_ID_TAG, TEST_SESSION_ID); replayAll(); ResetRequest req = new ResetRequest(); req.setType(ResetType.SOFT); ResetResponse resp = service.reset(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", ResetStatus.ACCEPTED, resp.getStatus()); } @Test public void resetWithActiveSessionHard() { // get the available socket IDs to look for sessions to stop Set<String> availableSocketIds = new LinkedHashSet<String>(Arrays.asList(TEST_SOCKET_ID)); expect(chargeSessionManager.availableSocketIds()).andReturn(availableSocketIds); // look for active charge session on socket final ChargeSession session = new ChargeSession(); session.setSessionId(TEST_SESSION_ID); session.setTransactionId(TEST_TRANSACTION_ID); session.setIdTag(TEST_ID_TAG); expect(chargeSessionManager.activeChargeSession(TEST_SOCKET_ID)).andReturn(session); // end session chargeSessionManager.completeChargeSession(TEST_ID_TAG, TEST_SESSION_ID); // reboot systemService.reboot(); replayAll(); ResetRequest req = new ResetRequest(); req.setType(ResetType.HARD); ResetResponse resp = service.reset(req, TEST_CHARGE_BOX_ID); assertNotNull("Response available", resp); assertEquals("Status", ResetStatus.ACCEPTED, resp.getStatus()); } }