forked from dotnet/msbuild
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNodePackets_Tests.cs
More file actions
347 lines (319 loc) · 20.2 KB
/
NodePackets_Tests.cs
File metadata and controls
347 lines (319 loc) · 20.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Microsoft.Build.BackEnd;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
using Xunit;
using TaskItem = Microsoft.Build.Execution.ProjectItemInstance.TaskItem;
#nullable disable
namespace Microsoft.Build.UnitTests.BackEnd
{
/// <summary>
/// Each packet is split up into a region, the region contains the tests for
/// a given packet type.
/// </summary>
public class NodePackets_Tests
{
#region LogMessagePacket Tests
/// <summary>
/// Verify a null build event throws an exception
/// </summary>
[Fact]
public void LogMessageConstructorNullBuildEvent()
{
Assert.Throws<InternalErrorException>(() =>
{
LogMessagePacket packet = new LogMessagePacket(null);
});
}
/// <summary>
/// Verify when creating a LogMessagePacket
/// that the correct Event Type is set.
/// </summary>
[Fact]
public void VerifyEventType()
{
BuildFinishedEventArgs buildFinished = new BuildFinishedEventArgs("Message", "Keyword", true);
BuildStartedEventArgs buildStarted = new BuildStartedEventArgs("Message", "Help");
BuildMessageEventArgs lowMessage = new BuildMessageEventArgs("Message", "help", "sender", MessageImportance.Low);
TaskStartedEventArgs taskStarted = new TaskStartedEventArgs("message", "help", "projectFile", "taskFile", "taskName");
TaskFinishedEventArgs taskFinished = new TaskFinishedEventArgs("message", "help", "projectFile", "taskFile", "taskName", true);
TaskCommandLineEventArgs commandLine = new TaskCommandLineEventArgs("commandLine", "taskName", MessageImportance.Low);
TaskParameterEventArgs taskParameter = CreateTaskParameter();
BuildWarningEventArgs warning = new BuildWarningEventArgs("SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender");
BuildErrorEventArgs error = new BuildErrorEventArgs("SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender");
TargetStartedEventArgs targetStarted = new TargetStartedEventArgs("message", "help", "targetName", "ProjectFile", "targetFile");
TargetFinishedEventArgs targetFinished = new TargetFinishedEventArgs("message", "help", "targetName", "ProjectFile", "targetFile", true);
TargetSkippedEventArgs targetSkipped = CreateTargetSkipped();
ProjectStartedEventArgs projectStarted = new ProjectStartedEventArgs(-1, "message", "help", "ProjectFile", "targetNames", null, null, null);
ProjectFinishedEventArgs projectFinished = new ProjectFinishedEventArgs("message", "help", "ProjectFile", true);
ExternalProjectStartedEventArgs externalStartedEvent = new ExternalProjectStartedEventArgs("message", "help", "senderName", "projectFile", "targetNames");
ExternalProjectFinishedEventArgs externalFinishedEvent = new("message", "help", "senderName", "projectFile", true);
ProjectEvaluationStartedEventArgs evaluationStarted = new ProjectEvaluationStartedEventArgs();
ProjectEvaluationFinishedEventArgs evaluationFinished = new ProjectEvaluationFinishedEventArgs();
AssemblyLoadBuildEventArgs assemblyLoad = new(AssemblyLoadingContext.Evaluation, null, null, "path", Guid.NewGuid(), null);
ExtendedBuildErrorEventArgs extError = new("extError", "SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender");
ExtendedBuildWarningEventArgs extWarning = new("extWarn", "SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender");
ExtendedBuildMessageEventArgs extMessage = new("extMsg", "SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender", MessageImportance.Normal);
ExtendedCustomBuildEventArgs extCustom = new("extCustom", "message", "help", "sender");
CriticalBuildMessageEventArgs criticalMessage = new("Subcategory", "Code", "File", 1, 2, 3, 4, "{0}", "HelpKeyword", "Sender", DateTime.Now, "arg1");
PropertyInitialValueSetEventArgs propInit = new("prop", "val", "propsource", "message", "help", "sender", MessageImportance.Normal);
MetaprojectGeneratedEventArgs metaProjectGenerated = new("metaName", "path", "message");
PropertyReassignmentEventArgs propReassign = new("prop", "prevValue", "newValue", "loc", "message", "help", "sender", MessageImportance.Normal);
ResponseFileUsedEventArgs responseFileUsed = new("path");
UninitializedPropertyReadEventArgs uninitializedPropertyRead = new("prop", "message", "help", "sender", MessageImportance.Normal);
EnvironmentVariableReadEventArgs environmentVariableRead = new("env", "message", "help", "sender", MessageImportance.Normal);
VerifyLoggingPacket(buildFinished, LoggingEventType.BuildFinishedEvent);
VerifyLoggingPacket(buildStarted, LoggingEventType.BuildStartedEvent);
VerifyLoggingPacket(lowMessage, LoggingEventType.BuildMessageEvent);
VerifyLoggingPacket(taskStarted, LoggingEventType.TaskStartedEvent);
VerifyLoggingPacket(taskFinished, LoggingEventType.TaskFinishedEvent);
VerifyLoggingPacket(commandLine, LoggingEventType.TaskCommandLineEvent);
VerifyLoggingPacket(taskParameter, LoggingEventType.TaskParameterEvent);
VerifyLoggingPacket(warning, LoggingEventType.BuildWarningEvent);
VerifyLoggingPacket(error, LoggingEventType.BuildErrorEvent);
VerifyLoggingPacket(targetStarted, LoggingEventType.TargetStartedEvent);
VerifyLoggingPacket(targetFinished, LoggingEventType.TargetFinishedEvent);
VerifyLoggingPacket(targetSkipped, LoggingEventType.TargetSkipped);
VerifyLoggingPacket(projectStarted, LoggingEventType.ProjectStartedEvent);
VerifyLoggingPacket(projectFinished, LoggingEventType.ProjectFinishedEvent);
VerifyLoggingPacket(evaluationStarted, LoggingEventType.ProjectEvaluationStartedEvent);
VerifyLoggingPacket(evaluationFinished, LoggingEventType.ProjectEvaluationFinishedEvent);
VerifyLoggingPacket(externalStartedEvent, LoggingEventType.ExternalProjectStartedEvent);
VerifyLoggingPacket(externalFinishedEvent, LoggingEventType.ExternalProjectFinishedEvent);
VerifyLoggingPacket(assemblyLoad, LoggingEventType.AssemblyLoadEvent);
VerifyLoggingPacket(extError, LoggingEventType.ExtendedBuildErrorEvent);
VerifyLoggingPacket(extWarning, LoggingEventType.ExtendedBuildWarningEvent);
VerifyLoggingPacket(extMessage, LoggingEventType.ExtendedBuildMessageEvent);
VerifyLoggingPacket(extCustom, LoggingEventType.ExtendedCustomEvent);
VerifyLoggingPacket(criticalMessage, LoggingEventType.CriticalBuildMessage);
VerifyLoggingPacket(propInit, LoggingEventType.PropertyInitialValueSet);
VerifyLoggingPacket(metaProjectGenerated, LoggingEventType.MetaprojectGenerated);
VerifyLoggingPacket(propReassign, LoggingEventType.PropertyReassignment);
VerifyLoggingPacket(responseFileUsed, LoggingEventType.ResponseFileUsedEvent);
VerifyLoggingPacket(uninitializedPropertyRead, LoggingEventType.UninitializedPropertyRead);
VerifyLoggingPacket(environmentVariableRead, LoggingEventType.EnvironmentVariableReadEvent);
}
private static BuildEventContext CreateBuildEventContext()
{
return new BuildEventContext(1, 2, 3, 4, 5, 6, 7);
}
private static ProjectEvaluationStartedEventArgs CreateProjectEvaluationStarted()
{
string projectFile = "test.csproj";
var result = new ProjectEvaluationStartedEventArgs(
ResourceUtilities.GetResourceString("EvaluationStarted"),
projectFile)
{
ProjectFile = projectFile
};
result.BuildEventContext = CreateBuildEventContext();
return result;
}
private static ProjectEvaluationFinishedEventArgs CreateProjectEvaluationFinished()
{
string projectFile = "test.csproj";
var result = new ProjectEvaluationFinishedEventArgs(
ResourceUtilities.GetResourceString("EvaluationFinished"),
projectFile)
{
ProjectFile = projectFile,
GlobalProperties = CreateProperties(),
Properties = CreateProperties(),
Items = new ArrayList
{
new DictionaryEntry("Compile", new TaskItemData("a", null)),
new DictionaryEntry("Compile", new TaskItemData("b", CreateStringDictionary())),
new DictionaryEntry("Reference", new TaskItemData("c", CreateStringDictionary())),
}
};
result.BuildEventContext = CreateBuildEventContext();
return result;
}
private static IEnumerable CreateProperties()
{
return new ArrayList
{
new DictionaryEntry("a", "b"),
new DictionaryEntry("c", "d")
};
}
private static Dictionary<string, string> CreateStringDictionary()
{
return new Dictionary<string, string>
{
{ "a", "b" },
{ "c", "d" }
};
}
private static TaskItemData[] CreateTaskItems()
{
var items = new TaskItemData[]
{
new TaskItemData("ItemSpec1", null),
new TaskItemData("ItemSpec1", CreateStringDictionary()),
new TaskItemData("ItemSpec2", Enumerable.Range(1, 3).ToDictionary(i => i.ToString(), i => i.ToString() + "value"))
};
return items;
}
private static TaskParameterEventArgs CreateTaskParameter()
{
// touch ItemGroupLoggingHelper to ensure static constructor runs
_ = ItemGroupLoggingHelper.ItemGroupIncludeLogMessagePrefix;
var items = CreateTaskItems();
var result = new TaskParameterEventArgs(
TaskParameterMessageKind.TaskInput,
"ItemName",
items,
logItemMetadata: true,
DateTime.MinValue);
result.LineNumber = 30000;
result.ColumnNumber = 50;
// normalize line endings as we can't rely on the line endings of NodePackets_Tests.cs
Assert.Equal(@"Task Parameter:
ItemName=
ItemSpec1
ItemSpec1
a=b
c=d
ItemSpec2
1=1value
2=2value
3=3value".Replace("\r\n", "\n"), result.Message);
return result;
}
private static TargetSkippedEventArgs CreateTargetSkipped()
{
var result = new TargetSkippedEventArgs(message: null)
{
BuildReason = TargetBuiltReason.DependsOn,
SkipReason = TargetSkipReason.PreviouslyBuiltSuccessfully,
BuildEventContext = CreateBuildEventContext(),
OriginalBuildEventContext = CreateBuildEventContext(),
Condition = "$(Condition) == 'true'",
EvaluatedCondition = "'true' == 'true'",
Importance = MessageImportance.Normal,
OriginallySucceeded = true,
ProjectFile = "1.proj",
TargetFile = "1.proj",
TargetName = "Build",
ParentTarget = "ParentTarget"
};
return result;
}
/// <summary>
/// Tests serialization of LogMessagePacket with each kind of event type.
/// </summary>
[Fact]
public void TestTranslation()
{
// need to touch the type so that the static constructor runs
_ = ItemGroupLoggingHelper.OutputItemParameterMessagePrefix;
TaskItem item = new TaskItem("Hello", "my.proj");
List<TaskItem> targetOutputs = new List<TaskItem>();
targetOutputs.Add(item);
string _initialTargetOutputLogging = Environment.GetEnvironmentVariable("MSBUILDTARGETOUTPUTLOGGING");
Environment.SetEnvironmentVariable("MSBUILDTARGETOUTPUTLOGGING", "1");
try
{
BuildEventArgs[] testArgs = new BuildEventArgs[]
{
new ResponseFileUsedEventArgs("path"),
new UninitializedPropertyReadEventArgs("prop", "message", "help", "sender", MessageImportance.Normal),
new EnvironmentVariableReadEventArgs("env", "message", "help", "sender", MessageImportance.Normal) { BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6) },
new PropertyReassignmentEventArgs("prop", "prevValue", "newValue", "loc", "message", "help", "sender", MessageImportance.Normal),
new PropertyInitialValueSetEventArgs("prop", "val", "propsource", "message", "help", "sender", MessageImportance.Normal),
new MetaprojectGeneratedEventArgs("metaName", "path", "message"),
new CriticalBuildMessageEventArgs("Subcategory", "Code", "File", 1, 2, 3, 4, "{0}", "HelpKeyword", "Sender", DateTime.Now, "arg1"),
new BuildFinishedEventArgs("Message", "Keyword", true),
new BuildStartedEventArgs("Message", "Help"),
new BuildMessageEventArgs("Message", "help", "sender", MessageImportance.Low),
new TaskStartedEventArgs("message", "help", "projectFile", "taskFile", "taskName")
{
LineNumber = 345,
ColumnNumber = 123
},
new TaskFinishedEventArgs("message", "help", "projectFile", "taskFile", "taskName", true),
new TaskCommandLineEventArgs("commandLine", "taskName", MessageImportance.Low),
CreateTaskParameter(),
new BuildWarningEventArgs("SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender"),
new BuildErrorEventArgs("SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender"),
new TargetStartedEventArgs("message", "help", "targetName", "ProjectFile", "targetFile"),
new TargetFinishedEventArgs("message", "help", "targetName", "ProjectFile", "targetFile", true, targetOutputs),
new ProjectStartedEventArgs(-1, "message", "help", "ProjectFile", "targetNames", null, null, null),
new ProjectFinishedEventArgs("message", "help", "ProjectFile", true),
new ExternalProjectStartedEventArgs("message", "help", "senderName", "projectFile", "targetNames"),
new ExternalProjectFinishedEventArgs("message", "help", "senderName", "projectFile", true),
CreateProjectEvaluationStarted(),
CreateProjectEvaluationFinished(),
new AssemblyLoadBuildEventArgs(AssemblyLoadingContext.Evaluation, "init", "aname", "path", Guid.NewGuid(), "domain", MessageImportance.Normal),
CreateTargetSkipped(),
new ExtendedBuildErrorEventArgs("extError", "SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender", DateTime.UtcNow, "arg1")
{
ExtendedData = "{'long-json':'mostly-strings'}",
ExtendedMetadata = new Dictionary<string, string> { { "m1", "v1" }, { "m2", "v2" } },
BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6, 7)
},
new ExtendedBuildWarningEventArgs("extWarn", "SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender", DateTime.UtcNow, "arg1")
{
ExtendedData = "{'long-json':'mostly-strings'}",
ExtendedMetadata = new Dictionary<string, string> { { "m1", "v1" }, { "m2", "v2" } },
BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6, 7)
},
new ExtendedBuildMessageEventArgs("extWarn", "SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender", MessageImportance.Normal, DateTime.UtcNow, "arg1")
{
ExtendedData = "{'long-json':'mostly-strings'}",
ExtendedMetadata = new Dictionary<string, string> { { "m1", "v1" }, { "m2", "v2" } },
BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6, 7)
},
new ExtendedCustomBuildEventArgs("extCustom", "message", "help", "sender", DateTime.UtcNow, "arg1")
{
ExtendedData = "{'long-json':'mostly-strings'}",
ExtendedMetadata = new Dictionary<string, string> { { "m1", "v1" }, { "m2", "v2" } },
BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6, 7)
},
};
foreach (BuildEventArgs arg in testArgs)
{
LogMessagePacket packet = new LogMessagePacket(new KeyValuePair<int, BuildEventArgs>(0, arg));
((ITranslatable)packet).Translate(TranslationHelpers.GetWriteTranslator());
INodePacket tempPacket = LogMessagePacket.FactoryForDeserialization(TranslationHelpers.GetReadTranslator()) as LogMessagePacket;
LogMessagePacket deserializedPacket = tempPacket as LogMessagePacket;
packet.Should().BeEquivalentTo(deserializedPacket, options => options
.RespectingRuntimeTypes());
BuildEventArgs args = packet.NodeBuildEvent?.Value;
BuildEventArgs desArgs = deserializedPacket?.NodeBuildEvent?.Value;
desArgs.Should().BeEquivalentTo(args, options => options
.RespectingRuntimeTypes()
// Since we use struct DictionaryEntry of class TaskItemData, generated DictionaryEntry.Equals compare TaskItemData by references.
// Bellow will instruct equivalency test to not use DictionaryEntry.Equals but its public members for equivalency tests.
.ComparingByMembers<DictionaryEntry>()
.WithTracing(), "Roundtrip deserialization of message type {0} should be equivalent", args.GetType().Name);
}
}
finally
{
Environment.SetEnvironmentVariable("MSBUILDTARGETOUTPUTLOGGING", _initialTargetOutputLogging);
}
}
/// <summary>
/// Verify the LoggingMessagePacket is properly created from a build event.
/// This includes the packet type and the event type depending on which build event arg is passed in.
/// </summary>
/// <param name="buildEvent">Build event to put into a packet, and verify after packet creation</param>
/// <param name="logEventType">What is the expected logging event type</param>
private static void VerifyLoggingPacket(BuildEventArgs buildEvent, LoggingEventType logEventType)
{
LogMessagePacket packet = new LogMessagePacket(new KeyValuePair<int, BuildEventArgs>(0, buildEvent));
Assert.Equal(logEventType, packet.EventType);
Assert.Equal(NodePacketType.LogMessage, packet.Type);
Assert.True(Object.ReferenceEquals(buildEvent, packet.NodeBuildEvent.Value.Value)); // "Expected buildEvent to have the same object reference as packet.BuildEvent"
}
#endregion
}
}