using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Perforce.P4;
namespace p4api.net.unit.test
{
[TestClass]
public class P4ServerMultiThreadingTest
{
String TestDir = "c:\\MyTestDir";
P4Command cmd1 = null;
P4Command cmd2 = null;
P4Command cmd3 = null;
P4Command cmd4 = null;
P4Command cmd5 = null;
P4Command cmd6 = null;
int cmdCnt1 = 0;
int cmdCnt2 = 0;
int cmdCnt3 = 0;
int cmdCnt4 = 0;
int cmdCnt5 = 0;
int cmdCnt6 = 0;
bool run = true;
TimeSpan delay = TimeSpan.FromMilliseconds(5);
private void cmdThreadProc1()
{
try
{
while (run)
{
cmdCnt1++;
cmd1 = new P4Command(server, "fstat", false, "//depot/...");
DateTime StartedAt = DateTime.Now;
WriteLine(string.Format("Thread 1 starting command: {0:X8}, at {1}",
cmd1.CommandId, StartedAt.ToLongTimeString()));
P4CommandResult result = cmd1.Run();
WriteLine(string.Format("Thread 1 Finished command: {0:X8}, at {1}, run time {2} Milliseconds",
cmd1.CommandId, StartedAt.ToLongTimeString(), (DateTime.Now - StartedAt).TotalMilliseconds));
P4CommandResult lastResult = server.LastResults;
Assert.AreEqual(result.Success, lastResult.Success);
if (result.InfoOutput != null)
{
Assert.AreEqual(result.InfoOutput.Count, lastResult.InfoOutput.Count);
}
else
{
Assert.IsNull(lastResult.InfoOutput);
}
if (result.ErrorList != null)
{
Assert.AreEqual(result.ErrorList.Count, lastResult.ErrorList.Count);
}
else
{
Assert.IsNull(result.ErrorList);
}
if (result.TextOutput != null)
{
Assert.AreEqual(result.TextOutput, lastResult.TextOutput);
}
else
{
Assert.IsNull(lastResult.TextOutput);
}
if (result.TaggedOutput != null)
{
Assert.AreEqual(result.TaggedOutput.Count, lastResult.TaggedOutput.Count);
}
else
{
Assert.IsNull(lastResult.TaggedOutput);
}
Assert.AreEqual(result.Cmd, lastResult.Cmd);
if (result.CmdArgs != null)
{
Assert.AreEqual(result.CmdArgs.Length, lastResult.CmdArgs.Length);
}
else
{
Assert.IsNull(lastResult.CmdArgs);
}
if (!result.Success)
{
WriteLine(string.Format("Thread 1, fstat failed:{0}", (result.ErrorList != null && result.ErrorList.Count > 0) ? result.ErrorList[0].ErrorMessage : "<unknown error>"));
}
else
{
WriteLine(string.Format("Thread 1, fstat Success:{0}", (result.InfoOutput != null && result.InfoOutput.Count > 0) ? result.InfoOutput[0].Message : "<no output>"));
}
//Assert.IsTrue(result.Success);
if (delay != TimeSpan.Zero)
{
Thread.Sleep(delay);
}
}
WriteLine(string.Format("Thread 1 cleanly exited after running {0} commands", cmdCnt1));
return;
}
catch (ThreadAbortException)
{
Thread.ResetAbort();
return;
}
catch (Exception ex)
{
Assert.Fail(ex.Message);
}
}
private void cmdThreadProc2()
{
try
{
while (run)
{
cmdCnt2++;
cmd2 = new P4Command(server, "dirs", false, "//depot/*");
DateTime StartedAt = DateTime.Now;
WriteLine(string.Format("Thread 2 starting command: {0:X8}, at {1}",
cmd2.CommandId, StartedAt.ToLongTimeString()));
P4CommandResult result = cmd2.Run();
WriteLine(string.Format("Thread 2 Finished command: {0:X8}, at {1}, run time {2} Milliseconds",
cmd2.CommandId, StartedAt.ToLongTimeString(), (DateTime.Now - StartedAt).TotalMilliseconds));
P4CommandResult lastResult = server.LastResults;
Assert.AreEqual(result.Success, lastResult.Success);
if (result.InfoOutput != null)
{
Assert.AreEqual(result.InfoOutput.Count, lastResult.InfoOutput.Count);
}
else
{
Assert.IsNull(lastResult.InfoOutput);
}
if (result.ErrorList != null)
{
Assert.AreEqual(result.ErrorList.Count, lastResult.ErrorList.Count);
}
else
{
Assert.IsNull(result.ErrorList);
}
if (result.TextOutput != null)
{
Assert.AreEqual(result.TextOutput, lastResult.TextOutput);
}
else
{
Assert.IsNull(lastResult.TextOutput);
}
if (result.TaggedOutput != null)
{
Assert.AreEqual(result.TaggedOutput.Count, lastResult.TaggedOutput.Count);
}
else
{
Assert.IsNull(lastResult.TaggedOutput);
}
Assert.AreEqual(result.Cmd, lastResult.Cmd);
if (result.CmdArgs != null)
{
Assert.AreEqual(result.CmdArgs.Length, lastResult.CmdArgs.Length);
}
else
{
Assert.IsNull(lastResult.CmdArgs);
}
if (!result.Success)
{
WriteLine(string.Format("Thread 2, dirs failed:{0}", (result.ErrorList != null && result.ErrorList.Count > 0) ? result.ErrorList[0].ErrorMessage : "<unknown error>"));
}
else
{
WriteLine(string.Format("Thread 2, dirs Success:{0}", (result.InfoOutput != null && result.InfoOutput.Count > 0) ? result.InfoOutput[0].Message : "<no output>"));
}
//Assert.IsTrue(result.Success);
if (delay != TimeSpan.Zero)
{
Thread.Sleep(delay);
}
}
WriteLine(string.Format("Thread 2 cleanly exited after running {0} commands", cmdCnt2));
}
catch (ThreadAbortException)
{
Thread.ResetAbort();
return;
}
catch (Exception ex)
{
Assert.Fail(ex.Message);
}
}
private void cmdThreadProc3()
{
try
{
while (run)
{
cmdCnt3++;
cmd3 = new P4Command(server, "edit", false, "-n", "C:\\MyTestDir\\admin_space\\...");
DateTime StartedAt = DateTime.Now;
WriteLine(string.Format("Thread 3 starting command: {0:X8}, at {1}",
cmd3.CommandId, StartedAt.ToLongTimeString()));
P4CommandResult result = cmd3.Run();
WriteLine(string.Format("Thread 3 Finished command: {0:X8}, at {1}, run time {2} Milliseconds",
cmd3.CommandId, StartedAt.ToLongTimeString(), (DateTime.Now - StartedAt).TotalMilliseconds));
P4CommandResult lastResult = server.LastResults;
Assert.AreEqual(result.Success, lastResult.Success);
if (result.InfoOutput != null)
{
Assert.AreEqual(result.InfoOutput.Count, lastResult.InfoOutput.Count);
}
else
{
Assert.IsNull(lastResult.InfoOutput);
}
if (result.ErrorList != null)
{
Assert.AreEqual(result.ErrorList.Count, lastResult.ErrorList.Count);
}
else
{
Assert.IsNull(result.ErrorList);
}
if (result.TextOutput != null)
{
Assert.AreEqual(result.TextOutput, lastResult.TextOutput);
}
else
{
Assert.IsNull(lastResult.TextOutput);
}
if (result.TaggedOutput != null)
{
Assert.AreEqual(result.TaggedOutput.Count, lastResult.TaggedOutput.Count);
}
else
{
Assert.IsNull(lastResult.TaggedOutput);
}
Assert.AreEqual(result.Cmd, lastResult.Cmd);
if (result.CmdArgs != null)
{
Assert.AreEqual(result.CmdArgs.Length, lastResult.CmdArgs.Length);
}
else
{
Assert.IsNull(lastResult.CmdArgs);
}
if (!result.Success)
{
WriteLine(string.Format("Thread 3, edit failed:{0}", (result.ErrorList != null && result.ErrorList.Count > 0) ? result.ErrorList[0].ErrorMessage : "<unknown error>"));
}
else
{
WriteLine(string.Format("Thread 3, edit Success:{0}", (result.InfoOutput != null && result.InfoOutput.Count > 0) ? result.InfoOutput[0].Message : "<no output>"));
}
//Assert.IsTrue(result.Success);
if (delay != TimeSpan.Zero)
{
Thread.Sleep(delay);
}
}
WriteLine(string.Format("Thread 3 cleanly exited after running {0} commands", cmdCnt3));
}
catch (ThreadAbortException)
{
Thread.ResetAbort();
return;
}
catch (Exception ex)
{
Assert.Fail(ex.Message);
}
}
private void cmdThreadProc4()
{
try
{
while (run)
{
cmdCnt4++;
string val = P4Server.Get("P4IGNORE");
bool _p4IgnoreSet = !string.IsNullOrEmpty(val);
if (_p4IgnoreSet)
{
WriteLine(string.Format("P4Ignore is set, {0}", val));
}
else
{
WriteLine("P4Ignore is not set");
}
cmd4 = new P4Command(server, "fstat", false, "//depot/...");
DateTime StartedAt = DateTime.Now;
WriteLine(string.Format("Thread 4 starting command: {0:X8}, at {1}",
cmd4.CommandId, StartedAt.ToLongTimeString()));
P4CommandResult result = cmd4.Run();
WriteLine(string.Format("Thread 4 Finished command: {0:X8}, at {1}, run time {2} Milliseconds",
cmd4.CommandId, StartedAt.ToLongTimeString(), (DateTime.Now - StartedAt).TotalMilliseconds));
P4CommandResult lastResult = server.LastResults;
Assert.AreEqual(result.Success, lastResult.Success);
if (result.InfoOutput != null)
{
Assert.AreEqual(result.InfoOutput.Count, lastResult.InfoOutput.Count);
}
else
{
Assert.IsNull(lastResult.InfoOutput);
}
if (result.ErrorList != null)
{
Assert.AreEqual(result.ErrorList.Count, lastResult.ErrorList.Count);
}
else
{
Assert.IsNull(result.ErrorList);
}
if (result.TextOutput != null)
{
Assert.AreEqual(result.TextOutput, lastResult.TextOutput);
}
else
{
Assert.IsNull(lastResult.TextOutput);
}
if (result.TaggedOutput != null)
{
Assert.AreEqual(result.TaggedOutput.Count, lastResult.TaggedOutput.Count);
}
else
{
Assert.IsNull(lastResult.TaggedOutput);
}
Assert.AreEqual(result.Cmd, lastResult.Cmd);
if (result.CmdArgs != null)
{
Assert.AreEqual(result.CmdArgs.Length, lastResult.CmdArgs.Length);
}
else
{
Assert.IsNull(lastResult.CmdArgs);
}
if (!result.Success)
{
WriteLine(string.Format("Thread 4, fstat failed:{0}", (result.ErrorList != null && result.ErrorList.Count > 0) ? result.ErrorList[0].ErrorMessage : "<unknown error>"));
}
else
{
WriteLine(string.Format("Thread 4, fstat Success:{0}", (result.InfoOutput != null && result.InfoOutput.Count > 0) ? result.InfoOutput[0].Message : "<no output>"));
}
//Assert.IsTrue(result.Success);
if (delay != TimeSpan.Zero)
{
Thread.Sleep(delay);
}
}
WriteLine(string.Format("Thread 4 cleanly exited after running {0} commands", cmdCnt4));
}
catch (ThreadAbortException)
{
Thread.ResetAbort();
return;
}
catch (Exception ex)
{
Assert.Fail(ex.Message);
}
}
private void cmdThreadProc5()
{
try
{
while (run)
{
cmdCnt5++;
cmd5 = new P4Command(server, "dirs", false, "//depot/*");
DateTime StartedAt = DateTime.Now;
WriteLine(string.Format("Thread 5 starting command: {0:X8}, at {1}",
cmd5.CommandId, StartedAt.ToLongTimeString()));
P4CommandResult result = cmd5.Run();
WriteLine(string.Format("Thread 5 Finished command: {0:X8}, at {1}, run time {2} Milliseconds",
cmd5.CommandId, StartedAt.ToLongTimeString(), (DateTime.Now - StartedAt).TotalMilliseconds));
P4CommandResult lastResult = server.LastResults;
Assert.AreEqual(result.Success, lastResult.Success);
if (result.InfoOutput != null)
{
Assert.AreEqual(result.InfoOutput.Count, lastResult.InfoOutput.Count);
}
else
{
Assert.IsNull(lastResult.InfoOutput);
}
if (result.ErrorList != null)
{
Assert.AreEqual(result.ErrorList.Count, lastResult.ErrorList.Count);
}
else
{
Assert.IsNull(result.ErrorList);
}
if (result.TextOutput != null)
{
Assert.AreEqual(result.TextOutput, lastResult.TextOutput);
}
else
{
Assert.IsNull(lastResult.TextOutput);
}
if (result.TaggedOutput != null)
{
Assert.AreEqual(result.TaggedOutput.Count, lastResult.TaggedOutput.Count);
}
else
{
Assert.IsNull(lastResult.TaggedOutput);
}
Assert.AreEqual(result.Cmd, lastResult.Cmd);
if (result.CmdArgs != null)
{
Assert.AreEqual(result.CmdArgs.Length, lastResult.CmdArgs.Length);
}
else
{
Assert.IsNull(lastResult.CmdArgs);
}
if (!result.Success)
{
WriteLine(string.Format("Thread 5, dirs failed:{0}", (result.ErrorList != null && result.ErrorList.Count > 0) ? result.ErrorList[0].ErrorMessage : "<unknown error>"));
}
else
{
WriteLine(string.Format("Thread 5, dirs Success:{0}", (result.InfoOutput != null && result.InfoOutput.Count > 0) ? result.InfoOutput[0].Message : "<no output>"));
}
//Assert.IsTrue(result.Success);
if (delay != TimeSpan.Zero)
{
Thread.Sleep(delay);
}
}
WriteLine(string.Format("Thread 5 cleanly exited after running {0} commands", cmdCnt5));
}
catch (ThreadAbortException)
{
Thread.ResetAbort();
return;
}
catch (Exception ex)
{
Assert.Fail(ex.Message);
}
}
private void cmdThreadProc6()
{
try
{
while (run)
{
cmdCnt6++;
cmd6 = new P4Command(server, "edit", false, "-n", "C:\\MyTestDir\\admin_space\\...");
DateTime StartedAt = DateTime.Now;
WriteLine(string.Format("Thread 6 starting command: {0:X8}, at {1}",
cmd6.CommandId, StartedAt.ToLongTimeString()));
P4CommandResult result = cmd6.Run();
WriteLine(string.Format("Thread 6 Finished command: {0:X8}, at {1}, run time {2} Milliseconds",
cmd6.CommandId, StartedAt.ToLongTimeString(), (DateTime.Now - StartedAt).TotalMilliseconds));
P4CommandResult lastResult = server.LastResults;
Assert.AreEqual(result.Success, lastResult.Success);
if (result.InfoOutput != null)
{
Assert.AreEqual(result.InfoOutput.Count, lastResult.InfoOutput.Count);
}
else
{
Assert.IsNull(lastResult.InfoOutput);
}
if (result.ErrorList != null)
{
Assert.AreEqual(result.ErrorList.Count, lastResult.ErrorList.Count);
}
else
{
Assert.IsNull(result.ErrorList);
}
if (result.TextOutput != null)
{
Assert.AreEqual(result.TextOutput, lastResult.TextOutput);
}
else
{
Assert.IsNull(lastResult.TextOutput);
}
if (result.TaggedOutput != null)
{
Assert.AreEqual(result.TaggedOutput.Count, lastResult.TaggedOutput.Count);
}
else
{
Assert.IsNull(lastResult.TaggedOutput);
}
Assert.AreEqual(result.Cmd, lastResult.Cmd);
if (result.CmdArgs != null)
{
Assert.AreEqual(result.CmdArgs.Length, lastResult.CmdArgs.Length);
}
else
{
Assert.IsNull(lastResult.CmdArgs);
}
if (!result.Success)
{
WriteLine(string.Format("Thread 6, edit failed:{0}", (result.ErrorList != null && result.ErrorList.Count > 0) ? result.ErrorList[0].ErrorMessage : "<unknown error>"));
}
else
{
WriteLine(string.Format("Thread 6, edit Success:{0}", (result.InfoOutput != null && result.InfoOutput.Count > 0) ? result.InfoOutput[0].Message : "<no output>"));
}
//Assert.IsTrue(result.Success);
if (delay != TimeSpan.Zero)
{
Thread.Sleep(delay);
}
}
WriteLine(string.Format("Thread 6 cleanly exited after running {0} commands", cmdCnt6));
}
catch (ThreadAbortException)
{
Thread.ResetAbort();
return;
}
catch (Exception ex)
{
Assert.Fail(ex.Message);
}
}
P4Server server = null;
#if _LOG_TO_FILE
static System.IO.StreamWriter sw = null;
public static void WriteLine(string msg)
{
lock (sw)
{
sw.WriteLine(msg);
sw.Flush();
}
}
public static void LogBridgeMessage( int log_level,String source,String message )
{
WriteLine(string.Format("[{0}] {1}:{2}", source, log_level, message));
}
private static LogFile.LogMessageDelgate LogFn = new LogFile.LogMessageDelgate(LogBridgeMessage);
#else
public void WriteLine(string msg)
{
Trace.WriteLine(msg);
}
#endif
/// <summary>
///A test for Running multiple command concurrently
///</summary>
[TestMethod()]
public void RunAsyncTest()
{
#if _LOG_TO_FILE
using (sw = new System.IO.StreamWriter("C:\\Logs\\RunAsyncTestLog.Txt", true))
{
LogFile.SetLoggingFunction(LogFn);
#endif
bool unicode = false;
string serverAddr = "localhost:6666";
string user = "admin";
string pass = string.Empty;
string ws_client = "admin_space";
// turn off exceptions for this test
ErrorSeverity oldExceptionLevel = P4Exception.MinThrowLevel;
P4Exception.MinThrowLevel = ErrorSeverity.E_NOEXC;
for (int i = 0; i < 1; i++) // run once for ascii, once for unicode
{
Process p4d = Utilities.DeployP4TestServer(TestDir, unicode);
try
{
using (server = new P4Server(serverAddr, user, pass, ws_client))
{
if (unicode)
Assert.IsTrue(server.UseUnicode, "Unicode server detected as not supporting Unicode");
else
Assert.IsFalse(server.UseUnicode, "Non Unicode server detected as supporting Unicode");
cmdCnt1 = 0;
cmdCnt2 = 0;
cmdCnt3 = 0;
cmdCnt4 = 0;
cmdCnt5 = 0;
cmdCnt6 = 0;
run = true;
Thread t1 = new Thread(new ThreadStart(cmdThreadProc1));
t1.Name = "RunAsyncTest Thread t1";
Thread t2 = new Thread(new ThreadStart(cmdThreadProc2));
t2.Name = "RunAsyncTest Thread t2";
Thread t3 = new Thread(new ThreadStart(cmdThreadProc3));
t3.Name = "RunAsyncTest Thread t3";
Thread t4 = new Thread(new ThreadStart(cmdThreadProc4));
t4.Name = "RunAsyncTest Thread t4";
Thread t5 = new Thread(new ThreadStart(cmdThreadProc5));
t5.Name = "RunAsyncTest Thread t5";
Thread t6 = new Thread(new ThreadStart(cmdThreadProc6));
t6.Name = "RunAsyncTest Thread t6";
t1.Start();
Thread.Sleep(TimeSpan.FromSeconds(5)); // wait to start a 4th thread
t2.Start();
t3.Start();
Thread.Sleep(TimeSpan.FromSeconds(5)); // wait to start a 4th thread
run = false;
if (t1.Join(1000) == false)
{
WriteLine("Thread 1 did not cleanly exit");
t1.Abort();
}
if (t2.Join(1000) == false)
{
WriteLine("Thread 2 did not cleanly exit");
t2.Abort();
}
if (t3.Join(1000) == false)
{
WriteLine("Thread 3 did not cleanly exit");
t3.Abort();
}
Thread.Sleep(TimeSpan.FromSeconds(15)); // wait 15 seconds so will disconnect
run = true; ;
t1 = new Thread(new ThreadStart(cmdThreadProc1));
t1.Name = "RunAsyncTest Thread t1b";
t2 = new Thread(new ThreadStart(cmdThreadProc2));
t2.Name = "RunAsyncTest Thread t2b";
t3 = new Thread(new ThreadStart(cmdThreadProc3));
t3.Name = "RunAsyncTest Thread t3b";
t1.Start();
t2.Start();
t3.Start();
Thread.Sleep(TimeSpan.FromSeconds(1)); // wait to start a 4th thread
t4.Start();
Thread.Sleep(TimeSpan.FromSeconds(2)); // wait to start a 5th thread
t5.Start();
Thread.Sleep(TimeSpan.FromSeconds(3)); // wait to start a 6th thread
t6.Start();
//Thread.Sleep(TimeSpan.FromMinutes(15)); // run all threads for 15 sseconds
Thread.Sleep(TimeSpan.FromSeconds(15)); // run all threads for 15 sseconds
run = false;
if (t1.Join(1000) == false)
{
WriteLine("Thread 1 did not cleanly exit");
t1.Abort();
}
if (t2.Join(1000) == false)
{
WriteLine("Thread 2 did not cleanly exit");
t2.Abort();
}
if (t3.Join(1000) == false)
{
WriteLine("Thread 3 did not cleanly exit");
t3.Abort();
}
if (t4.Join(1000) == false)
{
WriteLine("Thread 4 did not cleanly exit");
t4.Abort();
}
if (t5.Join(1000) == false)
{
WriteLine("Thread 5 did not cleanly exit");
t5.Abort();
}
if (t6.Join(1000) == false)
{
WriteLine("Thread 6 did not cleanly exit");
t6.Abort();
}
}
}
catch (Exception ex)
{
Assert.Fail("Test threw an exception: {0}\r\n{1}", ex.Message, ex.StackTrace);
}
finally
{
Utilities.RemoveTestServer(p4d, TestDir);
}
unicode = !unicode;
}
// reset the exception level
P4Exception.MinThrowLevel = oldExceptionLevel;
#if _LOG_TO_FILE
}
#endif
}
}
}