/*
         *  <wsnt:Message>
         *    <tt:Message UtcTime="2010-09-28T14:17:12.801" PropertyOperation="Initialized">
         *      <tt:Source>
         *        <tt:SimpleItem Name="VideoSourceToken" Value="1"></tt:SimpleItem>
         *      </tt:Source>
         *      <tt:Data>
         *        <tt:SimpleItem Name="State" Value="true"></tt:SimpleItem>
         *      </tt:Data>
         *    </tt:Message>
         *  </wsnt:Message>*/

        void GetMessageElements(List <FindEventResult> result,
                                Dictionary <FindEventResult, XmlDocument> rawResults,
                                Dictionary <FindEventResult, XmlElement> messageElements)
        {
            string messagePath;

            messagePath = "/s:Envelope/s:Body/search:GetEventSearchResultsResponse/search:ResultList/onvif:Result/onvif:Event";

            for (int i = 0; i < result.Count;)
            {
                FindEventResult     ev               = result[i];
                XmlDocument         soapRawPacket    = rawResults[ev];
                XmlNamespaceManager manager          = CreateNamespaceManager(soapRawPacket);
                XmlNodeList         responseNodeList = soapRawPacket.SelectNodes(messagePath, manager);

                for (int j = 0; j < responseNodeList.Count; j++)
                {
                    XmlNode    node    = responseNodeList[j];
                    XmlElement element = node as XmlElement;
                    if (element != null)
                    {
                        messageElements.Add(ev, element);
                        i++;
                        if (i < result.Count)
                        {
                            ev = result[i];
                        }
                    }
                }
            }
        }
        TopicInfo CreateTopicInfo(FindEventResult e, XmlElement messageElement)
        {
            XmlElement topicElement = null;

            foreach (XmlElement child in messageElement.ChildNodes)
            {
                if (child.LocalName == "Topic" && child.NamespaceURI == BaseNotification.WSNT)
                {
                    topicElement = child;
                    break;
                }
            }

            XmlText text = GetTopicElement(e);

            if (topicElement == null)
            {
                return(null);
            }
            if (text == null)
            {
                return(null);
            }

            //TopicInfo actual = TopicInfo.ExtractTopicInfoAll(text.Value, topicElement);
            //[26.03.2013] AKS: return behavior like before merge
            TopicInfo actual = TopicInfo.ExtractTopicInfoPACS(text.Value, topicElement);

            return(actual);
        }
        XmlText GetTopicElement(FindEventResult e)
        {
            XmlText text = null;

            foreach (XmlNode child in e.Event.Topic.Any)
            {
                if (child is XmlText)
                {
                    text = child as XmlText;
                    break;
                }
            }
            return(text);
        }
        bool AreTheSame(FindEventResult ev1, TopicInfo topic1, FindEventResult ev2, XmlElement element2)
        {
            bool scopeMatches = (ev1.Time == ev2.Time) && (ev2.RecordingToken == ev1.RecordingToken) &&
                                (ev1.TrackToken == ev2.TrackToken);

            bool topicMatches = false;

            if (scopeMatches)
            {
                TopicInfo t2 = CreateTopicInfo(ev2, element2);
                topicMatches = TopicInfo.TopicsMatch(topic1, t2);
            }

            return(topicMatches);
        }
        bool CheckEventTopic(FindEventResult e, XmlElement rawResultElement,
                             string topic,
                             string ns)
        {
            if (e.Event != null && e.Event.Topic != null)
            {
                TopicInfo expected =
                    TopicInfo.ConstructTopicInfo(new EventsTopicInfo()
                {
                    NamespacesDefinition = ns, Topic = topic
                });

                TopicInfo actual = CreateTopicInfo(e, rawResultElement);

                bool topicMatches = TopicInfo.TopicsMatch(actual, expected);

                return(topicMatches);
            }
            return(false);
        }
