ExpressionTest_SubtractChecked.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // Permission is hereby granted, free of charge, to any person obtaining
  2. // a copy of this software and associated documentation files (the
  3. // "Software"), to deal in the Software without restriction, including
  4. // without limitation the rights to use, copy, modify, merge, publish,
  5. // distribute, sublicense, and/or sell copies of the Software, and to
  6. // permit persons to whom the Software is furnished to do so, subject to
  7. // the following conditions:
  8. //
  9. // The above copyright notice and this permission notice shall be
  10. // included in all copies or substantial portions of the Software.
  11. //
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  13. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  14. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  15. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  16. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  17. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  18. //
  19. // Authors:
  20. // Federico Di Gregorio <[email protected]>
  21. using System;
  22. using System.Reflection;
  23. using System.Linq;
  24. using System.Linq.Expressions;
  25. using NUnit.Framework;
  26. namespace MonoTests.System.Linq.Expressions
  27. {
  28. [TestFixture]
  29. [Category("SRE")]
  30. public class ExpressionTest_SubtractChecked
  31. {
  32. [Test]
  33. [ExpectedException (typeof (ArgumentNullException))]
  34. public void Arg1Null ()
  35. {
  36. Expression.SubtractChecked (null, Expression.Constant(1));
  37. }
  38. [Test]
  39. [ExpectedException (typeof (ArgumentNullException))]
  40. public void Arg2Null ()
  41. {
  42. Expression.SubtractChecked (Expression.Constant (1), null);
  43. }
  44. [Test]
  45. [ExpectedException (typeof (InvalidOperationException))]
  46. public void ArgTypesDifferent ()
  47. {
  48. Expression.SubtractChecked (Expression.Constant (1), Expression.Constant (2.0));
  49. }
  50. [Test]
  51. [ExpectedException (typeof (InvalidOperationException))]
  52. public void NoOperatorClass ()
  53. {
  54. Expression.SubtractChecked (Expression.Constant (new NoOpClass ()), Expression.Constant (new NoOpClass ()));
  55. }
  56. [Test]
  57. [ExpectedException (typeof (InvalidOperationException))]
  58. public void Boolean ()
  59. {
  60. Expression.SubtractChecked (Expression.Constant (true), Expression.Constant (false));
  61. }
  62. [Test]
  63. public void Numeric ()
  64. {
  65. BinaryExpression expr = Expression.SubtractChecked (Expression.Constant (1), Expression.Constant (2));
  66. Assert.AreEqual (ExpressionType.SubtractChecked, expr.NodeType, "SubtractChecked#01");
  67. Assert.AreEqual (typeof (int), expr.Type, "SubtractChecked#02");
  68. Assert.IsNull (expr.Method, "SubtractChecked#03");
  69. Assert.AreEqual ("(1 - 2)", expr.ToString(), "SubtractChecked#15");
  70. }
  71. [Test]
  72. public void Nullable ()
  73. {
  74. int? a = 1;
  75. int? b = 2;
  76. BinaryExpression expr = Expression.SubtractChecked (Expression.Constant (a), Expression.Constant (b));
  77. Assert.AreEqual (ExpressionType.SubtractChecked, expr.NodeType, "SubtractChecked#04");
  78. Assert.AreEqual (typeof (int), expr.Type, "SubtractChecked#05");
  79. Assert.IsNull (expr.Method, null, "SubtractChecked#06");
  80. Assert.AreEqual ("(1 - 2)", expr.ToString(), "SubtractChecked#16");
  81. }
  82. [Test]
  83. public void UserDefinedClass ()
  84. {
  85. // We can use the simplest version of GetMethod because we already know only one
  86. // exists in the very simple class we're using for the tests.
  87. MethodInfo mi = typeof (OpClass).GetMethod ("op_Subtraction");
  88. BinaryExpression expr = Expression.SubtractChecked (Expression.Constant (new OpClass ()), Expression.Constant (new OpClass ()));
  89. Assert.AreEqual (ExpressionType.SubtractChecked, expr.NodeType, "SubtractChecked#07");
  90. Assert.AreEqual (typeof (OpClass), expr.Type, "SubtractChecked#08");
  91. Assert.AreEqual (mi, expr.Method, "SubtractChecked#09");
  92. Assert.AreEqual ("op_Subtraction", expr.Method.Name, "SubtractChecked#10");
  93. Assert.AreEqual ("(value(MonoTests.System.Linq.Expressions.OpClass) - value(MonoTests.System.Linq.Expressions.OpClass))",
  94. expr.ToString(), "SubtractChecked#17");
  95. }
  96. [Test]
  97. public void UserDefinedStruct ()
  98. {
  99. // We can use the simplest version of GetMethod because we already know only one
  100. // exists in the very simple class we're using for the tests.
  101. MethodInfo mi = typeof (OpStruct).GetMethod ("op_Subtraction");
  102. BinaryExpression expr = Expression.SubtractChecked (Expression.Constant (new OpStruct ()), Expression.Constant (new OpStruct ()));
  103. Assert.AreEqual (ExpressionType.SubtractChecked, expr.NodeType, "SubtractChecked#11");
  104. Assert.AreEqual (typeof (OpStruct), expr.Type, "SubtractChecked#12");
  105. Assert.AreEqual (mi, expr.Method, "SubtractChecked#13");
  106. Assert.AreEqual ("op_Subtraction", expr.Method.Name, "SubtractChecked#14");
  107. Assert.AreEqual ("(value(MonoTests.System.Linq.Expressions.OpStruct) - value(MonoTests.System.Linq.Expressions.OpStruct))",
  108. expr.ToString(), "SubtractChecked#18");
  109. }
  110. //
  111. // This method makes sure that compiling an AddChecked on two values
  112. // throws an OverflowException, if it doesnt, it fails
  113. //
  114. static void MustOverflow<T> (T v1, T v2)
  115. {
  116. Expression<Func<T>> l = Expression.Lambda<Func<T>> (
  117. Expression.SubtractChecked (Expression.Constant (v1), Expression.Constant (v2)));
  118. Func<T> del = l.Compile ();
  119. T res = default (T);
  120. try {
  121. res = del ();
  122. } catch (OverflowException){
  123. // OK
  124. return;
  125. }
  126. throw new Exception (String.Format ("SubtractChecked on {2} should have thrown an exception with values {0} {1}, result was: {3}",
  127. v1, v2, v1.GetType (), res));
  128. }
  129. //
  130. // This routine should execute the code, but not throw an
  131. // overflow exception
  132. //
  133. static void MustNotOverflow<T> (T v1, T v2)
  134. {
  135. Expression<Func<T>> l = Expression.Lambda<Func<T>> (
  136. Expression.SubtractChecked (Expression.Constant (v1), Expression.Constant (v2)));
  137. Func<T> del = l.Compile ();
  138. del ();
  139. }
  140. //
  141. // SubtractChecked is not defined for small types (byte, sbyte)
  142. //
  143. static void InvalidOperation<T> (T v1, T v2)
  144. {
  145. try {
  146. Expression.Lambda<Func<T>> (
  147. Expression.SubtractChecked (Expression.Constant (v1), Expression.Constant (v2)));
  148. } catch (InvalidOperationException){
  149. // OK
  150. return;
  151. }
  152. throw new Exception (String.Format ("SubtractChecked should have thrown for the creation of a tree with {0} operands", v1.GetType ()));
  153. }
  154. [Test]
  155. public void TestOverflows ()
  156. {
  157. // These should overflow, check the various types and codepaths
  158. // in BinaryExpression:
  159. MustOverflow<int> (Int32.MinValue, 1);
  160. MustOverflow<int> (Int32.MaxValue, -1);
  161. MustOverflow<long> (Int64.MinValue, 1);
  162. MustOverflow<long> (Int64.MaxValue, -1);
  163. MustOverflow<ushort> (UInt16.MinValue, 1);
  164. // unsigned values use Sub_Ovf_Un, check that too:
  165. MustOverflow<ulong> (0, 1);
  166. MustOverflow<uint> (0, 1);
  167. }
  168. //
  169. // These should not overflow
  170. //
  171. [Test]
  172. public void TestNoOverflow ()
  173. {
  174. // Simple stuff
  175. MustNotOverflow<int> (10, 20);
  176. // There are invalid:
  177. InvalidOperation<byte> (Byte.MinValue, 1);
  178. InvalidOperation<sbyte> (SByte.MaxValue, 2);
  179. MustNotOverflow<short> (Int16.MaxValue, 2);
  180. MustNotOverflow<ushort> (UInt16.MaxValue, 2);
  181. // Doubles, floats, do not overflow
  182. MustNotOverflow<float> (Single.MaxValue, 1);
  183. MustNotOverflow<double> (Double.MaxValue, 1);
  184. }
  185. }
  186. }