Skip to content

Commit

Permalink
SE - Nullable: Add UT for conversions (#6857)
Browse files Browse the repository at this point in the history
  • Loading branch information
pavel-mikula-sonarsource committed Apr 4, 2023
1 parent 4880c1b commit 8e8949f
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ protected override IConversionOperationWrapper Convert(IOperation operation) =>
operation.ToConversion();

protected override ProgramState Process(SymbolicContext context, IConversionOperationWrapper conversion) =>
context.State[conversion.Operand] is { } value
context.State[conversion.Operand] is { } value && conversion.OperatorMethod is null // Built-in conversions only
? context.State.SetOperationValue(context.Operation, value)
: context.State;
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,25 @@ public void Nullable_Ctor_Argument_PropagateConstraints()
validator.ValidateTag("IsFalse", x => x.AllConstraints.Select(x => x.Kind).Should().BeEquivalentTo(new[] { ConstraintKind.ObjectNotNull, ConstraintKind.BoolFalse, (ConstraintKind)ConstraintKindTest.First }));
validator.ValidateTag("IsInt", x => x.AllConstraints.Select(x => x.Kind).Should().BeEquivalentTo(new[] { ConstraintKind.ObjectNotNull }));
}

[TestMethod]
public void Nullable_Conversion_PropagateConstraints()
{
const string code = """
var isTrue = true;
bool? toNullableImplicit = isTrue;
bool? toNullableExplicit = (bool?)isTrue;
bool? toNullableAs = isTrue as bool?;
bool toBoolExplicit = (bool)toNullableImplicit;
Tag("ToNullableImplicit", toNullableImplicit);
Tag("ToNullableExplicit", toNullableExplicit);
Tag("ToNullableAs", toNullableAs);
Tag("ToBoolExplicit", toBoolExplicit);
""";
var validator = SETestContext.CreateCS(code).Validator;
validator.ValidateTag("ToNullableImplicit", x => x.HasConstraint(BoolConstraint.True).Should().BeTrue());
validator.ValidateTag("ToNullableExplicit", x => x.HasConstraint(BoolConstraint.True).Should().BeTrue());
validator.ValidateTag("ToNullableAs", x => x.HasConstraint(BoolConstraint.True).Should().BeTrue());
validator.ValidateTag("ToBoolExplicit", x => x.HasConstraint(BoolConstraint.True).Should().BeTrue());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,66 @@ public void Conversion_ToLocalVariable_FromLiteral_ImplicitCast()
validator.ValidateTag("b", x => x.HasConstraint(DummyConstraint.Dummy).Should().BeTrue());
}

[DataTestMethod]
[DataRow("Int16")]
[DataRow("Int32")]
[DataRow("Int64")]
[DataRow("decimal")]
[DataRow("float")]
[DataRow("double")]
public void Conversion_BuiltInConversion_PropagateState(string type)
{
var code = $"""
byte b = 42;
{type} value = b;
Tag("Value", value);
""";
SETestContext.CreateCS(code, new LiteralDummyTestCheck()).Validator.ValidateTag("Value", x => x.HasConstraint(DummyConstraint.Dummy).Should().BeTrue());
}

[TestMethod]
public void Conversion_CustomOperators_DoNotPropagateState()
{
const string code = """
public void Main()
{
var isTrue = true;
WithImplicit withImplicit = isTrue;
WithExplicit withExplicit = (WithExplicit)isTrue;
Tag("WithImplicit", withImplicit);
Tag("WithExplicit", withExplicit);
}
public struct WithImplicit
{
public static implicit operator WithImplicit(bool b) => new();
}
public struct WithExplicit
{
public static explicit operator WithExplicit(bool b) => new();
}
""";
var validator = SETestContext.CreateCSMethod(code, new LiteralDummyTestCheck()).Validator;
validator.ValidateTag("WithImplicit", x => x.Should().BeNull());
validator.ValidateTag("WithExplicit", x => x.Should().BeNull());
}

#if NET

[TestMethod]
public void Conversion_CustomOperators_DoNotPropagateState_Half()
{
const string code = """
byte b = 42;
Half h = b;
Tag("Half", h);
""";
var validator = SETestContext.CreateCS(code, new LiteralDummyTestCheck()).Validator;
validator.ValidateTag("Half", x => x.Should().BeNull()); // While it would be better to propagate constraints here, Half has custom conversion operators
}

#endif

[TestMethod]
public void Argument_Ref_ResetsConstraints_CS() =>
SETestContext.CreateCS(@"var b = true; Main(boolParameter, ref b); Tag(""B"", b);", ", ref bool outParam").Validator.ValidateTag("B", x => x.Should().BeNull());
Expand Down

0 comments on commit 8e8949f

Please sign in to comment.