Ejemplo n.º 6
0
        FindEventResult GenerateTrackEvent(RecordingInformation recording, TrackInformation track)
        {
            FindEventResult eventResult = new FindEventResult();

            eventResult.RecordingToken = recording.RecordingToken;
            if (track != null)
            {
                eventResult.TrackToken = track.TrackToken;
            }
            else
            {
                eventResult.TrackToken = "";
            }
            eventResult.Event = new NotificationMessageHolderType();
            //eventResult.Event.ProducerReference = new EndpointReferenceType();
            //eventResult.Event.ProducerReference.Address = new AttributedURIType(){Value= "http://localhost/dut.asmx"};
            eventResult.Event.Topic         = new TopicExpressionType();
            eventResult.Event.Topic.Dialect = "http://www.onvif.org/ver10/tev/topicExpression/ConcreteSet";
            return(eventResult);
        }
        bool ValidateMessage(FindEventResult eventResult, StringBuilder dump)
        {
            XmlText topicText = GetTopicElement(eventResult);
            string  topic     = topicText.Value;

            bool valid = true;

            List <string>       simpleItems = new List <string>();
            XmlNamespaceManager manager     = new XmlNamespaceManager(eventResult.Event.Message.OwnerDocument.NameTable);

            manager.AddNamespace(OnvifMessage.ONVIFPREFIX, OnvifMessage.ONVIF);

            string path;

            path = "/tt:Data/tt:SimpleItem";
            XmlNodeList itemNodesList = eventResult.Event.Message.SelectNodes(path, manager);

            StringBuilder local = new StringBuilder();

            foreach (XmlNode node in itemNodesList)
            {
                XmlElement element = node as XmlElement;
                if (element == null)
                {
                    continue;
                }
                string name = element.GetAttribute(OnvifMessage.NAME);
                if (simpleItems.Contains(name))
                {
                    valid = false;
                    local.AppendFormat("   Multiple SimpleItem elements with 'Name' attribute set to '{0}' found{1}", name, Environment.NewLine);
                }
                simpleItems.Add(name);
            }
            if (!valid)
            {
                dump.AppendFormat("Message for event with time={0}, topic ={1} is incorrect: {2}", eventResult.Time.StdDateTimeToString(), topic, Environment.NewLine);
                dump.Append(local.ToString());
            }
            return(valid);
        }
        bool AreTheSame(FindEventResult ev1, TopicInfo topic1, FindEventResult ev2, XmlElement element2)
        {
            // Two Event Results will be assumed as the same, if they have the same values for
            // GetEventSearchResultsResponse.ResultList.Result.RecordingToken,
            // GetEventSearchResultsResponse.ResultList.Result.TrackToken,
            // GetEventSearchResultsResponse.ResultList.Result.Time,
            // GetEventSearchResultsResponse.ResultList.Result.Event.Topic and
            // fields and values of GetEventSearchResultsResponse.ResultList.Result.Event.Message.Data.

            bool scopeMatches = (ev1.Time == ev2.Time) && (ev2.RecordingToken == ev1.RecordingToken) &&
                                (ev1.TrackToken == ev2.TrackToken);

            bool topicMatches = false;

            if (scopeMatches)
            {
                TopicInfo t2 = CreateTopicInfo(ev2, element2);
                topicMatches = TopicInfo.TopicsMatch(topic1, t2);
            }

            return(topicMatches);
        }
        bool HaveTheSamePayload(FindEventResult ev1, FindEventResult ev2)
        {
            bool theSame = true;

            if (ev1.Event != null && ev2.Event != null)
            {
                if (ev1.Event.Message != null && ev2.Event.Message != null)
                {
                    Dictionary <string, string> items1 = GetMessageSimpleItems(ev1.Event.Message);
                    Dictionary <string, string> items2 = GetMessageSimpleItems(ev2.Event.Message);

                    List <string> common  = new List <string>();
                    bool          localOk = true;

                    foreach (string key in items1.Keys)
                    {
                        if (!items2.ContainsKey(key))
                        {
                            localOk = false;
                            break;
                        }
                        else
                        {
                            common.Add(key);
                        }
                    }
                    if (localOk)
                    {
                        foreach (string key in items2.Keys)
                        {
                            if (!items2.ContainsKey(key))
                            {
                                localOk = false;
                                break;
                            }
                        }
                    }
                    if (localOk)
                    {
                        foreach (string key in common)
                        {
                            if (items1[key] != items2[key])
                            {
                                localOk = false;
                            }
                        }
                    }

                    theSame = localOk;
                }
                else
                {
                    theSame = (ev1.Event.Message == null && ev2.Event.Message == null);
                }
            }
            else
            {
                theSame = (ev1.Event == null && ev2.Event == null);
            }
            return(theSame);
        }
        void CompareLists(IEnumerable <FindEventResult> list1, IEnumerable <FindEventResult> list2,
                          Dictionary <FindEventResult, XmlElement> rawMessages1, Dictionary <FindEventResult, XmlElement> rawMessages2,
                          string descr1, string descr2)
        {
            bool          ok   = true;
            StringBuilder dump = new StringBuilder();

            Dictionary <FindEventResult, FindEventResult> intersection = new Dictionary <FindEventResult, FindEventResult>();

            Func <FindEventResult, string, string> getDescription =
                new Func <FindEventResult, string, string>(
                    (e, topic) =>
            {
                return(string.Format("Event with Time={0}, RecordingToken='{1}', TrackToken='{2}', Topic='{3}'", e.Time, e.RecordingToken, e.TrackToken, topic));
            });


            // check events in list1, find events that are not in list2,
            // find events that are in both lists (intersection)

            foreach (FindEventResult ev1 in list1)
            {
                if (!ev1.StartStateEvent)
                {
                    XmlText   topicText = GetTopicElement(ev1);
                    TopicInfo topicInfo = CreateTopicInfo(ev1, rawMessages1[ev1]);

                    List <FindEventResult> filtered2 =
                        list2.Where(E => AreTheSame(ev1, topicInfo, E, rawMessages2[E])).ToList();
                    string topic = topicText.Value;

                    string descr = getDescription(ev1, topic);

                    if (filtered2.Count() == 0)
                    {
                        ok = false;
                        dump.AppendFormat("{0} not found in {1}{2}",
                                          descr, descr2, Environment.NewLine);
                    }
                    else
                    {
                        FindEventResult ev2 = filtered2.Where(E => HaveTheSamePayload(ev1, E)).FirstOrDefault();

                        if (ev2 != null)
                        {
                            intersection.Add(ev1, ev2);
                        }
                        else
                        {
                            // how to describe the error ?????
                            ok = false;
                            dump.AppendFormat("For {0} (or one of them) in {1}, no event with the same Data can be found in {2}{3}", descr, descr1, descr2, Environment.NewLine);
                        }
                    }
                }
            }

            // check events in list2, find events that are not in list1

            foreach (FindEventResult ev2 in list2)
            {
                if (!ev2.StartStateEvent)
                {
                    XmlText   topicText = GetTopicElement(ev2);
                    TopicInfo topicInfo = CreateTopicInfo(ev2, rawMessages2[ev2]);
                    string    topic     = topicText.Value;
                    string    descr     = getDescription(ev2, topic);

                    List <FindEventResult> filtered1 =
                        list1.Where(E => AreTheSame(ev2, topicInfo, E, rawMessages1[E])).ToList();


                    if (filtered1.Count() == 0)
                    {
                        ok = false;
                        dump.AppendFormat("{0} not found in {1}{2}",
                                          descr, descr1, Environment.NewLine);
                    }
                    else
                    {
                        FindEventResult ev1 = filtered1.FirstOrDefault(E => HaveTheSamePayload(ev2, E));
                        if (ev1 == null)
                        {
                            ok = false;
                            dump.AppendFormat("For {0} (or one of them) in {1}, no event with the same Data can be found in {2}{3}", descr, descr2, descr1, Environment.NewLine);
                        }
                    }
                }
            }


            // compare event in intersection
            // StartStateEvent
            // in Event:  ProducerReference, SubscriptionReference (should not both be empty?)
            // message items...

            foreach (FindEventResult ev1 in intersection.Keys)
            {
                bool          localOk = true;
                StringBuilder sb      = new StringBuilder(getDescription(ev1, GetTopicElement(ev1).Value));
                sb.AppendLine(" is different: ");

                FindEventResult ev2 = intersection[ev1];

                if (ev1.StartStateEvent != ev2.StartStateEvent)
                {
                    sb.AppendLine("StartStateEvent fields don't match");
                }

                // ProducerReference ?
                if (ev1.Event.ProducerReference != null && ev2.Event.ProducerReference != null)
                {
                    if (ev1.Event.ProducerReference.Address.Value != ev2.Event.ProducerReference.Address.Value)
                    {
                        localOk = false;
                        sb.AppendFormat("Event.ProducerReference fields don't match {0}", Environment.NewLine);
                    }
                }
                else
                {
                    if (ev1.Event.ProducerReference != null)
                    {
                        localOk = false;
                        sb.AppendFormat("Event.ProducerReference is missing in message from {0}{1}", descr2,
                                        Environment.NewLine);
                    }
                    if (ev2.Event.ProducerReference != null)
                    {
                        localOk = false;
                        sb.AppendFormat("Event.ProducerReference is missing in message from {0}{1}", descr1,
                                        Environment.NewLine);
                    }
                }

                // SubscriptionReference (?)
                if (ev1.Event.SubscriptionReference != null && ev2.Event.SubscriptionReference != null)
                {
                    if (ev1.Event.SubscriptionReference.Address.Value != ev2.Event.SubscriptionReference.Address.Value)
                    {
                        localOk = false;
                        sb.AppendFormat("Event.SubscriptionReference fields don't match {0}", Environment.NewLine);
                    }
                }
                else
                {
                    if (ev1.Event.SubscriptionReference != null)
                    {
                        localOk = false;
                        sb.AppendFormat("Event.SubscriptionReference is missing in message from {0}{1}", descr2,
                                        Environment.NewLine);
                    }
                    if (ev2.Event.SubscriptionReference != null)
                    {
                        localOk = false;
                        sb.AppendFormat("Event.SubscriptionReference is missing in message from {0}{1}", descr1,
                                        Environment.NewLine);
                    }
                }


                // Message items
                //if (ev1.Event.Message != null && ev2.Event.Message != null)
                //{
                //    Dictionary<string, string> items1 = GetMessageSimpleItems(ev1.Event.Message);
                //    Dictionary<string, string> items2 = GetMessageSimpleItems(ev2.Event.Message);

                //    List<string> common = new List<string>();

                //    foreach (string key in items1.Keys)
                //    {
                //        if (!items2.ContainsKey(key))
                //        {
                //            localOk = false;
                //            sb.AppendFormat("SimpleItem with name='{0}' not found in message from {1}{2}", key, descr2,
                //                            Environment.NewLine);
                //        }
                //        else
                //        {
                //            common.Add(key);
                //        }
                //    }
                //    foreach (string key in items2.Keys)
                //    {
                //        if (!items2.ContainsKey(key))
                //        {
                //            localOk = false;
                //            sb.AppendFormat("SimpleItem with name='{0}' not found in message from {1}{2}", key, descr1,
                //                            Environment.NewLine);
                //        }
                //    }

                //    foreach (string key in common)
                //    {
                //        if (items1[key] != items2[key])
                //        {
                //            localOk = false;
                //            sb.AppendFormat("SimpleItem elements with name='{0}' have different values {1}", key, Environment.NewLine);
                //        }
                //    }
                //}
                //else
                //{
                //    if (ev1.Event.Message == null)
                //    {
                //        localOk = false;
                //        sb.AppendLine(string.Format("Message field is missing in structure from {0}", descr1));
                //    }
                //    if (ev2.Event.Message == null)
                //    {
                //        localOk = false;
                //        sb.AppendLine(string.Format("Message field is missing in structure from {0}", descr2));
                //    }
                //}


                if (!localOk)
                {
                    ok = false;
                    dump.Append(sb.ToString());
                }
            }

            Assert(ok, dump.ToStringTrimNewLine(), "Check that events lists are the same");
        }
