Table of Contents
List of Examples
JUV RTMP Tester is a lightweight library/tool that lets you execute functional/regression/load testing of the RTMP server side functionality.
Related:
JUV RTMP Client - J2SE RTMP client
JUV RTMP Client (J2ME edition) - J2ME RTMP client
JUV RTMP Researcher - RTMP debug tool
JUV RTMP Tester library consists of the only JAR file (no dependencies) that should be placed in the class path.
Library requires a license key. If it is not set or invalid then it operates in evaluation (lite) mode.
Evaluation version has next limitations:
There are 2 core entities (classes) provided by the library.
Every method invoked by the server is processed by the IMethodInvoker instance. The default implementation (com.smaxe.uv.invoker.support.MethodInvoker) is based on reflection.
public interface IMethodInvoker
{
/**
* Invokes method with the args of the object o.
* The result is returned through the {@link ICallback callback}.
*
* @param o object which method is invoked
* @param method method to invoke
* @param callback callback to receive invocation result
* @param args method arguments
*/
public void invoke(final Object o, final String method, final ICallback callback, final Object... args);
}
Every custom Java object that is sent/received to/from the server must be presented as ClassObject, i.e. class name + {property : property value} map. The IObjectCreator implementation is responsible for the such transformation.
public interface IObjectCreator
{
/**
* Converts {@link ClassObject co} to the custom type object.
*
* @param co ClassObject instance
* @return custom object
*/
public Object toObject(final ClassObject co);
/**
* Converts {@link Object o} to the {@link ClassObject} instance.
*
* @param o object to represent as ClassObject
* @return ClassObject instance
*/
public ClassObject toClassObject(final Object o);
}
The library doesn't use any specific logging system. It provides a simple interface that lets you either integrate the library with any logging library or use ILogger implementations provided in the com.smaxe.logger.support package.
public interface ILogger
{
/**
* Logs the message.
*
* @param level message level
* @param message message to log
* @param t thrown exception, null if the exception is not thrown
* @param args optional arguments
*/
public void log(final int level, final String message, final Throwable t, final Object... args);
}
Example 4.1. Set license key
com.smaxe.app.uv.loadtester.RtmpTester.setKey("00000-00000-00000-00000-00000");
Example 4.2. Simplest script (just connects to the server)
/**
* SimpleScript
* Behaviour:
* - Client just connects to the server.
*/
public final class SimpleScript extends RtmpClientScript
{
/**
* Constructor.
*/
public SimpleScript()
{
}
}
Example 4.3. Script that connects to the server using connection parameters
/**
* SimpleScript2
* Behaviour:
* - Client connects to the server using connection parameters.
*/
public final class SimpleScript2 extends RtmpClientScript
{
/**
* Constructor.
*/
public SimpleScript2()
{
}
@Override
public Object[] onStart()
{
return new Object[] {"username", "password", "age"}
}
}
Example 4.4. Script that plays stream and disconnects on playback stop
/**
* PlayStreamScript
* Behaviour:
* - Client connects to the server and starts stream playback on successfull connection
* (stream name is defined in the "streamToPlay" property)
* - Client disconnects from the server after stream playback is stopped/completed.
*/
public final class PlayStreamScript extends RtmpClientScript
{
/**
* Constructor.
*/
public PlayStreamScript()
{
}
@Override
public void onConnect(final String code, final Map info)
{
super.onConnect(code, info);
play((String) properties().get("streamToPlay"));
}
@Override
public void onPlayStop(final String stream, final MediaStreamInfo info)
{
super.onPlayStop(stream, info);
disconnect();
}
}
Example 4.5. Script that publishes stream and disconnects on publish stop
/**
* PublishStreamScript
* Behaviour:
* - Client connects to the server and publishes stream on successfull connection
* (stream name is defined in the "streamToPublish" property, stream source is a local flv file).
* - Client disconnects from the server after stream publish is stopped/completed.
*/
public final class PublishStreamScript extends RtmpClientScript
{
/**
* Constructor.
*/
public PublishStreamScript()
{
}
@Override
public void onConnect(final String code, final Map info)
{
super.onConnect(code, info);
publish((String) properties().get("streamToPublish") + "_" + getClientId(),
-1, PUBLISH_MODE_LIVE);
}
@Override
public void onPublishStop(final String stream)
{
super.onPublishStop(stream);
disconnect();
}
}
Example 4.6. Script that connects to the remote shared object
/**
* ConnectSharedObjectScript
* Behaviour:
* - Client connects to the server and connects to shared object "test"
* - Client sets "attribute" value to 1 on shared object connection.
* - Client increments "attribute" value by 1 on every "attribute" value update and
* disconnects if value exceeds 15.
*/
public final class ConnectSharedObjectScript extends RtmpClientScript
{
/**
* Constructor.
*/
public ConnectSharedObjectScript()
{
}
@Override
public void onConnect(final String code, final Map info)
{
super.onConnect(code, info);
connectSharedObject("test");
}
@Override
public void onSharedObjectConnect(final String name)
{
super.onSharedObjectConnect(name);
getSharedObjectData(name).put("attribute", 1 /*value*/);
}
@Override
public void onSharedObjectChange(final String name,
final String attribute, final Object oldValue, final Object newValue)
{
super.onSharedObjectChange(name, attribute, oldValue, newValue);
if ("test".equals(name))
{
if ("attribute".equals(attribute))
{
getSharedObjectData(name).put(attribute, ((Integer) newValue).intValue() + 1);
if ((Integer) getSharedObjectData(name).get(attribute) > 15)
{
closeSharedObject(name);
disconnect();
}
else
if ((Integer) getSharedObjectData(name).get(attribute) > 10)
{
sendSharedObjectAction(name, "notifyEveryone", new Object[] {"Attribute value exceeded 10!"});
}
}
}
}
@Override
public void onSharedObjectDisconnect(final String name)
{
super.onSharedObjectDisconnect(name);
}
}
Example 4.7. RtmpTester executes ConnectSharedObjectScript script
RtmpTester tester = new RtmpTester();
// note: set license key before tester.emulateClient(*) invocation
tester.emulateClient("rtmp://localhost/live", new RtmpClientInfo(ConnectSharedObjectScript.class.getCanonicalName), null /*callback*/);
Example 4.8. Get bandwidth used by script as a function of time
public final class RtmpTesterCallback extends Object implements RtmpTester.ICallback
{
/**
* Constructor.
*/
public RtmpTesterCallback()
{
}
/**
* Notifies about disconnection from the server.
* You can use {@link RtmpTester.IClientSessionInfoProvider provider}
* to get session details.
*/
public void onDisconnect(final RtmpTester.IClientSessionInfoProvider provider)
{
System.out.println("RtmpTesterCallback#onDisconnect: " + provider.id());
// NOTE:
// RtmpTester can provide you with Bandwidth as a function of time
System.out.println("Bandwidth(t):");
for (Map entry : provider.getEntities(RtmpTester.IClientSessionInfoProvider.BANDWIDTH, null /*selector*/))
{
// bandwidth entry represents a map (field name -> value)
// for example,
// {stimestamp=1297, readBytes=87237, writtenBytes=3420, readPackets=221, writtenPackets=5}
// where stimestamp is session timestamp
System.out.println(entry);
}
}
}