1
- // ----------------------------------------------------------------------------------
1
+ // ----------------------------------------------------------------------------------
2
2
//
3
3
// Copyright Microsoft Corporation
4
4
// Licensed under the Apache License, Version 2.0 (the "License");
13
13
// ----------------------------------------------------------------------------------
14
14
15
15
using Microsoft . Azure . PowerShell . Tools . AzPredictor . Test . Mocks ;
16
+ using System ;
17
+ using System . Collections . Generic ;
16
18
using System . Linq ;
19
+ using System . Management . Automation . Language ;
17
20
using System . Management . Automation . Subsystem ;
18
21
using System . Threading ;
19
22
using Xunit ;
@@ -26,10 +29,36 @@ namespace Microsoft.Azure.PowerShell.Tools.AzPredictor.Test
26
29
[ Collection ( "Model collection" ) ]
27
30
public class AzPredictorServiceTests
28
31
{
32
+ private class PredictiveSuggestionComparer : EqualityComparer < PredictiveSuggestion >
33
+ {
34
+ public override bool Equals ( PredictiveSuggestion first , PredictiveSuggestion second )
35
+ {
36
+ if ( ( first == null ) && ( second == null ) )
37
+ {
38
+ return true ;
39
+ }
40
+ else if ( ( first == null ) || ( second == null ) )
41
+ {
42
+ return false ;
43
+ }
44
+
45
+ return string . Equals ( first . SuggestionText , second . SuggestionText , StringComparison . Ordinal ) ;
46
+ }
47
+
48
+ public override int GetHashCode ( PredictiveSuggestion suggestion )
49
+ {
50
+ return suggestion . SuggestionText . GetHashCode ( ) ;
51
+ }
52
+ }
53
+
29
54
private readonly ModelFixture _fixture ;
30
55
private readonly AzPredictorService _service ;
31
- private readonly Predictor _suggestionsPredictor ;
32
- private readonly Predictor _commandsPredictor ;
56
+ private readonly CommandLinePredictor _commandBasedPredictor ;
57
+ private readonly CommandLinePredictor _fallbackPredictor ;
58
+
59
+ private readonly AzPredictorService _noFallbackPredictorService ;
60
+ private readonly AzPredictorService _noCommandBasedPredictorService ;
61
+ private readonly AzPredictorService _noPredictorService ;
33
62
34
63
/// <summary>
35
64
/// Constructs a new instance of <see cref="AzPredictorServiceTests"/>
@@ -39,15 +68,36 @@ public AzPredictorServiceTests(ModelFixture fixture)
39
68
{
40
69
this . _fixture = fixture ;
41
70
var startHistory = $ "{ AzPredictorConstants . CommandPlaceholder } { AzPredictorConstants . CommandConcatenator } { AzPredictorConstants . CommandPlaceholder } ";
42
- this . _suggestionsPredictor = new Predictor ( this . _fixture . PredictionCollection [ startHistory ] , null ) ;
43
- this . _commandsPredictor = new Predictor ( this . _fixture . CommandCollection , null ) ;
71
+ this . _commandBasedPredictor = new CommandLinePredictor ( this . _fixture . PredictionCollection [ startHistory ] , null ) ;
72
+ this . _fallbackPredictor = new CommandLinePredictor ( this . _fixture . CommandCollection , null ) ;
44
73
45
74
this . _service = new MockAzPredictorService ( startHistory , this . _fixture . PredictionCollection [ startHistory ] , this . _fixture . CommandCollection ) ;
75
+
76
+ this . _noFallbackPredictorService = new MockAzPredictorService ( startHistory , this . _fixture . PredictionCollection [ startHistory ] , null ) ;
77
+ this . _noCommandBasedPredictorService = new MockAzPredictorService ( null , null , this . _fixture . CommandCollection ) ;
78
+ this . _noPredictorService = new MockAzPredictorService ( null , null , null ) ;
46
79
}
47
80
81
+ /// <summary>
82
+ /// Verify the method checks parameter values.
83
+ /// </summary>
84
+ [ Fact ]
85
+ public void VerifyParameterValues ( )
86
+ {
87
+ var predictionContext = PredictionContext . Create ( "Get-AzContext" ) ;
88
+
89
+ Action actual = ( ) => this . _service . GetSuggestion ( null , 1 , 1 , CancellationToken . None ) ;
90
+ Assert . Throws < ArgumentNullException > ( actual ) ;
91
+
92
+ actual = ( ) => this . _service . GetSuggestion ( predictionContext . InputAst , 0 , 1 , CancellationToken . None ) ;
93
+ Assert . Throws < ArgumentOutOfRangeException > ( actual ) ;
94
+
95
+ actual = ( ) => this . _service . GetSuggestion ( predictionContext . InputAst , 1 , 0 , CancellationToken . None ) ;
96
+ Assert . Throws < ArgumentOutOfRangeException > ( actual ) ;
97
+ }
48
98
49
99
/// <summary>
50
- /// Verifies that the prediction comes from the suggestions list, not the command list.
100
+ /// Verifies that the prediction comes from the command based list, not the fallback list.
51
101
/// </summary>
52
102
[ Theory ]
53
103
[ InlineData ( "CONNECT-AZACCOUNT" ) ]
@@ -59,52 +109,126 @@ public AzPredictorServiceTests(ModelFixture fixture)
59
109
[ InlineData ( "new-azresourcegroup -name hello" ) ]
60
110
[ InlineData ( "Get-AzContext -Name" ) ]
61
111
[ InlineData ( "Get-AzContext -ErrorAction" ) ]
62
- public void VerifyUsingSuggestion ( string userInput )
112
+ public void VerifyUsingCommandBasedPredictor ( string userInput )
63
113
{
64
114
var predictionContext = PredictionContext . Create ( userInput ) ;
65
- var presentCommands = new System . Collections . Generic . Dictionary < string , int > ( ) ;
66
- var expected = this . _suggestionsPredictor . Query ( predictionContext . InputAst , presentCommands , 1 , 1 , CancellationToken . None ) ;
115
+ var commandAst = predictionContext . InputAst . FindAll ( p => p is CommandAst , true ) . LastOrDefault ( ) as CommandAst ;
116
+ var commandName = ( commandAst ? . CommandElements ? . FirstOrDefault ( ) as StringConstantExpressionAst ) ? . Value ;
117
+ var inputParameterSet = new ParameterSet ( commandAst ) ;
118
+ var rawUserInput = predictionContext . InputAst . Extent . Text ;
119
+ var presentCommands = new Dictionary < string , int > ( ) ;
120
+ var expected = this . _commandBasedPredictor . GetSuggestion ( commandName ,
121
+ inputParameterSet ,
122
+ rawUserInput ,
123
+ presentCommands ,
124
+ 1 ,
125
+ 1 ,
126
+ CancellationToken . None ) ;
127
+
67
128
var actual = this . _service . GetSuggestion ( predictionContext . InputAst , 1 , 1 , CancellationToken . None ) ;
68
- Assert . NotEmpty ( actual ) ;
69
- Assert . NotNull ( actual . First ( ) . Item1 ) ;
70
- Assert . Equal ( expected . Item1 . First ( ) . Key , actual . First ( ) . Item1 ) ;
71
- Assert . Equal ( PredictionSource . CurrentCommand , actual . First ( ) . Item3 ) ;
129
+ Assert . NotNull ( actual ) ;
130
+ Assert . True ( actual . Count > 0 ) ;
131
+ Assert . NotNull ( actual . PredictiveSuggestions . First ( ) ) ;
132
+ Assert . NotNull ( actual . PredictiveSuggestions . First ( ) . SuggestionText ) ;
133
+ Assert . Equal ( expected . Count , actual . Count ) ;
134
+ Assert . Equal < PredictiveSuggestion > ( expected . PredictiveSuggestions , actual . PredictiveSuggestions , new PredictiveSuggestionComparer ( ) ) ;
135
+ Assert . Equal < string > ( expected . SourceTexts , actual . SourceTexts ) ;
136
+ Assert . All < SuggestionSource > ( actual . SuggestionSources , ( source ) => Assert . Equal ( SuggestionSource . CurrentCommand , source ) ) ;
137
+
138
+ actual = this . _noFallbackPredictorService . GetSuggestion ( predictionContext . InputAst , 1 , 1 , CancellationToken . None ) ;
139
+ Assert . NotNull ( actual ) ;
140
+ Assert . True ( actual . Count > 0 ) ;
141
+ Assert . NotNull ( actual . PredictiveSuggestions . First ( ) ) ;
142
+ Assert . NotNull ( actual . PredictiveSuggestions . First ( ) . SuggestionText ) ;
143
+ Assert . Equal ( expected . Count , actual . Count ) ;
144
+ Assert . Equal < PredictiveSuggestion > ( expected . PredictiveSuggestions , actual . PredictiveSuggestions , new PredictiveSuggestionComparer ( ) ) ;
145
+ Assert . Equal < string > ( expected . SourceTexts , actual . SourceTexts ) ;
146
+ Assert . All < SuggestionSource > ( actual . SuggestionSources , ( source ) => Assert . Equal ( SuggestionSource . CurrentCommand , source ) ) ;
72
147
}
73
148
74
149
/// <summary>
75
- /// Verifies that when no prediction is in the suggestion list, we'll use the command list.
150
+ /// Verifies that when no prediction is in the command based list, we'll use the fallback list.
76
151
/// </summary>
77
152
[ Theory ]
78
153
[ InlineData ( "Get-AzResource -Name hello -Pre" ) ]
79
154
[ InlineData ( "Get-AzADServicePrincipal -ApplicationObject" ) ]
80
- public void VerifyUsingCommand ( string userInput )
155
+ public void VerifyUsingFallbackPredictor ( string userInput )
81
156
{
82
157
var predictionContext = PredictionContext . Create ( userInput ) ;
83
- var presentCommands = new System . Collections . Generic . Dictionary < string , int > ( ) ;
84
- var expected = this . _commandsPredictor . Query ( predictionContext . InputAst , presentCommands , 1 , 1 , CancellationToken . None ) ;
158
+ var commandAst = predictionContext . InputAst . FindAll ( p => p is CommandAst , true ) . LastOrDefault ( ) as CommandAst ;
159
+ var commandName = ( commandAst ? . CommandElements ? . FirstOrDefault ( ) as StringConstantExpressionAst ) ? . Value ;
160
+ var inputParameterSet = new ParameterSet ( commandAst ) ;
161
+ var rawUserInput = predictionContext . InputAst . Extent . Text ;
162
+ var presentCommands = new Dictionary < string , int > ( ) ;
163
+ var expected = this . _fallbackPredictor . GetSuggestion ( commandName ,
164
+ inputParameterSet ,
165
+ rawUserInput ,
166
+ presentCommands ,
167
+ 1 ,
168
+ 1 ,
169
+ CancellationToken . None ) ;
170
+
85
171
var actual = this . _service . GetSuggestion ( predictionContext . InputAst , 1 , 1 , CancellationToken . None ) ;
86
- Assert . NotEmpty ( actual ) ;
87
- Assert . NotNull ( actual . First ( ) . Item1 ) ;
88
- Assert . Equal ( expected . Item1 . First ( ) . Key , actual . First ( ) . Item1 ) ;
89
- Assert . Equal ( PredictionSource . StaticCommands , actual . First ( ) . Item3 ) ;
172
+ Assert . NotNull ( actual ) ;
173
+ Assert . True ( actual . Count > 0 ) ;
174
+ Assert . NotNull ( actual . PredictiveSuggestions . First ( ) ) ;
175
+ Assert . NotNull ( actual . PredictiveSuggestions . First ( ) . SuggestionText ) ;
176
+ Assert . Equal ( expected . Count , actual . Count ) ;
177
+ Assert . Equal < PredictiveSuggestion > ( expected . PredictiveSuggestions , actual . PredictiveSuggestions , new PredictiveSuggestionComparer ( ) ) ;
178
+ Assert . Equal < string > ( expected . SourceTexts , actual . SourceTexts ) ;
179
+ Assert . All < SuggestionSource > ( actual . SuggestionSources , ( source ) => Assert . Equal ( SuggestionSource . StaticCommands , source ) ) ;
180
+
181
+ actual = this . _noCommandBasedPredictorService . GetSuggestion ( predictionContext . InputAst , 1 , 1 , CancellationToken . None ) ;
182
+ Assert . NotNull ( actual ) ;
183
+ Assert . True ( actual . Count > 0 ) ;
184
+ Assert . NotNull ( actual . PredictiveSuggestions . First ( ) ) ;
185
+ Assert . NotNull ( actual . PredictiveSuggestions . First ( ) . SuggestionText ) ;
186
+ Assert . Equal ( expected . Count , actual . Count ) ;
187
+ Assert . Equal < PredictiveSuggestion > ( expected . PredictiveSuggestions , actual . PredictiveSuggestions , new PredictiveSuggestionComparer ( ) ) ;
188
+ Assert . Equal < string > ( expected . SourceTexts , actual . SourceTexts ) ;
189
+ Assert . All < SuggestionSource > ( actual . SuggestionSources , ( source ) => Assert . Equal ( SuggestionSource . StaticCommands , source ) ) ;
90
190
}
91
191
92
192
/// <summary>
93
- /// Verify that no prediction for the user input, meaning it's not in the prediction list or the command list.
193
+ /// Verify that no prediction for the user input, meaning it's not in the command based list or the fallback list.
94
194
/// </summary>
95
195
[ Theory ]
96
196
[ InlineData ( AzPredictorConstants . CommandPlaceholder ) ]
97
- [ InlineData ( "git status" ) ]
98
197
[ InlineData ( "Get-ChildItem" ) ]
99
198
[ InlineData ( "new-azresourcegroup -NoExistingParam" ) ]
100
199
[ InlineData ( "get-azaccount " ) ]
101
- [ InlineData ( "Get-AzContext Name" ) ]
102
200
[ InlineData ( "NEW-AZCONTEXT" ) ]
103
201
public void VerifyNoPrediction ( string userInput )
104
202
{
105
203
var predictionContext = PredictionContext . Create ( userInput ) ;
106
204
var actual = this . _service . GetSuggestion ( predictionContext . InputAst , 1 , 1 , CancellationToken . None ) ;
107
- Assert . Empty ( actual ) ;
205
+ Assert . Equal ( 0 , actual . Count ) ;
206
+
207
+ actual = this . _noFallbackPredictorService . GetSuggestion ( predictionContext . InputAst , 1 , 1 , CancellationToken . None ) ;
208
+ Assert . Equal ( 0 , actual . Count ) ;
209
+
210
+ actual = this . _noCommandBasedPredictorService . GetSuggestion ( predictionContext . InputAst , 1 , 1 , CancellationToken . None ) ;
211
+ Assert . Equal ( 0 , actual . Count ) ;
212
+
213
+ actual = this . _noPredictorService . GetSuggestion ( predictionContext . InputAst , 1 , 1 , CancellationToken . None ) ;
214
+ Assert . Null ( actual ) ;
215
+ }
216
+
217
+ /// <summary>
218
+ /// Verify when we cannot parse the user input correctly.
219
+ /// </summary>
220
+ /// <remarks>
221
+ /// When we can parse them correctly, please move the InlineData to the corresponding test methods, for example, "git status"
222
+ /// doesn't have any prediction so it should move to <see cref="VerifyNoPrediction"/>.
223
+ /// </remarks>
224
+ [ Theory ]
225
+ [ InlineData ( "git status" ) ]
226
+ [ InlineData ( "Get-AzContext Name" ) ]
227
+ public void VerifyMalFormattedCommandLine ( string userInput )
228
+ {
229
+ var predictionContext = PredictionContext . Create ( userInput ) ;
230
+ Action actual = ( ) => this . _service . GetSuggestion ( predictionContext . InputAst , 1 , 1 , CancellationToken . None ) ;
231
+ _ = Assert . Throws < InvalidOperationException > ( actual ) ;
108
232
}
109
233
}
110
234
}
0 commit comments