-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
332 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package net.sharksystem.asap; | ||
|
||
import java.io.FileNotFoundException; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
import java.util.NoSuchElementException; | ||
|
||
public class MessageIter implements Iterator { | ||
private final List<byte[]> byteMessages; | ||
private int nextIndex; | ||
private String nextString; | ||
|
||
|
||
public MessageIter(List<byte[]> byteMessages) throws FileNotFoundException { | ||
this.byteMessages = byteMessages; | ||
this.nextIndex = 0; | ||
} | ||
|
||
@Override | ||
public boolean hasNext() { | ||
return this.byteMessages.size() > nextIndex; | ||
} | ||
|
||
@Override | ||
public String next() { | ||
if (!this.hasNext()) { | ||
throw new NoSuchElementException("no more messages"); | ||
} | ||
|
||
return new String(this.byteMessages.get(nextIndex++)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package net.sharksystem.asap.apps; | ||
|
||
import net.sharksystem.asap.ASAPException; | ||
|
||
public interface ASAPMessageSender { | ||
/** | ||
* Send a message | ||
* @param appName | ||
* @param uri | ||
* @param message | ||
* @throws ASAPException | ||
*/ | ||
void sendASAPMessage(CharSequence appName, CharSequence uri, | ||
byte[] message) throws ASAPException; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package net.sharksystem.asap.apps.mock; | ||
|
||
import net.sharksystem.asap.ASAPException; | ||
import net.sharksystem.asap.ASAPMessages; | ||
import net.sharksystem.asap.MessageIter; | ||
|
||
import java.io.IOException; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
|
||
class ASAPMessagesMock implements ASAPMessages { | ||
private final CharSequence appName; | ||
private final CharSequence uri; | ||
private final List<byte[]> serializedAppPDUs; | ||
|
||
ASAPMessagesMock(CharSequence appName, CharSequence uri, List<byte[]> serializedAppPDUs) { | ||
this.appName = appName; | ||
this.uri = uri; | ||
this.serializedAppPDUs = serializedAppPDUs; | ||
} | ||
|
||
@Override | ||
public int size() throws IOException { | ||
return this.serializedAppPDUs.size(); | ||
} | ||
|
||
@Override | ||
public CharSequence getURI() { | ||
return this.uri; | ||
} | ||
|
||
@Override | ||
public CharSequence getFormat() { | ||
return this.appName; | ||
} | ||
|
||
@Override | ||
public Iterator<CharSequence> getMessagesAsCharSequence() throws IOException { | ||
return new MessageIter(this.serializedAppPDUs); | ||
} | ||
|
||
@Override | ||
public Iterator<byte[]> getMessages() throws IOException { | ||
return this.serializedAppPDUs.iterator(); | ||
} | ||
|
||
@Override | ||
public CharSequence getMessageAsCharSequence(int position, boolean chronologically) throws ASAPException, IOException { | ||
throw new ASAPException("not implemented in mocking class"); | ||
} | ||
|
||
@Override | ||
public byte[] getMessage(int position, boolean chronologically) throws ASAPException, IOException { | ||
throw new ASAPException("not implemented in mocking class"); | ||
} | ||
} |
108 changes: 108 additions & 0 deletions
108
src/net/sharksystem/asap/apps/mock/ASAPSessionMock.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package net.sharksystem.asap.apps.mock; | ||
|
||
import net.sharksystem.asap.ASAPException; | ||
import net.sharksystem.asap.ASAPMessages; | ||
import net.sharksystem.asap.apps.ASAPMessageReceivedListener; | ||
import net.sharksystem.asap.apps.ASAPMessageSender; | ||
|
||
import java.io.IOException; | ||
import java.util.*; | ||
|
||
public class ASAPSessionMock implements ASAPMessageSender { | ||
private Map<CharSequence, Map<CharSequence, List<byte[]>>> appMsgStorage = new HashMap<>(); | ||
private Map<CharSequence, List<ASAPMessageReceivedListener>> listenerMap = new HashMap<>(); | ||
private boolean connected = false; | ||
|
||
private List<byte[]> getStorage(CharSequence appName, CharSequence uri) { | ||
Map<CharSequence, List<byte[]>> charSequenceListMap = this.appMsgStorage.get(appName); | ||
if (charSequenceListMap == null) { | ||
charSequenceListMap = new HashMap<>(); | ||
this.appMsgStorage.put(appName, charSequenceListMap); | ||
} | ||
|
||
List<byte[]> byteMessageList = charSequenceListMap.get(uri); | ||
if (byteMessageList == null) { | ||
byteMessageList = new ArrayList<>(); | ||
charSequenceListMap.put(uri, byteMessageList); | ||
} | ||
|
||
return byteMessageList; | ||
} | ||
|
||
@Override | ||
public void sendASAPMessage(CharSequence appName, CharSequence uri, byte[] message) throws ASAPException { | ||
synchronized(this.appMsgStorage) { | ||
List<byte[]> storage = this.getStorage(appName, uri); | ||
storage.add(message); | ||
} | ||
|
||
if(this.connected) this.notifyListeners(); | ||
} | ||
|
||
public void addASAPMessageReceivedListener(CharSequence format, ASAPMessageReceivedListener listener) { | ||
List<ASAPMessageReceivedListener> asapMessageReceivedListeners = this.listenerMap.get(format); | ||
if(asapMessageReceivedListeners == null) { | ||
asapMessageReceivedListeners = new ArrayList<>(); | ||
this.listenerMap.put(format, asapMessageReceivedListeners); | ||
} | ||
|
||
asapMessageReceivedListeners.add(listener); | ||
} | ||
|
||
/** | ||
* Simulate a connection - this mock will notify all registered listeners and remove messages. | ||
* After connected - any sendASAPMessage call will immediately lead to a listener call. | ||
*/ | ||
public void connect() { | ||
this.connected = true; | ||
this.notifyListeners(); | ||
} | ||
|
||
private void notifyListeners() { | ||
Map<CharSequence, Map<CharSequence, List<byte[]>>> appUriMessages = null; | ||
synchronized(this.appMsgStorage) { | ||
if(this.appMsgStorage.isEmpty()) return; | ||
|
||
// else copy | ||
appUriMessages = this.appMsgStorage; | ||
|
||
// create empty | ||
this.appMsgStorage = new HashMap<>(); | ||
} | ||
|
||
// send | ||
for(CharSequence appName : appUriMessages.keySet()) { | ||
Map<CharSequence, List<byte[]>> appMap = appUriMessages.get(appName); | ||
if(appMap != null) { | ||
List<ASAPMessageReceivedListener> asapMessageReceivedListeners = this.listenerMap.get(appName); | ||
if(asapMessageReceivedListeners != null && !asapMessageReceivedListeners.isEmpty()) { | ||
Set<CharSequence> uris = appMap.keySet(); | ||
for(CharSequence uri : uris) { | ||
List<byte[]> serializedAppPDUs = appMap.get(uri); | ||
for(ASAPMessageReceivedListener listener : asapMessageReceivedListeners) { | ||
// create a thread for each listener | ||
new Thread(new Runnable() { | ||
@Override | ||
public void run() { | ||
ASAPMessages messagesMock = new ASAPMessagesMock(appName, uri, serializedAppPDUs); | ||
try { | ||
listener.asapMessagesReceived(messagesMock); | ||
} catch (IOException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
}).start(); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* disconnect - opposite of connect | ||
*/ | ||
public void disconnect() { | ||
this.connected = false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package net.sharksystem.asap.mock; | ||
|
||
import net.sharksystem.asap.ASAPException; | ||
import net.sharksystem.asap.ASAPMessages; | ||
import net.sharksystem.asap.apps.ASAPMessageSender; | ||
import net.sharksystem.asap.apps.ASAPMessageReceivedListener; | ||
import net.sharksystem.asap.apps.mock.ASAPSessionMock; | ||
import org.junit.Test; | ||
|
||
import java.io.*; | ||
import java.util.Iterator; | ||
|
||
/** | ||
* How to mock ASAP communication | ||
*/ | ||
public class ASAPMockUsage { | ||
|
||
private static final CharSequence YOUR_APP_NAME = "yourAppName"; | ||
private static final CharSequence YOUR_URI = "yourSchema://example"; | ||
|
||
/** | ||
* a serialization example | ||
* @param exampleLong | ||
* @param exampleString | ||
* @param exampleBoolean | ||
* @return | ||
*/ | ||
private static byte[] serializeExample(long exampleLong, String exampleString, boolean exampleBoolean) throws IOException { | ||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||
DataOutputStream daos = new DataOutputStream(baos); | ||
|
||
// serialize | ||
daos.writeLong(exampleLong); | ||
daos.writeUTF(exampleString); | ||
daos.writeBoolean(exampleBoolean); | ||
|
||
return baos.toByteArray(); | ||
} | ||
|
||
/** | ||
* a deserialization example | ||
*/ | ||
private static void deserializeExample(byte[] serializedData) throws IOException { | ||
ByteArrayInputStream bais = new ByteArrayInputStream(serializedData); | ||
DataInputStream dais = new DataInputStream(bais); | ||
|
||
// deserialize | ||
long exampleLong = dais.readLong(); | ||
String exampleString = dais.readUTF(); | ||
boolean exampleBoolean = dais.readBoolean(); | ||
|
||
// call a methode in your app | ||
|
||
// here: just print | ||
System.out.println("received: " + exampleLong + " | " + exampleString + " | " + exampleBoolean); | ||
} | ||
|
||
@Test | ||
public void usageTest1() throws IOException, ASAPException, InterruptedException { | ||
/* Imagine we are here inside your application code. Data are to be transmitted. You implemented | ||
a methode that serializes your data (PDU) into an array of bytes | ||
*/ | ||
|
||
// example - this should be produced by your application | ||
byte[] serializedData = ASAPMockUsage.serializeExample(42, "don't panic", true); | ||
|
||
// now: ASAP is used to deliver those data - we mock it | ||
ASAPSessionMock asapSessionMock = new ASAPSessionMock(); | ||
|
||
ASAPMessageSender asapMessageSender = asapSessionMock; | ||
|
||
asapMessageSender.sendASAPMessage(YOUR_APP_NAME, YOUR_URI, serializedData); | ||
|
||
// we simulated a sender - now, we need to simulate recipient | ||
|
||
// this should be replaced with your code - you must implement a listener. | ||
ASAPMessageReceivedListenerExample asapMessageReceivedListenerExample = | ||
new ASAPMessageReceivedListenerExample(); | ||
|
||
// register your listener (or that mock) with asap connection mock | ||
asapSessionMock.addASAPMessageReceivedListener(YOUR_APP_NAME, asapMessageReceivedListenerExample); | ||
|
||
// simulate ASAP encounter | ||
asapSessionMock.connect(); | ||
|
||
// give your app a moment to process | ||
Thread.sleep(1000); | ||
|
||
// add another message while still connected | ||
asapMessageSender.sendASAPMessage(YOUR_APP_NAME, YOUR_URI, | ||
ASAPMockUsage.serializeExample(43, "second message", false)); | ||
|
||
asapSessionMock.disconnect(); | ||
System.out.println("send message without connection"); | ||
asapMessageSender.sendASAPMessage(YOUR_APP_NAME, YOUR_URI, | ||
ASAPMockUsage.serializeExample(44, "third message", false)); | ||
asapMessageSender.sendASAPMessage(YOUR_APP_NAME, YOUR_URI, | ||
ASAPMockUsage.serializeExample(45, "forth message", false)); | ||
Thread.sleep(1000); | ||
|
||
System.out.println("re-connect"); | ||
asapSessionMock.connect(); | ||
Thread.sleep(1000); | ||
} | ||
|
||
private class ASAPMessageReceivedListenerExample implements ASAPMessageReceivedListener { | ||
@Override | ||
public void asapMessagesReceived(ASAPMessages messages) throws IOException { | ||
CharSequence format = messages.getFormat(); | ||
CharSequence uri = messages.getURI(); | ||
System.out.println("asap message received (" + format + " | " + uri + "). size == " + messages.size()); | ||
Iterator<byte[]> yourPDUIter = messages.getMessages(); | ||
while (yourPDUIter.hasNext()) { | ||
ASAPMockUsage.deserializeExample(yourPDUIter.next()); | ||
} | ||
} | ||
} | ||
} |