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);
        }
    }
}