|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable disable
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.UnitTests
{
public class CorLibTypesAndConstantTests : TestBase
{
[Fact]
public void IntegrityTest()
{
for (int i = 1; i < (int)InternalSpecialType.NextAvailable; i++)
{
string name = SpecialTypes.GetMetadataName((ExtendedSpecialType)i);
Assert.Equal((ExtendedSpecialType)i, SpecialTypes.GetTypeFromMetadataName(name));
}
for (int i = 0; i <= (int)SpecialType.Count; i++)
{
Cci.PrimitiveTypeCode code = SpecialTypes.GetTypeCode((SpecialType)i);
if (code != Cci.PrimitiveTypeCode.NotPrimitive)
{
Assert.Equal((SpecialType)i, SpecialTypes.GetTypeFromMetadataName(code));
}
}
for (int i = 0; i <= (int)Cci.PrimitiveTypeCode.Invalid; i++)
{
SpecialType id = SpecialTypes.GetTypeFromMetadataName((Cci.PrimitiveTypeCode)i);
if (id != SpecialType.None)
{
Assert.Equal((Cci.PrimitiveTypeCode)i, SpecialTypes.GetTypeCode(id));
}
}
Assert.Equal(SpecialType.System_Boolean, SpecialTypes.GetTypeFromMetadataName(Cci.PrimitiveTypeCode.Boolean));
Assert.Equal(SpecialType.System_Char, SpecialTypes.GetTypeFromMetadataName(Cci.PrimitiveTypeCode.Char));
Assert.Equal(SpecialType.System_Void, SpecialTypes.GetTypeFromMetadataName(Cci.PrimitiveTypeCode.Void));
Assert.Equal(SpecialType.System_String, SpecialTypes.GetTypeFromMetadataName(Cci.PrimitiveTypeCode.String));
Assert.Equal(SpecialType.System_Int64, SpecialTypes.GetTypeFromMetadataName(Cci.PrimitiveTypeCode.Int64));
Assert.Equal(SpecialType.System_Int32, SpecialTypes.GetTypeFromMetadataName(Cci.PrimitiveTypeCode.Int32));
Assert.Equal(SpecialType.System_Int16, SpecialTypes.GetTypeFromMetadataName(Cci.PrimitiveTypeCode.Int16));
Assert.Equal(SpecialType.System_SByte, SpecialTypes.GetTypeFromMetadataName(Cci.PrimitiveTypeCode.Int8));
Assert.Equal(SpecialType.System_UInt64, SpecialTypes.GetTypeFromMetadataName(Cci.PrimitiveTypeCode.UInt64));
Assert.Equal(SpecialType.System_UInt32, SpecialTypes.GetTypeFromMetadataName(Cci.PrimitiveTypeCode.UInt32));
Assert.Equal(SpecialType.System_UInt16, SpecialTypes.GetTypeFromMetadataName(Cci.PrimitiveTypeCode.UInt16));
Assert.Equal(SpecialType.System_Byte, SpecialTypes.GetTypeFromMetadataName(Cci.PrimitiveTypeCode.UInt8));
Assert.Equal(SpecialType.System_Single, SpecialTypes.GetTypeFromMetadataName(Cci.PrimitiveTypeCode.Float32));
Assert.Equal(SpecialType.System_Double, SpecialTypes.GetTypeFromMetadataName(Cci.PrimitiveTypeCode.Float64));
Assert.Equal(SpecialType.System_IntPtr, SpecialTypes.GetTypeFromMetadataName(Cci.PrimitiveTypeCode.IntPtr));
Assert.Equal(SpecialType.System_UIntPtr, SpecialTypes.GetTypeFromMetadataName(Cci.PrimitiveTypeCode.UIntPtr));
}
[Fact]
public void SpecialTypeIsValueType()
{
var comp = CSharp.CSharpCompilation.Create(
"c",
options: new CSharp.CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, warningLevel: CodeAnalysis.Diagnostic.MaxWarningLevel),
references: new[] { NetCoreApp.SystemRuntime });
var knownMissingTypes = new HashSet<SpecialType>()
{
SpecialType.System_Runtime_CompilerServices_InlineArrayAttribute
};
for (var specialType = SpecialType.None + 1; specialType <= SpecialType.Count; specialType++)
{
var symbol = comp.GetSpecialType(specialType);
if (knownMissingTypes.Contains(specialType))
{
Assert.Equal(SymbolKind.ErrorType, symbol.Kind);
}
else
{
Assert.NotEqual(SymbolKind.ErrorType, symbol.Kind);
Assert.Equal(symbol.IsValueType, specialType.IsValueType());
}
}
}
[Fact]
public void ConstantValueInvalidOperationTest01()
{
Assert.Throws<InvalidOperationException>(() => { ConstantValue.Create(null, ConstantValueTypeDiscriminator.Bad); });
var cv1 = ConstantValue.Create(1);
Assert.Throws<InvalidOperationException>(() => { var c = cv1.StringValue; });
Assert.Throws<InvalidOperationException>(() => { var c = cv1.DateTimeValue; });
var cv2 = ConstantValue.Create(2);
Assert.Throws<InvalidOperationException>(() => { var c = cv2.StringValue; });
Assert.Throws<InvalidOperationException>(() => { var c = cv2.CharValue; });
Assert.Throws<InvalidOperationException>(() => { var c = cv2.DateTimeValue; });
var cvNull = ConstantValue.Create(null, ConstantValueTypeDiscriminator.Null);
Assert.Throws<InvalidOperationException>(() => { var c = cvNull.BooleanValue; });
Assert.Throws<InvalidOperationException>(() => { var c = cvNull.DecimalValue; });
Assert.Throws<InvalidOperationException>(() => { var c = cvNull.DoubleValue; });
Assert.Throws<InvalidOperationException>(() => { var c = cvNull.SingleValue; });
Assert.Throws<InvalidOperationException>(() => { var c = cvNull.SByteValue; });
Assert.Throws<InvalidOperationException>(() => { var c = cvNull.ByteValue; });
}
[Fact]
public void ConstantValueOneTest01()
{
var cv1 = ConstantValue.Create(1);
Assert.True(cv1.IsOne);
Assert.Equal(1, cv1.ByteValue);
Assert.Equal(1, cv1.SByteValue);
Assert.True(cv1.BooleanValue);
Assert.Equal(1, cv1.DoubleValue);
Assert.Equal(1, cv1.SingleValue);
Assert.Equal(1, cv1.DecimalValue);
Assert.Equal(1, cv1.Int16Value);
Assert.Equal(1, cv1.UInt16Value);
Assert.Equal(1, cv1.Int32Value);
Assert.Equal(1U, cv1.UInt32Value);
Assert.Equal(1, cv1.Int64Value);
Assert.Equal(1U, cv1.UInt64Value);
Assert.Equal(1, cv1.CharValue);
}
[Fact]
public void ConstantValueOneTest02()
{
Assert.True(ConstantValue.Create((byte)1).IsOne);
Assert.True(ConstantValue.Create((sbyte)1).IsOne);
Assert.True(ConstantValue.Create(true).IsOne);
Assert.True(ConstantValue.Create((double)1).IsOne);
Assert.True(ConstantValue.Create((float)1).IsOne);
Assert.True(ConstantValue.Create((decimal)1).IsOne);
Assert.True(ConstantValue.Create((short)1).IsOne);
Assert.True(ConstantValue.Create((ushort)1).IsOne);
Assert.True(ConstantValue.Create((int)1).IsOne);
Assert.True(ConstantValue.Create((uint)1).IsOne);
Assert.True(ConstantValue.Create((long)1).IsOne);
Assert.True(ConstantValue.Create((ulong)1).IsOne);
Assert.True(ConstantValue.Create((char)1).IsOne);
}
[Fact]
public void ConstantValuePropertiesTest01()
{
Assert.Equal(ConstantValue.Bad, ConstantValue.Default(ConstantValueTypeDiscriminator.Bad));
var cv1 = ConstantValue.Create((sbyte)-1);
Assert.True(cv1.IsNegativeNumeric);
var cv2 = ConstantValue.Create(-0.12345f);
Assert.True(cv2.IsNegativeNumeric);
var cv3 = ConstantValue.Create((double)-1.234);
Assert.True(cv3.IsNegativeNumeric);
var cv4 = ConstantValue.Create((decimal)-12345m);
Assert.True(cv4.IsNegativeNumeric);
Assert.False(cv4.IsDateTime);
var cv5 = ConstantValue.Create(null);
Assert.False(cv5.IsNumeric);
Assert.False(cv5.IsBoolean);
Assert.False(cv5.IsFloating);
}
[Fact]
public void ConstantValueGetHashCodeTest01()
{
var cv11 = ConstantValue.Create((sbyte)-1);
var cv12 = ConstantValue.Create((sbyte)-1);
Assert.Equal(cv11.GetHashCode(), cv12.GetHashCode());
var cv21 = ConstantValue.Create((byte)255);
var cv22 = ConstantValue.Create((byte)255);
Assert.Equal(cv21.GetHashCode(), cv22.GetHashCode());
var cv31 = ConstantValue.Create((short)-32768);
var cv32 = ConstantValue.Create((short)-32768);
Assert.Equal(cv31.GetHashCode(), cv32.GetHashCode());
var cv41 = ConstantValue.Create((ushort)65535);
var cv42 = ConstantValue.Create((ushort)65535);
Assert.Equal(cv41.GetHashCode(), cv42.GetHashCode());
// int
var cv51 = ConstantValue.Create(12345);
var cv52 = ConstantValue.Create(12345);
Assert.Equal(cv51.GetHashCode(), cv52.GetHashCode());
var cv61 = ConstantValue.Create(uint.MinValue);
var cv62 = ConstantValue.Create(uint.MinValue);
Assert.Equal(cv61.GetHashCode(), cv62.GetHashCode());
var cv71 = ConstantValue.Create(long.MaxValue);
var cv72 = ConstantValue.Create(long.MaxValue);
Assert.Equal(cv71.GetHashCode(), cv72.GetHashCode());
var cv81 = ConstantValue.Create((ulong)123456789);
var cv82 = ConstantValue.Create((ulong)123456789);
Assert.Equal(cv81.GetHashCode(), cv82.GetHashCode());
var cv91 = ConstantValue.Create(1.1m);
var cv92 = ConstantValue.Create(1.1m);
Assert.Equal(cv91.GetHashCode(), cv92.GetHashCode());
}
// In general, different values are not required to have different hash codes.
// But for perf reasons we want hash functions with a good distribution,
// so we expect hash codes to differ if a single component is incremented.
// But program correctness should be preserved even with a null hash function,
// so we need a way to disable these tests during such correctness validation.
#if !DISABLE_GOOD_HASH_TESTS
[Fact]
public void ConstantValueGetHashCodeTest02()
{
var cv1 = ConstantValue.Create("1");
var cv2 = ConstantValue.Create("2");
Assert.NotEqual(cv1.GetHashCode(), cv2.GetHashCode());
}
#endif
[Fact]
public void ConstantValueToStringTest01()
{
string value = (RuntimeUtilities.IsCoreClrRuntime && !RuntimeUtilities.IsCoreClr6Runtime)
? "Nothing"
: "Null";
var cv = ConstantValue.Create(null, ConstantValueTypeDiscriminator.Null);
Assert.Equal($"ConstantValueNull(null: {value})", cv.ToString());
cv = ConstantValue.Create(null, ConstantValueTypeDiscriminator.String);
Assert.Equal($"ConstantValueNull(null: {value})", cv.ToString());
// Never hit "ConstantValueString(null: Null)"
var strVal = "QC";
cv = ConstantValue.Create(strVal);
Assert.Equal(@"ConstantValueString(""QC"": String)", cv.ToString());
cv = ConstantValue.Create((sbyte)-128);
Assert.Equal("ConstantValueI8(-128: SByte)", cv.ToString());
cv = ConstantValue.Create((ulong)123456789);
Assert.Equal("ConstantValueI64(123456789: UInt64)", cv.ToString());
}
}
}
|