/// <summary>
        /// Creates the test object.
        /// </summary>
        public MonitoredItemTest(
            Session session,
            ServerTestConfiguration configuration,
            ReportMessageEventHandler reportMessage,
            ReportProgressEventHandler reportProgress,
            TestBase template)
        : 
            base("MonitoredItem", session, configuration, reportMessage, reportProgress, template)
        {
            m_generator = new Opc.Ua.Test.DataGenerator(new Opc.Ua.Test.RandomSource(configuration.Seed));
            m_generator.NamespaceUris = Session.NamespaceUris;
            m_generator.ServerUris = Session.ServerUris;
            m_generator.MaxArrayLength = 3;
            m_generator.MaxStringLength = 10;
            m_generator.MaxXmlElementCount = 3;
            m_generator.MaxXmlAttributeCount = 3;
            m_comparer = new Opc.Ua.Test.DataComparer(Session.MessageContext);
            m_comparer.ThrowOnError = false;
            
            m_errorEvent = new ManualResetEvent(false);
            m_maximumTimingError = 300;

            m_variables = new List<TestVariable>();    
        }
Exemple #2
0
        /// <summary>
        /// Reads the attributes, verifies the results and updates the nodes.
        /// </summary>
        private bool Write(WriteValueCollection nodesToWrite)
        {
            bool success = true;

            StatusCodeCollection     results         = null;
            DiagnosticInfoCollection diagnosticInfos = null;

            RequestHeader requestHeader = new RequestHeader();

            requestHeader.ReturnDiagnostics = 0;

            try
            {
                Session.Write(
                    requestHeader,
                    nodesToWrite,
                    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, nodesToWrite);
            ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToWrite);

            // check diagnostics.
            if (diagnosticInfos != null && diagnosticInfos.Count > 0)
            {
                Log("Returned non-empty DiagnosticInfos array during Write.");
                return(false);
            }

            // check results.
            ReadValueIdCollection nodesToRead = new ReadValueIdCollection();

            for (int ii = 0; ii < nodesToWrite.Count; ii++)
            {
                WriteValue   request  = nodesToWrite[ii];
                TestVariable variable = (TestVariable)request.Handle;

                if (results[ii] == StatusCodes.BadUserAccessDenied)
                {
                    continue;
                }

                if (results[ii] == StatusCodes.BadNotWritable)
                {
                    Log(
                        "Write failed when writing a writeable value '{0}'. NodeId = {1}, Value = {2}, StatusCode = {3}",
                        variable.Variable,
                        variable.Variable.NodeId,
                        request.Value.WrappedValue,
                        results[ii]);

                    success = false;
                    break;
                }

                if (StatusCode.IsBad(results[ii]))
                {
                    if (request.Value.StatusCode != StatusCodes.Good)
                    {
                        if (results[ii] != StatusCodes.BadWriteNotSupported)
                        {
                            Log(
                                "Unexpected error when writing the StatusCode for a Value '{0}'. NodeId = {1}, Value = {2}, StatusCode = {3}",
                                variable.Variable,
                                variable.Variable.NodeId,
                                request.Value.WrappedValue,
                                results[ii]);

                            success = false;
                            break;
                        }

                        continue;
                    }

                    if (request.Value.SourceTimestamp != DateTime.MinValue || request.Value.ServerTimestamp != DateTime.MinValue)
                    {
                        if (results[ii] != StatusCodes.BadWriteNotSupported)
                        {
                            Log(
                                "Unexpected error when writing the Timestamp for a Value '{0}'. NodeId = {1}, Value = {2}, StatusCode = {3}",
                                variable.Variable,
                                variable.Variable.NodeId,
                                request.Value.WrappedValue,
                                results[ii]);

                            success = false;
                            break;
                        }

                        continue;
                    }

                    if (results[ii] != StatusCodes.BadTypeMismatch && results[ii] != StatusCodes.BadOutOfRange)
                    {
                        Log(
                            "Unexpected error when writing a valid value '{0}'. NodeId = {1}, Value = {2}, StatusCode = {3}",
                            variable.Variable,
                            variable.Variable.NodeId,
                            request.Value.WrappedValue,
                            results[ii]);

                        success = false;
                        break;
                    }

                    continue;
                }

                ReadValueId nodeToRead = new ReadValueId();

                nodeToRead.NodeId      = request.NodeId;
                nodeToRead.AttributeId = request.AttributeId;
                nodeToRead.IndexRange  = request.IndexRange;
                nodeToRead.Handle      = request.Handle;

                nodesToRead.Add(nodeToRead);
            }

            // skip read back on failed.
            if (!success)
            {
                return(success);
            }

            // check if nothing more do to.
            if (nodesToRead.Count == 0)
            {
                return(true);
            }

            requestHeader = new RequestHeader();
            requestHeader.ReturnDiagnostics = 0;

            DataValueCollection values = new DataValueCollection();

            try
            {
                Session.Read(
                    requestHeader,
                    0,
                    TimestampsToReturn.Both,
                    nodesToRead,
                    out values,
                    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(values, nodesToRead);
            ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead);

            // check diagnostics.
            if (diagnosticInfos != null && diagnosticInfos.Count > 0)
            {
                Log("Returned non-empty DiagnosticInfos array during Read.");
                return(false);
            }

            for (int ii = 0; ii < nodesToRead.Count; ii++)
            {
                ReadValueId  request      = nodesToRead[ii];
                TestVariable variable     = (TestVariable)request.Handle;
                DataValue    valueWritten = variable.Values[variable.Values.Count - 1];

                if (StatusCode.IsBad(values[ii].StatusCode) && StatusCode.IsNotBad(valueWritten.StatusCode))
                {
                    Log(
                        "Could not read back the value written '{0}'. NodeId = {1}, Value = {2}, StatusCode = {3}",
                        variable.Variable,
                        variable.Variable.NodeId,
                        valueWritten.WrappedValue,
                        values[ii].StatusCode);

                    success = false;
                    break;
                }

                Opc.Ua.Test.DataComparer comparer = new Opc.Ua.Test.DataComparer(Session.MessageContext);
                comparer.ThrowOnError = false;

                if (!comparer.CompareVariant(values[ii].WrappedValue, valueWritten.WrappedValue))
                {
                    Log(
                        "Read back value does not match the value written '{0}'. NodeId = {1}, Value = {2}, ReadValue = {3}",
                        variable.Variable,
                        variable.Variable.NodeId,
                        valueWritten.WrappedValue,
                        values[ii].WrappedValue);

                    success = false;
                    break;
                }

                if (valueWritten.StatusCode != StatusCodes.Good)
                {
                    if (values[ii].StatusCode != valueWritten.StatusCode)
                    {
                        Log(
                            "Read back StatusCode does not match the StatusCode written '{0}'. NodeId = {1}, StatusCode = {2}, ReadStatusCode = {3}",
                            variable.Variable,
                            variable.Variable.NodeId,
                            valueWritten.StatusCode,
                            values[ii].StatusCode);

                        success = false;
                        break;
                    }
                }

                if (valueWritten.SourceTimestamp != DateTime.MinValue)
                {
                    if (values[ii].SourceTimestamp != valueWritten.SourceTimestamp)
                    {
                        Log(
                            "Read back ServerTimestamp does not match the ServerTimestamp written '{0}'. NodeId = {1}, Timestamp = {2}, ReadTimestamp = {3}",
                            variable.Variable,
                            variable.Variable.NodeId,
                            valueWritten.SourceTimestamp,
                            values[ii].SourceTimestamp);

                        success = false;
                        break;
                    }
                }
            }

            return(success);
        }
Exemple #3
0
        /// <summary>
        /// Reads the attributes, verifies the results and updates the nodes.
        /// </summary>
        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);
        }
