public void ValidateSequenceNumber(
            [Values(DataSetFieldContentMask.None, DataSetFieldContentMask.RawData, // list here all possible DataSetFieldContentMask
                    DataSetFieldContentMask.ServerPicoSeconds, DataSetFieldContentMask.ServerTimestamp, DataSetFieldContentMask.SourcePicoSeconds,
                    DataSetFieldContentMask.SourceTimestamp, DataSetFieldContentMask.StatusCode,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.SourcePicoSeconds,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.SourceTimestamp,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.StatusCode,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourcePicoSeconds,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourceTimestamp,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.StatusCode,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourcePicoSeconds | DataSetFieldContentMask.SourceTimestamp,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourcePicoSeconds | DataSetFieldContentMask.StatusCode,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourcePicoSeconds | DataSetFieldContentMask.SourceTimestamp | DataSetFieldContentMask.StatusCode
                    )]
            DataSetFieldContentMask dataSetFieldContentMask)
        {
            // Arrange
            UadpDataSetMessage uadpDataSetMessage = GetFirstDataSetMessage(dataSetFieldContentMask);

            // Act
            uadpDataSetMessage.SetMessageContentMask(UadpDataSetMessageContentMask.SequenceNumber);
            uadpDataSetMessage.SequenceNumber = 1000;

            // Assert
            CompareEncodeDecode(uadpDataSetMessage);
        }
        public void ValidateMajorVersionEqMinorVersionEq(
            [Values(DataSetFieldContentMask.None, DataSetFieldContentMask.RawData, // list here all possible DataSetFieldContentMask
                    DataSetFieldContentMask.ServerPicoSeconds, DataSetFieldContentMask.ServerTimestamp, DataSetFieldContentMask.SourcePicoSeconds,
                    DataSetFieldContentMask.SourceTimestamp, DataSetFieldContentMask.StatusCode,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.SourcePicoSeconds,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.SourceTimestamp,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.StatusCode,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourcePicoSeconds,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourceTimestamp,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.StatusCode,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourcePicoSeconds | DataSetFieldContentMask.SourceTimestamp,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourcePicoSeconds | DataSetFieldContentMask.StatusCode,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourcePicoSeconds | DataSetFieldContentMask.SourceTimestamp | DataSetFieldContentMask.StatusCode
                    )]
            DataSetFieldContentMask dataSetFieldContentMask)
        {
            const int VersionValue = 2;

            // Arrange
            UadpDataSetMessage uadpDataSetMessage = GetFirstDataSetMessage(dataSetFieldContentMask);

            // Act
            uadpDataSetMessage.SetMessageContentMask(UadpDataSetMessageContentMask.MajorVersion | UadpDataSetMessageContentMask.MinorVersion);
            uadpDataSetMessage.MetaDataVersion.MajorVersion = VersionValue;
            uadpDataSetMessage.MetaDataVersion.MinorVersion = VersionValue * 10;

            IServiceMessageContext messageContextEncode = new ServiceMessageContext();

            byte[] bytes;
            var    memoryStream = new MemoryStream();

            using (BinaryEncoder encoder = new BinaryEncoder(memoryStream, messageContextEncode, true))
            {
                uadpDataSetMessage.Encode(encoder);
                _     = encoder.Close();
                bytes = ReadBytes(memoryStream);
            }

            UadpDataSetMessage uaDataSetMessageDecoded = new UadpDataSetMessage();
            BinaryDecoder      decoder = new BinaryDecoder(bytes, messageContextEncode);

            // Make sure the reader MajorVersion and MinorVersion are the same with the ones on the dataset message
            DataSetReaderDataType reader = (DataSetReaderDataType)m_firstDataSetReaderType.MemberwiseClone();

            reader.DataSetMetaData.ConfigurationVersion.MajorVersion = VersionValue;
            reader.DataSetMetaData.ConfigurationVersion.MinorVersion = VersionValue * 10;

            // workaround
            uaDataSetMessageDecoded.DataSetWriterId = TestDataSetWriterId;
            uaDataSetMessageDecoded.DecodePossibleDataSetReader(decoder, reader);
            decoder.Dispose();

            // Assert
            Assert.AreEqual(DataSetDecodeErrorReason.NoError, uaDataSetMessageDecoded.DecodeErrorReason);
            Assert.AreEqual(false, uaDataSetMessageDecoded.IsMetadataMajorVersionChange);
            Assert.AreNotEqual(null, uaDataSetMessageDecoded.DataSet);
            // compare uadpDataSetMessage with uaDataSetMessageDecoded
            CompareUadpDataSetMessages(uadpDataSetMessage, uaDataSetMessageDecoded);
        }
        public void ValidateMinorVersion(
            [Values(DataSetFieldContentMask.None, DataSetFieldContentMask.RawData, // list here all possible DataSetFieldContentMask
                    DataSetFieldContentMask.ServerPicoSeconds, DataSetFieldContentMask.ServerTimestamp, DataSetFieldContentMask.SourcePicoSeconds,
                    DataSetFieldContentMask.SourceTimestamp, DataSetFieldContentMask.StatusCode,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.SourcePicoSeconds,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.SourceTimestamp,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.StatusCode,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourcePicoSeconds,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourceTimestamp,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.StatusCode,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourcePicoSeconds | DataSetFieldContentMask.SourceTimestamp,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourcePicoSeconds | DataSetFieldContentMask.StatusCode,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourcePicoSeconds | DataSetFieldContentMask.SourceTimestamp | DataSetFieldContentMask.StatusCode
                    )]
            DataSetFieldContentMask dataSetFieldContentMask)
        {
            // Arrange
            UadpDataSetMessage uadpDataSetMessage = GetFirstDataSetMessage(dataSetFieldContentMask);

            // Act
            uadpDataSetMessage.SetMessageContentMask(UadpDataSetMessageContentMask.MinorVersion);
            uadpDataSetMessage.MetaDataVersion.MinorVersion = 101;

            // Assert
            CompareEncodeDecode(uadpDataSetMessage);
        }
        public void ValidateDataSetMessageMask(
            [Values(DataSetFieldContentMask.None, DataSetFieldContentMask.RawData, // list here all possible DataSetFieldContentMask
                    DataSetFieldContentMask.ServerPicoSeconds, DataSetFieldContentMask.ServerTimestamp, DataSetFieldContentMask.SourcePicoSeconds,
                    DataSetFieldContentMask.SourceTimestamp, DataSetFieldContentMask.StatusCode,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.SourcePicoSeconds,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.SourceTimestamp,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.StatusCode,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourcePicoSeconds,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourceTimestamp,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.StatusCode,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourcePicoSeconds | DataSetFieldContentMask.SourceTimestamp,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourcePicoSeconds | DataSetFieldContentMask.StatusCode,
                    DataSetFieldContentMask.ServerPicoSeconds | DataSetFieldContentMask.ServerTimestamp | DataSetFieldContentMask.SourcePicoSeconds | DataSetFieldContentMask.SourceTimestamp | DataSetFieldContentMask.StatusCode
                    )]
            DataSetFieldContentMask dataSetFieldContentMask)
        {
            // Arrange
            UadpDataSetMessage uadpDataSetMessage = GetFirstDataSetMessage(dataSetFieldContentMask);

            // Act
            // change network message mask
            for (uint dataSetMessageContentMask = 0; dataSetMessageContentMask < MessageContentMask; dataSetMessageContentMask++)
            {
                uadpDataSetMessage.SetMessageContentMask((UadpDataSetMessageContentMask)dataSetMessageContentMask);

                // Assert
                CompareEncodeDecode(uadpDataSetMessage);
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="fieldContentMask"> a DataSetFieldContentMask specifying what type of encoding is chosen for field values
        /// If none of the flags are set, the fields are represented as Variant.
        /// If the RawData flag is set, the fields are represented as RawData and all other bits are ignored.
        /// If one of the bits StatusCode, SourceTimestamp, ServerTimestamp, SourcePicoSeconds, ServerPicoSeconds is set,
        ///    the fields are represented as DataValue.
        /// </param>
        /// <returns></returns>
        private UadpDataSetMessage GetFirstDataSetMessage(DataSetFieldContentMask fieldContentMask)
        {
            LoadData();

            // set the configurable field content mask to allow only Variant data type
            foreach (DataSetWriterDataType dataSetWriter in m_firstWriterGroup.DataSetWriters)
            {
                // 00 The DataSet fields are encoded as Variant data type
                // The Variant can contain a StatusCode instead of the expected DataType if the status of the field is Bad.
                // The Variant can contain a DataValue with the value and the statusCode if the status of the field is Uncertain.
                dataSetWriter.DataSetFieldContentMask = (uint)fieldContentMask;
            }

            UadpNetworkMessage uaNetworkMessage = (UadpNetworkMessage)m_firstPublisherConnection.CreateNetworkMessage(m_firstWriterGroup);

            Assert.IsNotNull(uaNetworkMessage, "networkMessageEncode should not be null");

            // read first dataset message
            UadpDataSetMessage[] uadpDataSetMessages = uaNetworkMessage.UadpDataSetMessages.ToArray();
            Assert.IsNotEmpty(uadpDataSetMessages, "uadpDataSetMessages collection should not be empty");

            UadpDataSetMessage uadpDataSetMessage = uadpDataSetMessages[0];

            Assert.IsNotNull(uadpDataSetMessage, "uadpDataSetMessage should not be null");

            return(uadpDataSetMessage);
        }
        public void ValidateMinorVersionWithRawDataType()
        {
            // Arrange
            UadpDataSetMessage uadpDataSetMessage = GetFirstDataSetMessage(fieldContentMaskRawData);

            // Act
            uadpDataSetMessage.SetMessageContentMask(UadpDataSetMessageContentMask.MinorVersion);
            uadpDataSetMessage.ConfigurationMinorVersion = 101;

            // Assert
            CompareEncodeDecode(uadpDataSetMessage);
        }
        public void ValidateSequenceNumberWithRawDataType()
        {
            // Arrange
            UadpDataSetMessage uadpDataSetMessage = GetFirstDataSetMessage(fieldContentMaskRawData);

            // Act
            uadpDataSetMessage.SetMessageContentMask(UadpDataSetMessageContentMask.SequenceNumber);
            uadpDataSetMessage.SequenceNumber = 1000;

            // Assert
            CompareEncodeDecode(uadpDataSetMessage);
        }
        public void ValidateMajorVersionWithDataValueType()
        {
            // Arrange
            UadpDataSetMessage uadpDataSetMessage = GetFirstDataSetMessage(fieldContentMaskDataValue);

            // Act
            uadpDataSetMessage.SetMessageContentMask(UadpDataSetMessageContentMask.MajorVersion);
            uadpDataSetMessage.ConfigurationMajorVersion = 2;

            // Assert
            CompareEncodeDecode(uadpDataSetMessage);
        }
        public void ValidateStatusWithDataValueType()
        {
            // Arrange
            UadpDataSetMessage uadpDataSetMessage = GetFirstDataSetMessage(fieldContentMaskDataValue);

            // Act
            uadpDataSetMessage.SetMessageContentMask(UadpDataSetMessageContentMask.Status);
            uadpDataSetMessage.Status = 0x0384;

            // Assert
            CompareEncodeDecode(uadpDataSetMessage);
        }
        public void ValidatePicoSecondsWithRawDataType()
        {
            // Arrange
            UadpDataSetMessage uadpDataSetMessage = GetFirstDataSetMessage(fieldContentMaskRawData);

            // Act
            uadpDataSetMessage.SetMessageContentMask(UadpDataSetMessageContentMask.PicoSeconds);
            uadpDataSetMessage.PicoSeconds = 10;

            // Assert
            CompareEncodeDecode(uadpDataSetMessage);
        }
        public void ValidateDataSetTimeStampWithRawDataType()
        {
            // Arrange
            UadpDataSetMessage uadpDataSetMessage = GetFirstDataSetMessage(fieldContentMaskRawData);

            // Act
            uadpDataSetMessage.SetMessageContentMask(UadpDataSetMessageContentMask.Timestamp);
            uadpDataSetMessage.TimeStamp = DateTime.UtcNow;

            // Assert
            CompareEncodeDecode(uadpDataSetMessage);
        }
        public void ValidateDataSetMessageMaskWithRawDataType()
        {
            // Arrange
            UadpDataSetMessage uadpDataSetMessage = GetFirstDataSetMessage(fieldContentMaskRawData);

            // Act
            // change network message mask
            for (uint dataSetMessageContentMask = 0; dataSetMessageContentMask < MessageContentMask; dataSetMessageContentMask++)
            {
                uadpDataSetMessage.SetMessageContentMask((UadpDataSetMessageContentMask)dataSetMessageContentMask);

                // Assert
                CompareEncodeDecode(uadpDataSetMessage);
            }
        }
        /// <summary>
        /// Compare encoded/decoded dataset messages
        /// </summary>
        /// <param name="uadpDataSetMessage"></param>
        /// <returns></returns>
        private void CompareEncodeDecode(UadpDataSetMessage uadpDataSetMessage)
        {
            ServiceMessageContext messageContextEncode = new ServiceMessageContext();
            BinaryEncoder         encoder = new BinaryEncoder(messageContextEncode);

            uadpDataSetMessage.Encode(encoder);
            byte[] bytes = ReadBytes(encoder.BaseStream);
            encoder.Dispose();

            UadpDataSetMessage uaDataSetMessageDecoded = new UadpDataSetMessage();
            BinaryDecoder      decoder = new BinaryDecoder(bytes, messageContextEncode);

            // workaround
            uaDataSetMessageDecoded.DataSetWriterId = TestDataSetWriterId;
            uaDataSetMessageDecoded.DecodePossibleDataSetReader(decoder, m_firstDataSetReaderType);
            decoder.Dispose();

            // compare uadpDataSetMessage with uaDataSetMessageDecoded
            CompareUadpDataSetMessages(uadpDataSetMessage, uaDataSetMessageDecoded);
        }
        public void ValidateStatus(
            [Values(UadpDataSetMessageContentMask.None, UadpDataSetMessageContentMask.Timestamp,
                    UadpDataSetMessageContentMask.MajorVersion, UadpDataSetMessageContentMask.MinorVersion,
                    UadpDataSetMessageContentMask.SequenceNumber,
                    UadpDataSetMessageContentMask.MajorVersion | UadpDataSetMessageContentMask.MinorVersion,
                    UadpDataSetMessageContentMask.MajorVersion | UadpDataSetMessageContentMask.MinorVersion | UadpDataSetMessageContentMask.SequenceNumber)]
            UadpDataSetMessageContentMask messageContentMask,
            [Values(StatusCodes.Good, StatusCodes.UncertainDataSubNormal, StatusCodes.BadAggregateListMismatch, StatusCodes.BadUnknownResponse,
                    StatusCodes.Bad, StatusCodes.BadAggregateConfigurationRejected, StatusCodes.BadAggregateInvalidInputs, StatusCodes.BadAlreadyExists)]
            uint statusCode
            )
        {
            // Arrange
            UadpDataSetMessage uadpDataSetMessage = GetFirstDataSetMessage(DataSetFieldContentMask.None);

            // Act
            uadpDataSetMessage.SetMessageContentMask(messageContentMask | UadpDataSetMessageContentMask.Status);
            uadpDataSetMessage.Status = statusCode;

            // Assert
            CompareEncodeDecode(uadpDataSetMessage);
        }