Ejemplo n.º 11
0
        void GenerateEvents()
        {
            XmlDocument doc = new XmlDocument();

            _events = new List <FindEventResult>();
            foreach (RecordingInformation recording in Recordings)
            {
                foreach (TrackInformation track in recording.Track)
                {
                    {
                        FindEventResult dataAppeared = GenerateTrackEvent(recording, track);
                        dataAppeared.Time = track.DataFrom;

                        XmlText topic = doc.CreateTextNode("tns1:RecordingHistory/Track/State");
                        System.Xml.Serialization.XmlSerializerNamespaces xmlns =
                            new System.Xml.Serialization.XmlSerializerNamespaces();
                        xmlns.Add("tns1", "http://www.onvif.org/ver10/topics");
                        dataAppeared.Event.Topic.Xmlns = xmlns;

                        dataAppeared.Event.Topic.Any = new XmlNode[] { topic };

                        dataAppeared.Event.Message = doc.CreateElement("tt:Message",
                                                                       "http://docs.oasis-open.org/wsn/b-2");

                        XmlElement data = doc.CreateElement("tt", "Data", "http://www.onvif.org/ver10/schema");
                        dataAppeared.Event.Message.AppendChild(data);

                        data.AppendChild(CreateSimpleItemElement(doc, "IsDataPresent", "True"));

                        if (_eventsGenerationCrashTest)
                        {
                            dataAppeared.StartStateEvent         = true;
                            dataAppeared.Event.ProducerReference = new EndpointReferenceType()
                            {
                                Address = new AttributedURIType()
                                {
                                    Value = "http://localhost/dut/events.asmx"
                                }
                            };
                        }

                        _events.Add(dataAppeared);
                    }

                    {
                        FindEventResult dataSaved = GenerateTrackEvent(recording, track);
                        dataSaved.Time = track.DataTo;

                        XmlText topic = doc.CreateTextNode("tns1:RecordingHistory/Track/State");
                        System.Xml.Serialization.XmlSerializerNamespaces xmlns =
                            new System.Xml.Serialization.XmlSerializerNamespaces();
                        xmlns.Add("tns1", "http://www.onvif.org/ver10/topics");
                        dataSaved.Event.Topic.Xmlns = xmlns;

                        dataSaved.Event.Topic.Any = new XmlNode[] { topic };

                        dataSaved.Event.Message = doc.CreateElement("tt:Message", "http://docs.oasis-open.org/wsn/b-2");

                        XmlElement data = doc.CreateElement("tt", "Data", "http://www.onvif.org/ver10/schema");
                        dataSaved.Event.Message.AppendChild(data);

                        data.AppendChild(CreateSimpleItemElement(doc, "IsDataPresent", "False"));
                        data.AppendChild(CreateSimpleItemElement(doc, "IsDataPresent", "True"));

                        //if (_eventsGenerationCrashTest)
                        //{
                        //    dataSaved.Event.ProducerReference = null;
                        //}
                        //else
                        //{
                        //    dataSaved.Event.ProducerReference = new EndpointReferenceType() { Address = new AttributedURIType() { Value = "http://localhost/dut/events1.asmx" } };
                        //}

                        _events.Add(dataSaved);
                    }
                    if (_eventsGenerationCrashTest)
                    {
                        FindEventResult parametersEvent = GenerateTrackEvent(recording, track);
                        parametersEvent.Time = recording.EarliestRecording;
                        XmlText topic = doc.CreateTextNode("tns1:RecordingHistory/Track/VideoParameters");
                        System.Xml.Serialization.XmlSerializerNamespaces xmlns =
                            new System.Xml.Serialization.XmlSerializerNamespaces();
                        xmlns.Add("tns1", "http://www.onvif.org/ver10/topics");
                        parametersEvent.Event.Topic.Xmlns = xmlns;
                        parametersEvent.Event.Topic.Any   = new XmlNode[] { topic };
                        parametersEvent.Event.Message     = doc.CreateElement("tt:Message",
                                                                              "http://docs.oasis-open.org/wsn/b-2");
                        _events.Add(parametersEvent);

                        //if (_eventsGenerationCrashTest)
                        //{
                        //    parametersEvent.Event.SubscriptionReference = new EndpointReferenceType() { Address = new AttributedURIType() { Value = "http://localhost/dut/events.asmx" } };
                        //}
                        //else
                        //{
                        //    parametersEvent.Event.SubscriptionReference = new EndpointReferenceType() { Address = new AttributedURIType() { Value = "http://localhost/dut/events1.asmx" } };
                        //}
                    }

                    if (!_eventsGenerationCrashTest)
                    {
                        FindEventResult parametersEvent = GenerateTrackEvent(recording, track);
                        parametersEvent.Time = recording.EarliestRecording;
                        XmlText topic = doc.CreateTextNode("tns1:RecordingHistory/Track/AudioParameters");
                        System.Xml.Serialization.XmlSerializerNamespaces xmlns =
                            new System.Xml.Serialization.XmlSerializerNamespaces();
                        xmlns.Add("tns1", "http://www.onvif.org/ver10/topics");
                        parametersEvent.Event.Topic.Xmlns = xmlns;
                        parametersEvent.Event.Topic.Any   = new XmlNode[] { topic };
                        parametersEvent.Event.Message     = doc.CreateElement("tt:Message",
                                                                              "http://docs.oasis-open.org/wsn/b-2");
                        _events.Add(parametersEvent);

                        //if (_eventsGenerationCrashTest)
                        //{
                        //    parametersEvent.Event.SubscriptionReference = new EndpointReferenceType() { Address = new AttributedURIType() { Value = "http://localhost/dut/events.asmx" } };
                        //}
                    }
                } // foreach Track

                {
                    FindEventResult recordingStarted = GenerateTrackEvent(recording, null);
                    recordingStarted.Time = recording.EarliestRecording;
                    XmlText topic = doc.CreateTextNode("tns1:RecordingHistory/Recording/State");
                    System.Xml.Serialization.XmlSerializerNamespaces xmlns = new System.Xml.Serialization.XmlSerializerNamespaces();
                    xmlns.Add("tns1", "http://www.onvif.org/ver10/topics");
                    recordingStarted.Event.Topic.Xmlns = xmlns;
                    recordingStarted.Event.Topic.Any   = new XmlNode[] { topic };
                    recordingStarted.Event.Message     = doc.CreateElement("tt:Message", "http://docs.oasis-open.org/wsn/b-2");

                    XmlElement data = doc.CreateElement("tt", "Data", "http://www.onvif.org/ver10/schema");
                    recordingStarted.Event.Message.AppendChild(data);
                    data.AppendChild(CreateSimpleItemElement(doc, "IsRecording", "True"));
                    data.AppendChild(CreateSimpleItemElement(doc, "IsRecording", "True"));

                    //if (_eventsGenerationCrashTest)
                    //{
                    //    data.AppendChild(CreateSimpleItemElement(doc, "SomeValue", "True"));
                    //}

                    _events.Add(recordingStarted);
                }

                {
                    FindEventResult recordingfinished = GenerateTrackEvent(recording, null);
                    recordingfinished.Time = recording.LatestRecording;
                    XmlText topic = doc.CreateTextNode("tns1:RecordingHistory/Recording/State");
                    System.Xml.Serialization.XmlSerializerNamespaces xmlns =
                        new System.Xml.Serialization.XmlSerializerNamespaces();
                    xmlns.Add("tns1", "http://www.onvif.org/ver10/topics");
                    recordingfinished.Event.Topic.Xmlns = xmlns;
                    recordingfinished.Event.Topic.Any   = new XmlNode[] { topic };
                    recordingfinished.Event.Message     = doc.CreateElement("tt:Message",
                                                                            "http://docs.oasis-open.org/wsn/b-2");


                    XmlElement data = doc.CreateElement("tt", "Data", "http://www.onvif.org/ver10/schema");
                    recordingfinished.Event.Message.AppendChild(data);
                    data.AppendChild(CreateSimpleItemElement(doc, "IsRecording", "False"));


                    //if (_eventsGenerationCrashTest)
                    //{
                    //    data.AppendChild(CreateSimpleItemElement(doc, "SomeValue", "True"));
                    //}
                    //else
                    //{
                    //    data.AppendChild(CreateSimpleItemElement(doc, "SomeValue", "False"));
                    //}
                    _events.Add(recordingfinished);
                }
            }
        }
