Skip to content

Commit

Permalink
Add tests for OperatorResolution
Browse files Browse the repository at this point in the history
  • Loading branch information
exyi committed Jul 1, 2023
1 parent 0b13809 commit 168d21a
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 5 deletions.
10 changes: 10 additions & 0 deletions src/Framework/Framework/Compilation/Binding/OperatorResolution.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ public static Expression GetBinaryOperator(
right = Expression.Constant(null, left.Type.MakeNullableType());
}

// lift the other side to null
if (left.Type.IsNullable() && right.Type.IsValueType && !right.Type.IsNullable())
{
right = Expression.Convert(right, right.Type.MakeNullableType());
}
else if (right.Type.IsNullable() && left.Type.IsValueType && !left.Type.IsNullable())
{
left = Expression.Convert(left, left.Type.MakeNullableType());
}

var leftType = left.Type.UnwrapNullableType();
var rightType = right.Type.UnwrapNullableType();

Expand Down
22 changes: 22 additions & 0 deletions src/Tests/Binding/BindingCompilationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,22 @@ public void Error_DifferentDataContext()
);
}

[DataTestMethod]
[DataRow("IntProp + 1L", 101L)]
[DataRow("1L + IntProp", 101L)]
[DataRow("1L + UIntProp", 3_000_000_001L)]
[DataRow("1 + UIntProp", (uint)3_000_000_001)]
[DataRow("ShortProp", short.MaxValue)]
[DataRow("ShortProp - 1", short.MaxValue - 1)]
[DataRow("DoubleProp - 1", 0.5)]
[DataRow("DoubleProp + ShortProp", short.MaxValue + 1.5)]
[DataRow("NullableDoubleProp + ShortProp", null)]
public void BindingCompiler_OperatorType(string expr, object expectedResult)
{
var vm = new TestViewModel { IntProp = 100, DoubleProp = 1.5 };
Assert.AreEqual(expectedResult, ExecuteBinding(expr, vm));
}
>>>>>>> ba2cf6708 (Add tests for OperatorResolution)
}
class TestViewModel
{
Expand Down Expand Up @@ -1147,6 +1163,12 @@ class TestViewModel
public TestViewModel2[] VmArray => new TestViewModel2[] { new TestViewModel2() };
public int[] IntArray { get; set; }
public decimal DecimalProp { get; set; }
public byte ByteProp { get; set; } = 255;
public sbyte SByteProp { get; set; } = 127;
public short ShortProp { get; set; } = 32767;
public ushort UShortProp { get; set; } = 65535;
public uint UIntProp { get; set; } = 3_000_000_000;
public double? NullableDoubleProp { get; set; }

public ReadOnlyCollection<int> ReadOnlyCollection => new ReadOnlyCollection<int>(new[] { 1, 2, 3 });

Expand Down
56 changes: 51 additions & 5 deletions src/Tests/Binding/JavascriptCompilationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,57 @@ public string CompileBinding(Func<Dictionary<string, Expression>, Expression> ex
return JavascriptTranslator.FormatKnockoutScript(jsExpression);
}

[TestMethod]
public void JavascriptCompilation_EnumComparison()
{
var js = CompileBinding($"_this == 'Local'", typeof(DateTimeKind));
Assert.AreEqual("$data==\"Local\"", js);
[DataTestMethod]
[DataRow("_this == 'Local'", "$data==\"Local\"")]
[DataRow("'Local' == _this", "\"Local\"==$data")]
[DataRow("_this == 2", "$data==\"Local\"")]
[DataRow("2 == _this", "\"Local\"==$data")]
[DataRow("_this & 'Local'", "dotvvm.translations.enums.fromInt(dotvvm.translations.enums.toInt($data,\"G0/GAE51KlQlMR5T\")&2,\"G0/GAE51KlQlMR5T\")")]
[DataRow("'Local' & _this", "dotvvm.translations.enums.fromInt(2&dotvvm.translations.enums.toInt($data,\"G0/GAE51KlQlMR5T\"),\"G0/GAE51KlQlMR5T\")")]
[DataRow("_this | 'Local'", "dotvvm.translations.enums.fromInt(dotvvm.translations.enums.toInt($data,\"G0/GAE51KlQlMR5T\")|2,\"G0/GAE51KlQlMR5T\")")]
[DataRow("_this & 1", "dotvvm.translations.enums.fromInt(dotvvm.translations.enums.toInt($data,\"G0/GAE51KlQlMR5T\")&1,\"G0/GAE51KlQlMR5T\")")]
[DataRow("1 & _this", "dotvvm.translations.enums.fromInt(1&dotvvm.translations.enums.toInt($data,\"G0/GAE51KlQlMR5T\"),\"G0/GAE51KlQlMR5T\")")]
public void JavascriptCompilation_EnumOperators(string expr, string expectedJs)
{
var js = CompileBinding(expr, typeof(DateTimeKind));
Assert.AreEqual(expectedJs, js);
}

[DataTestMethod]
[DataRow("StringProp + StringProp", "(StringProp()??\"\")+(StringProp()??\"\")")]
[DataRow("StringProp + null", "StringProp()??\"\"")]
[DataRow("null + StringProp", "StringProp()??\"\"")]
[DataRow("'' + StringProp", "StringProp()??\"\"")]
[DataRow("BoolProp + StringProp", "BoolProp()+(StringProp()??\"\")")]
[DataRow("IntProp + IntProp + 'aa'", "IntProp()+IntProp()+\"aa\"")]
[DataRow("DoubleProp + 'aa'", "DoubleProp()+\"aa\"")]
[DataRow("'a' + DoubleProp", "\"a\"+DoubleProp()")]
[DataRow("'a' + NullableIntProp + null", "\"a\"+(NullableIntProp()??\"\")")]
public void JavascriptCompilation_StringPlus(string expr, string expectedJs)
{
var js = CompileBinding(expr, typeof(TestViewModel));
Assert.AreEqual(expectedJs, js);
}

[DataTestMethod]
[DataRow("NullableIntProp + NullableDoubleProp", "NullableIntProp()+NullableDoubleProp()")]
[DataRow("NullableIntProp & NullableIntProp", "NullableIntProp()&NullableIntProp()")]
[DataRow("NullableIntProp | NullableIntProp", "NullableIntProp()|NullableIntProp()")]
[DataRow("NullableIntProp ^ NullableIntProp", "NullableIntProp()^NullableIntProp()")]
[DataRow("NullableIntProp + 10", "NullableIntProp()+10")]
[DataRow("NullableIntProp - 10L", "NullableIntProp()-10")]
[DataRow("NullableIntProp / 10.0", "NullableIntProp()/10.0")]
[DataRow("10.0 / NullableIntProp", "10.0/NullableIntProp()")]
[DataRow("null / NullableIntProp", "null/NullableIntProp()")]
[DataRow("null == NullableIntProp", "null==NullableIntProp()")]
[DataRow("10 > NullableIntProp", "10>NullableIntProp()")]
[DataRow("NullableDoubleProp < 10", "NullableDoubleProp()<10")]
[DataRow("10+null", "10+null")]
[DataRow("10+null", "10+null")]
public void JavascriptCompilation_NullableOps(string expr, string expectedJs)
{
var js = CompileBinding(expr, typeof(TestViewModel));
Assert.AreEqual(expectedJs, js);
}

[TestMethod]
Expand Down

0 comments on commit 168d21a

Please sign in to comment.