/// <summary>
        /// Compares a given activity to the list of activities specified by IgnoringActivities list in the test configuration.
        /// </summary>
        /// <param name="activity">An activity that the client received from the bot.</param>
        /// <returns>true if the activity matches one of the activities in the list. Otherwise returns false.</returns>
        public bool IgnoreActivity(Activity activity)
        {
            bool ignore = false;

            if (this.ignoreActivitiesList != null)
            {
                foreach (Activity activityToIgnore in this.ignoreActivitiesList)
                {
                    string activityToIgnoreSerializedJson = JsonConvert.SerializeObject(activityToIgnore, new JsonSerializerSettings {
                        NullValueHandling = NullValueHandling.Ignore
                    });
                    string activitySerializedJson = JsonConvert.SerializeObject(activity, new JsonSerializerSettings {
                        NullValueHandling = NullValueHandling.Ignore
                    });
                    JObject activityToIgnoreJObject = JsonConvert.DeserializeObject <JObject>(activityToIgnoreSerializedJson);
                    JObject activityJObject         = JsonConvert.DeserializeObject <JObject>(activitySerializedJson);

                    DialogResult.ActivityMismatchCount = 0;
                    if (DialogResult.CompareJObjects(activityToIgnoreJObject, activityJObject) == 0)
                    {
                        Trace.TraceInformation($"Bot-reply activity matched IgnoreActivities[{this.ignoreActivitiesList.IndexOf(activityToIgnore)}]. Ignore it.");
                        ignore = true;
                        break;
                    }
                }
            }

            return(ignore);
        }
        /// <summary>
        /// Sends a message activity to the bot after wrapping a message in an Activity object.
        /// </summary>
        /// <param name="message">Utterance text in each turn.</param>
        /// <returns>Activity.</returns>
        public async Task <BotConnector> Send(string message)
        {
            IMessageActivity bfActivity = Activity.CreateMessageActivity();

            bfActivity.Text = message;
            string jsonConnectorActivity = JsonConvert.SerializeObject(bfActivity);

            return(await this.SendActivity(jsonConnectorActivity).ConfigureAwait(false));
        }
        /// <summary>
        /// Method to get Expected TTS Audio Response Duration corresponding to an Expected Response Text that matches Actual Response Text.
        /// </summary>
        /// <param name="expectedResponse">Expected Bot response activity.</param>
        /// <param name="actualResponse">Bot response activity.</param>
        /// <param name="expectedTTSAudioResponseDuration">Expected TTS Audio Response Duration that might be separated by OR operator.</param>
        private static int GetCorrespondingExpectedTTSAudioResponseDuration(Activity expectedResponse, Activity actualResponse, string expectedTTSAudioResponseDuration)
        {
            string normalizedExpectedText = GetNormalizedText(expectedResponse.Text);
            string normalizedActualText   = GetNormalizedText(actualResponse.Text);

            if (normalizedExpectedText.Contains(ProgramConstants.OROperator, StringComparison.OrdinalIgnoreCase))
            {
                int i = normalizedExpectedText.Split(ProgramConstants.OROperator).ToList().IndexOf(normalizedActualText);
                return(Convert.ToInt32(expectedTTSAudioResponseDuration.Split(ProgramConstants.OROperator)[i], CultureInfo.InvariantCulture));
            }
            else
            {
                return(Convert.ToInt32(expectedTTSAudioResponseDuration, CultureInfo.InvariantCulture));
            }
        }
