|
1 |
| -using CppSharp.AST; |
| 1 | +using CodingSeb.ExpressionEvaluator; |
| 2 | +using CppSharp.AST; |
2 | 3 | using CppSharp.Generators.CSharp;
|
3 | 4 | using CppSharp.Passes;
|
4 | 5 | using NUnit.Framework;
|
| 6 | +using System.Collections; |
| 7 | +using System.Collections.Generic; |
| 8 | +using System.Globalization; |
5 | 9 | using System.Linq;
|
| 10 | +using System.Runtime.CompilerServices; |
| 11 | +using System.Text.RegularExpressions; |
6 | 12 |
|
7 | 13 | namespace CppSharp.Generator.Tests.Passes
|
8 | 14 | {
|
@@ -84,7 +90,7 @@ public void TestCleanCommentsPass()
|
84 | 90 | passBuilder.AddPass(new CleanCommentsPass());
|
85 | 91 | passBuilder.RunPasses(pass => pass.VisitDeclaration(c));
|
86 | 92 |
|
87 |
| - var para = (ParagraphComment) c.Comment.FullComment.Blocks[0]; |
| 93 | + var para = (ParagraphComment)c.Comment.FullComment.Blocks[0]; |
88 | 94 | var textGenerator = new TextGenerator();
|
89 | 95 | textGenerator.Print(para, CommentKind.BCPLSlash);
|
90 | 96 |
|
@@ -135,6 +141,190 @@ public void TestCleanEnumItemNames()
|
135 | 141 | Assert.That(@enum.Items[1].Name, Is.EqualTo("_0"));
|
136 | 142 | }
|
137 | 143 |
|
| 144 | + [Test] |
| 145 | + public void TestEnumBaseTypesFromMacroValues() |
| 146 | + { |
| 147 | + AstContext.GenerateEnumFromMacros("TestEnumMaxSbyte", "TEST_ENUM_MAX_SBYTE"); |
| 148 | + var @enum = AstContext.Enum("TestEnumMaxSbyte"); |
| 149 | + Assert.IsNotNull(@enum); |
| 150 | + Assert.AreEqual(sbyte.MaxValue, @enum.Items[0].Value); |
| 151 | + Assert.AreEqual(PrimitiveType.UChar, @enum.BuiltinType.Type); |
| 152 | + |
| 153 | + AstContext.GenerateEnumFromMacros("TestEnumMaxByte", "TEST_ENUM_MAX_BYTE"); |
| 154 | + @enum = AstContext.Enum("TestEnumMaxByte"); |
| 155 | + Assert.IsNotNull(@enum); |
| 156 | + Assert.AreEqual(byte.MaxValue, @enum.Items[0].Value); |
| 157 | + Assert.AreEqual(PrimitiveType.UChar, @enum.BuiltinType.Type); |
| 158 | + |
| 159 | + AstContext.GenerateEnumFromMacros("TestEnumMaxShort", "TEST_ENUM_MAX_SHORT"); |
| 160 | + @enum = AstContext.Enum("TestEnumMaxShort"); |
| 161 | + Assert.IsNotNull(@enum); |
| 162 | + Assert.AreEqual(short.MaxValue, @enum.Items[0].Value); |
| 163 | + Assert.AreEqual(PrimitiveType.Short, @enum.BuiltinType.Type); |
| 164 | + |
| 165 | + AstContext.GenerateEnumFromMacros("TestEnumMaxUshort", "TEST_ENUM_MAX_USHORT"); |
| 166 | + @enum = AstContext.Enum("TestEnumMaxUshort"); |
| 167 | + Assert.IsNotNull(@enum); |
| 168 | + Assert.AreEqual(ushort.MaxValue, @enum.Items[0].Value); |
| 169 | + Assert.AreEqual(PrimitiveType.UShort, @enum.BuiltinType.Type); |
| 170 | + |
| 171 | + AstContext.GenerateEnumFromMacros("TestEnumMaxInt", "TEST_ENUM_MAX_INT"); |
| 172 | + @enum = AstContext.Enum("TestEnumMaxInt"); |
| 173 | + Assert.IsNotNull(@enum); |
| 174 | + Assert.AreEqual(int.MaxValue, @enum.Items[0].Value); |
| 175 | + Assert.AreEqual(PrimitiveType.Int, @enum.BuiltinType.Type); |
| 176 | + |
| 177 | + AstContext.GenerateEnumFromMacros("TestEnumMaxLong", "TEST_ENUM_MAX_LONG"); |
| 178 | + @enum = AstContext.Enum("TestEnumMaxLong"); |
| 179 | + Assert.IsNotNull(@enum); |
| 180 | + Assert.AreEqual(long.MaxValue, @enum.Items[0].Value); |
| 181 | + Assert.AreEqual(PrimitiveType.LongLong, @enum.BuiltinType.Type); |
| 182 | + |
| 183 | + AstContext.GenerateEnumFromMacros("TestEnumMaxUint", "TEST_ENUM_MAX_UINT"); |
| 184 | + @enum = AstContext.Enum("TestEnumMaxUint"); |
| 185 | + Assert.IsNotNull(@enum); |
| 186 | + Assert.AreEqual(uint.MaxValue, @enum.Items[0].Value); |
| 187 | + Assert.AreEqual(PrimitiveType.UInt, @enum.BuiltinType.Type); |
| 188 | + |
| 189 | + AstContext.GenerateEnumFromMacros("TestEnumMaxUlong", "TEST_ENUM_MAX_ULONG"); |
| 190 | + @enum = AstContext.Enum("TestEnumMaxUlong"); |
| 191 | + Assert.IsNotNull(@enum); |
| 192 | + Assert.AreEqual(ulong.MaxValue, @enum.Items[0].Value); |
| 193 | + Assert.AreEqual(PrimitiveType.ULongLong, @enum.BuiltinType.Type); |
| 194 | + |
| 195 | + AstContext.GenerateEnumFromMacros("TestEnumMinInt", "TEST_ENUM_MIN_INT"); |
| 196 | + @enum = AstContext.Enum("TestEnumMinInt"); |
| 197 | + Assert.IsNotNull(@enum); |
| 198 | + Assert.AreEqual(int.MinValue, (long)@enum.Items[0].Value); |
| 199 | + Assert.AreEqual(PrimitiveType.Int, @enum.BuiltinType.Type); |
| 200 | + |
| 201 | + AstContext.GenerateEnumFromMacros("TestEnumMinLong", "TEST_ENUM_MIN_LONG"); |
| 202 | + @enum = AstContext.Enum("TestEnumMinLong"); |
| 203 | + Assert.IsNotNull(@enum); |
| 204 | + Assert.AreEqual(long.MinValue, (long)@enum.Items[0].Value); |
| 205 | + Assert.AreEqual(PrimitiveType.LongLong, @enum.BuiltinType.Type); |
| 206 | + } |
| 207 | + |
| 208 | + // These tests have nothing to do with testing passes except that the expression evaluator |
| 209 | + // is only used by GenerateEnumFromMacros. Add a separate TestFixture? |
| 210 | + static ExprEvalTestParams[] TestExpressionEvaluatorTestCases = |
| 211 | + { |
| 212 | + new ExprEvalTestParams("2147483647", int.MaxValue), |
| 213 | + new ExprEvalTestParams("-2147483648", int.MinValue), |
| 214 | + new ExprEvalTestParams("4294967295", uint.MaxValue), |
| 215 | + new ExprEvalTestParams("9223372036854775807", long.MaxValue), |
| 216 | + new ExprEvalTestParams("-9223372036854775808", long.MinValue), |
| 217 | + new ExprEvalTestParams("18446744073709551615", ulong.MaxValue), |
| 218 | + |
| 219 | + // Must use "L" suffix here or the expression evaluator will overflow with no warning. Note |
| 220 | + // that it won't compile in C# without it. |
| 221 | + new ExprEvalTestParams("-2147483648L - 1", -2147483648L - 1), |
| 222 | + |
| 223 | + // Note that the dynamic subsystem used by the expression evaluator types this result as |
| 224 | + // long, but the compiler types the expression a uint. Adding the casts to dynamic in |
| 225 | + // the expressions below matches the result of the expression evaluator. Not sure we |
| 226 | + // care that they're different. |
| 227 | + new ExprEvalTestParams("2147483648 + 5", (dynamic)2147483648 + (dynamic)5), |
| 228 | + new ExprEvalTestParams("5 + 2147483648", (dynamic)5 + (dynamic)2147483648), |
| 229 | + |
| 230 | + new ExprEvalTestParams("0x2A828670572C << 1", 0x2A828670572C << 1), |
| 231 | + new ExprEvalTestParams("-0xFC84D76B0482", -0xFC84D76B0482), |
| 232 | + new ExprEvalTestParams("27 - 9223372036854775807", 27 - 9223372036854775807), |
| 233 | + new ExprEvalTestParams("9223372036854775807", 9223372036854775807), |
| 234 | + new ExprEvalTestParams("18446744073709551615", 18446744073709551615), |
| 235 | + new ExprEvalTestParams("1 << 5", 1 << 5), |
| 236 | + new ExprEvalTestParams("1 << 32", 1 << 32), |
| 237 | + new ExprEvalTestParams("1L << 32", 1L << 32), |
| 238 | + new ExprEvalTestParams("5u", 5u), |
| 239 | + new ExprEvalTestParams("5ul", 5ul), |
| 240 | + new ExprEvalTestParams("\"This is\" + \" a string expression\"", "This is" + " a string expression"), |
| 241 | + new ExprEvalTestParams("(17 - 48 + 80 * 81 - 88) + (74 + 79 - 50) - ((76 - 51 - 88 + (9 + 98 - 47)))", (17 - 48 + 80 * 81 - 88) + (74 + 79 - 50) - ((76 - 51 - 88 + (9 + 98 - 47)))), |
| 242 | + new ExprEvalTestParams("3.14159265", 3.14159265), |
| 243 | + new ExprEvalTestParams("16 - 47 * (75 / 91) + 44", 16 - 47 * (75 / 91) + 44), // Does C# truncate the same way? |
| 244 | + new ExprEvalTestParams("16 - 47 * (75d / 91d) + 44", 16 - 47 * (75d / 91d) + 44), |
| 245 | + new ExprEvalTestParams("69d / 5 - 48 - 47 / (82d - 71 + 2 + 6 / 39d) - 56", 69d / 5 - 48 - 47 / (82d - 71 + 2 + 6 / 39d) - 56), |
| 246 | + new ExprEvalTestParams("55.59m", 55.59m), |
| 247 | + new ExprEvalTestParams("55.59m + 23", 55.59m + 23), |
| 248 | + new ExprEvalTestParams("'A'", 'A'), |
| 249 | + new ExprEvalTestParams("'A'+'B'", 'A' + 'B'), |
| 250 | + new ExprEvalTestParams("(int)'A'", (int)'A'), |
| 251 | + |
| 252 | + // C++ specific sufixes not supported. C++ octal not supported. |
| 253 | + //new EETestParams("5ll", 5L), |
| 254 | + //new EETestParams("5ull", 5UL), |
| 255 | + //new EETestParams("016", 8 + 6), |
| 256 | + |
| 257 | + new ExprEvalTestParams("V1 | V2", 3, ("V1", 1), ("V2", 2)), |
| 258 | + new ExprEvalTestParams("TRUE && FALSE", false, ("TRUE", true), ("FALSE", false)), |
| 259 | + }; |
| 260 | + |
| 261 | + class ExprEvalTestParams |
| 262 | + { |
| 263 | + public readonly string Expression; |
| 264 | + public readonly object ExpectedResult; |
| 265 | + public readonly (string Name, object Value)[] Symbols; |
| 266 | + public ExprEvalTestParams(string expression, object expectedResult, params (string Name, object Value)[] symbols) |
| 267 | + { |
| 268 | + Expression = expression; |
| 269 | + ExpectedResult = expectedResult; |
| 270 | + Symbols = symbols; |
| 271 | + } |
| 272 | + } |
| 273 | + |
| 274 | + static IEnumerable GetExpressionEvaluatorTestCases() |
| 275 | + { |
| 276 | + var testNumber = 100; |
| 277 | + foreach (var tc in TestExpressionEvaluatorTestCases) |
| 278 | + { |
| 279 | + // "testNumber" is just used to cause the test runner to show the tests in the order |
| 280 | + // we've listed them which is simply a development time convenience. |
| 281 | + yield return new TestCaseData(testNumber++, tc.Expression, tc.ExpectedResult, tc.Symbols); |
| 282 | + } |
| 283 | + } |
| 284 | + |
| 285 | + [TestCaseSource(nameof(GetExpressionEvaluatorTestCases))] |
| 286 | + public void TestExpressionEvaluator(int testNumber, string expression, object expectedResult, (string SymbolName, object SymbolValue)[] symbols) |
| 287 | + { |
| 288 | + var evaluator = symbols == null || symbols.Length == 0 |
| 289 | + ? new ExpressionEvaluator() |
| 290 | + : new ExpressionEvaluator(symbols.ToDictionary(s => s.SymbolName, s => s.SymbolValue)); |
| 291 | + |
| 292 | + var result = evaluator.Evaluate(expression); |
| 293 | + Assert.AreEqual(expectedResult, result); |
| 294 | + Assert.AreEqual(expectedResult.GetType(), result.GetType()); |
| 295 | + } |
| 296 | + |
| 297 | + [Test] |
| 298 | + public void TestEnumsWithBitwiseExpressionMacroValues() |
| 299 | + { |
| 300 | + var @enum = AstContext.GenerateEnumFromMacros("TestBitwiseShift", "TEST_BITWISE_SHIFT_(.*)"); |
| 301 | + Assert.IsNotNull(@enum); |
| 302 | + Assert.AreEqual(PrimitiveType.LongLong, @enum.BuiltinType.Type); |
| 303 | + Assert.AreEqual(0x2A828670572C << 1, (long)@enum.Items[0].Value); |
| 304 | + |
| 305 | + @enum = AstContext.GenerateEnumFromMacros("TestNegativeHex", "TEST_NEGATIVE_HEX_(.*)"); |
| 306 | + Assert.IsNotNull(@enum); |
| 307 | + Assert.AreEqual(PrimitiveType.LongLong, @enum.BuiltinType.Type); |
| 308 | + Assert.AreEqual(-0xFC84D76B0482, (long)@enum.Items[0].Value); |
| 309 | + |
| 310 | + @enum = AstContext.GenerateEnumFromMacros("TestBitwiseOr", "TEST_BITWISE_OR_1"); |
| 311 | + Assert.IsNotNull(@enum); |
| 312 | + Assert.AreEqual(PrimitiveType.UChar, @enum.BuiltinType.Type); |
| 313 | + Assert.AreEqual(0x7F | 0x80, @enum.Items[0].Value); |
| 314 | + |
| 315 | + @enum = AstContext.GenerateEnumFromMacros("TestBitwiseAnd", "TEST_BITWISE_AND_(.*)"); |
| 316 | + Assert.IsNotNull(@enum); |
| 317 | + Assert.AreEqual(PrimitiveType.UChar, @enum.BuiltinType.Type); |
| 318 | + Assert.AreEqual(0x7F & 0xFF, @enum.Items[0].Value); |
| 319 | + Assert.AreEqual(0x73 & -1, @enum.Items[1].Value); |
| 320 | + Assert.AreEqual(0x42 & ~0x2, @enum.Items[2].Value); |
| 321 | + |
| 322 | + @enum = AstContext.GenerateEnumFromMacros("TestBitwiseXor", "TEST_BITWISE_XOR_(.*)"); |
| 323 | + Assert.IsNotNull(@enum); |
| 324 | + Assert.AreEqual(PrimitiveType.UChar, @enum.BuiltinType.Type); |
| 325 | + Assert.AreEqual(0x7F ^ 0x03, @enum.Items[0].Value); |
| 326 | + } |
| 327 | + |
138 | 328 | [Test]
|
139 | 329 | public void TestUnnamedEnumSupport()
|
140 | 330 | {
|
|
0 commit comments