Skip to content

Commit

Permalink
asap session mocking implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
thsc42 committed Nov 13, 2020
1 parent 52d836d commit 8fe4339
Show file tree
Hide file tree
Showing 7 changed files with 332 additions and 27 deletions.
26 changes: 0 additions & 26 deletions src/net/sharksystem/asap/ASAPChunkFS.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package net.sharksystem.asap;

import net.sharksystem.asap.util.Helper;
import net.sharksystem.asap.util.Log;

import java.io.*;
import java.util.*;
Expand Down Expand Up @@ -421,29 +420,4 @@ public int getEra() throws IOException {
return this.era;
}

private class MessageIter implements Iterator {
private final List<byte[]> byteMessages;
private int nextIndex;
private String nextString;


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++));
}
}
}
32 changes: 32 additions & 0 deletions src/net/sharksystem/asap/MessageIter.java
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++));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import net.sharksystem.asap.ASAPMessages;

import java.io.IOException;

public interface ASAPMessageReceivedListener {
void asapMessagesReceived(ASAPMessages messages);
void asapMessagesReceived(ASAPMessages messages) throws IOException;
}
15 changes: 15 additions & 0 deletions src/net/sharksystem/asap/apps/ASAPMessageSender.java
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;
}
56 changes: 56 additions & 0 deletions src/net/sharksystem/asap/apps/mock/ASAPMessagesMock.java
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 src/net/sharksystem/asap/apps/mock/ASAPSessionMock.java
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;
}
}
118 changes: 118 additions & 0 deletions test/net/sharksystem/asap/mock/ASAPMockUsage.java
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());
}
}
}
}

0 comments on commit 8fe4339

Please sign in to comment.