/*
* Commons eID Project.
* Copyright (C) 2008-2013 FedICT.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version
* 3.0 as published by the Free Software Foundation.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, see
* http://www.gnu.org/licenses/.
*/
/**
* Manual exercise for CardAndTerminalManager.
* Prints events and list of readers with cards.
* [short readername] ...
* readers with cards inserted have a "*" behind their short name
*
* @author Frank Marien
*
*/
package test.integ.be.fedict.commons.eid.client;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import javax.smartcardio.ATR;
import javax.smartcardio.Card;
import javax.smartcardio.CardTerminal;
import org.junit.Before;
import org.junit.Test;
import test.integ.be.fedict.commons.eid.client.simulation.SimulatedCard;
import test.integ.be.fedict.commons.eid.client.simulation.SimulatedCardTerminal;
import test.integ.be.fedict.commons.eid.client.simulation.SimulatedCardTerminals;
import be.fedict.commons.eid.client.CardAndTerminalManager;
import be.fedict.commons.eid.client.event.CardEventsListener;
import be.fedict.commons.eid.client.event.CardTerminalEventsListener;
public class CardAndTerminalManagerTests {
private static final int numberOfTerminals = 16;
private static final int numberOfCards = 16;
private List<SimulatedCard> simulatedBeIDCard;
private List<SimulatedCardTerminal> simulatedCardTerminal;
private SimulatedCardTerminals simulatedCardTerminals;
@Before
public void setUp() {
this.simulatedBeIDCard = new ArrayList<SimulatedCard>(numberOfCards);
for (int i = 0; i < numberOfCards; i++) {
this.simulatedBeIDCard.add(new SimulatedCard(new ATR(new byte[]{
0x3b, (byte) 0x98, (byte) i, 0x40, (byte) i, (byte) i,
(byte) i, (byte) i, 0x01, 0x01, (byte) 0xad, 0x13, 0x10})));
}
this.simulatedCardTerminal = new ArrayList<SimulatedCardTerminal>(
numberOfTerminals);
for (int i = 0; i < numberOfTerminals; i++) {
this.simulatedCardTerminal.add(new SimulatedCardTerminal(
"Fedix SCR " + i));
}
this.simulatedCardTerminals = new SimulatedCardTerminals();
}
// ---------------------------------------------------------------------------------------------
private class RecordKeepingCardTerminalEventsListener
implements
CardTerminalEventsListener {
private final Set<CardTerminal> recordedState;
public RecordKeepingCardTerminalEventsListener() {
super();
this.recordedState = new HashSet<CardTerminal>();
}
@Override
public synchronized void terminalAttached(
final CardTerminal cardTerminal) {
this.recordedState.add(cardTerminal);
}
@Override
public synchronized void terminalDetached(
final CardTerminal cardTerminal) {
this.recordedState.remove(cardTerminal);
}
public synchronized Set<CardTerminal> getRecordedState() {
return new HashSet<CardTerminal>(this.recordedState);
}
@Override
public void terminalEventsInitialized() {
// TODO Auto-generated method stub
}
}
private class RecordKeepingCardEventsListener implements CardEventsListener {
private final Map<CardTerminal, Card> recordedState;
public RecordKeepingCardEventsListener() {
super();
this.recordedState = new HashMap<CardTerminal, Card>();
}
@Override
public synchronized void cardInserted(final CardTerminal cardTerminal,
final Card card) {
if (this.recordedState.containsKey(cardTerminal)) {
throw new IllegalStateException(
"Cannot Insert 2 Cards in 1 CardTerminal");
}
this.recordedState.put(cardTerminal, card);
}
@Override
public synchronized void cardRemoved(final CardTerminal cardTerminal) {
if (!this.recordedState.containsKey(cardTerminal)) {
throw new IllegalStateException(
"Cannot Remove Card That is not There");
}
this.recordedState.remove(cardTerminal);
}
public synchronized Map<CardTerminal, Card> getRecordedState() {
return this.recordedState;
}
@Override
public void cardEventsInitialized() {
// TODO Auto-generated method stub
}
}
@Test
public void testTerminalAttachDetachDetection() throws Exception {
final Random random = new Random(0);
final Set<CardTerminal> expectedState = new HashSet<CardTerminal>();
final CardAndTerminalManager cardAndTerminalManager = new CardAndTerminalManager(
new TestLogger(), this.simulatedCardTerminals);
final RecordKeepingCardTerminalEventsListener recorder = new RecordKeepingCardTerminalEventsListener();
cardAndTerminalManager.addCardTerminalListener(recorder);
cardAndTerminalManager
.addCardTerminalListener(new NPEProneCardTerminalEventsListener());
cardAndTerminalManager.start();
System.err
.println("attaching and detaching some simulated cardterminals");
final ArrayList<SimulatedCardTerminal> terminalsToExercise = new ArrayList<SimulatedCardTerminal>(
this.simulatedCardTerminal);
final Set<SimulatedCardTerminal> detachedTerminalSet = new HashSet<SimulatedCardTerminal>(
terminalsToExercise);
final Set<SimulatedCardTerminal> attachedTerminalSet = new HashSet<SimulatedCardTerminal>();
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < random.nextInt(numberOfTerminals); j++) {
final SimulatedCardTerminal terminalToAttach = terminalsToExercise
.get(random.nextInt(numberOfTerminals));
if (detachedTerminalSet.contains(terminalToAttach)) {
expectedState.add(terminalToAttach);
this.simulatedCardTerminals
.attachCardTerminal(terminalToAttach);
detachedTerminalSet.remove(terminalToAttach);
attachedTerminalSet.add(terminalToAttach);
System.out.println("attached ["
+ terminalToAttach.getName() + "]");
StringUtils.printTerminalSet(expectedState);
StringUtils.printTerminalSet(recorder.getRecordedState());
}
}
for (int j = 0; j < random.nextInt(numberOfTerminals); j++) {
final SimulatedCardTerminal terminalToDetach = terminalsToExercise
.get(random.nextInt(numberOfTerminals));
if (attachedTerminalSet.contains(terminalToDetach)) {
expectedState.remove(terminalToDetach);
this.simulatedCardTerminals
.detachCardTerminal(terminalToDetach);
detachedTerminalSet.add(terminalToDetach);
attachedTerminalSet.remove(terminalToDetach);
System.out.println("detached ["
+ terminalToDetach.getName() + "]");
StringUtils.printTerminalSet(expectedState);
StringUtils.printTerminalSet(recorder.getRecordedState());
}
}
}
Thread.sleep(1000);
cardAndTerminalManager.stop();
assertEquals(expectedState, recorder.getRecordedState());
}
@Test
public void testCardInsertRemoveDetection() throws Exception {
final Random random = new Random(0);
final Map<SimulatedCardTerminal, SimulatedCard> expectedState = new HashMap<SimulatedCardTerminal, SimulatedCard>();
final CardAndTerminalManager cardAndTerminalManager = new CardAndTerminalManager(
new TestLogger(), this.simulatedCardTerminals);
final RecordKeepingCardEventsListener recorder = new RecordKeepingCardEventsListener();
cardAndTerminalManager.addCardListener(recorder);
cardAndTerminalManager
.addCardListener(new NPEProneCardEventsListener());
cardAndTerminalManager.start();
final ArrayList<SimulatedCardTerminal> terminalsToExercise = new ArrayList<SimulatedCardTerminal>(
this.simulatedCardTerminal);
final Set<SimulatedCardTerminal> emptyTerminalSet = new HashSet<SimulatedCardTerminal>(
terminalsToExercise);
final Set<SimulatedCardTerminal> fullTerminalSet = new HashSet<SimulatedCardTerminal>();
final ArrayList<SimulatedCard> cardsToExercise = new ArrayList<SimulatedCard>(
this.simulatedBeIDCard);
final Set<SimulatedCard> unusedCardSet = new HashSet<SimulatedCard>(
cardsToExercise);
final Set<SimulatedCard> usedCardSet = new HashSet<SimulatedCard>();
System.err.println("attaching some simulated card readers");
// attach all simulated CardTerminals
for (SimulatedCardTerminal terminal : emptyTerminalSet) {
this.simulatedCardTerminals.attachCardTerminal(terminal);
}
System.err.println("inserting and removing some simulated cards");
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < random.nextInt(numberOfCards); j++) {
final SimulatedCardTerminal terminalToInsertCardInto = terminalsToExercise
.get(random.nextInt(numberOfTerminals));
final SimulatedCard cardToInsert = cardsToExercise.get(random
.nextInt(numberOfCards));
if (emptyTerminalSet.contains(terminalToInsertCardInto)
&& unusedCardSet.contains(cardToInsert)) {
expectedState.put(terminalToInsertCardInto, cardToInsert);
terminalToInsertCardInto.insertCard(cardToInsert);
emptyTerminalSet.remove(terminalToInsertCardInto);
fullTerminalSet.add(terminalToInsertCardInto);
unusedCardSet.remove(cardToInsert);
usedCardSet.add(cardToInsert);
System.out.println("inserted ["
+ StringUtils.atrToString(cardToInsert.getATR())
+ "] into [" + terminalToInsertCardInto.getName()
+ "]");
}
}
for (int j = 0; j < random.nextInt(numberOfCards); j++) {
final SimulatedCardTerminal terminalToRemoveCardFrom = terminalsToExercise
.get(random.nextInt(numberOfTerminals));
final SimulatedCard cardToRemove = expectedState
.get(terminalToRemoveCardFrom);
if (fullTerminalSet.contains(terminalToRemoveCardFrom)
&& usedCardSet.contains(cardToRemove)) {
expectedState.remove(terminalToRemoveCardFrom);
terminalToRemoveCardFrom.removeCard();
emptyTerminalSet.add(terminalToRemoveCardFrom);
fullTerminalSet.remove(terminalToRemoveCardFrom);
usedCardSet.remove(cardToRemove);
unusedCardSet.add(cardToRemove);
System.out.println("removed ["
+ StringUtils.atrToString(cardToRemove.getATR())
+ "] from [" + terminalToRemoveCardFrom.getName()
+ "]");
}
}
}
Thread.sleep(1000);
cardAndTerminalManager.stop();
assertEquals(expectedState, recorder.getRecordedState());
}
private final class NPEProneCardTerminalEventsListener
implements
CardTerminalEventsListener {
@Override
public void terminalAttached(final CardTerminal cardTerminal) {
throw new NullPointerException(
"Fake NPE attempting to trash a CardTerminalEventsListener");
}
@Override
public void terminalDetached(final CardTerminal cardTerminal) {
throw new NullPointerException(
"Fake NPE attempting to trash a CardTerminalEventsListener");
}
@Override
public void terminalEventsInitialized() {
System.out.println("Terminal Events Initialised");
}
}
private final class NPEProneCardEventsListener
implements
CardEventsListener {
@Override
public void cardInserted(final CardTerminal cardTerminal,
final Card card) {
throw new NullPointerException(
"Fake NPE attempting to trash a CardEventsListener");
}
@Override
public void cardRemoved(final CardTerminal cardTerminal) {
throw new NullPointerException(
"Fake NPE attempting to trash a CardEventsListener");
}
@Override
public void cardEventsInitialized() {
System.out.println("Card Events Initialised");
}
}
}