Ejemplo n.º 12
0
 public static bool IsOnvifMessage(FindEventResult msg)
 {
     return(IsOnvifMessage(msg.Event));
 }
        void ValidateTrackEvents(RecordingInformation recording,
                                 TrackInformation track,
                                 IEnumerable <FindEventResult> results,
                                 Dictionary <FindEventResult, XmlElement> elements,
                                 bool checkEdges)
        {
            {
                Func <FindEventResult, bool> eventCheck =
                    (E =>
                {
                    bool topicMatches = CheckEventTopic(E, elements[E], "tns1:RecordingHistory/Track/State",
                                                        TNS1NAMESPACE);

                    return(topicMatches);
                });

                List <FindEventResult> filtered = results.Where(E => eventCheck(E) && E.TrackToken == track.TrackToken).OrderBy(E => E.Time).ToList();

                bool dataPresentOk   = true;
                bool?lastDataPresent = null;
                if (checkEdges)
                {
                    lastDataPresent = false;

                    // checkEdges = false means that interval is narrowed and virtual events are sent
                    // in this case 1 event is OK
                    Assert(filtered.Count >= 2,
                           string.Format(
                               "Not enough events with topic=tns1:RecordingHistory/Track/State, RecordingToken='{0}' for track '{1}' found in the response",
                               recording.RecordingToken, track.TrackToken),
                           string.Format("Check that at least two events with topic tns1:RecordingHistory/Track/State are present for track '{0}'", track.TrackToken));
                }

                StringBuilder dump = new StringBuilder();
                for (int i = 0; i < filtered.Count; i++)
                {
                    FindEventResult ev = filtered[i];

                    XmlElement message = ev.Event.Message;

                    string value = GetSimpleItem(message, "IsDataPresent");

                    if (value == null)
                    {
                        dataPresentOk = false;
                        dump.AppendFormat(
                            string.Format(
                                "IsDataPresent value not found for event with RecordingToken='{0}', Time='{1}'{2}",
                                ev.RecordingToken, ev.Time.StdDateTimeToString(), Environment.NewLine));
                    }
                    else
                    {
                        bool dataPresent;
                        bool attrOk = bool.TryParse(value, out dataPresent);
                        if (!attrOk)
                        {
                            dataPresentOk = false;
                            dump.AppendFormat(
                                string.Format(
                                    "IsDataPresent value for event with RecordingToken='{0}', Time='{1}' is incorrect ({2}){3}",
                                    ev.RecordingToken, ev.Time.StdDateTimeToString(), value, Environment.NewLine));
                        }
                        else
                        {
                            if (ev.StartStateEvent)
                            {
                                continue;
                            }

                            if (lastDataPresent.HasValue)
                            {
                                if (dataPresent == lastDataPresent)
                                {
                                    dataPresentOk = false;
                                    if (i == 0)
                                    {
                                        dump.AppendFormat(
                                            string.Format(
                                                "IsDataPresent value for first event with RecordingToken='{0}', Time='{1}' is false {2}",
                                                ev.RecordingToken, ev.Time.StdDateTimeToString(), Environment.NewLine));
                                    }
                                    else
                                    {
                                        dump.AppendFormat(
                                            string.Format(
                                                "IsDataPresent value for event with RecordingToken='{0}', Time='{1}' is {2} while previous is also {2}{3}",
                                                ev.RecordingToken, ev.Time.StdDateTimeToString(), dataPresent,
                                                Environment.NewLine));
                                    }
                                }
                            }
                            lastDataPresent = dataPresent;
                        }
                    }
                }

                Assert(dataPresentOk, dump.ToStringTrimNewLine(), "Check that IsDataPresent values in events are correct");
            }
        }
        void ValidateRecordingEventsSequence(RecordingInformation recording,
                                             IEnumerable <FindEventResult> results,
                                             Dictionary <FindEventResult, XmlElement> elements,
                                             bool checkEdges)
        {
            Func <FindEventResult, bool> eventCheck;

            //
            // recording events
            //
            eventCheck =
                (E =>
            {
                bool topicMatches = CheckEventTopic(E, elements[E], "tns1:RecordingHistory/Recording/State",
                                                    TNS1NAMESPACE);

                return(topicMatches);
            });

            // select Recording/State events
            List <FindEventResult> filtered = results.Where(eventCheck).OrderBy(E => E.Time).ToList();

            // check that there is no events for other recordings
            List <FindEventResult> nonmatching =
                filtered.Where(E => E.RecordingToken != recording.RecordingToken).ToList();

            Assert(nonmatching.Count == 0,
                   "Event with topic 'tns1:RecordingHistory/Recording/State' for other recordings found",
                   string.Format(
                       "Check that all events with topic 'tns1:RecordingHistory/Recording/State' relate to recording '{0}'",
                       recording.RecordingToken));

            bool isRecordingOk   = true;
            bool?lastIsRecording = null;

            if (checkEdges)
            {
                lastIsRecording = false;


                // when checkEdges = false (narrowed interval), 1 event is OK (only virtual event)
                Assert(filtered.Count >= 2, "Not enough tns1:RecordingHistory/Recording/State events found",
                       "Check that at least two events with topic tns1:RecordingHistory/Recording/State found");
            }


            StringBuilder dump = new StringBuilder();

            for (int i = 0; i < filtered.Count; i++)
            {
                FindEventResult ev = filtered[i];

                XmlElement message = ev.Event.Message;

                string value = GetSimpleItem(message, "IsRecording");

                if (value == null)
                {
                    isRecordingOk = false;
                    dump.AppendFormat(
                        string.Format(
                            "IsRecording value not found for event with RecordingToken='{0}', Time='{1}'{2}",
                            ev.RecordingToken, ev.Time.StdDateTimeToString(), Environment.NewLine));
                }
                else
                {
                    bool isRecording;
                    bool attrOk = bool.TryParse(value, out isRecording);
                    if (!attrOk)
                    {
                        isRecordingOk = false;
                        dump.AppendFormat(
                            string.Format(
                                "IsRecording value for event with RecordingToken='{0}', Time='{1}' is incorrect ({2}){3}",
                                ev.RecordingToken, ev.Time.StdDateTimeToString(), value, Environment.NewLine));
                    }
                    else
                    {
                        if (ev.StartStateEvent)
                        {
                            continue;
                        }

                        if (lastIsRecording.HasValue)
                        {
                            if (isRecording == lastIsRecording.Value)
                            {
                                isRecordingOk = false;
                                if (i == 0)
                                {
                                    dump.AppendFormat(
                                        string.Format(
                                            "IsRecording value for first event with RecordingToken='{0}', Time='{1}' is false {2}",
                                            ev.RecordingToken, ev.Time.StdDateTimeToString(), Environment.NewLine));
                                }
                                else
                                {
                                    dump.AppendFormat(
                                        string.Format(
                                            "IsRecording value for event with RecordingToken='{0}', Time='{1}' is {2} while previous is also {2}{3}",
                                            ev.RecordingToken, ev.Time.StdDateTimeToString(), isRecording, Environment.NewLine));
                                }
                            }
                        }
                        lastIsRecording = isRecording;
                    }
                }
            }

            Assert(isRecordingOk, dump.ToStringTrimNewLine(), "Check that IsRecording values in events are correct");
        }