Beispiel #4
0
        /// <summary>
        /// Checks for proper, valid input combination of the dialog turns.
        /// </summary>
        /// <param name="turn">A turn object.</param>
        /// <param name="botGreeting">Bot greeting value from the application settings.</param>
        /// <param name="singleConnection">Single connection value from the test settings.</param>
        /// <param name="firstDialog">true if this is the first dialog in the test file.</param>
        /// <param name="firstTurn">true if this is the first turn in the dialog.</param>
        /// <returns>A tuple of a boolean and a list of strings. The boolean is set to true if the string is valid and the list of strings captures the error messages if the turn is not valid.</returns>
        private static (bool ValidTurn, List <string> ExceptionMesssage) ValidateTurnInput(Turn turn, bool botGreeting, bool singleConnection, bool firstDialog, bool firstTurn)
        {
            bool utterancePresentValid       = CheckNotNullNotEmptyString(turn.Utterance);
            bool activityPresentValid        = CheckNotNullNotEmptyString(turn.Activity);
            bool wavFilePresentValid         = CheckNotNullNotEmptyString(turn.WAVFile);
            bool expectedLatencyPresentValid = CheckNotNullNotEmptyString(turn.ExpectedUserPerceivedLatency);

            List <string> exceptionMessage = new List <string>();

            if (activityPresentValid)
            {
                var(activityObjectValid, errorMsg) = CheckValidActivity(turn.Activity);
                if (!activityObjectValid)
                {
                    exceptionMessage.Add(errorMsg);
                }
            }

            if (expectedLatencyPresentValid)
            {
                if (turn.ExpectedResponses != null && turn.ExpectedResponses.Count != 0)
                {
                    var expectedLatencyObjectValid = CheckValidExpectedLatency(turn.ExpectedUserPerceivedLatency, turn.ExpectedResponses.Count);
                    if (!expectedLatencyObjectValid)
                    {
                        exceptionMessage.Add(ErrorStrings.LATENCY_STRING_MALFORMED);
                    }
                }
                else
                {
                    exceptionMessage.Add(ErrorStrings.LATENCY_STRING_PRESENT);
                }
            }

            if (turn.ExpectedResponses != null && turn.ExpectedResponses.Count != 0 && turn.ExpectedTTSAudioResponseDurations != null)
            {
                if (turn.ExpectedTTSAudioResponseDurations.Count != turn.ExpectedResponses.Count)
                {
                    exceptionMessage.Add(ErrorStrings.TTS_AUDIO_DURATION_INVALID);
                }
                else
                {
                    for (int i = 0; i < turn.ExpectedResponses.Count; i++)
                    {
                        Activity expectedResponse = turn.ExpectedResponses[i];
                        int      orsInText        = (expectedResponse.Text == null) ? 0 : expectedResponse.Text.Split(ProgramConstants.OROperator).Length - 1;
                        int      orsInSpeak       = (expectedResponse.Speak == null) ? 0 : expectedResponse.Speak.Split(ProgramConstants.OROperator).Length - 1;
                        int      orsInExpectedTTSAudioResponseDuration = turn.ExpectedTTSAudioResponseDurations[i].Split(ProgramConstants.OROperator).Length - 1;

                        if (orsInText != orsInSpeak || orsInSpeak != orsInExpectedTTSAudioResponseDuration)
                        {
                            exceptionMessage.Add(ErrorStrings.OR_OCCURRENCE_INCONSISTENT);
                        }
                    }

                    if (!CheckValidExpectedTTSAudioDuration(turn.ExpectedTTSAudioResponseDurations))
                    {
                        exceptionMessage.Add(ErrorStrings.TTS_AUDIO_DURATION_VALUES_INVALID);
                    }
                }
            }

            if ((turn.ExpectedResponses == null || turn.ExpectedResponses.Count == 0) && turn.ExpectedTTSAudioResponseDurations != null)
            {
                exceptionMessage.Add(ErrorStrings.TTS_AUDIO_DURATION_PRESENT);
            }

            if (utterancePresentValid && wavFilePresentValid && activityPresentValid)
            {
                exceptionMessage.Add($"{ErrorStrings.AMBIGUOUS_TURN_INPUT} - {ErrorStrings.ALL_PRESENT}");
            }

            if (wavFilePresentValid && !utterancePresentValid && activityPresentValid)
            {
                exceptionMessage.Add($"{ErrorStrings.AMBIGUOUS_TURN_INPUT} - {ErrorStrings.WAV_FILE_ACTIVITY_PRESENT}");
            }

            if (utterancePresentValid && !wavFilePresentValid && activityPresentValid)
            {
                exceptionMessage.Add($"{ErrorStrings.AMBIGUOUS_TURN_INPUT} - {ErrorStrings.UTTERANCE_ACTIVITY_PRESENT}");
            }

            // By default, assume there should be an input ("Utterance", "Activity" or "WAVFile")
            bool inputExpected = true;

            // Change the default for the case where a turn checking bot greeting is expected. For bot greeting, there should be no input.
            if (botGreeting && firstTurn && ((firstDialog && singleConnection) || !singleConnection))
            {
                inputExpected = false;
            }

            // Does the current dialog have input?
            bool inputPresent = utterancePresentValid || wavFilePresentValid || activityPresentValid;

            if (inputExpected && !inputPresent)
            {
                // There should have been an input specified ("Utterance", "Activity" or "WAVFile"), but there are none. That's an error.
                exceptionMessage.Add($"{ErrorStrings.AMBIGUOUS_TURN_INPUT} - {ErrorStrings.NONE_PRESENT}");
            }

            if (!inputExpected && inputPresent)
            {
                // There is an input specified ("Utterance", "Activity" or "WAVFile"), but there should be no input. That's an error
                exceptionMessage.Add(ErrorStrings.BOT_GREETING_MISSING);
            }

            if (turn.Sleep < 0)
            {
                // Sleep duration in msec - The value should be non-negative
                exceptionMessage.Add(ErrorStrings.NEGATIVE_SLEEP_DURATION);
            }

            if (exceptionMessage.Count > 0)
            {
                return(false, exceptionMessage);
            }

            return(true, exceptionMessage);
        }