package de.persosim.simulator; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.PrintStream; import java.io.UnsupportedEncodingException; import org.junit.After; import org.junit.Before; import org.junit.Test; import de.persosim.simulator.perso.Personalization; import de.persosim.simulator.perso.Profile01; import de.persosim.simulator.platform.Iso7816; import de.persosim.simulator.test.PersoSimTestCase; import de.persosim.simulator.utils.HexString; import de.persosim.simulator.utils.Utils; public class PersoSimTest extends PersoSimTestCase { PersoSim persoSim; public static final String SELECT_APDU = "00A4020C02011C"; public static final String SW_NO_ERROR = "9000"; //FIXME why this constant? static PrintStream origOut; static ByteArrayOutputStream redStdOut; @Before public void setUp() throws FileNotFoundException { origOut = System.out; } @After public void tearDown() { if(persoSim != null) { persoSim.stopSimulator(); } System.setOut(origOut); } /** * This method returns the default personalization. Currently we use * Profile01 as no specific requirements are known. This might change in the * future. * * @return the default personalization * @throws FileNotFoundException */ public Personalization getDefaultPerso() throws FileNotFoundException { return new Profile01(); } /** * This method extracts the status word from an APDU response String. * @param responseBulk the bulk APDU response * @return the status word */ public static String extractStatusWord(String responseBulk) { return responseBulk.substring(responseBulk.length() - 4); } /** * This method extracts the data response from an APDU response String. * @param responseBulk the bulk APDU response * @return the data */ public static String extractResponse(String responseBulk) { return responseBulk.substring(0, responseBulk.length() - 4).trim(); } /** * This method activates redirection of System.out. */ public static void activateStdOutRedirection() { redStdOut = new ByteArrayOutputStream(); PrintStream stdout = new PrintStream(redStdOut); System.setOut(stdout); origOut.print(redStdOut.toString()); origOut.flush(); } /** * This method reads from redirected System.out. * @return the trimmed data read from redirected System.out * @throws UnsupportedEncodingException */ public static String readRedStdOut() throws UnsupportedEncodingException { String responseBulk = ""; responseBulk = redStdOut.toString("UTF-8").trim(); origOut.print(responseBulk); origOut.flush(); return responseBulk; } /** * Positive test case: check behavior of PersoSim constructor when called with empty argument. * @throws Exception */ @Test public void testPersoSimConstructor_EmptyArgument() throws Exception { activateStdOutRedirection(); persoSim = new PersoSim(new String[]{}); String response = readRedStdOut(); assertTrue(response.contains(CommandParser.LOG_NO_OPERATION)); } /** * Positive test case: check how PersoSim constructor handles null argument. * @throws Exception */ @Test public void testPersoSimConstructor_NullArgument() throws Exception { activateStdOutRedirection(); persoSim = new PersoSim((String) null); String response = readRedStdOut(); assertTrue(response.contains(CommandParser.LOG_NO_OPERATION)); } /** * Positive test case: check how PersoSim command line handles empty argument. * @throws Exception */ @Test public void testExecuteUserCommands_EmptyArgument() throws Exception { activateStdOutRedirection(); CommandParser.executeUserCommands(""); String response = readRedStdOut(); assertTrue(response.contains(CommandParser.LOG_NO_OPERATION)); } /** * Positive test case: check how PersoSim command line handles an unknown argument. * @throws Exception */ @Test public void testExecuteUserCommands_UnknownArgument() throws Exception { activateStdOutRedirection(); CommandParser.executeUserCommands("unknown"); String response = readRedStdOut(); assertTrue(response.contains(CommandParser.LOG_UNKNOWN_ARG)); } /** * Positive test case: test start of socket simulator. * @throws Exception */ @Test public void testStartSimulator() throws Exception { persoSim = new PersoSim(); byte [] response = persoSim.processCommand(HexString.toByteArray(SELECT_APDU)); assertArrayEquals(Utils.toUnsignedByteArray((short)(Iso7816.SW_6F00_UNKNOWN+0x85)), response); persoSim.loadPersonalization(getDefaultPerso()); persoSim.startSimulator(); response = persoSim.processCommand(HexString.toByteArray(SELECT_APDU)); assertArrayEquals(Utils.toUnsignedByteArray(Iso7816.SW_9000_NO_ERROR), response); } /** * Positive test case: second execution of startSimulator() shouldn't do anything, especially not fail or throw an exception. * @throws Exception */ @Test public void testStartSimulator_twice() throws Exception { persoSim = new PersoSim(); persoSim.loadPersonalization(getDefaultPerso()); persoSim.startSimulator(); assertTrue(persoSim.startSimulator()); //ensure that the simulator is still responding byte [] response = persoSim.processCommand(HexString.toByteArray(SELECT_APDU)); assertArrayEquals(Utils.toUnsignedByteArray(Iso7816.SW_9000_NO_ERROR), response); } /** * Positive test case: test stop of socket simulator. * @throws Exception */ @Test public void testStopSimulator() throws Exception { persoSim = new PersoSim(); persoSim.loadPersonalization(getDefaultPerso()); persoSim.startSimulator(); byte [] responseSelect = persoSim.processCommand(HexString.toByteArray(SELECT_APDU)); assertArrayEquals(Utils.toUnsignedByteArray(Iso7816.SW_9000_NO_ERROR), responseSelect); persoSim.stopSimulator(); responseSelect = persoSim.processCommand(HexString.toByteArray(SELECT_APDU)); assertArrayEquals(Utils.toUnsignedByteArray((short)(Iso7816.SW_6F00_UNKNOWN+0x85)), responseSelect); } /** * Positive test case: check behavior of PersoSim constructor when called with unknown argument. */ @Test public void testPersoSimConstructor_UnknownArgument() { persoSim = new PersoSim(new String[]{"unknownCommand"}); assertNotNull(persoSim); } }