/// <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>(); }
/// <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); }
/// <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); }
/// <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; }
/// <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; }