Warnings fix group 15.
This commit is contained in:
Родитель
c5692beadc
Коммит
10e1e53eb6
|
@ -1,5 +1,8 @@
|
|||
namespace Microsoft.Bot.Builder.AI.TriggerTrees
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension method to swap between <see cref="RelationshipType"/> "Generalizes" and "Specializes".
|
||||
/// </summary>
|
||||
public static partial class Extensions
|
||||
{
|
||||
public static RelationshipType Swap(this RelationshipType original)
|
||||
|
|
|
@ -7,6 +7,9 @@ using Microsoft.Bot.Builder.Dialogs.Debugging;
|
|||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension method for <see cref="DialogContext"/> provides <see cref="DebugSupport"/>.
|
||||
/// </summary>
|
||||
public static partial class Extensions
|
||||
{
|
||||
public static async Task DebuggerStepAsync(this DialogContext context, IOnEvent rule, DialogEvent dialogEvent, CancellationToken cancellationToken)
|
||||
|
|
|
@ -28,69 +28,63 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
private readonly ConcurrentDictionary<string, ThreadModel> threadByTurnId = new ConcurrentDictionary<string, ThreadModel>();
|
||||
private readonly Identifier<ThreadModel> threads = new Identifier<ThreadModel>();
|
||||
|
||||
private readonly Task task;
|
||||
|
||||
private int sequence = 0;
|
||||
|
||||
public DebugAdapter(int port, Source.IRegistry registry, IBreakpoints breakpoints, Action terminate, IEvents events = null, ICodeModel codeModel = null, IDataModel dataModel = null, ILogger logger = null, ICoercion coercion = null)
|
||||
: base(logger)
|
||||
{
|
||||
this.events = events ?? new Events<DialogEvents>();
|
||||
this.codeModel = codeModel ?? new CodeModel();
|
||||
this.dataModel = dataModel ?? new DataModel(coercion ?? new Coercion());
|
||||
this.registry = registry ?? throw new ArgumentNullException(nameof(registry));
|
||||
this.breakpoints = breakpoints ?? throw new ArgumentNullException(nameof(breakpoints));
|
||||
this.terminate = terminate ?? new Action(() => Environment.Exit(0));
|
||||
this.task = ListenAsync(new IPEndPoint(IPAddress.Any, port), cancellationToken.Token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Thread debugging phases.
|
||||
/// </summary>
|
||||
public enum Phase
|
||||
{
|
||||
/// <summary>
|
||||
/// "Started" signals Visual Studio Code that there is a new thread.
|
||||
/// </summary>
|
||||
Started,
|
||||
|
||||
/// <summary>
|
||||
/// Follows "Next".
|
||||
/// </summary>
|
||||
Continue,
|
||||
|
||||
/// <summary>
|
||||
/// Signal to "Step" or to "Ccontinue".
|
||||
/// </summary>
|
||||
Next,
|
||||
|
||||
/// <summary>
|
||||
/// Follows "Next".
|
||||
/// </summary>
|
||||
Step,
|
||||
|
||||
/// <summary>
|
||||
/// At breakpoint?
|
||||
/// </summary>
|
||||
Breakpoint,
|
||||
|
||||
/// <summary>
|
||||
/// Thread paused.
|
||||
/// </summary>
|
||||
Pause,
|
||||
|
||||
/// <summary>
|
||||
/// Thread exited.
|
||||
/// </summary>
|
||||
Exited
|
||||
}
|
||||
|
||||
private sealed class ThreadModel
|
||||
{
|
||||
public ThreadModel(ITurnContext turnContext, ICodeModel codeModel)
|
||||
{
|
||||
TurnContext = turnContext;
|
||||
CodeModel = codeModel;
|
||||
}
|
||||
|
||||
public ITurnContext TurnContext { get; }
|
||||
|
||||
public ICodeModel CodeModel { get; }
|
||||
|
||||
public string Name => TurnContext.Activity.Text;
|
||||
|
||||
public IReadOnlyList<ICodePoint> Frames => CodeModel.PointsFor(LastContext, LastItem, LastMore);
|
||||
|
||||
public RunModel Run { get; } = new RunModel();
|
||||
|
||||
public Identifier<ICodePoint> FrameCodes { get; } = new Identifier<ICodePoint>();
|
||||
|
||||
public Identifier<object> ValueCodes { get; } = new Identifier<object>();
|
||||
|
||||
public DialogContext LastContext { get; set; }
|
||||
|
||||
public object LastItem { get; set; }
|
||||
|
||||
public string LastMore { get; set; }
|
||||
}
|
||||
|
||||
public sealed class RunModel
|
||||
{
|
||||
public Phase? PhaseSent { get; set; }
|
||||
|
||||
public Phase Phase { get; set; } = Phase.Started;
|
||||
|
||||
public object Gate { get; } = new object();
|
||||
|
||||
public void Post(Phase what)
|
||||
{
|
||||
Monitor.Enter(Gate);
|
||||
try
|
||||
{
|
||||
Phase = what;
|
||||
Monitor.Pulse(Gate);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Monitor.Exit(Gate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ulong EncodeValue(ThreadModel thread, object value)
|
||||
{
|
||||
if (dataModel.IsScalar(value))
|
||||
|
@ -124,18 +118,96 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
frame = thread.FrameCodes[valueCode];
|
||||
}
|
||||
|
||||
private readonly Task task;
|
||||
|
||||
public DebugAdapter(int port, Source.IRegistry registry, IBreakpoints breakpoints, Action terminate, IEvents events = null, ICodeModel codeModel = null, IDataModel dataModel = null, ILogger logger = null, ICoercion coercion = null)
|
||||
: base(logger)
|
||||
public static string Ellipsis(string text, int length)
|
||||
{
|
||||
this.events = events ?? new Events<DialogEvents>();
|
||||
this.codeModel = codeModel ?? new CodeModel();
|
||||
this.dataModel = dataModel ?? new DataModel(coercion ?? new Coercion());
|
||||
this.registry = registry ?? throw new ArgumentNullException(nameof(registry));
|
||||
this.breakpoints = breakpoints ?? throw new ArgumentNullException(nameof(breakpoints));
|
||||
this.terminate = terminate ?? new Action(() => Environment.Exit(0));
|
||||
this.task = ListenAsync(new IPEndPoint(IPAddress.Any, port), cancellationToken.Token);
|
||||
if (text == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (text.Length <= length)
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
int pos = text.IndexOf(" ", length);
|
||||
if (pos >= 0)
|
||||
{
|
||||
return text.Substring(0, pos) + "...";
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
async Task DebugSupport.IDebugger.StepAsync(DialogContext context, object item, string more, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
var turnText = context.Context.Activity.Text?.Trim() ?? string.Empty;
|
||||
if (turnText.Length == 0)
|
||||
{
|
||||
turnText = context.Context.Activity.Type;
|
||||
}
|
||||
|
||||
var threadText = $"'{Ellipsis(turnText, 18)}'";
|
||||
await OutputAsync($"{threadText} ==> {more?.PadRight(16) ?? string.Empty} ==> {codeModel.NameFor(item)} ", item, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
await UpdateBreakpointsAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (threadByTurnId.TryGetValue(TurnIdFor(context.Context), out ThreadModel thread))
|
||||
{
|
||||
thread.LastContext = context;
|
||||
thread.LastItem = item;
|
||||
thread.LastMore = more;
|
||||
|
||||
var run = thread.Run;
|
||||
if (breakpoints.IsBreakPoint(item) && events[more])
|
||||
{
|
||||
run.Post(Phase.Breakpoint);
|
||||
}
|
||||
|
||||
// TODO: implement asynchronous condition variables
|
||||
Monitor.Enter(run.Gate);
|
||||
try
|
||||
{
|
||||
// TODO: remove synchronous waits
|
||||
UpdateThreadPhaseAsync(thread, item, cancellationToken).GetAwaiter().GetResult();
|
||||
|
||||
// while the stopped condition is true, atomically release the mutex
|
||||
while (!(run.Phase == Phase.Started || run.Phase == Phase.Continue || run.Phase == Phase.Next))
|
||||
{
|
||||
Monitor.Wait(run.Gate);
|
||||
}
|
||||
|
||||
// "Started" signals to Visual Studio Code that there is a new thread
|
||||
if (run.Phase == Phase.Started)
|
||||
{
|
||||
run.Phase = Phase.Continue;
|
||||
}
|
||||
|
||||
// TODO: remove synchronous waits
|
||||
UpdateThreadPhaseAsync(thread, item, cancellationToken).GetAwaiter().GetResult();
|
||||
|
||||
// allow one step to progress since next was requested
|
||||
if (run.Phase == Phase.Next)
|
||||
{
|
||||
run.Phase = Phase.Step;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Monitor.Exit(run.Gate);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.logger.LogError($"thread context not found");
|
||||
}
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
this.logger.LogError(error, error.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DisposeAsync()
|
||||
|
@ -172,103 +244,39 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
}
|
||||
}
|
||||
|
||||
protected override async Task AcceptAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
var token = await ReadAsync(cancellationToken).ConfigureAwait(false);
|
||||
var request = Protocol.Parse(token);
|
||||
Protocol.Message message;
|
||||
try
|
||||
{
|
||||
message = await DispatchAsync(request, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
message = Protocol.Response.Fail(NextSeq, request, error.Message);
|
||||
}
|
||||
|
||||
await SendAsync(message, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
this.logger.LogError(error, error.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string TurnIdFor(ITurnContext turnContext)
|
||||
{
|
||||
return $"{turnContext.Activity.ChannelId}-{turnContext.Activity.Id}";
|
||||
}
|
||||
|
||||
static public string Ellipsis(string text, int length)
|
||||
{
|
||||
if (text == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (text.Length <= length)
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
int pos = text.IndexOf(" ", length);
|
||||
if (pos >= 0)
|
||||
{
|
||||
return text.Substring(0, pos) + "...";
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
async Task DebugSupport.IDebugger.StepAsync(DialogContext context, object item, string more, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
var turnText = context.Context.Activity.Text?.Trim() ?? string.Empty;
|
||||
if (turnText.Length == 0)
|
||||
{
|
||||
turnText = context.Context.Activity.Type;
|
||||
}
|
||||
|
||||
var threadText = $"'{Ellipsis(turnText, 18)}'";
|
||||
await OutputAsync($"{threadText} ==> {more?.PadRight(16) ?? ""} ==> {codeModel.NameFor(item)} ", item, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
await UpdateBreakpointsAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (threadByTurnId.TryGetValue(TurnIdFor(context.Context), out ThreadModel thread))
|
||||
{
|
||||
thread.LastContext = context;
|
||||
thread.LastItem = item;
|
||||
thread.LastMore = more;
|
||||
|
||||
var run = thread.Run;
|
||||
if (breakpoints.IsBreakPoint(item) && events[more])
|
||||
{
|
||||
run.Post(Phase.Breakpoint);
|
||||
}
|
||||
|
||||
// TODO: implement asynchronous condition variables
|
||||
Monitor.Enter(run.Gate);
|
||||
try
|
||||
{
|
||||
// TODO: remove synchronous waits
|
||||
UpdateThreadPhaseAsync(thread, item, cancellationToken).GetAwaiter().GetResult();
|
||||
|
||||
// while the stopped condition is true, atomically release the mutex
|
||||
while (!(run.Phase == Phase.Started || run.Phase == Phase.Continue || run.Phase == Phase.Next))
|
||||
{
|
||||
Monitor.Wait(run.Gate);
|
||||
}
|
||||
|
||||
// started is just use the signal to Visual Studio Code that there is a new thread
|
||||
if (run.Phase == Phase.Started)
|
||||
{
|
||||
run.Phase = Phase.Continue;
|
||||
}
|
||||
|
||||
// TODO: remove synchronous waits
|
||||
UpdateThreadPhaseAsync(thread, item, cancellationToken).GetAwaiter().GetResult();
|
||||
|
||||
// allow one step to progress since next was requested
|
||||
if (run.Phase == Phase.Next)
|
||||
{
|
||||
run.Phase = Phase.Step;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Monitor.Exit(run.Gate);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.logger.LogError($"thread context not found");
|
||||
}
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
this.logger.LogError(error, error.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UpdateBreakpointsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var breakpoints = this.breakpoints.ApplyUpdates();
|
||||
|
@ -360,8 +368,6 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
await SendAsync(Protocol.Event.From(NextSeq, "output", body), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private int sequence = 0;
|
||||
|
||||
private int NextSeq => Interlocked.Increment(ref sequence);
|
||||
|
||||
private Protocol.Capabilities MakeCapabilities()
|
||||
|
@ -605,32 +611,56 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
}
|
||||
}
|
||||
|
||||
protected override async Task AcceptAsync(CancellationToken cancellationToken)
|
||||
public sealed class RunModel
|
||||
{
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
public Phase? PhaseSent { get; set; }
|
||||
|
||||
public Phase Phase { get; set; } = Phase.Started;
|
||||
|
||||
public object Gate { get; } = new object();
|
||||
|
||||
public void Post(Phase what)
|
||||
{
|
||||
Monitor.Enter(Gate);
|
||||
try
|
||||
{
|
||||
var token = await ReadAsync(cancellationToken).ConfigureAwait(false);
|
||||
var request = Protocol.Parse(token);
|
||||
Protocol.Message message;
|
||||
try
|
||||
{
|
||||
message = await DispatchAsync(request, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
message = Protocol.Response.Fail(NextSeq, request, error.Message);
|
||||
}
|
||||
|
||||
await SendAsync(message, cancellationToken).ConfigureAwait(false);
|
||||
Phase = what;
|
||||
Monitor.Pulse(Gate);
|
||||
}
|
||||
catch (Exception error)
|
||||
finally
|
||||
{
|
||||
this.logger.LogError(error, error.Message);
|
||||
throw;
|
||||
Monitor.Exit(Gate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class ThreadModel
|
||||
{
|
||||
public ThreadModel(ITurnContext turnContext, ICodeModel codeModel)
|
||||
{
|
||||
TurnContext = turnContext;
|
||||
CodeModel = codeModel;
|
||||
}
|
||||
|
||||
public ITurnContext TurnContext { get; }
|
||||
|
||||
public ICodeModel CodeModel { get; }
|
||||
|
||||
public string Name => TurnContext.Activity.Text;
|
||||
|
||||
public IReadOnlyList<ICodePoint> Frames => CodeModel.PointsFor(LastContext, LastItem, LastMore);
|
||||
|
||||
public RunModel Run { get; } = new RunModel();
|
||||
|
||||
public Identifier<ICodePoint> FrameCodes { get; } = new Identifier<ICodePoint>();
|
||||
|
||||
public Identifier<object> ValueCodes { get; } = new Identifier<object>();
|
||||
|
||||
public DialogContext LastContext { get; set; }
|
||||
|
||||
public object LastItem { get; set; }
|
||||
|
||||
public string LastMore { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,22 @@ using static Microsoft.Bot.Builder.Dialogs.DialogContext;
|
|||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
||||
{
|
||||
public interface IEvents
|
||||
{
|
||||
Protocol.ExceptionBreakpointFilter[] Filters
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
bool this[string filter]
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
void Reset(IEnumerable<string> filters);
|
||||
}
|
||||
|
||||
public sealed class Events<TDialogEvents> : IEvents
|
||||
where TDialogEvents : DialogEvents
|
||||
{
|
||||
|
@ -31,6 +47,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
this.stateByFilter[DialogContext.DialogEvents.EndDialog] = false;
|
||||
}
|
||||
|
||||
Protocol.ExceptionBreakpointFilter[] IEvents.Filters =>
|
||||
this.stateByFilter.Select(kv => new Protocol.ExceptionBreakpointFilter() { Label = kv.Key, Filter = kv.Key, Default = kv.Value }).ToArray();
|
||||
|
||||
bool IEvents.this[string filter]
|
||||
{
|
||||
get => this.stateByFilter.TryGetValue(filter, out var state) ? state : false;
|
||||
|
@ -45,23 +64,5 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
stateByFilter[filter] = index.Contains(filter);
|
||||
}
|
||||
}
|
||||
|
||||
Protocol.ExceptionBreakpointFilter[] IEvents.Filters => this.stateByFilter.Select(kv => new Protocol.ExceptionBreakpointFilter() { Label = kv.Key, Filter = kv.Key, Default = kv.Value }).ToArray();
|
||||
}
|
||||
|
||||
public interface IEvents
|
||||
{
|
||||
Protocol.ExceptionBreakpointFilter[] Filters
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
void Reset(IEnumerable<string> filters);
|
||||
|
||||
bool this[string filter]
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension method implementing await for <see cref="SemaphoreSlim"/>.
|
||||
/// </summary>
|
||||
public static partial class Extensions
|
||||
{
|
||||
public static async Task<Releaser> WithWaitAsync(this SemaphoreSlim semaphore, CancellationToken cancellationToken)
|
||||
|
|
|
@ -64,14 +64,12 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
{
|
||||
private readonly ICoercion coercion;
|
||||
|
||||
public abstract int Rank { get; }
|
||||
|
||||
protected DataModelBase(ICoercion coercion)
|
||||
{
|
||||
this.coercion = coercion ?? throw new ArgumentNullException(nameof(coercion));
|
||||
}
|
||||
|
||||
protected T Coerce<T>(object item) => (T)this.coercion.Coerce(item, typeof(T));
|
||||
public abstract int Rank { get; }
|
||||
|
||||
public abstract TValue this[TContext context, TName name]
|
||||
{
|
||||
|
@ -79,16 +77,16 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
set;
|
||||
}
|
||||
|
||||
public virtual bool IsScalar(TContext context) => false;
|
||||
|
||||
public abstract IEnumerable<TName> Names(TContext context);
|
||||
|
||||
object IDataModel.this[object context, object name]
|
||||
{
|
||||
get => this[(TContext)context, Coerce<TName>(name)];
|
||||
set => this[(TContext)context, Coerce<TName>(name)] = Coerce<TValue>(value);
|
||||
}
|
||||
|
||||
public virtual bool IsScalar(TContext context) => false;
|
||||
|
||||
public abstract IEnumerable<TName> Names(TContext context);
|
||||
|
||||
public virtual string ToString(TContext context) => (context is ICollection collection)
|
||||
? $"Count = {collection.Count}"
|
||||
: context.ToString();
|
||||
|
@ -97,6 +95,8 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
|
||||
string IDataModel.ToString(object context) => ToString((TContext)context);
|
||||
|
||||
protected T Coerce<T>(object item) => (T)this.coercion.Coerce(item, typeof(T));
|
||||
|
||||
IEnumerable<object> IDataModel.Names(object context) => Names((TContext)context).Cast<object>();
|
||||
}
|
||||
|
||||
|
@ -210,6 +210,12 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
set => ModelFor(context)[context, name] = value;
|
||||
}
|
||||
|
||||
bool IDataModel.IsScalar(object context) => ModelFor(context).IsScalar(context);
|
||||
|
||||
IEnumerable<object> IDataModel.Names(object context) => ModelFor(context).Names(context);
|
||||
|
||||
string IDataModel.ToString(object context) => ModelFor(context).ToString(context);
|
||||
|
||||
private IDataModel Create(Type definition, params Type[] typeArguments) =>
|
||||
(IDataModel)Activator.CreateInstance(definition.MakeGenericType(typeArguments), this.coercion);
|
||||
|
||||
|
@ -270,11 +276,5 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
|
||||
return model;
|
||||
}
|
||||
|
||||
bool IDataModel.IsScalar(object context) => ModelFor(context).IsScalar(context);
|
||||
|
||||
IEnumerable<object> IDataModel.Names(object context) => ModelFor(context).Names(context);
|
||||
|
||||
string IDataModel.ToString(object context) => ModelFor(context).ToString(context);
|
||||
}
|
||||
}
|
|
@ -10,6 +10,21 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
private const ulong MORE = 0x80;
|
||||
private const ulong DATA = 0x7F;
|
||||
|
||||
public static ulong Encode(ulong one, ulong two)
|
||||
{
|
||||
ulong target = 0;
|
||||
int offset = 0;
|
||||
Encode(one, ref target, ref offset);
|
||||
Encode(two, ref target, ref offset);
|
||||
return target;
|
||||
}
|
||||
|
||||
public static void Decode(ulong item, out ulong one, out ulong two)
|
||||
{
|
||||
Decode(ref item, out one);
|
||||
Decode(ref item, out two);
|
||||
}
|
||||
|
||||
private static void Encode(ulong source, ref ulong target, ref int offset)
|
||||
{
|
||||
while (source > DATA)
|
||||
|
@ -45,21 +60,6 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
offset += 7;
|
||||
}
|
||||
}
|
||||
|
||||
public static ulong Encode(ulong one, ulong two)
|
||||
{
|
||||
ulong target = 0;
|
||||
int offset = 0;
|
||||
Encode(one, ref target, ref offset);
|
||||
Encode(two, ref target, ref offset);
|
||||
return target;
|
||||
}
|
||||
|
||||
public static void Decode(ulong item, out ulong one, out ulong two)
|
||||
{
|
||||
Decode(ref item, out one);
|
||||
Decode(ref item, out two);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -71,6 +71,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
/// Some identifiers have a lifetime scoped to a thread (e.g. values or stack frames)
|
||||
/// For these combined identifiers, we use 7 bit encoding.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Datatype of the stored items.</typeparam>
|
||||
public sealed class Identifier<T> : IEnumerable<KeyValuePair<ulong, T>>
|
||||
{
|
||||
private readonly Dictionary<T, ulong> codeByItem = new Dictionary<T, ulong>(ReferenceEquality<T>.Instance);
|
||||
|
|
|
@ -7,6 +7,41 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
// https://github.com/Microsoft/debug-adapter-protocol/blob/gh-pages/debugAdapterProtocol.json
|
||||
public static class Protocol
|
||||
{
|
||||
public static Request Parse(JToken token)
|
||||
{
|
||||
switch ((string)token["type"])
|
||||
{
|
||||
case "request":
|
||||
switch ((string)token["command"])
|
||||
{
|
||||
case "launch": return token.ToObject<Request<Launch>>();
|
||||
case "attach": return token.ToObject<Request<Attach>>();
|
||||
case "initialize": return token.ToObject<Request<Initialize>>();
|
||||
case "setBreakpoints": return token.ToObject<Request<SetBreakpoints>>();
|
||||
case "setFunctionBreakpoints": return token.ToObject<Request<SetFunctionBreakpoints>>();
|
||||
case "setExceptionBreakpoints": return token.ToObject<Request<SetExceptionBreakpoints>>();
|
||||
case "configurationDone": return token.ToObject<Request<ConfigurationDone>>();
|
||||
case "threads": return token.ToObject<Request<Threads>>();
|
||||
case "stackTrace": return token.ToObject<Request<StackTrace>>();
|
||||
case "scopes": return token.ToObject<Request<Scopes>>();
|
||||
case "variables": return token.ToObject<Request<Variables>>();
|
||||
case "setVariable": return token.ToObject<Request<SetVariable>>();
|
||||
case "evaluate": return token.ToObject<Request<Evaluate>>();
|
||||
case "continue": return token.ToObject<Request<Continue>>();
|
||||
case "pause": return token.ToObject<Request<Pause>>();
|
||||
case "next": return token.ToObject<Request<Next>>();
|
||||
case "stepIn": return token.ToObject<Request<Next>>();
|
||||
case "stepOut": return token.ToObject<Request<Next>>();
|
||||
case "terminate": return token.ToObject<Request<Terminate>>();
|
||||
case "disconnect": return token.ToObject<Request<Disconnect>>();
|
||||
default: return token.ToObject<Request>();
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class Message
|
||||
{
|
||||
public int Seq { get; set; }
|
||||
|
@ -290,40 +325,5 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
{
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
public static Request Parse(JToken token)
|
||||
{
|
||||
switch ((string)token["type"])
|
||||
{
|
||||
case "request":
|
||||
switch ((string)token["command"])
|
||||
{
|
||||
case "launch": return token.ToObject<Request<Launch>>();
|
||||
case "attach": return token.ToObject<Request<Attach>>();
|
||||
case "initialize": return token.ToObject<Request<Initialize>>();
|
||||
case "setBreakpoints": return token.ToObject<Request<SetBreakpoints>>();
|
||||
case "setFunctionBreakpoints": return token.ToObject<Request<SetFunctionBreakpoints>>();
|
||||
case "setExceptionBreakpoints": return token.ToObject<Request<SetExceptionBreakpoints>>();
|
||||
case "configurationDone": return token.ToObject<Request<ConfigurationDone>>();
|
||||
case "threads": return token.ToObject<Request<Threads>>();
|
||||
case "stackTrace": return token.ToObject<Request<StackTrace>>();
|
||||
case "scopes": return token.ToObject<Request<Scopes>>();
|
||||
case "variables": return token.ToObject<Request<Variables>>();
|
||||
case "setVariable": return token.ToObject<Request<SetVariable>>();
|
||||
case "evaluate": return token.ToObject<Request<Evaluate>>();
|
||||
case "continue": return token.ToObject<Request<Continue>>();
|
||||
case "pause": return token.ToObject<Request<Pause>>();
|
||||
case "next": return token.ToObject<Request<Next>>();
|
||||
case "stepIn": return token.ToObject<Request<Next>>();
|
||||
case "stepOut": return token.ToObject<Request<Next>>();
|
||||
case "terminate": return token.ToObject<Request<Terminate>>();
|
||||
case "disconnect": return token.ToObject<Request<Disconnect>>();
|
||||
default: return token.ToObject<Request>();
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,11 +12,42 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
private readonly Dictionary<object, Source.Range> sourceByItem = new Dictionary<object, Source.Range>(ReferenceEquality<object>.Instance);
|
||||
private bool dirty = true;
|
||||
|
||||
private readonly Identifier<Row> rows = new Identifier<Row>();
|
||||
private readonly HashSet<object> items = new HashSet<object>(ReferenceEquality<object>.Instance);
|
||||
|
||||
public SourceMap(ICodeModel codeModel)
|
||||
{
|
||||
this.codeModel = codeModel ?? throw new ArgumentNullException(nameof(codeModel));
|
||||
}
|
||||
|
||||
public static bool Equals(Protocol.Range target, Source.Range source) =>
|
||||
(target.Source == null && source == null)
|
||||
|| (PathEquals(target.Source.Path, source.Path)
|
||||
&& target.Line == source.Start.LineIndex
|
||||
&& target.EndLine == source.After.LineIndex
|
||||
&& target.Column == source.Start.CharIndex
|
||||
&& target.EndColumn == source.After.CharIndex);
|
||||
|
||||
public static void Assign(Protocol.Range target, Source.Range source)
|
||||
{
|
||||
if (source != null)
|
||||
{
|
||||
target.Source = new Protocol.Source(source.Path);
|
||||
target.Line = source.Start.LineIndex;
|
||||
target.EndLine = source.After.LineIndex;
|
||||
target.Column = source.Start.CharIndex;
|
||||
target.EndColumn = source.After.CharIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
target.Source = null;
|
||||
target.Line = null;
|
||||
target.EndLine = null;
|
||||
target.Column = null;
|
||||
target.EndColumn = null;
|
||||
}
|
||||
}
|
||||
|
||||
void Source.IRegistry.Add(object item, Source.Range range)
|
||||
{
|
||||
if (!Path.IsPathRooted(range.Path))
|
||||
|
@ -47,58 +78,89 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
}
|
||||
}
|
||||
|
||||
public sealed class Row
|
||||
IReadOnlyList<Protocol.Breakpoint> IBreakpoints.SetBreakpoints(Protocol.Source source, IReadOnlyList<Protocol.SourceBreakpoint> sourceBreakpoints)
|
||||
{
|
||||
public Row(Protocol.Source source, Protocol.SourceBreakpoint sourceBreakpoint)
|
||||
lock (gate)
|
||||
{
|
||||
Source = source;
|
||||
SourceBreakpoint = sourceBreakpoint;
|
||||
var path = source.Path;
|
||||
foreach (var row in rows.Items)
|
||||
{
|
||||
if (row.FunctionBreakpoint == null && PathEquals(row.Source.Path, path))
|
||||
{
|
||||
rows.Remove(row);
|
||||
}
|
||||
}
|
||||
|
||||
var breakpoints = new List<Protocol.Breakpoint>(sourceBreakpoints.Count);
|
||||
|
||||
foreach (var sourceBreakpoint in sourceBreakpoints)
|
||||
{
|
||||
var row = new Row(source, sourceBreakpoint);
|
||||
TryUpdate(row);
|
||||
breakpoints.Add(row.Breakpoint);
|
||||
}
|
||||
|
||||
RebuildItems();
|
||||
|
||||
return breakpoints;
|
||||
}
|
||||
|
||||
public Row(Protocol.FunctionBreakpoint functionBreakpoint)
|
||||
{
|
||||
FunctionBreakpoint = functionBreakpoint;
|
||||
}
|
||||
|
||||
public Protocol.Source Source { get; }
|
||||
|
||||
public Protocol.SourceBreakpoint SourceBreakpoint { get; }
|
||||
|
||||
public Protocol.FunctionBreakpoint FunctionBreakpoint { get; }
|
||||
|
||||
public Protocol.Breakpoint Breakpoint { get; } = new Protocol.Breakpoint();
|
||||
|
||||
public object Item { get; set; }
|
||||
}
|
||||
|
||||
private readonly Identifier<Row> rows = new Identifier<Row>();
|
||||
private readonly HashSet<object> items = new HashSet<object>(ReferenceEquality<object>.Instance);
|
||||
|
||||
public static bool Equals(Protocol.Range target, Source.Range source) =>
|
||||
(target.Source == null && source == null)
|
||||
|| (PathEquals(target.Source.Path, source.Path)
|
||||
&& target.Line == source.Start.LineIndex
|
||||
&& target.EndLine == source.After.LineIndex
|
||||
&& target.Column == source.Start.CharIndex
|
||||
&& target.EndColumn == source.After.CharIndex);
|
||||
|
||||
public static void Assign(Protocol.Range target, Source.Range source)
|
||||
IReadOnlyList<Protocol.Breakpoint> IBreakpoints.SetBreakpoints(IReadOnlyList<Protocol.FunctionBreakpoint> functionBreakpoints)
|
||||
{
|
||||
if (source != null)
|
||||
lock (gate)
|
||||
{
|
||||
target.Source = new Protocol.Source(source.Path);
|
||||
target.Line = source.Start.LineIndex;
|
||||
target.EndLine = source.After.LineIndex;
|
||||
target.Column = source.Start.CharIndex;
|
||||
target.EndColumn = source.After.CharIndex;
|
||||
foreach (var row in rows.Items)
|
||||
{
|
||||
if (row.FunctionBreakpoint != null)
|
||||
{
|
||||
rows.Remove(row);
|
||||
}
|
||||
}
|
||||
|
||||
var breakpoints = new List<Protocol.Breakpoint>(functionBreakpoints.Count);
|
||||
|
||||
foreach (var functionBreakpoint in functionBreakpoints)
|
||||
{
|
||||
var row = new Row(functionBreakpoint);
|
||||
TryUpdate(row);
|
||||
breakpoints.Add(row.Breakpoint);
|
||||
}
|
||||
|
||||
RebuildItems();
|
||||
|
||||
return breakpoints;
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
IReadOnlyList<Protocol.Breakpoint> IBreakpoints.ApplyUpdates()
|
||||
{
|
||||
lock (gate)
|
||||
{
|
||||
target.Source = null;
|
||||
target.Line = null;
|
||||
target.EndLine = null;
|
||||
target.Column = null;
|
||||
target.EndColumn = null;
|
||||
IReadOnlyList<Protocol.Breakpoint> updates = Array.Empty<Protocol.Breakpoint>();
|
||||
if (dirty)
|
||||
{
|
||||
updates = Update();
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
return updates;
|
||||
}
|
||||
}
|
||||
|
||||
bool IBreakpoints.IsBreakPoint(object item)
|
||||
{
|
||||
lock (gate)
|
||||
{
|
||||
return this.items.Contains(item);
|
||||
}
|
||||
}
|
||||
|
||||
object IBreakpoints.ItemFor(Protocol.Breakpoint breakpoint)
|
||||
{
|
||||
lock (gate)
|
||||
{
|
||||
return this.rows[breakpoint.Id].Item;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,90 +260,28 @@ namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
|||
}
|
||||
}
|
||||
|
||||
IReadOnlyList<Protocol.Breakpoint> IBreakpoints.SetBreakpoints(Protocol.Source source, IReadOnlyList<Protocol.SourceBreakpoint> sourceBreakpoints)
|
||||
public sealed class Row
|
||||
{
|
||||
lock (gate)
|
||||
public Row(Protocol.Source source, Protocol.SourceBreakpoint sourceBreakpoint)
|
||||
{
|
||||
var path = source.Path;
|
||||
foreach (var row in rows.Items)
|
||||
{
|
||||
if (row.FunctionBreakpoint == null && PathEquals(row.Source.Path, path))
|
||||
{
|
||||
rows.Remove(row);
|
||||
}
|
||||
}
|
||||
|
||||
var breakpoints = new List<Protocol.Breakpoint>(sourceBreakpoints.Count);
|
||||
|
||||
foreach (var sourceBreakpoint in sourceBreakpoints)
|
||||
{
|
||||
var row = new Row(source, sourceBreakpoint);
|
||||
TryUpdate(row);
|
||||
breakpoints.Add(row.Breakpoint);
|
||||
}
|
||||
|
||||
RebuildItems();
|
||||
|
||||
return breakpoints;
|
||||
Source = source;
|
||||
SourceBreakpoint = sourceBreakpoint;
|
||||
}
|
||||
}
|
||||
|
||||
IReadOnlyList<Protocol.Breakpoint> IBreakpoints.SetBreakpoints(IReadOnlyList<Protocol.FunctionBreakpoint> functionBreakpoints)
|
||||
{
|
||||
lock (gate)
|
||||
public Row(Protocol.FunctionBreakpoint functionBreakpoint)
|
||||
{
|
||||
foreach (var row in rows.Items)
|
||||
{
|
||||
if (row.FunctionBreakpoint != null)
|
||||
{
|
||||
rows.Remove(row);
|
||||
}
|
||||
}
|
||||
|
||||
var breakpoints = new List<Protocol.Breakpoint>(functionBreakpoints.Count);
|
||||
|
||||
foreach (var functionBreakpoint in functionBreakpoints)
|
||||
{
|
||||
var row = new Row(functionBreakpoint);
|
||||
TryUpdate(row);
|
||||
breakpoints.Add(row.Breakpoint);
|
||||
}
|
||||
|
||||
RebuildItems();
|
||||
|
||||
return breakpoints;
|
||||
FunctionBreakpoint = functionBreakpoint;
|
||||
}
|
||||
}
|
||||
|
||||
IReadOnlyList<Protocol.Breakpoint> IBreakpoints.ApplyUpdates()
|
||||
{
|
||||
lock (gate)
|
||||
{
|
||||
IReadOnlyList<Protocol.Breakpoint> updates = Array.Empty<Protocol.Breakpoint>();
|
||||
if (dirty)
|
||||
{
|
||||
updates = Update();
|
||||
dirty = false;
|
||||
}
|
||||
public Protocol.Source Source { get; }
|
||||
|
||||
return updates;
|
||||
}
|
||||
}
|
||||
public Protocol.SourceBreakpoint SourceBreakpoint { get; }
|
||||
|
||||
bool IBreakpoints.IsBreakPoint(object item)
|
||||
{
|
||||
lock (gate)
|
||||
{
|
||||
return this.items.Contains(item);
|
||||
}
|
||||
}
|
||||
public Protocol.FunctionBreakpoint FunctionBreakpoint { get; }
|
||||
|
||||
object IBreakpoints.ItemFor(Protocol.Breakpoint breakpoint)
|
||||
{
|
||||
lock (gate)
|
||||
{
|
||||
return this.rows[breakpoint.Id].Item;
|
||||
}
|
||||
public Protocol.Breakpoint Breakpoint { get; } = new Protocol.Breakpoint();
|
||||
|
||||
public object Item { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Plugins
|
|||
this.Loader = Activator.CreateInstance(assembly.GetType(info.CustomLoaderClassName)) as ICustomDeserializer;
|
||||
}
|
||||
|
||||
await Task.FromResult<object>(null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,10 @@ using static Microsoft.Bot.Builder.Dialogs.Debugging.Source;
|
|||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Debugging
|
||||
{
|
||||
public static partial class DebugSupport
|
||||
/// <summary>
|
||||
/// Debugger support for <see cref="ITurnContext"/>, <see cref="DialogContext"/>.
|
||||
/// </summary>
|
||||
public static class DebugSupport
|
||||
{
|
||||
public interface IDebugger
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace Microsoft.Bot.Builder.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines interface for a LG system to bind to text.
|
||||
/// Defines interface for a Language Generator system to bind to text.
|
||||
/// </summary>
|
||||
public interface ILanguageGenerator
|
||||
{
|
||||
|
|
|
@ -155,7 +155,13 @@ namespace Microsoft.Bot.Builder.Dialogs
|
|||
return activity;
|
||||
}
|
||||
|
||||
protected async Task<object> ReadAttachmentFile(ITurnContext turnContext, ILanguageGenerator languageGenerator, string fileLocation, string contentType, bool isCard, object data)
|
||||
protected async Task<object> ReadAttachmentFile(
|
||||
ITurnContext turnContext,
|
||||
ILanguageGenerator languageGenerator,
|
||||
string fileLocation,
|
||||
string contentType,
|
||||
bool isCard,
|
||||
object data)
|
||||
{
|
||||
if (Uri.TryCreate(fileLocation, UriKind.Absolute, out Uri uri))
|
||||
{
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
grammar CommonRegex;
|
||||
|
||||
@parser::header {#pragma warning disable 3021} // Disable StyleCop warning CS3021 re CLSCompliant attribute in generated files.
|
||||
@lexer::header {#pragma warning disable 3021} // Disable StyleCop warning CS3021 re CLSCompliant attribute in generated files.
|
||||
@parser::header {
|
||||
#pragma warning disable 3021 // Disable StyleCop warning CS3021 re CLSCompliant attribute in generated files.
|
||||
#pragma warning disable 0108 // Disable StyleCop warning CS0108, hides inherited member in generated files.
|
||||
}
|
||||
@lexer::header {
|
||||
#pragma warning disable 3021 // Disable StyleCop warning CS3021 re CLSCompliant attribute in generated files.
|
||||
#pragma warning disable 0108 // Disable StyleCop warning CS0108, hides inherited member in generated files.
|
||||
}
|
||||
|
||||
parse
|
||||
: alternation EOF
|
||||
|
|
|
@ -7,6 +7,9 @@ using System.Linq;
|
|||
|
||||
namespace Microsoft.Bot.Builder.Expressions
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for detecting or value testing of various types.
|
||||
/// </summary>
|
||||
public static partial class Extensions
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -6,6 +6,9 @@ using System.Linq;
|
|||
|
||||
namespace Microsoft.Bot.Builder.Expressions
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for manipulation of <see cref="Expression"/> values.
|
||||
/// </summary>
|
||||
public static partial class Extensions
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
public ILanguagePolicy LanguagePolicy { get; set; } = new LanguagePolicy();
|
||||
|
||||
/// <summary>
|
||||
/// abstract method to lookup a ILanguageGenerator by locale.
|
||||
/// Abstract method to get an ILanguageGenerator by locale.
|
||||
/// </summary>
|
||||
/// <param name="context">context.</param>
|
||||
/// <param name="locale">locale.</param>
|
||||
|
@ -30,12 +30,12 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
public abstract bool TryGetGenerator(ITurnContext context, string locale, out ILanguageGenerator generator);
|
||||
|
||||
/// <summary>
|
||||
/// Find language generators that match the current context locale??
|
||||
/// Find a language generator that matches the current context locale.
|
||||
/// </summary>
|
||||
/// <param name="turnContext">Context for the current turn of conversation.</param>
|
||||
/// <param name="template">The template.</param>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="data">data to bind to.</param>
|
||||
/// <returns>The generator.</returns>
|
||||
public async Task<string> Generate(ITurnContext turnContext, string template, object data)
|
||||
{
|
||||
// see if we have any locales that match
|
||||
|
|
|
@ -5,6 +5,11 @@ using Microsoft.Bot.Builder.Expressions;
|
|||
|
||||
namespace Microsoft.Bot.Builder.LanguageGeneration
|
||||
{
|
||||
public interface IGetMethod
|
||||
{
|
||||
ExpressionEvaluator GetMethodX(string name);
|
||||
}
|
||||
|
||||
internal class GetMethodExtensions : IGetMethod
|
||||
{
|
||||
// Hold an evaluator instance to make sure all functions have access
|
||||
|
@ -61,9 +66,4 @@ namespace Microsoft.Bot.Builder.LanguageGeneration
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface IGetMethod
|
||||
{
|
||||
ExpressionEvaluator GetMethodX(string name);
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
namespace Microsoft.Bot.Schema
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for converting strongly typed Card objects to Attachement.
|
||||
/// Extension methods for converting strongly typed Card objects to <see cref="Attachment"/>.
|
||||
/// </summary>
|
||||
public static partial class Extensions
|
||||
{
|
||||
|
|
|
@ -6,54 +6,6 @@ using Microsoft.Bot.Builder.Expressions;
|
|||
|
||||
namespace Microsoft.Bot.Builder.AI.TriggerTrees.Tests
|
||||
{
|
||||
public class Comparison
|
||||
{
|
||||
public string Type;
|
||||
public object Value;
|
||||
|
||||
public Comparison(string type, object value)
|
||||
{
|
||||
Type = type;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public class ExpressionInfo
|
||||
{
|
||||
public Expression Expression;
|
||||
public Dictionary<string, Comparison> Bindings = new Dictionary<string, Comparison>();
|
||||
public List<Quantifier> Quantifiers = new List<Quantifier>();
|
||||
|
||||
public ExpressionInfo(Expression expression)
|
||||
{
|
||||
Expression = expression;
|
||||
}
|
||||
|
||||
public ExpressionInfo(Expression expression, string name, object value, string type)
|
||||
{
|
||||
Expression = expression;
|
||||
Bindings.Add(name, new Comparison(type, value));
|
||||
}
|
||||
|
||||
public ExpressionInfo(Expression expression, Dictionary<string, Comparison> bindings, List<Quantifier> quantifiers = null)
|
||||
{
|
||||
Expression = expression;
|
||||
Bindings = bindings;
|
||||
if (quantifiers != null)
|
||||
{
|
||||
Quantifiers = quantifiers;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString() => Expression.ToString();
|
||||
}
|
||||
|
||||
public class TriggerInfo
|
||||
{
|
||||
public Expression Trigger;
|
||||
public Dictionary<string, object> Bindings = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
public class Generator
|
||||
{
|
||||
public Random Rand;
|
||||
|
@ -91,33 +43,6 @@ namespace Microsoft.Bot.Builder.AI.TriggerTrees.Tests
|
|||
return builder.ToString();
|
||||
}
|
||||
|
||||
private int AdjustValue(int value, string type)
|
||||
{
|
||||
var result = value;
|
||||
const int epsilon = 1;
|
||||
switch (type)
|
||||
{
|
||||
case ExpressionType.LessThan: result += epsilon; break;
|
||||
case ExpressionType.NotEqual: result += epsilon; break;
|
||||
case ExpressionType.GreaterThan: result -= epsilon; break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private double AdjustValue(double value, string type)
|
||||
{
|
||||
var result = value;
|
||||
switch (type)
|
||||
{
|
||||
case ExpressionType.LessThan: result += DoubleEpsilon; break;
|
||||
case ExpressionType.NotEqual: result += DoubleEpsilon; break;
|
||||
case ExpressionType.GreaterThan: result -= DoubleEpsilon; break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ExpressionInfo GenerateSimpleComparison(string name)
|
||||
{
|
||||
Expression expression = null;
|
||||
|
@ -290,8 +215,8 @@ namespace Microsoft.Bot.Builder.AI.TriggerTrees.Tests
|
|||
|
||||
public Expression Binary(
|
||||
string type,
|
||||
IEnumerable<ExpressionInfo> expressions,
|
||||
out Dictionary<string, Comparison> bindings)
|
||||
IEnumerable<ExpressionInfo> expressions,
|
||||
out Dictionary<string, Comparison> bindings)
|
||||
{
|
||||
bindings = MergeBindings(expressions);
|
||||
Expression binaryExpression = null;
|
||||
|
@ -318,21 +243,6 @@ namespace Microsoft.Bot.Builder.AI.TriggerTrees.Tests
|
|||
}
|
||||
}
|
||||
|
||||
private int SplitMemory(string mem, out string baseName)
|
||||
{
|
||||
var i = 0;
|
||||
for (; i < mem.Length; ++i)
|
||||
{
|
||||
if (char.IsDigit(mem[i]))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
baseName = mem.Substring(0, i);
|
||||
return int.Parse(mem.Substring(i));
|
||||
}
|
||||
|
||||
public List<ExpressionInfo> GenerateQuantfiers(List<ExpressionInfo> predicates, int numExpressions, int maxVariable, int maxExpansion, int maxQuantifiers)
|
||||
{
|
||||
var result = new List<ExpressionInfo>();
|
||||
|
@ -406,6 +316,137 @@ namespace Microsoft.Bot.Builder.AI.TriggerTrees.Tests
|
|||
return result;
|
||||
}
|
||||
|
||||
public IEnumerable<ExpressionInfo> GenerateNots(IList<ExpressionInfo> predicates, int numNots)
|
||||
{
|
||||
for (var i = 0; i < numNots; ++i)
|
||||
{
|
||||
var expr = RandomChoice(predicates);
|
||||
var bindings = new Dictionary<string, Comparison>();
|
||||
foreach (var binding in expr.Bindings)
|
||||
{
|
||||
var comparison = NotValue(binding.Value);
|
||||
if (comparison != null)
|
||||
{
|
||||
bindings.Add(binding.Key, comparison);
|
||||
}
|
||||
}
|
||||
|
||||
yield return new ExpressionInfo(Expression.NotExpression(expr.Expression), bindings, expr.Quantifiers);
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, Comparison> MergeBindings(IEnumerable<ExpressionInfo> expressions)
|
||||
{
|
||||
var bindings = new Dictionary<string, Comparison>();
|
||||
foreach (var info in expressions)
|
||||
{
|
||||
foreach (var binding in info.Bindings)
|
||||
{
|
||||
bindings[binding.Key] = binding.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return bindings;
|
||||
}
|
||||
|
||||
public T RandomChoice<T>(IList<T> choices) => choices[Rand.Next(choices.Count)];
|
||||
|
||||
public T RandomWeighted<T>(IEnumerable<WeightedChoice<T>> choices)
|
||||
{
|
||||
var totalWeight = 0.0;
|
||||
foreach (var choice in choices)
|
||||
{
|
||||
totalWeight += choice.Weight;
|
||||
}
|
||||
|
||||
var selection = Rand.NextDouble() * totalWeight;
|
||||
var soFar = 0.0;
|
||||
var result = default(T);
|
||||
foreach (var choice in choices)
|
||||
{
|
||||
if (soFar <= selection)
|
||||
{
|
||||
soFar += choice.Weight;
|
||||
result = choice.Choice;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public int RandomWeighted(IReadOnlyList<double> weights)
|
||||
{
|
||||
var totalWeight = 0.0;
|
||||
foreach (var weight in weights)
|
||||
{
|
||||
totalWeight += weight;
|
||||
}
|
||||
|
||||
var selection = Rand.NextDouble() * totalWeight;
|
||||
var soFar = 0.0;
|
||||
var result = 0;
|
||||
for (var i = 0; i < weights.Count; ++i)
|
||||
{
|
||||
if (soFar <= selection)
|
||||
{
|
||||
soFar += weights[i];
|
||||
result = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private int SplitMemory(string mem, out string baseName)
|
||||
{
|
||||
var i = 0;
|
||||
for (; i < mem.Length; ++i)
|
||||
{
|
||||
if (char.IsDigit(mem[i]))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
baseName = mem.Substring(0, i);
|
||||
return int.Parse(mem.Substring(i));
|
||||
}
|
||||
|
||||
private int AdjustValue(int value, string type)
|
||||
{
|
||||
var result = value;
|
||||
const int epsilon = 1;
|
||||
switch (type)
|
||||
{
|
||||
case ExpressionType.LessThan: result += epsilon; break;
|
||||
case ExpressionType.NotEqual: result += epsilon; break;
|
||||
case ExpressionType.GreaterThan: result -= epsilon; break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private double AdjustValue(double value, string type)
|
||||
{
|
||||
var result = value;
|
||||
switch (type)
|
||||
{
|
||||
case ExpressionType.LessThan: result += DoubleEpsilon; break;
|
||||
case ExpressionType.NotEqual: result += DoubleEpsilon; break;
|
||||
case ExpressionType.GreaterThan: result -= DoubleEpsilon; break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Comparison NotValue(Comparison comparison)
|
||||
{
|
||||
var value = comparison.Value;
|
||||
|
@ -484,25 +525,6 @@ namespace Microsoft.Bot.Builder.AI.TriggerTrees.Tests
|
|||
return isNot ? null : new Comparison(comparison.Type, value);
|
||||
}
|
||||
|
||||
public IEnumerable<ExpressionInfo> GenerateNots(IList<ExpressionInfo> predicates, int numNots)
|
||||
{
|
||||
for (var i = 0; i < numNots; ++i)
|
||||
{
|
||||
var expr = RandomChoice(predicates);
|
||||
var bindings = new Dictionary<string, Comparison>();
|
||||
foreach (var binding in expr.Bindings)
|
||||
{
|
||||
var comparison = NotValue(binding.Value);
|
||||
if (comparison != null)
|
||||
{
|
||||
bindings.Add(binding.Key, comparison);
|
||||
}
|
||||
}
|
||||
|
||||
yield return new ExpressionInfo(Expression.NotExpression(expr.Expression), bindings, expr.Quantifiers);
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<Type, List<string>> VariablesByType(Dictionary<string, Comparison> bindings)
|
||||
{
|
||||
var result = new Dictionary<Type, List<string>>();
|
||||
|
@ -519,83 +541,12 @@ namespace Microsoft.Bot.Builder.AI.TriggerTrees.Tests
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Dictionary<string, Comparison> MergeBindings(IEnumerable<ExpressionInfo> expressions)
|
||||
{
|
||||
var bindings = new Dictionary<string, Comparison>();
|
||||
foreach (var info in expressions)
|
||||
{
|
||||
foreach (var binding in info.Bindings)
|
||||
{
|
||||
bindings[binding.Key] = binding.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return bindings;
|
||||
}
|
||||
|
||||
public T RandomChoice<T>(IList<T> choices) => choices[Rand.Next(choices.Count)];
|
||||
|
||||
public class WeightedChoice<T>
|
||||
{
|
||||
public double Weight = 0.0;
|
||||
public T Choice = default(T);
|
||||
}
|
||||
|
||||
public T RandomWeighted<T>(IEnumerable<WeightedChoice<T>> choices)
|
||||
{
|
||||
var totalWeight = 0.0;
|
||||
foreach (var choice in choices)
|
||||
{
|
||||
totalWeight += choice.Weight;
|
||||
}
|
||||
|
||||
var selection = Rand.NextDouble() * totalWeight;
|
||||
var soFar = 0.0;
|
||||
var result = default(T);
|
||||
foreach (var choice in choices)
|
||||
{
|
||||
if (soFar <= selection)
|
||||
{
|
||||
soFar += choice.Weight;
|
||||
result = choice.Choice;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public int RandomWeighted(IReadOnlyList<double> weights)
|
||||
{
|
||||
var totalWeight = 0.0;
|
||||
foreach (var weight in weights)
|
||||
{
|
||||
totalWeight += weight;
|
||||
}
|
||||
|
||||
var selection = Rand.NextDouble() * totalWeight;
|
||||
var soFar = 0.0;
|
||||
var result = 0;
|
||||
for (var i = 0; i < weights.Count; ++i)
|
||||
{
|
||||
if (soFar <= selection)
|
||||
{
|
||||
soFar += weights[i];
|
||||
result = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public class SimpleValues
|
||||
{
|
||||
public int Int = 1;
|
||||
|
@ -621,6 +572,14 @@ namespace Microsoft.Bot.Builder.AI.TriggerTrees.Tests
|
|||
{
|
||||
Object = obj;
|
||||
}
|
||||
|
||||
public static bool Test(SimpleValues obj, int? value) => value.HasValue && obj.Int == value;
|
||||
|
||||
public static bool Test(SimpleValues obj, double? value) => value.HasValue && obj.Double == value;
|
||||
|
||||
public static bool Test(SimpleValues obj, string value) => value != null && obj.String == value;
|
||||
|
||||
public static bool Test(SimpleValues obj, object other) => other != null && obj.Object.Equals(other);
|
||||
|
||||
public bool Test(int? value) => value.HasValue && Int == value;
|
||||
|
||||
|
@ -629,14 +588,54 @@ namespace Microsoft.Bot.Builder.AI.TriggerTrees.Tests
|
|||
public bool Test(string value) => value != null && String == value;
|
||||
|
||||
public bool Test(SimpleValues value) => Int == value.Int && Double == value.Double && String == value.String && Object.Equals(value.Object);
|
||||
|
||||
public static bool Test(SimpleValues obj, int? value) => value.HasValue && obj.Int == value;
|
||||
|
||||
public static bool Test(SimpleValues obj, double? value) => value.HasValue && obj.Double == value;
|
||||
|
||||
public static bool Test(SimpleValues obj, string value) => value != null && obj.String == value;
|
||||
|
||||
public static bool Test(SimpleValues obj, object other) => other != null && obj.Object.Equals(other);
|
||||
}
|
||||
}
|
||||
|
||||
public class Comparison
|
||||
{
|
||||
public string Type;
|
||||
public object Value;
|
||||
|
||||
public Comparison(string type, object value)
|
||||
{
|
||||
Type = type;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public class ExpressionInfo
|
||||
{
|
||||
public Expression Expression;
|
||||
public Dictionary<string, Comparison> Bindings = new Dictionary<string, Comparison>();
|
||||
public List<Quantifier> Quantifiers = new List<Quantifier>();
|
||||
|
||||
public ExpressionInfo(Expression expression)
|
||||
{
|
||||
Expression = expression;
|
||||
}
|
||||
|
||||
public ExpressionInfo(Expression expression, string name, object value, string type)
|
||||
{
|
||||
Expression = expression;
|
||||
Bindings.Add(name, new Comparison(type, value));
|
||||
}
|
||||
|
||||
public ExpressionInfo(Expression expression, Dictionary<string, Comparison> bindings, List<Quantifier> quantifiers = null)
|
||||
{
|
||||
Expression = expression;
|
||||
Bindings = bindings;
|
||||
if (quantifiers != null)
|
||||
{
|
||||
Quantifiers = quantifiers;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString() => Expression.ToString();
|
||||
}
|
||||
|
||||
public class TriggerInfo
|
||||
{
|
||||
public Expression Trigger;
|
||||
public Dictionary<string, object> Bindings = new Dictionary<string, object>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -553,6 +553,30 @@ namespace Microsoft.Bot.Builder.Azure.Tests
|
|||
return _hasEmulator.Value;
|
||||
}
|
||||
|
||||
private static async Task CreateCosmosDbWithPartitionedCollection(string partitionKey)
|
||||
{
|
||||
using (var client = new DocumentClient(new Uri(CosmosServiceEndpoint), CosmosAuthKey))
|
||||
{
|
||||
Database database = await client.CreateDatabaseIfNotExistsAsync(new Database { Id = CosmosDatabaseName });
|
||||
var partitionKeyDefinition = new PartitionKeyDefinition { Paths = new Collection<string> { $"/{partitionKey}" } };
|
||||
var collectionDefinition = new DocumentCollection { Id = CosmosCollectionName, PartitionKey = partitionKeyDefinition };
|
||||
|
||||
await client.CreateDocumentCollectionIfNotExistsAsync(database.SelfLink, collectionDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
private static CosmosDbStorageOptions CreateCosmosDbStorageOptions(string partitionKey = "")
|
||||
{
|
||||
return new CosmosDbStorageOptions()
|
||||
{
|
||||
PartitionKey = partitionKey,
|
||||
AuthKey = CosmosAuthKey,
|
||||
CollectionId = CosmosCollectionName,
|
||||
CosmosDBEndpoint = new Uri(CosmosServiceEndpoint),
|
||||
DatabaseId = CosmosDatabaseName,
|
||||
};
|
||||
}
|
||||
|
||||
private Mock<IDocumentClient> GetDocumentClient()
|
||||
{
|
||||
var mock = new Mock<IDocumentClient>();
|
||||
|
@ -578,30 +602,6 @@ namespace Microsoft.Bot.Builder.Azure.Tests
|
|||
return mock;
|
||||
}
|
||||
|
||||
private static async Task CreateCosmosDbWithPartitionedCollection(string partitionKey)
|
||||
{
|
||||
using (var client = new DocumentClient(new Uri(CosmosServiceEndpoint), CosmosAuthKey))
|
||||
{
|
||||
Database database = await client.CreateDatabaseIfNotExistsAsync(new Database { Id = CosmosDatabaseName });
|
||||
var partitionKeyDefinition = new PartitionKeyDefinition { Paths = new Collection<string> { $"/{partitionKey}" } };
|
||||
var collectionDefinition = new DocumentCollection { Id = CosmosCollectionName, PartitionKey = partitionKeyDefinition };
|
||||
|
||||
await client.CreateDocumentCollectionIfNotExistsAsync(database.SelfLink, collectionDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
private static CosmosDbStorageOptions CreateCosmosDbStorageOptions(string partitionKey = "")
|
||||
{
|
||||
return new CosmosDbStorageOptions()
|
||||
{
|
||||
PartitionKey = partitionKey,
|
||||
AuthKey = CosmosAuthKey,
|
||||
CollectionId = CosmosCollectionName,
|
||||
CosmosDBEndpoint = new Uri(CosmosServiceEndpoint),
|
||||
DatabaseId = CosmosDatabaseName,
|
||||
};
|
||||
}
|
||||
|
||||
internal class StoreItem : IStoreItem
|
||||
{
|
||||
[JsonProperty(PropertyName = "messageList")]
|
||||
|
|
|
@ -164,7 +164,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Tests
|
|||
Assert.AreEqual("joe", value);
|
||||
|
||||
Assert.AreEqual("default", state.GetValue("user.xxx", "default"));
|
||||
Assert.AreEqual("default", state.GetValue<String>("user.xxx", "default"));
|
||||
Assert.AreEqual("default", state.GetValue<string>("user.xxx", "default"));
|
||||
Assert.IsFalse(state.TryGetValue<string>("user.xxx", out value));
|
||||
Assert.AreEqual(null, value);
|
||||
}
|
||||
|
|
|
@ -17,8 +17,6 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Tests
|
|||
{
|
||||
public IConfiguration Configuration;
|
||||
|
||||
public TestContext TestContext { get; set; }
|
||||
|
||||
public SettingsStateTests()
|
||||
{
|
||||
var builder = new ConfigurationBuilder()
|
||||
|
@ -27,6 +25,8 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Tests
|
|||
this.Configuration = builder.Build();
|
||||
}
|
||||
|
||||
public TestContext TestContext { get; set; }
|
||||
|
||||
[TestMethod]
|
||||
public async Task DialogContextState_SettingsTest()
|
||||
{
|
||||
|
|
|
@ -36,11 +36,6 @@ namespace Microsoft.Bot.Builder.Dialogs.Composition.Recognizers.Tests
|
|||
|
||||
public TestContext TestContext { get; set; }
|
||||
|
||||
private TurnContext GetTurnContext(string text, string locale = "en-us")
|
||||
{
|
||||
return new TurnContext(new TestAdapter(TestAdapter.CreateConversation(TestContext.TestName)), new Schema.Activity(type: Schema.ActivityTypes.Message, text: text, locale: locale));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestAge()
|
||||
{
|
||||
|
@ -211,5 +206,10 @@ namespace Microsoft.Bot.Builder.Dialogs.Composition.Recognizers.Tests
|
|||
Assert.AreEqual(2, results.Count, "Should be 1 entities found");
|
||||
Assert.AreEqual(1, results.Where(entity => entity.Type == "url").Count(), "Should have 1 url");
|
||||
}
|
||||
|
||||
private TurnContext GetTurnContext(string text, string locale = "en-us")
|
||||
{
|
||||
return new TurnContext(new TestAdapter(TestAdapter.CreateConversation(TestContext.TestName)), new Schema.Activity(type: Schema.ActivityTypes.Message, text: text, locale: locale));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,25 +14,6 @@ namespace Microsoft.Bot.Builder.Dialogs.Composition.Tests
|
|||
|
||||
public TestContext TestContext { get; set; }
|
||||
|
||||
public class RecognizerDialog : Dialog, IDialog
|
||||
{
|
||||
public IRecognizer Recognizer { get; set; }
|
||||
|
||||
public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var result = await Recognizer.RecognizeAsync(dc.Context, cancellationToken);
|
||||
await dc.Context.SendActivityAsync(dc.Context.Activity.CreateReply(result.Text));
|
||||
return new DialogTurnResult(DialogTurnStatus.Waiting);
|
||||
}
|
||||
|
||||
public override async Task<DialogTurnResult> ContinueDialogAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var result = await Recognizer.RecognizeAsync(dc.Context, cancellationToken);
|
||||
await dc.Context.SendActivityAsync(dc.Context.Activity.CreateReply(result.Text));
|
||||
return new DialogTurnResult(DialogTurnStatus.Waiting);
|
||||
}
|
||||
}
|
||||
|
||||
private Activity CreateLocaleActivity(string locale)
|
||||
{
|
||||
var activity = Activity.CreateMessageActivity();
|
||||
|
@ -40,6 +21,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Composition.Tests
|
|||
activity.Locale = locale;
|
||||
return (Activity)activity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create test flow.
|
||||
/// </summary>
|
||||
|
@ -67,6 +49,25 @@ namespace Microsoft.Bot.Builder.Dialogs.Composition.Tests
|
|||
|
||||
return adapter;
|
||||
}
|
||||
|
||||
public class RecognizerDialog : Dialog, IDialog
|
||||
{
|
||||
public IRecognizer Recognizer { get; set; }
|
||||
|
||||
public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var result = await Recognizer.RecognizeAsync(dc.Context, cancellationToken);
|
||||
await dc.Context.SendActivityAsync(dc.Context.Activity.CreateReply(result.Text));
|
||||
return new DialogTurnResult(DialogTurnStatus.Waiting);
|
||||
}
|
||||
|
||||
public override async Task<DialogTurnResult> ContinueDialogAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var result = await Recognizer.RecognizeAsync(dc.Context, cancellationToken);
|
||||
await dc.Context.SendActivityAsync(dc.Context.Activity.CreateReply(result.Text));
|
||||
return new DialogTurnResult(DialogTurnStatus.Waiting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TestRecognizer : IRecognizer
|
||||
|
@ -80,13 +81,13 @@ namespace Microsoft.Bot.Builder.Dialogs.Composition.Tests
|
|||
|
||||
public async Task<RecognizerResult> RecognizeAsync(ITurnContext turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
return new RecognizerResult() { Text = this.Id };
|
||||
return await Task.FromResult(new RecognizerResult() { Text = this.Id });
|
||||
}
|
||||
|
||||
public async Task<T> RecognizeAsync<T>(ITurnContext turnContext, CancellationToken cancellationToken)
|
||||
where T : IRecognizerConvert, new()
|
||||
{
|
||||
return new T();
|
||||
return await Task.FromResult(new T());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Composition.Tests
|
|||
{
|
||||
public class TestUtilities
|
||||
{
|
||||
static Lazy<Dictionary<string, string>> environmentKeys = new Lazy<Dictionary<string, string>>(() =>
|
||||
private static Lazy<Dictionary<string, string>> environmentKeys = new Lazy<Dictionary<string, string>>(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
@ -10,22 +10,6 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
{
|
||||
private TestContext testContextInstance;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the test context which provides
|
||||
/// information about and functionality for the current test run.
|
||||
///</summary>
|
||||
/// <value>
|
||||
/// The test context which provides
|
||||
/// information about and functionality for the current test run.
|
||||
/// </value>
|
||||
public TestContext TestContext
|
||||
{
|
||||
get { return testContextInstance; }
|
||||
set { testContextInstance = value; }
|
||||
}
|
||||
|
||||
public static object[] Test(string input) => new object[] { input };
|
||||
|
||||
public static IEnumerable<object[]> InvalidExpressions => new[]
|
||||
{
|
||||
Test("a+"),
|
||||
|
@ -38,21 +22,7 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("user.lists.{dialog.listName}")
|
||||
};
|
||||
|
||||
[DataTestMethod]
|
||||
[DynamicData(nameof(InvalidExpressions))]
|
||||
[ExpectedException(typeof(Exception))]
|
||||
public void Parse(string exp)
|
||||
{
|
||||
try
|
||||
{
|
||||
new ExpressionEngine().Parse(exp);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
TestContext.WriteLine(e.Message);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
public static object[] Test(string input) => new object[] { input };
|
||||
|
||||
public static IEnumerable<object[]> BadExpressions => new[]
|
||||
{
|
||||
|
@ -292,12 +262,12 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
#endregion
|
||||
|
||||
#region uri parsing function test
|
||||
Test("uriHost(relatibeUri)"),
|
||||
Test("uriPath(relatibeUri)"),
|
||||
Test("uriPathAndQuery(relatibeUri)"),
|
||||
Test("uriPort(relatibeUri)"),
|
||||
Test("uriQuery(relatibeUri)"),
|
||||
Test("uriScheme(relatibeUri)"),
|
||||
Test("uriHost(relativeUri)"),
|
||||
Test("uriPath(relativeUri)"),
|
||||
Test("uriPathAndQuery(relativeUri)"),
|
||||
Test("uriPort(relativeUri)"),
|
||||
Test("uriQuery(relativeUri)"),
|
||||
Test("uriScheme(relativeUri)"),
|
||||
#endregion
|
||||
|
||||
#region collection functions test
|
||||
|
@ -399,6 +369,36 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
#endregion
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the test context which provides
|
||||
/// information about and functionality for the current test run.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The test context which provides
|
||||
/// information about and functionality for the current test run.
|
||||
/// </value>
|
||||
public TestContext TestContext
|
||||
{
|
||||
get { return testContextInstance; }
|
||||
set { testContextInstance = value; }
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DynamicData(nameof(InvalidExpressions))]
|
||||
[ExpectedException(typeof(Exception))]
|
||||
public void Parse(string exp)
|
||||
{
|
||||
try
|
||||
{
|
||||
new ExpressionEngine().Parse(exp);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
TestContext.WriteLine(e.Message);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DynamicData(nameof(BadExpressions))]
|
||||
public void Evaluate(string exp)
|
||||
|
|
|
@ -10,10 +10,8 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
[TestClass]
|
||||
public class ExpressionEngineTests
|
||||
{
|
||||
public static object[] Test(string input, object value, HashSet<string> paths = null) => new object[] { input, value, paths };
|
||||
|
||||
public static HashSet<string> one = new HashSet<string> { "one" };
|
||||
public static HashSet<string> oneTwo = new HashSet<string> { "one", "two" };
|
||||
public static HashSet<string> One = new HashSet<string> { "one" };
|
||||
public static HashSet<string> OneTwo = new HashSet<string> { "one", "two" };
|
||||
private static readonly string NullStr = null;
|
||||
|
||||
private readonly object scope = new Dictionary<string, object>
|
||||
|
@ -97,7 +95,8 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
]
|
||||
}
|
||||
]
|
||||
}" },
|
||||
}"
|
||||
},
|
||||
{
|
||||
"turn", new
|
||||
{
|
||||
|
@ -216,7 +215,7 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
};
|
||||
|
||||
public static IEnumerable<object[]> Data => new[]
|
||||
{
|
||||
{
|
||||
#region SetPathToProperty test
|
||||
// TODO: We should support this.
|
||||
// Test("@@['c' + 'ity']", "Seattle"),
|
||||
|
@ -262,7 +261,7 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("!!exists(one) == !!exists(one)", true),
|
||||
Test("!(one == 1.0)", false, new HashSet<string> { "one" }),
|
||||
Test("!!(one == 1.0)", true, new HashSet<string> { "one" }),
|
||||
Test("!(one == 1.0) || !!(two == 2.0)", true, oneTwo),
|
||||
Test("!(one == 1.0) || !!(two == 2.0)", true, OneTwo),
|
||||
Test("!true", false),
|
||||
Test("!!true", true),
|
||||
Test("!(one == 1.0) || !!(two == 2.0)", true),
|
||||
|
@ -282,7 +281,7 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("float(5.5) <= float(4 - 1)", false),
|
||||
Test("'string'&'builder'", "stringbuilder"),
|
||||
Test("\"string\"&\"builder\"", "stringbuilder"),
|
||||
Test("one > 0.5 && two < 2.5", true, oneTwo),
|
||||
Test("one > 0.5 && two < 2.5", true, OneTwo),
|
||||
Test("notThere > 4", false),
|
||||
Test("float(5.5) && float(0.0)", true),
|
||||
Test("hello && \"hello\"", true),
|
||||
|
@ -291,7 +290,7 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("!(hello)", false), // false
|
||||
Test("!(10)", false),
|
||||
Test("!(0)", false),
|
||||
Test("one > 0.5 || two < 1.5", true, oneTwo),
|
||||
Test("one > 0.5 || two < 1.5", true, OneTwo),
|
||||
Test("one / 0 || two", true),
|
||||
Test("0/3", 0),
|
||||
Test("True == true", true),
|
||||
|
@ -336,21 +335,21 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("addOrdinal(11 + 11)", "22nd"),
|
||||
Test("addOrdinal(11 + 12)", "23rd"),
|
||||
Test("addOrdinal(11 + 13)", "24th"),
|
||||
Test("addOrdinal(-1)", "-1"), //original string value
|
||||
Test("addOrdinal(-1)", "-1"), // original string value
|
||||
|
||||
# endregion
|
||||
#endregion
|
||||
|
||||
# region Logical comparison functions test
|
||||
#region Logical comparison functions test
|
||||
Test("and(1 == 1, 1 < 2, 1 > 2)", false),
|
||||
Test("and(!true, !!true)", false), //false && true
|
||||
Test("and(!!true, !!true)", true), //true && true
|
||||
Test("and(hello != 'world', bool('true'))", true), //true && true
|
||||
Test("and(hello == 'world', bool('true'))", false), //false && true
|
||||
Test("or(!exists(one), !!exists(one))", true), //false && true
|
||||
Test("or(!exists(one), !exists(one))", false), //false && false
|
||||
Test("greater(one, two)", false, oneTwo),
|
||||
Test("and(!true, !!true)", false), // false && true
|
||||
Test("and(!!true, !!true)", true), // true && true
|
||||
Test("and(hello != 'world', bool('true'))", true), // true && true
|
||||
Test("and(hello == 'world', bool('true'))", false), // false && true
|
||||
Test("or(!exists(one), !!exists(one))", true), // false && true
|
||||
Test("or(!exists(one), !exists(one))", false), // false && false
|
||||
Test("greater(one, two)", false, OneTwo),
|
||||
Test("greater(one , 0.5) && less(two , 2.5)", true), // true && true
|
||||
Test("greater(one , 0.5) || less(two , 1.5)", true), //true || false
|
||||
Test("greater(one , 0.5) || less(two , 1.5)", true), // true || false
|
||||
Test("greater(5, 2)", true),
|
||||
Test("greater(2, 2)", false),
|
||||
Test("greater(one, two)", false),
|
||||
|
@ -359,14 +358,14 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("greaterOrEquals(float(5.5) , float(4 - 1))", true),
|
||||
Test("greaterOrEquals(one, one)", true),
|
||||
Test("greaterOrEquals(one, two)", false),
|
||||
Test("greaterOrEquals(one, one)", true, one),
|
||||
Test("greaterOrEquals(one, two)", false, oneTwo),
|
||||
Test("greaterOrEquals(one, one)", true, One),
|
||||
Test("greaterOrEquals(one, two)", false, OneTwo),
|
||||
Test("less(5, 2)", false),
|
||||
Test("less(2, 2)", false),
|
||||
Test("less(one, two)", true),
|
||||
Test("less(one, two)", true, oneTwo),
|
||||
Test("less(one, two)", true, OneTwo),
|
||||
Test("lessOrEquals(one, one)", true, new HashSet<string> { "one" }),
|
||||
Test("lessOrEquals(one, two)", true, oneTwo),
|
||||
Test("lessOrEquals(one, two)", true, OneTwo),
|
||||
Test("lessOrEquals(one, one)", true),
|
||||
Test("lessOrEquals(one, two)", true),
|
||||
Test("lessOrEquals((1 + 2) , (4 - 1))", true),
|
||||
|
@ -377,13 +376,13 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("equals(hello, 'hello')", true),
|
||||
Test("equals(bag.index, 3)", true),
|
||||
Test("equals(bag.index, 2)", false),
|
||||
Test("equals(hello == 'world', bool('true'))", false), //false, true
|
||||
Test("equals(hello == 'world', bool(0))", false), //false, true
|
||||
Test("if(!exists(one), 'r1', 'r2')", "r2"), //false
|
||||
Test("if(!!exists(one), 'r1', 'r2')", "r1"), //true
|
||||
Test("if(0, 'r1', 'r2')", "r1"), //true
|
||||
Test("if(bool('true'), 'r1', 'r2')", "r1"), //true
|
||||
Test("if(istrue, 'r1', 'r2')", "r1"), //true
|
||||
Test("equals(hello == 'world', bool('true'))", false), // false, true
|
||||
Test("equals(hello == 'world', bool(0))", false), // false, true
|
||||
Test("if(!exists(one), 'r1', 'r2')", "r2"), // false
|
||||
Test("if(!!exists(one), 'r1', 'r2')", "r1"), // true
|
||||
Test("if(0, 'r1', 'r2')", "r1"), // true
|
||||
Test("if(bool('true'), 'r1', 'r2')", "r1"), // true
|
||||
Test("if(istrue, 'r1', 'r2')", "r1"), // true
|
||||
Test("exists(one)", true),
|
||||
Test("exists(xxx)", false),
|
||||
Test("exists(one.xxx)", false),
|
||||
|
@ -393,7 +392,7 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("not(one == 1.0)", false, new HashSet<string> { "one" }),
|
||||
Test("not(not(one == 1.0))", true, new HashSet<string> { "one" }),
|
||||
Test("not(false)", true),
|
||||
Test("and(one > 0.5, two < 2.5)", true, oneTwo),
|
||||
Test("and(one > 0.5, two < 2.5)", true, OneTwo),
|
||||
Test("and(float(5.5), float(0.0))", true),
|
||||
Test("and(hello, \"hello\")", true),
|
||||
Test("or(items, (2 + 2) <= (4 - 1))", true), // true || false
|
||||
|
@ -405,9 +404,9 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("if(null, 'r1', 'r2')", "r2"),
|
||||
Test("if(hello * 5, 'r1', 'r2')", "r2"),
|
||||
Test("if(10, 'r1', 'r2')", "r1"),
|
||||
# endregion
|
||||
#endregion
|
||||
|
||||
# region Conversion functions test
|
||||
#region Conversion functions test
|
||||
Test("float('10.333')", 10.333f),
|
||||
Test("float('10')", 10.0f),
|
||||
Test("int('10')", 10),
|
||||
|
@ -448,7 +447,7 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("min(mul(1, 2), 5) ", 2),
|
||||
Test("min(4, 5) ", 4),
|
||||
Test("min(4) ", 4),
|
||||
Test("min(1.0, two) + max(one, 2.0)", 3.0, oneTwo),
|
||||
Test("min(1.0, two) + max(one, 2.0)", 3.0, OneTwo),
|
||||
Test("sub(2, 1)", 1),
|
||||
Test("sub(2, 1, 1)", 0),
|
||||
Test("sub(2.0, 0.5)", 1.5),
|
||||
|
@ -463,11 +462,11 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("rand(2, 3)", 2),
|
||||
Test("range(1,4)", new[] { 1, 2, 3, 4 }),
|
||||
Test("range(-1,6)", new[] { -1, 0, 1, 2, 3, 4 }),
|
||||
# endregion
|
||||
#endregion
|
||||
|
||||
# region Date and time function test
|
||||
#region Date and time function test
|
||||
|
||||
//init dateTime: 2018-03-15T13:00:00Z
|
||||
// init dateTime: 2018-03-15T13:00:00Z
|
||||
Test("addDays(timestamp, 1)", "2018-03-16T13:00:00.000Z"),
|
||||
Test("addDays(timestamp, 1,'MM-dd-yy')", "03-16-18"),
|
||||
Test("addHours(timestamp, 1)", "2018-03-15T14:00:00.000Z"),
|
||||
|
@ -477,10 +476,10 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("addSeconds(timestamp, 1)", "2018-03-15T13:00:01.000Z"),
|
||||
Test("addSeconds(timestamp, 1, 'MM-dd-yy hh-mm-ss')", "03-15-18 01-00-01"),
|
||||
Test("dayOfMonth(timestamp)", 15),
|
||||
Test("dayOfWeek(timestamp)", 4), //Thursday
|
||||
Test("dayOfWeek(timestamp)", 4), // Thursday
|
||||
Test("dayOfYear(timestamp)", 74),
|
||||
Test("month(timestamp)", 3),
|
||||
Test("date(timestamp)", "3/15/2018"), //Default. TODO
|
||||
Test("date(timestamp)", "3/15/2018"), // Default. TODO
|
||||
Test("year(timestamp)", 2018),
|
||||
Test("length(utcNow())", 24),
|
||||
Test("utcNow('MM-DD-YY')", DateTime.UtcNow.ToString("MM-DD-YY")),
|
||||
|
@ -584,9 +583,9 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("lastIndexOf(newGuid(), '-')", 23),
|
||||
Test("lastIndexOf(hello, '-')", -1),
|
||||
Test("length(newGuid())", 36),
|
||||
# endregion
|
||||
#endregion
|
||||
|
||||
# region Object manipulation and construction functions
|
||||
#region Object manipulation and construction functions
|
||||
Test("string(addProperty(json('{\"key1\":\"value1\"}'), 'key2','value2'))", "{\"key1\":\"value1\",\"key2\":\"value2\"}"),
|
||||
Test("string(setProperty(json('{\"key1\":\"value1\"}'), 'key1','value2'))", "{\"key1\":\"value2\"}"),
|
||||
Test("string(removeProperty(json('{\"key1\":\"value1\",\"key2\":\"value2\"}'), 'key2'))", "{\"key1\":\"value1\"}"),
|
||||
|
@ -595,9 +594,9 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("xPath(xmlStr,'sum(/produce/item/count)')", 30),
|
||||
Test("jPath(jsonStr,'Manufacturers[0].Products[0].Price')", 50),
|
||||
Test("jPath(jsonStr,'$..Products[?(@.Price >= 50)].Name')", new[] { "Anvil", "Elbow Grease" }),
|
||||
# endregion
|
||||
#endregion
|
||||
|
||||
# region Short Hand Expression
|
||||
#region Short Hand Expression
|
||||
Test("@city == 'Bellevue'", false, new HashSet<string> { "turn.recognized.entities.city" }),
|
||||
Test("@city", "Seattle", new HashSet<string> { "turn.recognized.entities.city" }),
|
||||
Test("@city == 'Seattle'", true, new HashSet<string> { "turn.recognized.entities.city" }),
|
||||
|
@ -644,7 +643,7 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("(getProperty(null, 'p'))[1]", null),
|
||||
#endregion
|
||||
|
||||
# region Dialog
|
||||
#region Dialog
|
||||
Test("user.lists.todo[int(@@ordinal[0]) - 1] != null", true),
|
||||
Test("user.lists.todo[int(@@ordinal[0]) + 3] != null", false),
|
||||
Test("count(user.lists.todo) > int(@@ordinal[0]))", true),
|
||||
|
@ -653,7 +652,7 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("user.lists[user.listType][int(@@ordinal[0]) - 1]", "todo1"),
|
||||
#endregion
|
||||
|
||||
# region Regex
|
||||
#region Regex
|
||||
Test("isMatch('abc', '^[ab]+$')", false), // simple character classes ([abc]), "+" (one or more)
|
||||
Test("isMatch('abb', '^[ab]+$')", true), // simple character classes ([abc])
|
||||
Test("isMatch('123', '^[^abc]+$')", true), // complemented character classes ([^abc])
|
||||
|
@ -678,10 +677,25 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("isMatch('12abc', '([0-9]+)([a-z]+)([0-9]+)')", false), // "(...)" (simple group)
|
||||
Test(@"isMatch('a', '\\w{1}')", true), // "\w" (match [a-zA-Z0-9_])
|
||||
Test(@"isMatch('1', '\\d{1}')", true), // "\d" (match [0-9])
|
||||
# endregion
|
||||
#endregion
|
||||
};
|
||||
|
||||
[DataTestMethod()]
|
||||
public static object[] Test(string input, object value, HashSet<string> paths = null) => new object[] { input, value, paths };
|
||||
|
||||
public static bool IsNumber(object value) =>
|
||||
value is sbyte
|
||||
|| value is byte
|
||||
|| value is short
|
||||
|| value is ushort
|
||||
|| value is int
|
||||
|| value is uint
|
||||
|| value is long
|
||||
|| value is ulong
|
||||
|| value is float
|
||||
|| value is double
|
||||
|| value is decimal;
|
||||
|
||||
[DataTestMethod]
|
||||
[DynamicData(nameof(Data))]
|
||||
public void Evaluate(string input, object expected, HashSet<string> expectedRefs)
|
||||
{
|
||||
|
@ -714,19 +728,6 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
}
|
||||
}
|
||||
|
||||
public static bool IsNumber(object value) =>
|
||||
value is sbyte
|
||||
|| value is byte
|
||||
|| value is short
|
||||
|| value is ushort
|
||||
|| value is int
|
||||
|| value is uint
|
||||
|| value is long
|
||||
|| value is ulong
|
||||
|| value is float
|
||||
|| value is double
|
||||
|| value is decimal;
|
||||
|
||||
private void AssertObjectEquals(object expected, object actual)
|
||||
{
|
||||
if (IsNumber(actual) && IsNumber(expected))
|
||||
|
|
|
@ -7,8 +7,6 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
[TestClass]
|
||||
public class RewriteTests
|
||||
{
|
||||
public static object[] Test(string input, string expected) => new object[] { input, expected };
|
||||
|
||||
public static IEnumerable<object[]> Data => new[]
|
||||
{
|
||||
/*
|
||||
|
@ -38,6 +36,19 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
Test("!(ignore(bark == 3))", "ignore(bark != 3)")
|
||||
};
|
||||
|
||||
public static object[] Test(string input, string expected) => new object[] { input, expected };
|
||||
|
||||
[DataTestMethod]
|
||||
[DynamicData(nameof(Data))]
|
||||
public void Evaluate(string input, string expected)
|
||||
{
|
||||
var parser = new ExpressionEngine(Lookup);
|
||||
var original = parser.Parse(input);
|
||||
var dnf = original.DisjunctiveNormalForm();
|
||||
var expectedDnf = parser.Parse(expected);
|
||||
Assert.IsTrue(dnf.DeepEquals(expectedDnf), $"{original} is {dnf}, not {expectedDnf}");
|
||||
}
|
||||
|
||||
private ExpressionEvaluator Lookup(string type)
|
||||
{
|
||||
ExpressionEvaluator eval;
|
||||
|
@ -53,16 +64,5 @@ namespace Microsoft.Bot.Builder.Expressions.Tests
|
|||
|
||||
return eval;
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DynamicData(nameof(Data))]
|
||||
public void Evaluate(string input, string expected)
|
||||
{
|
||||
var parser = new ExpressionEngine(Lookup);
|
||||
var original = parser.Parse(input);
|
||||
var dnf = original.DisjunctiveNormalForm();
|
||||
var expectedDnf = parser.Parse(expected);
|
||||
Assert.IsTrue(dnf.DeepEquals(expectedDnf), $"{original} is {dnf}, not {expectedDnf}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,10 +20,10 @@ namespace Microsoft.Bot.Builder.AI.LanguageGeneration.Tests
|
|||
[TestClass]
|
||||
public class LGGeneratorTests
|
||||
{
|
||||
private readonly ImportResolverDelegate resourceResolver = LanguageGeneratorManager.ResourceResolver(resourceExplorer);
|
||||
|
||||
private static ResourceExplorer resourceExplorer;
|
||||
|
||||
private readonly ImportResolverDelegate resourceResolver = LanguageGeneratorManager.ResourceResolver(resourceExplorer);
|
||||
|
||||
public TestContext TestContext { get; set; }
|
||||
|
||||
[ClassInitialize]
|
||||
|
|
|
@ -9,16 +9,6 @@ namespace Microsoft.Bot.Builder.AI.LanguageGeneration.Tests
|
|||
[TestClass]
|
||||
public class TemplateEngineThrowExceptionTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the test context which provides
|
||||
/// information about and functionality for the current test run.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The test context which provides
|
||||
/// information about and functionality for the current test run.
|
||||
/// </value>
|
||||
public TestContext TestContext { get; set; }
|
||||
|
||||
public static IEnumerable<object[]> StaticCheckExceptionData => new[]
|
||||
{
|
||||
Test("EmptyTemplate.lg"),
|
||||
|
@ -60,6 +50,16 @@ namespace Microsoft.Bot.Builder.AI.LanguageGeneration.Tests
|
|||
TestTemplate("LoopDetected.lg", "NotExistTemplate"),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the test context which provides
|
||||
/// information about and functionality for the current test run.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The test context which provides
|
||||
/// information about and functionality for the current test run.
|
||||
/// </value>
|
||||
public TestContext TestContext { get; set; }
|
||||
|
||||
public static object[] Test(string input) => new object[] { input };
|
||||
|
||||
public static object[] TestTemplate(string input, string templateName) => new object[] { input, templateName };
|
||||
|
|
Загрузка…
Ссылка в новой задаче