1

I have created application using Lync client side SDK 2013 and UCMA 4.0 . Now I test my application with large number of users. How can I simulate large number of client using UCMA or Lync client side SDK?

swapnil
  • 125
  • 11

2 Answers2

1

It depends on what exactly what you want to "simulate".

If you just want call traffic there is sipp, but that is just simple sip calls and doesn't really reflect an actual Microsoft Lync Client.

As far as I know, Microsoft doesn't provide any load testing tools in Lync. You will have to generate them yourself base on what exactly you want to "simulate".

With a UCMA trusted application, you should be able to startup and use a large number of user endpoints to "simulate" common lync services (like randomly changing presence, making calls, send IM's, etc). You would have to create such an app yourself.

Shane Powell
  • 13,698
  • 2
  • 49
  • 61
1

I created a tool in UCMA to do my stress test for all my applications than I have made.

It is simple to make, and it is composed of two parts. This example is a stress tester for calls. Of course, you can easily make a different one by using this example.

  1. We create our platform, follow our Set-CsTrustedApplication.

    var platformSettings = new ProvisionedApplicationPlatformSettings("InnixiTester", "urn:application:innixitester"); 
    var collabPlatform = new CollaborationPlatform(platformSettings);
    
    collabPlatform.EndStartup(collabPlatform.BeginStartup(null, null));
    

Ok, I know what I am doing here is a wrong chaining together, the Begin and the End into one line of code. However, this is just a code exemple. I invite you to read the article of Tom Morgan, he explains why it is not good to do it like me.

  1. We use here a Parallel loop to create all our users-endpoint. In that way, it goes faster.

    /*
     * Proprieties of the class 
     */
    
    private AutoResetEvent _waitForStressTestToFinish = new AutoResetEvent(false);
    private List<UserEndpoint> _listUserEndpoints = new List<UserEndpoint>();
    private int _maxUsers = 200;
    private int _tickTotal;
    private int _tickCount;
    private int _nbrCallsByIntervall;
    
    /*
     * End
     */
    
    _maxUsers = 200; // Nbr max of users
    const var callsTotal = 200; // Nbr of total call
    const var timeToTest = 30; // Total time to test
    const var intervalOfCalls = 5; // We want to make our calls between specific intervals
    
    
    Parallel.For(0, _maxUsers, i => 
            {
                CreateUserEndpoint(collabPlatform, i.ToString());
            });
    
  2. You simply create your UserEndpoint here. The scenario is that my users in the active directory are stressuser0 to stressuser200. With extension starting from +14250 to +1425200

    private void CreateUserEndpoint(CollaborationPlatform cp, string iteration)
    {
        try
        {
            UserEndpointSettings settingsUser = new UserEndpointSettings($"sip:stressuser{iteration}@pferde.net", "pool2010.pferde.net", 5061);
    
            settingsUser = InitializePublishAlwaysOnlineSettings(settingsUser);
    
            var userEndpoint = new UserEndpoint(cp, settingsUser);
    
            userEndpoint.EndEstablish(userEndpoint.BeginEstablish(null, null));
    
            PublishOnline(userEndpoint);
    
            _listUserEndpoints.Add(userEndpoint);
    
            Console.WriteLine($"The User Endpoint owned by URI: {userEndpoint.OwnerUri} was created\n");
        }
        catch (Exception)
        {
            Console.WriteLine($"failed to create for --> sip:stressuser{iteration}@pferde.net");
            throw;
        }
    
    }
    
    private UserEndpointSettings InitializePublishAlwaysOnlineSettings(UserEndpointSettings settings)
    {
        settings.AutomaticPresencePublicationEnabled = true;
        settings.Presence.PreferredServiceCapabilities.AudioSupport = CapabilitySupport.Supported;
    
        return (settings);
    }
    
  3. Now time to place the calls! We are going to code a simple algorithm with a timer. Is going to calculate how many calls it needs to make for X time and for Y Calls and for Z intervals.

       Console.WriteLine("Tape a key to place calls...");
       Console.ReadKey();
    
       PlaceCalls(callsTotal, timeToTest, intervalOfCalls);
    
       _waitForStressTestToFinish.WaitOne();
    
       }
      catch (Exception ex)
     {
     Console.WriteLine($"Shutting down platform due to error {ex}");
     ShutdownPlatform(collabPlatform);
     }
     ShutdownPlatform(collabPlatform);
    }
    
    private void PlaceCalls(int callsMax, int timeMax, int timeIntervall)
    {
        _tickTotal = timeMax / timeIntervall;
        _nbrCallsByIntervall= callsMax / _tickTotal;
    
        Console.WriteLine($"_nbrCallsByIntervall --> {_nbrCallsByIntervall}");
    
        var timeIntervalTimespan = new TimeSpan(0, 0, 0, timeIntervall);
        _timer = new Timer(timeIntervalTimespan.TotalMilliseconds);
        _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
        _timer.Enabled = true;
    }
    
    
    void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        if (_tickCount < _tickTotal)
        {
            Console.WriteLine($"\n Pause Timer | On {_tickCount} to {_tickTotal}\n");
            _timer.Enabled = false;
            for (var i = 0; i <= _nbrCallsByIntervall - 1; ++i)
            {
                ConversationSettings convSettings = new ConversationSettings();
                Conversation conversation = new Conversation(_listUserEndpoints[generateNumber(0, _listUserEndpoints.Count)], convSettings);
    
                var audioVideoCall = new AudioVideoCall(conversation);
                CallEstablishOptions options = new CallEstablishOptions();
    
                var gNbr = generateNumber(0, _listUserEndpoints.Count);
                try
                {
                 // Here I'm calling a single phone number. You can use GenerateNumber to call stressusers each others. But you have to extend your code to accept the calls coming.
                    audioVideoCall.BeginEstablish($"3322", options, null, audioVideoCall);
                }
                catch (Exception)
                {
                    Console.WriteLine("Fail to Call the remote user...");
                    throw;
                }
               Console.WriteLine($"Call--> +1425{gNbr}.Counter--> {_tickCount} Ticket--> {_tickTotal} and thread id {Thread.CurrentThread.ManagedThreadId}");
            }
            _tickCount++;
            _timer.Enabled = true;
            Console.WriteLine("\n reStart Timer \n");
        }
        else
        {
            Console.WriteLine("\n!!! END Stress test !!!\n");
            _timer.Enabled = false;
            _waitForCallToEstablish.Set();
        }
    }
    
    private int generateNumber(int min, int max)
    {
        var r = new Random();
        Thread.Sleep(200);
        return (r.Next(min, max));
    }
    
Magellan
  • 325
  • 4
  • 12