public TestResultArgs(Process process, Activity activity, TestResultStage resultStage, string extraDetails)
 {
     CurrentProcess = process;
     CurrentActivity = activity;
     ResultStage = resultStage;
     ExtraDetails = extraDetails;
 }
        private void CheckActivityStatus(Process p, Activity a, out bool breakFromLoop)
        {
            breakFromLoop = false;
            char[] squareBrackets = { '[', ']' };
            string statusToCheck = a.Action.Trim(squareBrackets);
            int processInstanceIDToUse = p.ProcessInstanceID;
            //This is a system event and we just want to check if it is there and finished.
            if (!p.ProcessName.Equals(a.ProcessName))
            {//TODO: doesnot cater for recursive IPCs
                processInstanceIDToUse = SmartObjectHelper.GetIPCProcessInstanceByFolio(K2Server, p.ProcessInstanceID, a.ProcessName);
                //////SendResult(new TestResultArgs(p, a, TestResultStage.DebugMessage, string.Format("IPC detected pid:{0} originalProcessName:{1} newProcessName{2}",processInstanceIDToUse,p.ProcessName, a.ProcessName)));
                //Check for IPC and if so get the child IPC pid
                if (processInstanceIDToUse == (int)SmartObjectHelper.ReturnCodes.NoProcessInstanceFound)
                {
                    string IPCMessage = string.Format("'{0}' ({1})- '{2}':IPC child not found", p.ProcessName, a.ProcessName, a.Name);
                    //////a.TestStatus = IPCMessage;
                    SendResult(new TestResultArgs(p, a, TestResultStage.ActivityNotFoundRetrying, IPCMessage));
                    //////break;
                }
            }

            if (statusToCheck == "NotTaken")
            {
                //check path taken or not taken as appropriate.
                if (string.IsNullOrEmpty(SmartObjectHelper.GetActivityStatus(K2Server, processInstanceIDToUse, a.Name).Trim()))
                {
                    a.Retry = false;
                    a.TestStatus = string.Format("'{0}' - '{1}':Activity Not Taken Correctly: '", a.ProcessName, a.Name);
                    SendResult(new TestResultArgs(p, a, TestResultStage.ActivityActioned, a.TestStatus + a.Name + "' "));
                    breakFromLoop = true; return;
                }
                else
                {
                    string err = string.Format("'{0}' - '{1}':Activity Taken Incorrectly: ", a.ProcessName, a.Name);
                    FailTest(err, TestResultStage.ActivityExecutionError, p, a);
                    breakFromLoop = true; return;
                }
            }
            else //Completed, Active etc.
            {
                string actualStatus = SmartObjectHelper.GetActivityStatus(K2Server, processInstanceIDToUse, a.Name).Trim();
                //////SendResult(new TestResultArgs(p, a, TestResultStage.DebugMessage, string.Format("statusToCheck:{0} actualStatus:{1} newProcessName{2}", statusToCheck, actualStatus, a.ProcessName)));
                if (actualStatus == statusToCheck)
                {
                    a.Retry = false;
                    a.TestStatus = string.Format("'{0}' - '{1}':Activity {2}: '", a.ProcessName, a.Name, actualStatus);
                    SendResult(new TestResultArgs(p, a, TestResultStage.ActivityActioned, a.TestStatus + a.Name + "' "));
                    bool breakOut;
                    //process the datafields to determine if we have to save a dfs value
                    processDataFields(p, a, out breakOut);
                    breakFromLoop = true; return;
                }
                else
                {
                    //
                    string err = string.Format("'{0}' - '{1}':[{2}] action expected but actual status was [{3}]", a.ProcessName, a.Name, statusToCheck, actualStatus);
                    FailTest(err, TestResultStage.ActivityNotFoundRetrying, p, a);
                }
            }
        }
        private void ProcessActivity(Process p, Activity a)
        {
            //Ok so we have an activity to action.
            //try and get the item from the worklist, but only a limited number of times.
            bool actioned = false;
            for (int i = 0; i < a.MaxRetryCount; i++)
            {
                bool breakFromLoop = false;
                
                retryLoopIteration(i, p, a, out breakFromLoop, out actioned);
                if (breakFromLoop)
                {
                    break;
                }
            }//retry loop
            if (a.Retry)
            {
                p.ActivityExecutionError = "Could not find activity event: '" + a.Name + "'";

                ////////SendResult(new TestResultArgs(p, a, TestResultStage.DebugMessage, string.Format("a.teststatus blank {0}",a.TestStatus)));
                SendResult(new TestResultArgs(p, a, TestResultStage.ActivityNotFoundGivingUp, "Error: Activity Name: '" + a.Name + "' could not be found after " + a.MaxRetryCount.ToString() + " retries."));
                p.ProcessStatus = "Error";
                a.TestStatus = "Could not find activity";
                p.ProcessHasUnexpectedErrors = true;
                a.Retry = false;
            }
        }
        private void ProcessActivities(Process p)
        {
            foreach (Activity a in p.Activities)
            {
                currentActivity = a;
                //Break out of this test if there is an error.
                if (p.ProcessHasUnexpectedErrors) break;

                if (a.Name.Equals("start", StringComparison.OrdinalIgnoreCase))
                {
                    ProcessStartActivity(p, a);
                }//END OF START ACTIVITY
                else if (a.Name.Equals("SubProcess", StringComparison.OrdinalIgnoreCase))
                {
                    foreach (Process subProcess in a.SubProcesses)
                    {
                        ProcessProcess(subProcess);
                    }
                }
                    
                else //Not start
                {
                    ProcessActivity(p, a);
                }//Not Start
                if (!this.ProceedWithTest)
                {
                    break;
                }
            }//foreach activity
        }
        private void ProcessProcess(Process p)
        {
            currentProcess = p;
            try
            {
                string message = string.Format("Starting test {0,30}", p.Description);
                SendResult(new TestResultArgs(p, null, TestResultStage.NewProcessTestStarting, message));
                p.TestStartDate = DateTime.Now;

                ProcessActivities(p);

                p.TestEndDate = DateTime.Now;
                SendResult(new TestResultArgs(p, null, TestResultStage.NewProcessTestFinished, "Test " + p.Description + " ended"));
                var servItems = k2helper.WorkflowServer().GetProcessInstances(p.Folio);
                if (servItems.Count == 1)
                {
                    var err = k2helper.WorkflowServer().GetError(servItems[0].ProcID, servItems[0].ID);
                    if (!string.IsNullOrEmpty(err))
                    {
                        if (err.Count() > 0) p.ProcessError = err.ToString();
                        p.ProcessStatus = "In Error";
                    }
                    else
                    {
                        p.ProcessStatus = "Running";
                    }
                }
                else
                {
                    p.ProcessStatus = "Complete";
                }
            }
            catch (Exception ex)
            {
                if (ex.IsFatal())
                {
                    throw;
                }
                string innerExceptionStackTrace = null;
                if (ex.InnerException != null)
                {
                    innerExceptionStackTrace = ex.InnerException.StackTrace;
                }
                SendResult(new TestResultArgs(currentProcess, currentActivity, TestResultStage.FatalError, string.Format(new NullFormat(),"Process : {0}{1}{2} innerexception:{3}", currentActivity.ProcessName, ex.Message, ex.StackTrace, innerExceptionStackTrace)));
                p.ProcessStatus = "In Error";
            }
        }
        private void InvokeMethod(Process process, Activity activity, string assembly, string className, string method, List<string> parameters)
        {
            object[] para = new object[parameters.Count];

            for (int i = 0; i < parameters.Count; i++)
            {
                switch (parameters[i])
                {

                    case "[Process]":
                        para[i] = process;
                        break;

                    case "[Activity]":
                        para[i] = activity;
                        break;

                    default:
                        para[i] = parameters[i];
                        break;
                }
            }
            DynamicCodeExecution.InvokeMethod(assembly, className, method, para);
        }
 private Process ConstructProcessFromXmlNodeListOldStyle(XmlNode processNode, Process newprocess, string xmlRootDir, string parentFilename)
 {
     newprocess.Description = XmlHelper.GetAttributeValue(processNode, "description", XmlHelper.NameCaseSensitive.No);
     //Now lets get all Activities listed in the XML
     newprocess.Activities.AddRange(ConstructActivitiesFromXMLNodeList(processNode.ChildNodes, xmlRootDir, newprocess, parentFilename));
     return newprocess;
 }
        private void processDataFields(Process p, Activity a, out bool breakFromLoop)
        {
            bool needsUpdate = false;
            breakFromLoop = false;

            foreach (var df in a.DataFields)
            {
                string dfValue = null;
                int i = 0;
                while (dfValue == null)
                {
                    dfValue = SmartObjectHelper.GetProcessDataFieldValue(K2Server, p.ProcessInstanceID, df.Key);
                    System.Threading.Thread.Sleep(1000);
                    i++;
                    if (i > 10)
                    {
                        break;
                    }
                }

                var mockDF = new CoreDataField();
                mockDF.Name = df.Key;
                SendResult(new TestResultArgs(p,a, TestResultStage.DebugMessage, string.Format(new NullFormat(), "dfKey:{0} - dfvalue:{0}",df.Key, dfValue)));
                if (dfValue == null)
                {
                    dfValue = "NULL";
                }
                mockDF.Value = dfValue;
                processDataField(df.Value, null, mockDF, out needsUpdate, out breakFromLoop);
            }

        }
        private void RunMethod(Process p, Activity a, MethodType type)
        {
            //Do a quick check
            switch (type)
            {
                case MethodType.PreMethod:
                    if (!a.PreMethodCall.NeedToInvoke) return;
                    break;

                case MethodType.PostMethod:
                    if (!a.PostMethodCall.NeedToInvoke) return;
                    break;
            }

            string sAssembly = (type == MethodType.PreMethod) ? a.PreMethodCall.Assembly : a.PostMethodCall.Assembly;
            string sClass = (type == MethodType.PreMethod) ? a.PreMethodCall.Class : a.PostMethodCall.Class;
            string sMethod = (type == MethodType.PreMethod) ? a.PreMethodCall.Method : a.PostMethodCall.Method;

            List<string> sParameters = (type == MethodType.PreMethod) ? a.PreMethodCall.Parameters : a.PostMethodCall.Parameters;

            //Run method.
            try
            {
                InvokeMethod(p, a, sAssembly, sClass, sMethod, sParameters);
                SendResult(new TestResultArgs(p, a, (type == MethodType.PreMethod) ? TestResultStage.ActivityPreMethodExecuted : TestResultStage.ActivityPostMethodExecuted));
            }
            catch (Exception ex)
            {
                if (ex.IsFatal())
                {
                    throw;
                }
                //TODO: refactor to use FailTest
                p.ActivityExecutionError = a.ActivityExecutionError = ex.Message.ToString();
                SendResult(new TestResultArgs(p, a, TestResultStage.ActivityExecutionError, type.ToString() + " execution error : " + p.ActivityExecutionError));
                p.ProcessHasUnexpectedErrors = true;
            }
        }
        private void ConstructProcessesFromXMLNodeList(XmlNodeList xmlnodelist, List<Process> processes, string xmlRootDir, string parentFilename)
        {
            //List<Process> newProcesses = new List<Process>();
            foreach (XmlNode processNode in xmlnodelist)
            {
                string processTypeString = XmlHelper.GetAttributeValue(processNode, "type", "Assert").ToLower();
                ProcessType processType = (ProcessType)Enum.Parse(typeof(ProcessType), processTypeString);
                string processName = XmlHelper.GetAttributeValue(processNode, "processName");
                string processUniqueID = XmlHelper.GetAttributeValue(processNode, "uniqueID", "NoUniqueID");
                string fileName = XmlHelper.GetAttributeValue(processNode, "fileName");

                bool runTest = bool.Parse(XmlHelper.GetAttributeValue(processNode, "TestEnabled", "True"));
                if (!runTest) continue;   // Skip the remainder of this iteration.;

                if (!Regex.Match(this.TestsTypesToRun.ToString(), processTypeString, RegexOptions.IgnoreCase).Success)
                {
                    //These are not the process types you are looking for. #jedimindtrick
                    continue;
                }

                if (string.IsNullOrEmpty(fileName))
                {//This is an actual process to test and not a pointer to another file
                    if (processUniqueID == "NoUniqueID" || !uniqueProcessIdList.Contains(processUniqueID))
                    {
                        uniqueProcessIdList.Add(processUniqueID);
                        Process newProcess = new Process();
                        if (string.IsNullOrEmpty(processName))
                        {//old style Process Name is a node of the child nodes
                            newProcess = ConstructProcessFromXmlNodeListOldStyle(processNode, xmlRootDir, parentFilename);
                        }
                        else
                        {
                            newProcess = ConstructProcessFromXmlNodeListNewStyle(processNode, xmlRootDir, parentFilename);
                        }
                        newProcess.ProcessType = processType;
                        processes.Add(newProcess);
                    }
                    else
                    {
                        SendResult(new TestResultArgs(null, null, TestResultStage.DebugMessage, string.Format("Constructed Process already exists in test file, so skipping it {0} - {1}", processName, processUniqueID)));
                    }
                }
            }
        }
        private bool ActionActivity(Process p, Activity a, SourceCode.Workflow.Client.WorklistItem item, string actionuser, bool impersonateUser)
        {
            try
            {
                ////////item.ActivityInstanceDestination.DataFields["Data.Actioner"].Value = "bob";
                ////////item.ProcessInstance.Update();
                bool fieldToSaveFound = false;

                foreach (KeyValuePair<string, CoreDataField> kvp in a.DataFields)
                {
                    if (kvp.Value.Check == "set")
                    {
                        //try to set the datafield
                        if (kvp.Value.Type == CoreDataFieldType.Activity)
                        {
                            item.ActivityInstanceDestination.DataFields[kvp.Value.Name].Value = kvp.Value.Value;
                        }
                        else
                        {
                            item.ProcessInstance.DataFields[kvp.Value.Name].Value = kvp.Value.Value;
                        }
                        fieldToSaveFound = true;
                    }
                }
                if (fieldToSaveFound)
                {
                    item.ProcessInstance.Update();
                }


                if (impersonateUser)
                {
                    k2helper.WorkflowClient().connection.ImpersonateUser(actionuser);
                }

                if (this.AutoActionTasks)
                {

                    item.Actions[a.Action].Execute();
                }
                else
                {
                    this.CurrentTaskURL = item.Data;
                    SendResult(new TestResultArgs(p,a, TestResultStage.CreateTask, item.Data));
                    try
                    {
                        Thread.Sleep(Timeout.Infinite);
                    }
                    catch(ThreadInterruptedException) 
                    {

                    }
                }
                string actionMsg = string.Format("'{0}' - '{1}': Activity '{2}' as user {3}", a.ProcessName, a.Name, a.Action, actionuser);
                a.Retry = false;
                a.TestStatus = actionMsg;
                SendResult(new TestResultArgs(p, a, TestResultStage.ActivityActioned, actionMsg));
                if (impersonateUser)
                {
                    k2helper.WorkflowClient().connection.RevertUser();
                }
                return true;
            }
            catch (Exception ex)
            {
                if (ex.IsFatal())
                {
                    throw;
                }

                if (impersonateUser)
                {
                    k2helper.WorkflowClient().connection.RevertUser();
                }
                string err = string.Format("'{0}' - '{1}': Execution failed : {2}, {3}", a.ProcessName, a.Name, ex.Message, ex.StackTrace);
                //Some errors are temporary, so retry
                FailTest(err, TestResultStage.ActivityNotFoundRetrying, p, a);
                return false;
            }

        }
        private void ProcessStartActivity(Process p, Activity a)
        {
            RunMethod(p, a, MethodType.PreMethod);
            //Start Process
            SendResult(new TestResultArgs(p, a, TestResultStage.ProcessStarting, "Process : " + a.ProcessName));
            p.Folio = string.Format("{0}", "TEST : " + DateTime.Now.ToString());

            //If we need to set a datafield to an existing variable, we need to modify the a.DataFields collection
            prepareDataFields(a.DataFields);
            try
            {
                p.ProcessInstanceID = k2helper.StartK2Process(a.ProcessName, p.Folio, a.DataFields);
            }
            catch (Exception ex)
            {
                if (ex.IsFatal())
                {
                    throw;
                }
                SendResult(new TestResultArgs(p, a, TestResultStage.FatalError, string.Format("Process : {0}{1}{2}", a.ProcessName, ex.Message, ex.StackTrace)));
                /// throw
            }

            if (p.ProcessInstanceID < 0)
            {
                //TODO: refactor to use FailTest
                p.ActivityExecutionError = "Process did not start : ";
                a.ActivityExecutionError = p.ActivityExecutionError;

                SendResult(new TestResultArgs(p, a, TestResultStage.FatalError, "Process did not start : " + p.ActivityExecutionError));
                p.ProcessHasUnexpectedErrors = true;
            }
            else
            {
                //the p.Processname only gets assigned once the start activity has been initiated.
                p.ProcessName = a.ProcessName;
                a.Retry = false;
                a.TestStatus = "Created";
                //////SendResult(new TestResultArgs(p, a, TestResultStage.DebugMessage, "a.teststatus set to created"));
                SendResult(new TestResultArgs(p, a, TestResultStage.ProcessStarted));
            }

            //Post Method
            RunMethod(p, a, MethodType.PostMethod);
        }
 private void FailTest(string reasonText, TestResultStage tesResultStage, Process p, Activity a)
 {
     p.ActivityExecutionError = reasonText;
     a.ActivityExecutionError = p.ActivityExecutionError;
     if (tesResultStage != TestResultStage.ActivityNotFoundRetrying)
     {
         p.ProcessHasUnexpectedErrors = true;
         
         a.Retry = false;
         a.TestStatus = "Failed";
     }
     SendResult(new TestResultArgs(p, a, TestResultStage.ActivityExecutionError, reasonText));
 }
 private void ActionWorklistItemsIfFound(WorklistItems items, Process p, Activity a, out bool breakFromLoop, out bool actioned, out bool IPCeventFound)
 {
     actioned = false;
     breakFromLoop = false;
     IPCeventFound = false;
     
      string currentUser = "******" + System.Security.Principal.WindowsIdentity.GetCurrent().Name;
     for (int x = 0; x < items.Count; x++)
     {
         //Loop through and see if there is an item for this activity assigned to the current user.
         if (string.Equals(currentUser, items[x].Destination, StringComparison.OrdinalIgnoreCase)
             && a.Name.Equals(items[x].ActivityName))
         {
             //if we are here then maybe we have an item in an IPC event, 
             //set the a.ProcInstID which will be called on the next round.
             // important to note that IPC retry counts should be set higher to
             //cope with this hack!
             a.ProcessInstanceID = items[x].ProcInstID;
             IPCeventFound = true;
             breakFromLoop = true; return;
         }
         if (!this.ProceedWithTest)
         {
             breakFromLoop = true; return;
         }
     }
     for (int x = 0; x < items.Count; x++)
     {
         //we have a matching activity, but it is not assigned to the current user.
         if (string.Equals(items[x].ActivityName, a.Name, StringComparison.OrdinalIgnoreCase))
         {
             try
             {
                 //If we are on the last loop, lets impersonate the destination user and action the item.
                 string impersonatedUser = string.Empty;
                 Dictionary<string, object> filter = new Dictionary<string, object>();
                 switch (items[x].Actioner.ActionerType)
                 {
                     case ActionerType.User:
                         impersonatedUser = items[x].Actioner.Name;
                         break;
                     case ActionerType.Groups:
                         filter.Add("Group_name", items[x].Actioner.Name);
                         filter.Add("LabelName", "K2:");
                         //get the first user in the group.
                         var group = k2helper.SmartObjectClient().SmartObjectGetList(filter, "UMUSer", "Get_Group_Users");
                         impersonatedUser = group.Rows[0]["Name"].ToString();
                         break;
                     case ActionerType.Role:
                         filter.Add("Role_Name", items[x].Actioner.Name);
                         //get the first user in the group.
                         var role = k2helper.SmartObjectClient().SmartObjectGetList(filter, "UMUSer", "Get_Role_Users");
                         impersonatedUser = role.Rows[0]["Name"].ToString();
                         break;
                 }
                 //now impersonate them and action the worklist item.
                 var wlitem = k2helper.WorkflowClient().GetWorkListItem(items[x].ProcInstID + "_ " + items[x].ActInstDestID, impersonatedUser);
                 
                 actioned = ActionActivity(p, a, wlitem, impersonatedUser, true);
                 if (!actioned)
                 {
                     breakFromLoop = true; return;
                 }
                 //wlitem.Actions[a.Action].Execute();
                 //k2helper.WorkflowServer().RedirectWorklistItem(items[x].Destination, currentUser, items[x].ProcInstID, items[x].ActInstDestID, items[x].ID);
             }
             catch (Exception ex)
             {
                 if (ex.IsFatal())
                 {
                     throw;
                 }
                 string err = "Error getting worklist item : " + ex.Message;
                 FailTest(err, TestResultStage.ActivityExecutionError, p, a);
                 breakFromLoop = true; return;
             }
             if (!this.ProceedWithTest)
             {
                 breakFromLoop = true; return;
             }
             Thread.Sleep(1000);
         }
     }//end for
 }
        private List<Activity> ConstructActivitiesFromXMLNodeList(XmlNodeList processChildrenNodeList, string xmlRootDir, Process newProcess, string parentFilename)
        {
            //Old format contained Activities node for every activity
            //new format - not every nodes may be Activity node
            //for each activity in the process
            List<Activity> activities = new List<Activity>();
            foreach (XmlNode activityNode in processChildrenNodeList)
            {
                if (activityNode.Name == "Activities")
                {
                    string activitiesFileName = XmlHelper.GetAttributeValue(activityNode, "fileName");
                    //if Node contains a filename attribute and it is populated 
                    if (string.IsNullOrEmpty(activitiesFileName))
                    {
                        List<Activity> newactivities = ConstructActivityFromXMLNode(activityNode, xmlRootDir, parentFilename);
                        activities.AddRange(newactivities);
                    }
                    else
                    {
                        List<Activity> subFileActivities = ConstructActivitiesFromXMLFile(activitiesFileName, xmlRootDir, parentFilename);
                        activities.AddRange(subFileActivities);
                    }
                }
                else if (activityNode.Name == "Activity")
                {

                    //We have found that this activity is of type "StartProcess"
                    XmlNodeList xmlnodelistProceesses = activityNode.SelectNodes(@"Process");
                    if (xmlnodelistProceesses != null && xmlnodelistProceesses.Count > 0)
                    {
                        Activity activityWithSubProcess = new Activity();
                        
                        activityWithSubProcess.ErrorExpected = bool.Parse(XmlHelper.GetAttributeValue(activityNode, "exceptionExpected", "False"));
                        activityWithSubProcess.Name = "SubProcess";
                        activityWithSubProcess.SubProcesses = new List<Process>();
                        ConstructProcessesFromXMLNodeList(xmlnodelistProceesses, activityWithSubProcess.SubProcesses, xmlRootDir, parentFilename);
                        foreach (Process proc in activityWithSubProcess.SubProcesses)
                        {
                            proc.RootProcess = newProcess;
                        }
                        activities.Add(activityWithSubProcess);
                    }
                    else
                    {
                        List<Activity> newactivities = ConstructActivityFromXMLNode(activityNode, xmlRootDir, parentFilename);
                        activities.AddRange(newactivities);
                    }
                }
                else
                {
                    //could be DataFields, PreMethodCall etc.
                }
            }
            return activities;
        }
        private void whatdoesthisdo(SourceCode.Workflow.Client.Worklist wl, Process p, Activity a, out bool breakFromLoop, out bool actioned)
        {
            breakFromLoop = false;
            actioned = false;
            //Incase there are multiple worklist items, lets find the activity we want to action.
            foreach (SourceCode.Workflow.Client.WorklistItem item in wl)
            {
                if (string.Equals(item.ActivityInstanceDestination.Name, a.Name, StringComparison.OrdinalIgnoreCase))
                {
                    string currentuser = "******" + System.Security.Principal.WindowsIdentity.GetCurrent().Name;

                    //We have found the activity that we should update 
                    //first set process instance data fields.
                    Dictionary<string, object> input = new Dictionary<string, object>();
                    bool breakFromInnerLoop = false;
                    processDataFields(item, a, out breakFromInnerLoop);
                    if (breakFromInnerLoop)
                    {
                        breakFromLoop = true; return;
                    }
                    //We need to see if the allocated person is the curent person , otehrwise reopen the worklst item.
                    if (string.Equals(item.AllocatedUser, currentuser, StringComparison.OrdinalIgnoreCase))
                    {
                        //Pre Method
                        RunMethod(p, a, MethodType.PreMethod);
                        actioned = ActionActivity(p, a, item, currentuser, false);
                        if (!actioned)
                        {
                            breakFromLoop = true; return;
                        }
                        RunMethod(p, a, MethodType.PostMethod);
                    }
                    else
                    {
                        //open this item as the allocated user.
                        SourceCode.Workflow.Client.WorklistItem newitem = null;
                        try
                        {
                            newitem = k2helper.WorkflowClient().GetWorkListItem(item.SerialNumber, item.AllocatedUser);
                        }
                        catch (Exception ex)
                        {
                            if (ex.IsFatal())
                            {
                                throw;
                            }
                            string err = "Error getting worklist " + ex.Message;
                            FailTest(err, TestResultStage.ActivityExecutionError, p, a);
                            breakFromLoop = true; return;
                        }

                        actioned = ActionActivity(p, a, newitem, currentuser, false);
                        if (!actioned)
                        {
                            breakFromLoop = true; return;
                        }
                    }//open as allocated user
                    breakFromLoop = true; return;
                }//activity name matches
                if (!this.ProceedWithTest)
                {
                    breakFromLoop = true; return;
                }
            }//foreach workitem
        }
        private void retryLoopIteration(int i, Process p, Activity a, out bool breakFromLoop, out bool actioned)
        {
            actioned = false;
            breakFromLoop = false;
            a.CountOfRetries = i;
            SendResult(new TestResultArgs(p, a, TestResultStage.DebugMessage, string.Format("a.Retry was {0}", a.Retry)));
            bool IPCeventFound = false;
            /////////////////////////////////////////////////////////////////////////////////////////////////////
            if (a.Action.StartsWith("[") && a.Action.EndsWith("]"))
            {
                CheckActivityStatus(p, a, out breakFromLoop);
                if (!this.ProceedWithTest)
                {
                    breakFromLoop = true;
                }
                if (breakFromLoop)
                {
                    return;
                }
            }//search for an activity in a certain state
            else //try to execute the action
            {
                
                //Get all items by the folio so it should be unique
                SourceCode.Workflow.Management.Criteria.WorklistCriteriaFilter fil = new SourceCode.Workflow.Management.Criteria.WorklistCriteriaFilter();
                fil.AddRegularFilter(SourceCode.Workflow.Management.WorklistFields.Folio, SourceCode.Workflow.Management.Criteria.Comparison.Equals, p.Folio);
                fil.AddRegularFilter(SourceCode.Workflow.Management.WorklistFields.ProcessFullName, SourceCode.Workflow.Management.Criteria.Comparison.Equals, string.IsNullOrEmpty(a.ProcessName) ? p.ProcessName : a.ProcessName);
                WorklistItems items = k2helper.WorkflowServer().GetWorklistItems(fil);
                ActionWorklistItemsIfFound(items, p, a, out breakFromLoop, out actioned, out IPCeventFound);
                
                if (!actioned)
                {
                    //Open a conection to the server
                    SourceCode.Workflow.Client.Worklist wl = k2helper.WorkflowClient().GetAllWorkListItem((a.ProcessInstanceID == 0) ? p.ProcessInstanceID : a.ProcessInstanceID);

                    whatdoesthisdo(wl,p,a, out breakFromLoop, out actioned);
                    if (breakFromLoop)
                    {
                        return;
                    }
                }//workitem exists
            }// else try to execute action

            if (a.Retry)
            {
                string msg = string.Format("Activity Name: '{0}' was not available, retrying in {1} seconds. Retries left : {2}", a.Name , a.RetryInSeconds , (a.MaxRetryCount - a.CountOfRetries));
                SendResult(new TestResultArgs(p, a, TestResultStage.ActivityNotFoundRetrying, msg));
            }
            ErrorLog newError = GetLastError();
            if (!AreIDsEqual(newError, lastError))
            { //Basically if there is a new error
                if (a.ErrorExpected)
                {//Are We expecting an error?
                    SendResult(new TestResultArgs(p, null, TestResultStage.ActivityActioned, string.Format("Error Expected and occured: {0} '{2}' ---> '{1}'"
                        , newError.ID, newError.Description, newError.ProcessName)));
                    a.Retry = false;
                    breakFromLoop = true;
                }
                else
                {
                    SendResult(new TestResultArgs(p, null, TestResultStage.FatalError, string.Format("Error: {0} '{2}' ---> '{1}'"
                        , newError.ID, newError.Description, newError.ProcessName)));
                    a.Retry = false;
                    a.TestStatus = "More errors";
                    p.ProcessHasUnexpectedErrors = true;
                }
            }
            else
            {//no new error
                if (a.ErrorExpected)
                {
                    SendResult(new TestResultArgs(p, null, TestResultStage.ActivityNotFoundRetrying, string.Format("'{0}' ({1})- '{2}': Error Expected but did not occur!.. yet!: {3}", p.ProcessName, a.ProcessName, a.Name, a.TestStatus)));
                    //Thread.Sleep(1000);
                    actioned = false;
                    a.Retry = true;
                    a.TestStatus = string.Empty;
                }
                else
                {
                    SendResult(new TestResultArgs(p, a, TestResultStage.DebugMessage, "No Error expected and no error!"));
                }
            }
            lastError = newError;
            if (!this.ProceedWithTest)
            {
                breakFromLoop = true; return;
            }
            if (a.Retry)
            {
                SendResult(new TestResultArgs(p, a, TestResultStage.DebugMessage, "told to retry, sleeping"));
                System.Threading.Thread.Sleep(a.RetryInSeconds * 1000);
            }
        }