@ -1,8 +1,14 @@
@@ -1,8 +1,14 @@
using CppSharp.AST ;
using CodingSeb.ExpressionEvaluator ;
using CppSharp.AST ;
using CppSharp.Generators.CSharp ;
using CppSharp.Passes ;
using NUnit.Framework ;
using System.Collections ;
using System.Collections.Generic ;
using System.Globalization ;
using System.Linq ;
using System.Runtime.CompilerServices ;
using System.Text.RegularExpressions ;
namespace CppSharp.Generator.Tests.Passes
{
@ -84,7 +90,7 @@ namespace CppSharp.Generator.Tests.Passes
@@ -84,7 +90,7 @@ namespace CppSharp.Generator.Tests.Passes
passBuilder . AddPass ( new CleanCommentsPass ( ) ) ;
passBuilder . RunPasses ( pass = > pass . VisitDeclaration ( c ) ) ;
var para = ( ParagraphComment ) c . Comment . FullComment . Blocks [ 0 ] ;
var para = ( ParagraphComment ) c . Comment . FullComment . Blocks [ 0 ] ;
var textGenerator = new TextGenerator ( ) ;
textGenerator . Print ( para , CommentKind . BCPLSlash ) ;
@ -135,6 +141,190 @@ namespace CppSharp.Generator.Tests.Passes
@@ -135,6 +141,190 @@ namespace CppSharp.Generator.Tests.Passes
Assert . That ( @enum . Items [ 1 ] . Name , Is . EqualTo ( "_0" ) ) ;
}
[Test]
public void TestEnumBaseTypesFromMacroValues ( )
{
AstContext . GenerateEnumFromMacros ( "TestEnumMaxSbyte" , "TEST_ENUM_MAX_SBYTE" ) ;
var @enum = AstContext . Enum ( "TestEnumMaxSbyte" ) ;
Assert . IsNotNull ( @enum ) ;
Assert . AreEqual ( sbyte . MaxValue , @enum . Items [ 0 ] . Value ) ;
Assert . AreEqual ( PrimitiveType . UChar , @enum . BuiltinType . Type ) ;
AstContext . GenerateEnumFromMacros ( "TestEnumMaxByte" , "TEST_ENUM_MAX_BYTE" ) ;
@enum = AstContext . Enum ( "TestEnumMaxByte" ) ;
Assert . IsNotNull ( @enum ) ;
Assert . AreEqual ( byte . MaxValue , @enum . Items [ 0 ] . Value ) ;
Assert . AreEqual ( PrimitiveType . UChar , @enum . BuiltinType . Type ) ;
AstContext . GenerateEnumFromMacros ( "TestEnumMaxShort" , "TEST_ENUM_MAX_SHORT" ) ;
@enum = AstContext . Enum ( "TestEnumMaxShort" ) ;
Assert . IsNotNull ( @enum ) ;
Assert . AreEqual ( short . MaxValue , @enum . Items [ 0 ] . Value ) ;
Assert . AreEqual ( PrimitiveType . Short , @enum . BuiltinType . Type ) ;
AstContext . GenerateEnumFromMacros ( "TestEnumMaxUshort" , "TEST_ENUM_MAX_USHORT" ) ;
@enum = AstContext . Enum ( "TestEnumMaxUshort" ) ;
Assert . IsNotNull ( @enum ) ;
Assert . AreEqual ( ushort . MaxValue , @enum . Items [ 0 ] . Value ) ;
Assert . AreEqual ( PrimitiveType . UShort , @enum . BuiltinType . Type ) ;
AstContext . GenerateEnumFromMacros ( "TestEnumMaxInt" , "TEST_ENUM_MAX_INT" ) ;
@enum = AstContext . Enum ( "TestEnumMaxInt" ) ;
Assert . IsNotNull ( @enum ) ;
Assert . AreEqual ( int . MaxValue , @enum . Items [ 0 ] . Value ) ;
Assert . AreEqual ( PrimitiveType . Int , @enum . BuiltinType . Type ) ;
AstContext . GenerateEnumFromMacros ( "TestEnumMaxLong" , "TEST_ENUM_MAX_LONG" ) ;
@enum = AstContext . Enum ( "TestEnumMaxLong" ) ;
Assert . IsNotNull ( @enum ) ;
Assert . AreEqual ( long . MaxValue , @enum . Items [ 0 ] . Value ) ;
Assert . AreEqual ( PrimitiveType . LongLong , @enum . BuiltinType . Type ) ;
AstContext . GenerateEnumFromMacros ( "TestEnumMaxUint" , "TEST_ENUM_MAX_UINT" ) ;
@enum = AstContext . Enum ( "TestEnumMaxUint" ) ;
Assert . IsNotNull ( @enum ) ;
Assert . AreEqual ( uint . MaxValue , @enum . Items [ 0 ] . Value ) ;
Assert . AreEqual ( PrimitiveType . UInt , @enum . BuiltinType . Type ) ;
AstContext . GenerateEnumFromMacros ( "TestEnumMaxUlong" , "TEST_ENUM_MAX_ULONG" ) ;
@enum = AstContext . Enum ( "TestEnumMaxUlong" ) ;
Assert . IsNotNull ( @enum ) ;
Assert . AreEqual ( ulong . MaxValue , @enum . Items [ 0 ] . Value ) ;
Assert . AreEqual ( PrimitiveType . ULongLong , @enum . BuiltinType . Type ) ;
AstContext . GenerateEnumFromMacros ( "TestEnumMinInt" , "TEST_ENUM_MIN_INT" ) ;
@enum = AstContext . Enum ( "TestEnumMinInt" ) ;
Assert . IsNotNull ( @enum ) ;
Assert . AreEqual ( int . MinValue , ( long ) @enum . Items [ 0 ] . Value ) ;
Assert . AreEqual ( PrimitiveType . Int , @enum . BuiltinType . Type ) ;
AstContext . GenerateEnumFromMacros ( "TestEnumMinLong" , "TEST_ENUM_MIN_LONG" ) ;
@enum = AstContext . Enum ( "TestEnumMinLong" ) ;
Assert . IsNotNull ( @enum ) ;
Assert . AreEqual ( long . MinValue , ( long ) @enum . Items [ 0 ] . Value ) ;
Assert . AreEqual ( PrimitiveType . LongLong , @enum . BuiltinType . Type ) ;
}
// These tests have nothing to do with testing passes except that the expression evaluator
// is only used by GenerateEnumFromMacros. Add a separate TestFixture?
static ExprEvalTestParams [ ] TestExpressionEvaluatorTestCases =
{
new ExprEvalTestParams ( "2147483647" , int . MaxValue ) ,
new ExprEvalTestParams ( "-2147483648" , int . MinValue ) ,
new ExprEvalTestParams ( "4294967295" , uint . MaxValue ) ,
new ExprEvalTestParams ( "9223372036854775807" , long . MaxValue ) ,
new ExprEvalTestParams ( "-9223372036854775808" , long . MinValue ) ,
new ExprEvalTestParams ( "18446744073709551615" , ulong . MaxValue ) ,
// Must use "L" suffix here or the expression evaluator will overflow with no warning. Note
// that it won't compile in C# without it.
new ExprEvalTestParams ( "-2147483648L - 1" , - 2 1 4 7 4 8 3 6 4 8L - 1 ) ,
// Note that the dynamic subsystem used by the expression evaluator types this result as
// long, but the compiler types the expression a uint. Adding the casts to dynamic in
// the expressions below matches the result of the expression evaluator. Not sure we
// care that they're different.
new ExprEvalTestParams ( "2147483648 + 5" , ( dynamic ) 2 1 4 7 4 8 3 6 4 8 + ( dynamic ) 5 ) ,
new ExprEvalTestParams ( "5 + 2147483648" , ( dynamic ) 5 + ( dynamic ) 2 1 4 7 4 8 3 6 4 8 ) ,
new ExprEvalTestParams ( "0x2A828670572C << 1" , 0x2A828670572C < < 1 ) ,
new ExprEvalTestParams ( "-0xFC84D76B0482" , - 0xFC84D76B0482 ) ,
new ExprEvalTestParams ( "27 - 9223372036854775807" , 2 7 - 9 2 2 3 3 7 2 0 3 6 8 5 4 7 7 5 8 0 7 ) ,
new ExprEvalTestParams ( "9223372036854775807" , 9 2 2 3 3 7 2 0 3 6 8 5 4 7 7 5 8 0 7 ) ,
new ExprEvalTestParams ( "18446744073709551615" , 1 8 4 4 6 7 4 4 0 7 3 7 0 9 5 5 1 6 1 5 ) ,
new ExprEvalTestParams ( "1 << 5" , 1 < < 5 ) ,
new ExprEvalTestParams ( "1 << 32" , 1 < < 3 2 ) ,
new ExprEvalTestParams ( "1L << 32" , 1L < < 3 2 ) ,
new ExprEvalTestParams ( "5u" , 5 u ) ,
new ExprEvalTestParams ( "5ul" , 5 ul ) ,
new ExprEvalTestParams ( "\"This is\" + \" a string expression\"" , "This is" + " a string expression" ) ,
new ExprEvalTestParams ( "(17 - 48 + 80 * 81 - 88) + (74 + 79 - 50) - ((76 - 51 - 88 + (9 + 98 - 47)))" , ( 1 7 - 4 8 + 8 0 * 8 1 - 8 8 ) + ( 7 4 + 7 9 - 5 0 ) - ( ( 7 6 - 5 1 - 8 8 + ( 9 + 9 8 - 4 7 ) ) ) ) ,
new ExprEvalTestParams ( "3.14159265" , 3.14159265 ) ,
new ExprEvalTestParams ( "16 - 47 * (75 / 91) + 44" , 1 6 - 4 7 * ( 7 5 / 9 1 ) + 4 4 ) , // Does C# truncate the same way?
new ExprEvalTestParams ( "16 - 47 * (75d / 91d) + 44" , 1 6 - 4 7 * ( 7 5d / 9 1d ) + 4 4 ) ,
new ExprEvalTestParams ( "69d / 5 - 48 - 47 / (82d - 71 + 2 + 6 / 39d) - 56" , 6 9d / 5 - 4 8 - 4 7 / ( 8 2d - 7 1 + 2 + 6 / 3 9d ) - 5 6 ) ,
new ExprEvalTestParams ( "55.59m" , 5 5.59 m ) ,
new ExprEvalTestParams ( "55.59m + 23" , 5 5.59 m + 2 3 ) ,
new ExprEvalTestParams ( "'A'" , 'A' ) ,
new ExprEvalTestParams ( "'A'+'B'" , 'A' + 'B' ) ,
new ExprEvalTestParams ( "(int)'A'" , ( int ) 'A' ) ,
// C++ specific sufixes not supported. C++ octal not supported.
//new EETestParams("5ll", 5L),
//new EETestParams("5ull", 5UL),
//new EETestParams("016", 8 + 6),
new ExprEvalTestParams ( "V1 | V2" , 3 , ( "V1" , 1 ) , ( "V2" , 2 ) ) ,
new ExprEvalTestParams ( "TRUE && FALSE" , false , ( "TRUE" , true ) , ( "FALSE" , false ) ) ,
} ;
class ExprEvalTestParams
{
public readonly string Expression ;
public readonly object ExpectedResult ;
public readonly ( string Name , object Value ) [ ] Symbols ;
public ExprEvalTestParams ( string expression , object expectedResult , params ( string Name , object Value ) [ ] symbols )
{
Expression = expression ;
ExpectedResult = expectedResult ;
Symbols = symbols ;
}
}
static IEnumerable GetExpressionEvaluatorTestCases ( )
{
var testNumber = 1 0 0 ;
foreach ( var tc in TestExpressionEvaluatorTestCases )
{
// "testNumber" is just used to cause the test runner to show the tests in the order
// we've listed them which is simply a development time convenience.
yield return new TestCaseData ( testNumber + + , tc . Expression , tc . ExpectedResult , tc . Symbols ) ;
}
}
[TestCaseSource(nameof(GetExpressionEvaluatorTestCases))]
public void TestExpressionEvaluator ( int testNumber , string expression , object expectedResult , ( string SymbolName , object SymbolValue ) [ ] symbols )
{
var evaluator = symbols = = null | | symbols . Length = = 0
? new ExpressionEvaluator ( )
: new ExpressionEvaluator ( symbols . ToDictionary ( s = > s . SymbolName , s = > s . SymbolValue ) ) ;
var result = evaluator . Evaluate ( expression ) ;
Assert . AreEqual ( expectedResult , result ) ;
Assert . AreEqual ( expectedResult . GetType ( ) , result . GetType ( ) ) ;
}
[Test]
public void TestEnumsWithBitwiseExpressionMacroValues ( )
{
var @enum = AstContext . GenerateEnumFromMacros ( "TestBitwiseShift" , "TEST_BITWISE_SHIFT_(.*)" ) ;
Assert . IsNotNull ( @enum ) ;
Assert . AreEqual ( PrimitiveType . LongLong , @enum . BuiltinType . Type ) ;
Assert . AreEqual ( 0x2A828670572C < < 1 , ( long ) @enum . Items [ 0 ] . Value ) ;
@enum = AstContext . GenerateEnumFromMacros ( "TestNegativeHex" , "TEST_NEGATIVE_HEX_(.*)" ) ;
Assert . IsNotNull ( @enum ) ;
Assert . AreEqual ( PrimitiveType . LongLong , @enum . BuiltinType . Type ) ;
Assert . AreEqual ( - 0xFC84D76B0482 , ( long ) @enum . Items [ 0 ] . Value ) ;
@enum = AstContext . GenerateEnumFromMacros ( "TestBitwiseOr" , "TEST_BITWISE_OR_1" ) ;
Assert . IsNotNull ( @enum ) ;
Assert . AreEqual ( PrimitiveType . UChar , @enum . BuiltinType . Type ) ;
Assert . AreEqual ( 0x7F | 0x80 , @enum . Items [ 0 ] . Value ) ;
@enum = AstContext . GenerateEnumFromMacros ( "TestBitwiseAnd" , "TEST_BITWISE_AND_(.*)" ) ;
Assert . IsNotNull ( @enum ) ;
Assert . AreEqual ( PrimitiveType . UChar , @enum . BuiltinType . Type ) ;
Assert . AreEqual ( 0x7F & 0xFF , @enum . Items [ 0 ] . Value ) ;
Assert . AreEqual ( 0x73 & - 1 , @enum . Items [ 1 ] . Value ) ;
Assert . AreEqual ( 0x42 & ~ 0x2 , @enum . Items [ 2 ] . Value ) ;
@enum = AstContext . GenerateEnumFromMacros ( "TestBitwiseXor" , "TEST_BITWISE_XOR_(.*)" ) ;
Assert . IsNotNull ( @enum ) ;
Assert . AreEqual ( PrimitiveType . UChar , @enum . BuiltinType . Type ) ;
Assert . AreEqual ( 0x7F ^ 0x03 , @enum . Items [ 0 ] . Value ) ;
}
[Test]
public void TestUnnamedEnumSupport ( )
{