Skip to content

Commit

Permalink
SE - Nullable: Add UTs for Debug.Assert (#6956)
Browse files Browse the repository at this point in the history
  • Loading branch information
pavel-mikula-sonarsource committed Mar 28, 2023
1 parent afcfd16 commit 41cc7cf
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ private static ProgramState ProcessAssertedBoolSymbol(ProgramState state, IOpera
else
{
return operation.TrackedSymbol() is { } symbol
? state.SetSymbolConstraint(symbol, BoolConstraint.From(!isNegated))
? state.SetSymbolConstraint(symbol, BoolConstraint.From(!isNegated)).SetSymbolConstraint(symbol, ObjectConstraint.NotNull)
: state;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -750,15 +750,30 @@ public void Invocation_InformationIsNothing_NoTrackedSymbol()
}

[DataTestMethod]
[DataRow("arg != null")]
[DataRow("arg is not null")]
[DataRow("arg is { }")]
public void Invocation_DebugAssert_LearnsNotNull_Simple(string expression) =>
DebugAssertValues(expression).Should().HaveCount(1).And.ContainSingle(x => x.HasConstraint(ObjectConstraint.NotNull));
[DataRow("arg is not true", "bool?")]
[DataRow("arg is not false", "bool?")]
[DataRow("arg is not 42", "object")]
[DataRow("arg is not { Length: 0 }", "string")]
[DataRow("arg.GetValueOrDefault()", "bool?")]
public void Invocation_DebugAssert_DoesNotLearn(string expression, string argType) =>
DebugAssertValues(expression, argType).Should().SatisfyRespectively(x => x.Should().HaveNoConstraints());

[DataTestMethod]
[DataRow("arg != null", "object")]
[DataRow("arg != null", "int?")]
[DataRow("arg != null", "bool?")]
[DataRow("arg is not null", "object")]
[DataRow("arg is not null", "int?")]
[DataRow("arg is not null", "bool?")]
[DataRow("arg is { }", "object")]
[DataRow("arg is { }", "int?")]
[DataRow("arg is { }", "bool?")]
public void Invocation_DebugAssert_LearnsNotNull_Simple(string expression, string argType) =>
DebugAssertValues(expression, argType).Should().SatisfyRespectively(x => x.Should().HaveOnlyConstraint(ObjectConstraint.NotNull));

[TestMethod]
public void Invocation_DebugAssert_LearnsNotNull_AndAlso() =>
DebugAssertValues("arg != null && condition").Should().HaveCount(1).And.ContainSingle(x => x.HasConstraint(ObjectConstraint.NotNull));
DebugAssertValues("arg != null && condition").Should().SatisfyRespectively(x => x.Should().HaveOnlyConstraint(ObjectConstraint.NotNull));

[TestMethod]
public void Invocation_DebugAssert_LearnsNotNullForAll_AndAlso()
Expand All @@ -768,24 +783,30 @@ public void Invocation_DebugAssert_LearnsNotNullForAll_AndAlso()
Tag(""Arg1"", arg1);
Tag(""Arg2"", arg2);";
var validator = SETestContext.CreateCS(code, $", object arg1, object arg2").Validator;
validator.ValidateTag("Arg1", x => x.HasConstraint(ObjectConstraint.NotNull).Should().BeTrue());
validator.ValidateTag("Arg2", x => x.HasConstraint(ObjectConstraint.NotNull).Should().BeTrue());
validator.ValidateTag("Arg1", x => x.Should().HaveOnlyConstraint(ObjectConstraint.NotNull));
validator.ValidateTag("Arg2", x => x.Should().HaveOnlyConstraint(ObjectConstraint.NotNull));
}

[TestMethod]
public void Invocation_DebugAssert_LearnsNotNull_OrElse() =>
DebugAssertValues("arg != null || condition").Should().HaveCount(2)
.And.ContainSingle(x => x != null && x.HasConstraint(ObjectConstraint.Null))
.And.ContainSingle(x => x != null && x.HasConstraint(ObjectConstraint.NotNull));
DebugAssertValues("arg != null || condition").Should().SatisfyRespectively(
x => x.Should().HaveOnlyConstraint(ObjectConstraint.NotNull),
x => x.Should().HaveOnlyConstraint(ObjectConstraint.Null));

[TestMethod]
public void Invocation_DebugAssert_LearnsBoolConstraint_Simple() =>
DebugAssertValues("arg", "bool").Should().HaveCount(1).And.ContainSingle(x => x.HasConstraint(BoolConstraint.True));
DebugAssertValues("arg", "bool").Should().SatisfyRespectively(x => x.Should().HaveOnlyConstraints(BoolConstraint.True, ObjectConstraint.NotNull));

[TestMethod]
public void Invocation_DebugAssert_LearnsBoolConstraint_Binary() =>
DebugAssertValues("arg == true", "bool").Should().SatisfyRespectively(x => x.Should().HaveOnlyConstraints(ObjectConstraint.NotNull, BoolConstraint.True));

[DataTestMethod]
[DataRow("arg is true", true)]
[DataRow("arg is false", false)]
public void Invocation_DebugAssert_LearnsBoolConstraint_Nullable(string expression, bool expected) =>
DebugAssertValues(expression, "bool?").Should().SatisfyRespectively(x => x.Should().HaveOnlyConstraints(BoolConstraint.From(expected)));

[TestMethod]
public void Invocation_DebugAssert_LearnsBoolConstraint_AlwaysEnds() =>
DebugAssertValues("false", "bool").Should().BeEmpty();
Expand All @@ -794,7 +815,7 @@ public void Invocation_DebugAssert_LearnsBoolConstraint_AlwaysEnds() =>
[DataRow("!arg")]
[DataRow("!!!arg")]
public void Invocation_DebugAssert_LearnsBoolConstraint_Negated(string expression) =>
DebugAssertValues(expression, "bool").Should().HaveCount(1).And.ContainSingle(x => x.HasConstraint(BoolConstraint.False));
DebugAssertValues(expression, "bool").Should().SatisfyRespectively(x => x.Should().HaveOnlyConstraints(BoolConstraint.False, ObjectConstraint.NotNull));

[TestMethod]
public void Invocation_DebugAssert_CustomNoParameters_DoesNotFail()
Expand Down Expand Up @@ -823,6 +844,18 @@ public static void Assert() { }
new SETestContext(code, AnalyzerLanguage.CSharp, Array.Empty<SymbolicCheck>()).Validator.ValidateTagOrder("End");
}

[DataTestMethod]
[DataRow("int?")]
[DataRow("bool?")]
public void Invocation_DebugAssert_NullableHasValue_Simple(string argType) =>
DebugAssertValues("arg.HasValue", argType).Should().SatisfyRespectively(x => x.Should().HaveOnlyConstraint(ObjectConstraint.NotNull));

[DataTestMethod]
[DataRow("int?")]
[DataRow("bool?")]
public void Invocation_DebugAssert_NullableHasValue_Binary(string argType) =>
DebugAssertValues("arg.HasValue == true", argType).Should().SatisfyRespectively(x => x.Should().HaveOnlyConstraint(ObjectConstraint.NotNull));

private static SymbolicValue[] DebugAssertValues(string expression, string argType = "object")
{
var code = $@"
Expand Down

0 comments on commit 41cc7cf

Please sign in to comment.