Exemple #4
0
        /// <summary>
        /// Reads the attributes, verifies the results and updates the nodes.
        /// </summary>
        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;
        }
Exemple #5
0
        /// <summary>
        /// Reads the attributes, verifies the results and updates the nodes.
        /// </summary>
        private bool Write(WriteValueCollection nodesToWrite)
        {
            bool success = true;

            StatusCodeCollection results = null;
            DiagnosticInfoCollection diagnosticInfos = null;

            RequestHeader requestHeader = new RequestHeader();
            requestHeader.ReturnDiagnostics = 0;

            try
            {
                Session.Write(
                    requestHeader,
                    nodesToWrite,
                    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, nodesToWrite);
            ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToWrite);
            
            // check diagnostics.
            if (diagnosticInfos != null && diagnosticInfos.Count > 0)
            {
                Log("Returned non-empty DiagnosticInfos array during Write.");
                return false;
            }
            
            // check results.
            ReadValueIdCollection nodesToRead = new ReadValueIdCollection();

            for (int ii = 0; ii < nodesToWrite.Count; ii++)
            {
                WriteValue request = nodesToWrite[ii];
                TestVariable variable = (TestVariable)request.Handle;

                if (results[ii] == StatusCodes.BadUserAccessDenied)
                {
                    continue;
                }

                if (results[ii] == StatusCodes.BadNotWritable)
                {
                    Log(
                        "Write failed when writing a writeable value '{0}'. NodeId = {1}, Value = {2}, StatusCode = {3}",
                        variable.Variable,
                        variable.Variable.NodeId,
                        request.Value.WrappedValue,
                        results[ii]);

                    success = false;
                    break;
                }

                if (StatusCode.IsBad(results[ii]))
                {
                    if (request.Value.StatusCode != StatusCodes.Good)
                    {
                        if (results[ii] != StatusCodes.BadWriteNotSupported)
                        {
                            Log(
                                "Unexpected error when writing the StatusCode for a Value '{0}'. NodeId = {1}, Value = {2}, StatusCode = {3}",
                                variable.Variable,
                                variable.Variable.NodeId,
                                request.Value.WrappedValue, 
                                results[ii]);

                            success = false;
                            break;
                        }

                        continue;
                    }
                    
                    if (request.Value.SourceTimestamp != DateTime.MinValue || request.Value.ServerTimestamp != DateTime.MinValue)
                    {
                        if (results[ii] != StatusCodes.BadWriteNotSupported)
                        {
                            Log(
                                "Unexpected error when writing the Timestamp for a Value '{0}'. NodeId = {1}, Value = {2}, StatusCode = {3}",
                                variable.Variable,
                                variable.Variable.NodeId,
                                request.Value.WrappedValue, 
                                results[ii]);

                            success = false;
                            break;
                        }

                        continue;
                    }

                    if (results[ii] != StatusCodes.BadTypeMismatch && results[ii] != StatusCodes.BadOutOfRange)
                    {
                        Log(
                            "Unexpected error when writing a valid value '{0}'. NodeId = {1}, Value = {2}, StatusCode = {3}",
                            variable.Variable,
                            variable.Variable.NodeId,
                            request.Value.WrappedValue, 
                            results[ii]);

                        success = false;
                        break;
                    }

                    continue;
                }
                
                ReadValueId nodeToRead = new ReadValueId();
                
                nodeToRead.NodeId = request.NodeId;
                nodeToRead.AttributeId = request.AttributeId;
                nodeToRead.IndexRange = request.IndexRange;
                nodeToRead.Handle = request.Handle;

                nodesToRead.Add(nodeToRead);
            }
            
            // skip read back on failed.
            if (!success)
            {
                return success;
            }

            // check if nothing more do to.
            if (nodesToRead.Count == 0)
            {
                return true;
            }

            requestHeader = new RequestHeader();
            requestHeader.ReturnDiagnostics = 0;

            DataValueCollection values = new DataValueCollection();

            try
            {
                Session.Read(
                    requestHeader,
                    0,
                    TimestampsToReturn.Both,
                    nodesToRead,
                    out values,
                    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(values, nodesToRead);
            ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead);
            
            // check diagnostics.
            if (diagnosticInfos != null && diagnosticInfos.Count > 0)
            {
                Log("Returned non-empty DiagnosticInfos array during Read.");
                return false;
            }

            for (int ii = 0; ii < nodesToRead.Count; ii++)
            {
                ReadValueId request = nodesToRead[ii];
                TestVariable variable = (TestVariable)request.Handle;
                DataValue valueWritten = variable.Values[variable.Values.Count-1];
                                
                if (StatusCode.IsBad(values[ii].StatusCode) && StatusCode.IsNotBad(valueWritten.StatusCode))
                {
                    Log(
                        "Could not read back the value written '{0}'. NodeId = {1}, Value = {2}, StatusCode = {3}",
                        variable.Variable,
                        variable.Variable.NodeId,
                        valueWritten.WrappedValue, 
                        values[ii].StatusCode);

                    success = false;
                    break;
                }

                Opc.Ua.Test.DataComparer comparer = new Opc.Ua.Test.DataComparer(Session.MessageContext);
                comparer.ThrowOnError = false;

                if (!comparer.CompareVariant(values[ii].WrappedValue, valueWritten.WrappedValue))
                {
                    Log(
                        "Read back value does not match the value written '{0}'. NodeId = {1}, Value = {2}, ReadValue = {3}",
                        variable.Variable,
                        variable.Variable.NodeId,
                        valueWritten.WrappedValue, 
                        values[ii].WrappedValue);

                    success = false;
                    break;
                }

                if (valueWritten.StatusCode != StatusCodes.Good)
                {
                    if (values[ii].StatusCode != valueWritten.StatusCode)
                    {
                        Log(
                            "Read back StatusCode does not match the StatusCode written '{0}'. NodeId = {1}, StatusCode = {2}, ReadStatusCode = {3}",
                            variable.Variable,
                            variable.Variable.NodeId,
                            valueWritten.StatusCode, 
                            values[ii].StatusCode);

                        success = false;
                        break;
                    }
                }

                if (valueWritten.SourceTimestamp != DateTime.MinValue)
                {
                    if (values[ii].SourceTimestamp != valueWritten.SourceTimestamp)
                    {
                        Log(
                            "Read back ServerTimestamp does not match the ServerTimestamp written '{0}'. NodeId = {1}, Timestamp = {2}, ReadTimestamp = {3}",
                            variable.Variable,
                            variable.Variable.NodeId,
                            valueWritten.SourceTimestamp, 
                            values[ii].SourceTimestamp);

                        success = false;
                        break;
                    }
                }
            }

            return success;
        }