/* ================================================================== * RfidChargeSessionManagerTests.java - 30/07/2016 12:50:40 PM * * Copyright 2007-2016 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.charge.rfid.test; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import org.easymock.EasyMock; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.osgi.service.event.Event; import net.solarnetwork.node.ocpp.ChargeSession; import net.solarnetwork.node.ocpp.ChargeSessionManager; import net.solarnetwork.node.ocpp.SocketManager; import net.solarnetwork.node.ocpp.charge.rfid.RfidChargeSessionManager; import net.solarnetwork.node.ocpp.charge.rfid.RfidSocketMapping; import net.solarnetwork.node.test.AbstractNodeTest; import net.solarnetwork.node.test.CapturingExecutorService; /** * Test cases for the {@link RfidChargeSessionManager} class. * * @author matt * @version 1.0 */ public class RfidChargeSessionManagerTests extends AbstractNodeTest { private static final String TEST_RFID_UID = "Test RFID Scanner"; private static final String TEST_RFID_UID2 = "Test RFID Scanner 2"; private static final String TEST_ID_TAG = "TestIdTag"; private static final String TEST_SOCKET_ID = "/socket/test/1"; private static final String TEST_SOCKET_ID2 = "/socket/test/2"; private static final String TEST_SESSION_ID = "test-session-id"; private ChargeSessionManager chargeSessionManager; private SocketManager socketManager; private RfidChargeSessionManager manager; @Before public void setup() { chargeSessionManager = EasyMock.createMock(ChargeSessionManager.class); socketManager = EasyMock.createMock(SocketManager.class); manager = new RfidChargeSessionManager(); manager.setExecutor(new CapturingExecutorService(Executors.newSingleThreadExecutor())); manager.setChargeSessionManager(chargeSessionManager); manager.setSocketManager(socketManager); } @After public void shutdown() { manager.shutdown(); } private void replayAll() { replay(chargeSessionManager, socketManager); } private List<Future<?>> verifyAll(boolean waitForTasks) { List<Future<?>> futures = null; if ( waitForTasks ) { // wait for startup thread to complete manager.getExecutor().shutdown(); try { manager.getExecutor().awaitTermination(2, TimeUnit.MINUTES); } catch ( InterruptedException e ) { // ignore } if ( manager.getExecutor() instanceof CapturingExecutorService ) { futures = ((CapturingExecutorService) manager.getExecutor()).getCapturedFutures(); } } verify(chargeSessionManager, socketManager); if ( futures != null ) { for ( Future<?> future : futures ) { if ( future.isDone() ) { // trigger ExecutionException try { future.get(); } catch ( InterruptedException e ) { // ignore } catch ( ExecutionException e ) { throw new RuntimeException(e); } } } } return futures; } private Event createRfidEvent(final String msg) { return createRfidEvent(msg, TEST_RFID_UID); } private Event createRfidEvent(final String msg, final String uid) { Map<String, Object> eventProps = new HashMap<String, Object>(5); eventProps.put(RfidChargeSessionManager.EVENT_PARAM_UID, uid); eventProps.put(RfidChargeSessionManager.EVENT_PARAM_MESSAGE, msg); return new Event(RfidChargeSessionManager.TOPIC_RFID_MESSAGE_RECEIVED, eventProps); } @Test public void startChargeSessionNoActiveSessions() { List<String> availableSocketIds = Arrays.asList(TEST_SOCKET_ID); // get available sockets expect(chargeSessionManager.availableSocketIds()).andReturn(availableSocketIds); // for each socket, look for active session expect(chargeSessionManager.activeChargeSession(TEST_SOCKET_ID)).andReturn(null).anyTimes(); // no active sessions, so start one for the available socket expect(chargeSessionManager.initiateChargeSession(TEST_ID_TAG, TEST_SOCKET_ID, null)) .andReturn(TEST_SESSION_ID); // and because session started, enable the socket expect(socketManager.adjustSocketEnabledState(TEST_SOCKET_ID, true)).andReturn(true); replayAll(); manager.handleEvent(createRfidEvent(TEST_ID_TAG)); verifyAll(true); } @Test public void startChargeSessionActiveSessionsNoSocketAvailable() { List<String> availableSocketIds = Arrays.asList(TEST_SOCKET_ID); // get available sockets expect(chargeSessionManager.availableSocketIds()).andReturn(availableSocketIds); // for each socket, look for active session ChargeSession activeSession = new ChargeSession(); activeSession.setIdTag("some.other.id"); expect(chargeSessionManager.activeChargeSession(TEST_SOCKET_ID)).andReturn(activeSession); replayAll(); manager.handleEvent(createRfidEvent(TEST_ID_TAG)); verifyAll(true); } @Test public void startChargeSessionActiveSessionsSecondSocketAvailable() { List<String> availableSocketIds = Arrays.asList(TEST_SOCKET_ID, TEST_SOCKET_ID2); // get available sockets expect(chargeSessionManager.availableSocketIds()).andReturn(availableSocketIds); // for each socket, look for active session ChargeSession activeSession = new ChargeSession(); activeSession.setIdTag("some.other.id"); expect(chargeSessionManager.activeChargeSession(TEST_SOCKET_ID)).andReturn(activeSession); // first socket has session, so test 2nd socket expect(chargeSessionManager.activeChargeSession(TEST_SOCKET_ID2)).andReturn(null).anyTimes(); // start session on the 2nd socket expect(chargeSessionManager.initiateChargeSession(TEST_ID_TAG, TEST_SOCKET_ID2, null)) .andReturn(TEST_SESSION_ID); // and because session started, enable the socket expect(socketManager.adjustSocketEnabledState(TEST_SOCKET_ID2, true)).andReturn(true); replayAll(); manager.handleEvent(createRfidEvent(TEST_ID_TAG)); verifyAll(true); } private void configureRfidMappings() { List<RfidSocketMapping> mappings = new ArrayList<RfidSocketMapping>(2); mappings.add(new RfidSocketMapping(TEST_RFID_UID, TEST_SOCKET_ID)); mappings.add(new RfidSocketMapping(TEST_RFID_UID2, TEST_SOCKET_ID2)); manager.setRfidSocketMappings(mappings); } @Test public void startChargeSessionWithMappingNoMatchingRfidUID() { configureRfidMappings(); List<String> availableSocketIds = Arrays.asList(TEST_SOCKET_ID); // get available sockets expect(chargeSessionManager.availableSocketIds()).andReturn(availableSocketIds); // for each socket, look for active session expect(chargeSessionManager.activeChargeSession(TEST_SOCKET_ID)).andReturn(null).anyTimes(); replayAll(); manager.handleEvent(createRfidEvent(TEST_ID_TAG, "Rogue Scanner")); verifyAll(true); } @Test public void startChargeSessionWithMappingNoActiveSession() { configureRfidMappings(); List<String> availableSocketIds = Arrays.asList(TEST_SOCKET_ID); // get available sockets expect(chargeSessionManager.availableSocketIds()).andReturn(availableSocketIds); // for each socket, look for active session expect(chargeSessionManager.activeChargeSession(TEST_SOCKET_ID)).andReturn(null).anyTimes(); // no active sessions, so start one for the available socket expect(chargeSessionManager.initiateChargeSession(TEST_ID_TAG, TEST_SOCKET_ID, null)) .andReturn(TEST_SESSION_ID); // and because session started, enable the socket expect(socketManager.adjustSocketEnabledState(TEST_SOCKET_ID, true)).andReturn(true); replayAll(); manager.handleEvent(createRfidEvent(TEST_ID_TAG, TEST_RFID_UID)); verifyAll(true); } @Test public void startChargeSessionWithMappingActiveSessionsSecondSocketAvailable() { configureRfidMappings(); List<String> availableSocketIds = Arrays.asList(TEST_SOCKET_ID, TEST_SOCKET_ID2); // get available sockets expect(chargeSessionManager.availableSocketIds()).andReturn(availableSocketIds); // for each socket, look for active session ChargeSession activeSession = new ChargeSession(); activeSession.setIdTag("some.other.id"); expect(chargeSessionManager.activeChargeSession(TEST_SOCKET_ID)).andReturn(activeSession); // first socket has session, so test 2nd socket expect(chargeSessionManager.activeChargeSession(TEST_SOCKET_ID2)).andReturn(null).anyTimes(); // session not started though, because RFID UID maps only to socket 1 replayAll(); manager.handleEvent(createRfidEvent(TEST_ID_TAG, TEST_RFID_UID)); verifyAll(true); } @Test public void endChargeSession() { List<String> availableSocketIds = Arrays.asList(TEST_SOCKET_ID); // get available sockets expect(chargeSessionManager.availableSocketIds()).andReturn(availableSocketIds); // look for active session on socket ChargeSession activeSession = new ChargeSession(); activeSession.setSessionId(TEST_SESSION_ID); activeSession.setIdTag(TEST_ID_TAG); expect(chargeSessionManager.activeChargeSession(TEST_SOCKET_ID)).andReturn(activeSession) .anyTimes(); // found session, so end it chargeSessionManager.completeChargeSession(TEST_ID_TAG, TEST_SESSION_ID); // and because session ended, disable the socket expect(socketManager.adjustSocketEnabledState(TEST_SOCKET_ID, false)).andReturn(true); replayAll(); manager.handleEvent(createRfidEvent(TEST_ID_TAG)); verifyAll(true); } @Test public void endChargeSessionWithMapping() { configureRfidMappings(); List<String> availableSocketIds = Arrays.asList(TEST_SOCKET_ID); // get available sockets expect(chargeSessionManager.availableSocketIds()).andReturn(availableSocketIds); // look for active session on socket ChargeSession activeSession = new ChargeSession(); activeSession.setSessionId(TEST_SESSION_ID); activeSession.setIdTag(TEST_ID_TAG); expect(chargeSessionManager.activeChargeSession(TEST_SOCKET_ID)).andReturn(activeSession) .anyTimes(); // found session, so end it chargeSessionManager.completeChargeSession(TEST_ID_TAG, TEST_SESSION_ID); // and because session ended, disable the socket expect(socketManager.adjustSocketEnabledState(TEST_SOCKET_ID, false)).andReturn(true); replayAll(); manager.handleEvent(createRfidEvent(TEST_ID_TAG, TEST_RFID_UID)); verifyAll(true); } @Test public void endChargeSessionWithMappingEvenThoughOtherRfidUID() { configureRfidMappings(); List<String> availableSocketIds = Arrays.asList(TEST_SOCKET_ID); // get available sockets expect(chargeSessionManager.availableSocketIds()).andReturn(availableSocketIds); // look for active session on socket ChargeSession activeSession = new ChargeSession(); activeSession.setSessionId(TEST_SESSION_ID); activeSession.setIdTag(TEST_ID_TAG); expect(chargeSessionManager.activeChargeSession(TEST_SOCKET_ID)).andReturn(activeSession) .anyTimes(); // found session, so end it chargeSessionManager.completeChargeSession(TEST_ID_TAG, TEST_SESSION_ID); // and because session ended, disable the socket expect(socketManager.adjustSocketEnabledState(TEST_SOCKET_ID, false)).andReturn(true); replayAll(); // now send RFID scan from OTHER device; shouldn't matter because we find the session // based on the tag value manager.handleEvent(createRfidEvent(TEST_ID_TAG, TEST_RFID_UID2)); verifyAll(true); } }