Opc.Ua.ServerTest.CallTest.Call C# (CSharp) Method

Call() private method

Reads the attributes, verifies the results and updates the nodes.
private Call ( CallMethodRequestCollection methodsToCall ) : bool
methodsToCall CallMethodRequestCollection
return bool
        private bool Call(CallMethodRequestCollection methodsToCall)
        {
           Opc.Ua.Test.DataComparer comparer = new Opc.Ua.Test.DataComparer(Session.MessageContext);

            bool success = true;

            CallMethodResultCollection results = null;
            DiagnosticInfoCollection diagnosticInfos = null;
            
            RequestHeader requestHeader = new RequestHeader();
            requestHeader.ReturnDiagnostics = 0;

            try
            {
                Session.Call(
                    requestHeader,
                    methodsToCall,
                    out results,
                    out diagnosticInfos);
            }
            catch (System.ServiceModel.CommunicationException e)
            {
                Log("WARNING: Communication error (random data may have resulted in a message that is too large). {0}", e.Message);
                return true;
            }   
            catch (System.Xml.XmlException e)
            {
                Log("WARNING: XML parsing error (random data may have resulted in a message that is too large). {0}", e.Message);
                return true;
            } 
            catch (ServiceResultException e)
            {
                if (e.StatusCode == StatusCodes.BadEncodingLimitsExceeded)
                {
                    Log("WARNING: Communication error (random data may have resulted in a message that is too large). {0}", e.Message);
                    return true;
                }

                throw new ServiceResultException(new ServiceResult(e));
            }

            ClientBase.ValidateResponse(results, methodsToCall);
            ClientBase.ValidateDiagnosticInfos(diagnosticInfos, methodsToCall);
            
            // check diagnostics.
            if (diagnosticInfos != null && diagnosticInfos.Count > 0)
            {
                Log("Returned non-empty DiagnosticInfos array during Call.");
                return false;
            }
            
            // check results.
            for (int ii = 0; ii < methodsToCall.Count; ii++)
            {
                CallMethodRequest request = methodsToCall[ii];
                TestMethod method = (TestMethod)request.Handle;

                if (request.ObjectId != method.Parent.NodeId)
                {
                    if (results[ii].StatusCode != StatusCodes.BadMethodInvalid)
                    {
                        Log(
                            "Invalid result when method called on wrong object '{0}'. NodeId = {1}, Method = {2}, StatusCode = {3}",
                            method.Parent,
                            method.Parent.NodeId,
                            method.Method,
                            results[ii].StatusCode);

                        success = false;
                        break;
                    }

                    continue;
                }
     
                if (results[ii].StatusCode == StatusCodes.BadUserAccessDenied)
                {
                    if (method.Method.UserExecutable)
                    {
                        Log(
                            "Call failed when calling an executable method '{0}'. NodeId = {1}, Method = {2}, StatusCode = {3}",
                            method.Parent,
                            method.Parent.NodeId,
                            method.Method,
                            results[ii].StatusCode);

                        success = false;
                        break;
                    }

                    continue;
                }

                if (results[ii].StatusCode == StatusCodes.BadNotImplemented)
                {
                    continue;
                }                           
                    
                if (request.InputArguments.Count != method.InputArguments.Count)
                {                
                    if (results[ii].StatusCode != StatusCodes.BadArgumentsMissing)
                    {
                        Log(
                            "Incorrect error returned when passing method wrong number of arguments '{0}'. NodeId = {1}, Method = {2}, StatusCode = {3}",
                            method.Parent,
                            method.Parent.NodeId,
                            method.Method,
                            results[ii].StatusCode);

                        success = false;
                        break;
                    }

                    continue;
                }
                
                if (results[ii].StatusCode == StatusCodes.BadInvalidArgument || results[ii].StatusCode == StatusCodes.BadOutOfRange)
                {
                    if (results[ii].InputArgumentResults.Count != request.InputArguments.Count)
                    {
                        Log(
                            "Incorrect number of result returned when reporting argument error '{0}'. NodeId = {1}, Method = {2}, Expected = {3}, Actual = {4}",
                            method.Parent,
                            method.Parent.NodeId,
                            method.Method,
                            request.InputArguments.Count,
                            results[ii].InputArgumentResults.Count);

                        success = false;
                        break;
                    }

                    bool errorFound = false;

                    for (int jj = 0; jj < method.InputArguments.Count; jj++)
                    {
                        if (results[ii].InputArgumentResults[jj] != results[ii].StatusCode)
                        {
                            errorFound = true;
                        }

                        Argument argument = method.InputArguments[jj];

                        // check if data type matches.
                        TypeInfo typeInfo = TypeInfo.IsInstanceOfDataType(
                            request.InputArguments[jj].Value,
                            argument.DataType,
                            argument.ValueRank,
                            Session.NamespaceUris,
                            Session.TypeTree);

                        if (typeInfo == null)
                        {
                            if (results[ii].InputArgumentResults[jj] != StatusCodes.BadTypeMismatch)
                            {
                                Log(
                                    "Incorrect error returned for invalid argument '{0}'. NodeId = {1}, Method = {2}, Argument = {3}, StatusCode = {4}",
                                    method.Parent,
                                    method.Parent.NodeId,
                                    method.Method,
                                    method.InputArguments[jj].Name,
                                    results[ii].InputArgumentResults[jj]);

                                success = false;
                            }
                                
                            continue;
                        }
                        
                        if (results[ii].InputArgumentResults[jj] != StatusCodes.Good && results[ii].InputArgumentResults[jj] != StatusCodes.BadOutOfRange)
                        {
                            Log(
                                "Incorrect error returned for valid argument '{0}'. NodeId = {1}, Method = {2}, Argument = {3}, StatusCode = {4}",
                                method.Parent,
                                method.Parent.NodeId,
                                method.Method,
                                method.InputArguments[jj].Name,
                                results[ii].InputArgumentResults[jj]);

                            success = false;
                        }
                    }

                    if (!success)
                    {
                        break;
                    }

                    if (!errorFound)
                    {
                        Log(
                            "No matching argument level error for method '{0}'. NodeId = {1}, Method = {2}, StatusCode = {4}",
                            method.Parent,
                            method.Parent.NodeId,
                            method.Method,
                            results[ii].StatusCode);
                        
                        success = false;
                        break;
                    }

                    continue;
                }

                if (StatusCode.IsBad(results[ii].StatusCode))
                {
                    if (results[ii].StatusCode != StatusCodes.BadNotImplemented)
                    {
                        Log(
                            "Unexpected error when calling method '{0}'. NodeId = {1}, Method = {2}, StatusCode = {3}",
                            method.Parent,
                            method.Parent.NodeId,
                            method.Method,
                            results[ii].StatusCode);

                        success = false;
                        break;
                    }

                    continue;
                }

                if (results[ii].OutputArguments.Count != method.OutputArguments.Count)
                {
                    Log(
                        "Incorrect number of output arguments '{0}'. NodeId = {1}, Method = {2}, Expected = {3}, Actual = {4}",
                        method.Parent,
                        method.Parent.NodeId,
                        method.Method,
                        method.OutputArguments.Count,
                        results[ii].OutputArguments.Count);

                    success = false;
                    break;
                }
                 
                for (int jj = 0; jj < method.OutputArguments.Count; jj++)
                {
                    Argument argument = method.OutputArguments[jj];

                    // check if data type matches.
                    TypeInfo typeInfo = TypeInfo.IsInstanceOfDataType(
                        results[ii].OutputArguments[jj].Value,
                        argument.DataType,
                        argument.ValueRank,
                        Session.NamespaceUris,
                        Session.TypeTree);

                    if (typeInfo == null)
                    {
                        Log(
                            "Datatype for output argument is invalid '{0}'. NodeId = {1}, Method = {2}, Argument = {3}, Value = {4}",
                            method.Parent,
                            method.Parent.NodeId,
                            method.Method,
                            method.OutputArguments[jj].Name,
                            results[ii].OutputArguments[jj]);

                        success = false;                            
                        continue;
                    }

                    // check for special test methods that return the input parameters.
                    if (method.Parent.BrowseName.Name == "MethodTest")
                    {
                        if (jj < request.InputArguments.Count)
                        {
                            if (!comparer.CompareVariant(request.InputArguments[jj], results[ii].OutputArguments[jj]))
                            {
                                Log(
                                    "Output argument did not match input '{0}'. NodeId = {1}, Method = {2}, Argument = {3}, Value = {4}, Output = {5}",
                                    method.Parent,
                                    method.Parent.NodeId,
                                    method.Method,
                                    method.OutputArguments[jj].Name,
                                    request.InputArguments[jj],
                                    results[ii].OutputArguments[jj]);

                                success = false;                            
                                continue;
                            }
                        }
                    }
                }

                if (!success)
                {
                    break;
                }
            }
            
            return success;
        }