diff --git a/src/Build.UnitTests/Construction/ElementLocation_Tests.cs b/src/Build.UnitTests/Construction/ElementLocation_Tests.cs
index 7a33e0d5343..ce99b967fa5 100644
--- a/src/Build.UnitTests/Construction/ElementLocation_Tests.cs
+++ b/src/Build.UnitTests/Construction/ElementLocation_Tests.cs
@@ -2,9 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Reflection;
+using System.Text;
using System.Xml;
+using System.Xml.Linq;
using Microsoft.Build.BackEnd;
using Microsoft.Build.Construction;
using Microsoft.Build.Exceptions;
@@ -13,442 +17,333 @@
using Microsoft.Build.UnitTests.BackEnd;
using Xunit;
-#nullable disable
+#pragma warning disable CA3075 // Insecure DTD processing in XML
+#pragma warning disable IDE0022 // Use expression body for method
+#pragma warning disable IDE0058 // Expression value is never used
+#pragma warning disable SA1010 // Opening square brackets should be spaced correctly
namespace Microsoft.Build.UnitTests.Construction
{
///
- /// Tests for the ElementLocation class
+ /// Unit tests for .
///
+ [Collection("ElementLocation")]
public class ElementLocation_Tests
{
///
- /// Path to the common targets
+ /// Reset the file path cache index to zero. We have tests which validate that
+ /// returns a specific storage type, and
+ /// that requires the index to be within certain ranges.
///
- private string _pathToCommonTargets =
-#if FEATURE_INSTALLED_MSBUILD
- Path.Combine(FrameworkLocationHelper.PathToDotNetFrameworkV45, "Microsoft.Common.targets");
-#else
- Path.Combine(AppContext.BaseDirectory, "Microsoft.Common.targets");
-#endif
+ public ElementLocation_Tests() => ElementLocation.DangerousInternalResetFileIndex();
- ///
- /// Tests constructor specifying only file.
- ///
- [Fact]
- public void ConstructorTest1()
+ [Theory]
+ [MemberData(nameof(GetCreateTestCases))]
+ public void Create(string? file, int line, int column, string typeName)
{
- IElementLocation location = ElementLocation.Create("file", 65536, 0);
- Assert.Equal("file", location.File);
- Assert.Equal(65536, location.Line);
- Assert.Equal(0, location.Column);
- Assert.Contains("RegularElementLocation", location.GetType().FullName);
- }
+ ElementLocation location = ElementLocation.Create(file, line, column);
- ///
- /// Tests constructor specifying only file.
- ///
- [Fact]
- public void ConstructorTest2()
- {
- IElementLocation location = ElementLocation.Create("file", 0, 65536);
- Assert.Equal("file", location.File);
- Assert.Equal(0, location.Line);
- Assert.Equal(65536, location.Column);
- Assert.Contains("RegularElementLocation", location.GetType().FullName);
- }
+ Assert.Equal(file ?? "", location.File);
+ Assert.Equal(line, location.Line);
+ Assert.Equal(column, location.Column);
- ///
- /// Tests constructor specifying only file.
- ///
- [Fact]
- public void ConstructorTest3()
- {
- IElementLocation location = ElementLocation.Create("file", 65536, 65537);
- Assert.Equal("file", location.File);
- Assert.Equal(65536, location.Line);
- Assert.Equal(65537, location.Column);
- Assert.Contains("RegularElementLocation", location.GetType().FullName);
+ Assert.Contains(typeName, location.GetType().FullName);
}
- ///
- /// Test equality
- ///
- [Fact]
- public void Equality()
+ [Theory]
+ [InlineData("file", -1, 0)]
+ [InlineData("file", 0, -1)]
+ [InlineData("file", int.MaxValue, -1)]
+ [InlineData("file", -1, int.MaxValue)]
+ [InlineData("file", -1, -1)]
+ [InlineData("file", int.MinValue, 0)]
+ [InlineData("file", 0, int.MinValue)]
+ [InlineData("file", int.MinValue, int.MinValue)]
+ public void Create_NegativeValuesThrow(string file, int line, int column)
{
- IElementLocation location1 = ElementLocation.Create("file", 65536, 65537);
- IElementLocation location2 = ElementLocation.Create("file", 0, 1);
- IElementLocation location3 = ElementLocation.Create("file", 0, 65537);
- IElementLocation location4 = ElementLocation.Create("file", 65536, 1);
- IElementLocation location5 = ElementLocation.Create("file", 0, 1);
- IElementLocation location6 = ElementLocation.Create("file", 65536, 65537);
-
- Assert.True(location1.Equals(location6));
- Assert.True(location2.Equals(location5));
- Assert.False(location3.Equals(location1));
- Assert.False(location4.Equals(location2));
- Assert.False(location4.Equals(location6));
+ _ = Assert.Throws(
+ () => ElementLocation.Create(file, line, column));
}
- ///
- /// Check it will use large element location when it should.
- /// Using file as BIZARRELY XmlTextReader+StringReader crops or trims.
- ///
[Fact]
- public void TestLargeElementLocationUsedLargeColumn()
+ public void Create_FileIndexPacking()
{
- string file = null;
-
- try
- {
- file = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
+ int i = 0;
- File.WriteAllText(file, ObjectModelHelpers.CleanupFileContents("\r\n") + new string(' ', 70000) + @"");
-
- ProjectRootElement.Open(file);
- }
- catch (InvalidProjectFileException ex)
+ for (int j = 0; j < ushort.MaxValue; j++)
{
- Assert.Equal(70012, ex.ColumnNumber);
- Assert.Equal(2, ex.LineNumber);
+ Assert.Contains("SmallFileElementLocation", Next());
}
- finally
- {
- File.Delete(file);
- }
- }
-
- ///
- /// Check it will use large element location when it should.
- /// Using file as BIZARRELY XmlTextReader+StringReader crops or trims.
- ///
- [Fact]
- public void TestLargeElementLocationUsedLargeLine()
- {
- string file = null;
- try
- {
- string longstring = String.Empty;
-
- for (int i = 0; i < 7000; i++)
- {
- longstring += "\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n";
- }
-
- file = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
-
- File.WriteAllText(file, ObjectModelHelpers.CleanupFileContents("\r\n") + longstring + @" ");
+ // If the file index exceed 65,535 items, we use a larger storage type.
+ Assert.Contains("LargeFileElementLocation", Next());
- ProjectRootElement.Open(file);
- }
- catch (InvalidProjectFileException ex)
- {
- Assert.Equal(70002, ex.LineNumber);
- Assert.Equal(2, ex.ColumnNumber);
- }
- finally
- {
- File.Delete(file);
- }
+ string? Next() => ElementLocation.Create("file" + i++, 0, 0).GetType().FullName;
}
- ///
- /// Tests serialization.
- ///
[Fact]
- public void SerializationTest()
+ public void Create_NullFile()
{
- IElementLocation location = ElementLocation.Create("file", 65536, 65537);
-
- TranslationHelpers.GetWriteTranslator().Translate(ref location, ElementLocation.FactoryForDeserialization);
- IElementLocation deserializedLocation = null;
- TranslationHelpers.GetReadTranslator().Translate(ref deserializedLocation, ElementLocation.FactoryForDeserialization);
+ ElementLocation location = ElementLocation.Create(null);
- Assert.Equal(location.File, deserializedLocation.File);
- Assert.Equal(location.Line, deserializedLocation.Line);
- Assert.Equal(location.Column, deserializedLocation.Column);
- Assert.Contains("RegularElementLocation", location.GetType().FullName);
+ Assert.Equal("", location.File);
+ Assert.Equal(0, location.Line);
+ Assert.Equal(0, location.Column);
}
- ///
- /// Tests serialization of empty location.
- ///
- [Fact]
- public void SerializationTestForEmptyLocation()
+ [Theory]
+ [MemberData(nameof(GetCreateTestCases))]
+ public void RoundTripSerialisation(string? file, int line, int column, string typeName)
{
- IElementLocation location = ElementLocation.EmptyLocation;
+ ElementLocation location = ElementLocation.Create(file, line, column);
TranslationHelpers.GetWriteTranslator().Translate(ref location, ElementLocation.FactoryForDeserialization);
- IElementLocation deserializedLocation = null;
+ ElementLocation? deserializedLocation = null;
TranslationHelpers.GetReadTranslator().Translate(ref deserializedLocation, ElementLocation.FactoryForDeserialization);
+ Assert.NotNull(deserializedLocation);
- Assert.Equal(location.File, deserializedLocation.File);
- Assert.Equal(location.Line, deserializedLocation.Line);
- Assert.Equal(location.Column, deserializedLocation.Column);
- Assert.Contains("SmallElementLocation", deserializedLocation.GetType().FullName);
- }
+ Assert.Equal(file ?? "", deserializedLocation.File);
+ Assert.Equal(line, deserializedLocation.Line);
+ Assert.Equal(column, deserializedLocation.Column);
- ///
- /// Tests constructor specifying file, line and column.
- ///
- [Fact]
- public void ConstructorWithIndicesTest_SmallElementLocation()
- {
- IElementLocation location = ElementLocation.Create("file", 65535, 65534);
- Assert.Equal("file", location.File);
- Assert.Equal(65535, location.Line);
- Assert.Equal(65534, location.Column);
- Assert.Contains("SmallElementLocation", location.GetType().FullName);
+ Assert.Contains(typeName, deserializedLocation.GetType().FullName);
}
- ///
- /// Tests constructor specifying file, negative line, column
- ///
- [Fact]
- public void ConstructorWithNegativeIndicesTest1()
- {
- Assert.Throws(() =>
- {
- ElementLocation.Create("file", -1, 2);
- });
- }
- ///
- /// Tests constructor specifying file, line, negative column
- ///
- [Fact]
- public void ConstructorWithNegativeIndicesTest2n()
- {
- Assert.Throws(() =>
- {
- ElementLocation.Create("file", 1, -2);
- });
- }
- ///
- /// Tests constructor with invalid null file.
- ///
- [Fact]
- public void ConstructorTestNullFile()
+ public static IEnumerable