internal static bool AreEqual(ITestOutputHelper testOutputHelper, Type sourceType, Type targetType, CastResult compilerResult, CastResult castResult, CastFlag expectedCastFlag)
        {
            if (compilerResult.IsSuccessful == true && castResult.IsSuccessful == false)
            {
                // Let's assert the details if the compiler generates a successful result
                // but the CastTo method does not the same.

                var castFlagsAreEqual = compilerResult.CastFlag == castResult.CastFlag || castResult.CastFlag == CastFlag.Implicit;
                if (!castFlagsAreEqual)
                {
                    testOutputHelper.WriteLine("CastFlags of conversion between {0} and {1} are not equal." + Environment.NewLine +
                        "Expected CastFlag: {2}" + Environment.NewLine +
                        "Resulted CastFlag: {3}" + Environment.NewLine,
                        sourceType.GetFormattedName(),
                        targetType.GetFormattedName(),
                        expectedCastFlag,
                        castResult.CastFlag);
                    return false;
                }

                var valuesAreNotEqual = compilerResult.CastFlag == castResult.CastFlag && !Equals(compilerResult.Value, castResult.Value);
                if (valuesAreNotEqual)
                {
                    testOutputHelper.WriteLine("Result of {0} conversion between {1} and {2} are not equal.",
                        expectedCastFlag == CastFlag.Implicit ? "implicit" : "explicit",
                        sourceType.GetFormattedName(),
                        targetType.GetFormattedName());

                    return false;
                }
            }

            return true;
        }
 public CompilerConversionTestCase(Type sourceType, Type targetType, CastFlag castFlag, string codeline = null, CompilerError compilerError = null)
 {
     this.SourceType = sourceType;
     this.TargetType = targetType;
     this.Codeline = codeline;
     this.CompilerError = compilerError;
     this.CastFlag = castFlag;
 }
 public CompilerConversionTestCase(Type sourceType, Type targetType, CastFlag castFlag, string codeline = null, CompilerError compilerError = null)
 {
     this.SourceType    = sourceType;
     this.TargetType    = targetType;
     this.Codeline      = codeline;
     this.CompilerError = compilerError;
     this.CastFlag      = castFlag;
 }
        internal static CastResult CastValueWithGeneratedCode(object value, Type sourceType, Type targetType, CastFlag castFlag)
        {
            string className = "GeneratedTestClass";
            string methodName = "RunTest";
            string castLine = string.Format(
                "{0} x = {1}value; return x;",
                targetType.GetFormattedFullname(),
                castFlag == CastFlag.Implicit ? string.Empty : "(" + targetType.GetFormattedFullname() + ")");

            string code = "public class " + className + " { public " + targetType.GetFormattedFullname() + " " + methodName + "(" + sourceType.GetFormattedFullname() + " value)" +
                          "{" + castLine + "}}";

            using (CSharpCodeProvider provider = new CSharpCodeProvider())
            {
                var compilerParams = new CompilerParameters();
                compilerParams.ReferencedAssemblies.Add(typeof(CastTestRunner).Assembly.Location);
                compilerParams.GenerateExecutable = false;
                compilerParams.GenerateInMemory = true;
                var compilationResult = provider.CompileAssemblyFromSource(compilerParams, code);
                if (compilationResult.Errors.HasErrors)
                {

                    var compilerException = new AggregateException("CastValueWithGeneratedCode failed to generate test class.",
                                                  compilationResult.Errors
                                                      .OfType<CompilerError>()
                                                      .Where(e => !e.IsWarning)
                                                      .Select(e => new CompilerException(e.Line, e.Column, e.ErrorText)));
                    return new CastResult(compilerException, castFlag);
                }

                var generatedClass = compilationResult.CompiledAssembly.GetType(className);

                var instance = Activator.CreateInstance(generatedClass);
                var testMethod = generatedClass.GetMethod(methodName);

                try
                {
                    var castedValue = testMethod.Invoke(instance, new[] { value });
                    return new CastResult(castedValue, castFlag);
                }
                catch (TargetInvocationException ex)
                {
                    if (ex.InnerException is InvalidProgramException)
                    {
                        // This is most probably an error in Roslyn compiler.
                        // See http://stackoverflow.com/questions/18342943/serious-bugs-with-lifted-nullable-conversions-from-int-allowing-conversion-from
                        return new CastResult(value, castFlag);
                    }

                    return new CastResult(ex, castFlag);
                }
                catch (Exception ex)
                {
                    return new CastResult(ex, castFlag);
                }
            }
        }
 public CastResult(Exception exception, CastFlag castFlag)
     : base(exception)
 {
     this.CastFlag = castFlag;
 }
 public CastResult(object value, CastFlag castFlag)
     : base(value)
 {
     this.CastFlag = castFlag;
 }
Example #7
0
 public CastResult(object value, CastFlag castFlag)
     : base(value)
 {
     this.CastFlag = castFlag;
 }
Example #8
0
 public CastResult(Exception exception, CastFlag castFlag)
     : base(exception)
 {
     this.CastFlag = castFlag;
 }
 private static string GetCodeline(int index, Type sourceType, Type targetType, CastFlag castFlag)
 {
     return string.Format(
         "{0} var{1} = {2}Get<{3}>();",
         targetType.GetFormattedFullname(),
         index,
         castFlag == CastFlag.Implicit ? string.Empty : "(" + targetType.GetFormattedFullname() + ")",
         sourceType.GetFormattedFullname());
 }
        private static List<CompilerConversionTestCase> GenerateTestCases(IEnumerable<Type> allTypes, CastFlag castFlag)
        {
            // generate cross product of given types
            var typeCrossProduct = allTypes.SelectMany(type => allTypes, (sourceType, targetType) => new { sourceType, targetType })
                                           .Select((type, index) =>
                                               new {
                                                        type.sourceType,
                                                        type.targetType,
                                                        index,
                                                        codeline = GetCodeline(index, type.sourceType, type.targetType, castFlag)
                                                    }).ToArray();

            // create the code to pass to the compiler
            var code = string.Join(
                Environment.NewLine,
                new[] { "namespace A { public class B { static T Get<T>() { return default(T); } public void C() {" }.Concat(
                    typeCrossProduct.Select(t => t.codeline))
                    .Concat(new[] { "}}}" }));

            // compile the code
            var provider = new CSharpCodeProvider();
            var compilerParams = new CompilerParameters();
            compilerParams.ReferencedAssemblies.Add(typeof(CastTestRunner).Assembly.Location); // reference the current assembly!
            compilerParams.GenerateExecutable = false;
            compilerParams.GenerateInMemory = true;
            var compilationResult = provider.CompileAssemblyFromSource(compilerParams, code);

            // determine the outcome of each conversion by matching compiler errors with conversions by line #
            var testCases = typeCrossProduct.GroupJoin(compilationResult.Errors.Cast<CompilerError>(),
                type => type.index,
                e => e.Line - 2,
                (type, errors) => new CompilerConversionTestCase(type.sourceType, type.targetType, castFlag, type.codeline, errors.FirstOrDefault()))
                .ToList();

            // add a special case
            // this can't be verified by the normal means, since it's a private class
            ////testCases.Add(new CompilerConversionTestCase(typeof(PrivateOperators), typeof(int), string.Empty, default(CompilerError)));

            return testCases;
        }
Example #11
0
        public static void ReadSpellCastData(Packet packet, params object[] idx)
        {
            bool    isSpellGo  = packet.Opcode == Opcodes.GetOpcode(Opcode.SMSG_SPELL_GO, Direction.ServerToClient);
            WowGuid targetGUID = new WowGuid64();

            var casterGUID = packet.ReadPackedGuid("CasterGUID", idx);

            packet.ReadPackedGuid("CasterUnit", idx);
            packet.ReadByte("CastID", idx);
            var      spellId = packet.ReadInt32 <SpellId>("SpellID", idx);
            CastFlag flags   = packet.ReadInt32E <CastFlag>("CastFlags", idx);

            packet.ReadUInt32("CastFlagsEx", idx);
            packet.ReadUInt32("CastTime", idx);

            if (isSpellGo)
            {
                var hitTargetsCount = packet.ReadByte("HitTargetsCount", idx);
                for (var i = 0; i < hitTargetsCount; ++i)
                {
                    packet.ReadGuid("HitTarget", idx, i);
                }

                var missCount = packet.ReadByte("MissStatusCount", idx);
                for (var i = 0; i < missCount; ++i)
                {
                    ReadSpellMissStatus(packet, idx, "MissStatus", i);
                }
            }

            TargetFlag targetFlags = TargetFlag.Self;

            ReadSpellTargetData(packet, ref targetFlags, targetGUID, idx, "Target");

            if (flags.HasAnyFlag(CastFlag.PredictedPower))
            {
                packet.ReadUInt32("RemainingPower");
            }

            if (flags.HasAnyFlag(CastFlag.RuneInfo))
            {
                ReadRuneData(packet, idx, "RemainingRunes");
            }

            if (isSpellGo)
            {
                if (flags.HasAnyFlag(CastFlag.AdjustMissile))
                {
                    ReadMissileTrajectoryResult(packet, idx, "MissileTrajectory");
                }
            }

            if (flags.HasAnyFlag(CastFlag.Projectile))
            {
                ReadSpellAmmo(packet, idx, "Ammo");
            }

            if (isSpellGo)
            {
                if (flags.HasAnyFlag(CastFlag.VisualChain))
                {
                    ReadProjectileVisual(packet, idx, "ProjectileVisual");
                }

                if (targetFlags.HasAnyFlag(TargetFlag.DestinationLocation))
                {
                    packet.ReadByte("DestLocSpellCastIndex", idx);
                }

                if (targetFlags.HasAnyFlag(TargetFlag.ExtraTargets))
                {
                    var targetPointsCount = packet.ReadInt32("TargetPointsCount", idx);
                    for (var i = 0; i < targetPointsCount; ++i)
                    {
                        ReadTargetLocation(packet, idx, "TargetPoints", i);
                    }
                }
            }
            else
            {
                if (flags.HasAnyFlag(CastFlag.Immunity))
                {
                    ReadCreatureImmunities(packet, idx, "Immunities");
                }

                if (flags.HasAnyFlag(CastFlag.HealPrediction))
                {
                    ReadSpellHealPrediction(packet, idx, "Predict");
                }
            }

            if (flags.HasAnyFlag(CastFlag.Unknown21) && !isSpellGo)
            {
                NpcSpellClick spellClick = new NpcSpellClick
                {
                    SpellID    = (uint)spellId,
                    CasterGUID = casterGUID,
                    TargetGUID = targetGUID
                };

                Storage.SpellClicks.Add(spellClick, packet.TimeSpan);
            }

            if (isSpellGo)
            {
                packet.AddSniffData(StoreNameType.Spell, spellId, "SPELL_GO");
            }
        }
        private static List <CompilerConversionTestCase> GenerateTestCases(IEnumerable <Type> allTypes, CastFlag castFlag)
        {
            // generate cross product of given types
            var typeCrossProduct = allTypes.SelectMany(type => allTypes, (sourceType, targetType) => new { sourceType, targetType })
                                   .Select((type, index) =>
                                           new {
                type.sourceType,
                type.targetType,
                index,
                codeline = GetCodeline(index, type.sourceType, type.targetType, castFlag)
            }).ToArray();

            // create the code to pass to the compiler
            var code = string.Join(
                Environment.NewLine,
                new[] { "namespace A { public class B { static T Get<T>() { return default(T); } public void C() {" }.Concat(
                    typeCrossProduct.Select(t => t.codeline))
                .Concat(new[] { "}}}" }));

            // compile the code
            var provider       = new CSharpCodeProvider();
            var compilerParams = new CompilerParameters();

            compilerParams.ReferencedAssemblies.Add(typeof(CastTestRunner).Assembly.Location); // reference the current assembly!
            compilerParams.GenerateExecutable = false;
            compilerParams.GenerateInMemory   = true;
            var compilationResult = provider.CompileAssemblyFromSource(compilerParams, code);

            // determine the outcome of each conversion by matching compiler errors with conversions by line #
            var testCases = typeCrossProduct.GroupJoin(compilationResult.Errors.Cast <CompilerError>(),
                                                       type => type.index,
                                                       e => e.Line - 2,
                                                       (type, errors) => new CompilerConversionTestCase(type.sourceType, type.targetType, castFlag, type.codeline, errors.FirstOrDefault()))
                            .ToList();

            // add a special case
            // this can't be verified by the normal means, since it's a private class
            ////testCases.Add(new CompilerConversionTestCase(typeof(PrivateOperators), typeof(int), string.Empty, default(CompilerError)));

            return(testCases);
        }
        internal static bool AreEqual(ITestOutputHelper testOutputHelper, Type sourceType, Type targetType, CastResult compilerResult, CastResult castResult, CastFlag expectedCastFlag)
        {
            if (compilerResult.IsSuccessful == true && castResult.IsSuccessful == false)
            {
                // Let's assert the details if the compiler generates a successful result
                // but the CastTo method does not the same.

                var castFlagsAreEqual = compilerResult.CastFlag == castResult.CastFlag || castResult.CastFlag == CastFlag.Implicit;
                if (!castFlagsAreEqual)
                {
                    testOutputHelper.WriteLine("CastFlags of conversion between {0} and {1} are not equal." + Environment.NewLine +
                                               "Expected CastFlag: {2}" + Environment.NewLine +
                                               "Resulted CastFlag: {3}" + Environment.NewLine,
                                               sourceType.GetFormattedName(),
                                               targetType.GetFormattedName(),
                                               expectedCastFlag,
                                               castResult.CastFlag);
                    return(false);
                }

                var valuesAreNotEqual = compilerResult.CastFlag == castResult.CastFlag && !Equals(compilerResult.Value, castResult.Value);
                if (valuesAreNotEqual)
                {
                    testOutputHelper.WriteLine("Result of {0} conversion between {1} and {2} are not equal.",
                                               expectedCastFlag == CastFlag.Implicit ? "implicit" : "explicit",
                                               sourceType.GetFormattedName(),
                                               targetType.GetFormattedName());

                    return(false);
                }
            }

            return(true);
        }
        internal static CastResult CastValueWithGeneratedCode(object value, Type sourceType, Type targetType, CastFlag castFlag)
        {
            string className  = "GeneratedTestClass";
            string methodName = "RunTest";
            string castLine   = string.Format(
                "{0} x = {1}value; return x;",
                targetType.GetFormattedFullname(),
                castFlag == CastFlag.Implicit ? string.Empty : "(" + targetType.GetFormattedFullname() + ")");

            string code = "public class " + className + " { public " + targetType.GetFormattedFullname() + " " + methodName + "(" + sourceType.GetFormattedFullname() + " value)" +
                          "{" + castLine + "}}";

            using (CSharpCodeProvider provider = new CSharpCodeProvider())
            {
                var compilerParams = new CompilerParameters();
                compilerParams.ReferencedAssemblies.Add(typeof(CastTestRunner).Assembly.Location);
                compilerParams.GenerateExecutable = false;
                compilerParams.GenerateInMemory   = true;
                var compilationResult = provider.CompileAssemblyFromSource(compilerParams, code);
                if (compilationResult.Errors.HasErrors)
                {
                    var compilerException = new AggregateException("CastValueWithGeneratedCode failed to generate test class.",
                                                                   compilationResult.Errors
                                                                   .OfType <CompilerError>()
                                                                   .Where(e => !e.IsWarning)
                                                                   .Select(e => new CompilerException(e.Line, e.Column, e.ErrorText)));
                    return(new CastResult(compilerException, castFlag));
                }

                var generatedClass = compilationResult.CompiledAssembly.GetType(className);

                var instance   = Activator.CreateInstance(generatedClass);
                var testMethod = generatedClass.GetMethod(methodName);

                try
                {
                    var castedValue = testMethod.Invoke(instance, new[] { value });
                    return(new CastResult(castedValue, castFlag));
                }
                catch (TargetInvocationException ex)
                {
                    if (ex.InnerException is InvalidProgramException)
                    {
                        // This is most probably an error in Roslyn compiler.
                        // See http://stackoverflow.com/questions/18342943/serious-bugs-with-lifted-nullable-conversions-from-int-allowing-conversion-from
                        return(new CastResult(value, castFlag));
                    }

                    return(new CastResult(ex, castFlag));
                }
                catch (Exception ex)
                {
                    return(new CastResult(ex, castFlag));
                }
            }
        }
 private static string GetCodeline(int index, Type sourceType, Type targetType, CastFlag castFlag)
 {
     return(string.Format(
                "{0} var{1} = {2}Get<{3}>();",
                targetType.GetFormattedFullname(),
                index,
                castFlag == CastFlag.Implicit ? string.Empty : "(" + targetType.GetFormattedFullname() + ")",
                sourceType.GetFormattedFullname()));
 }
Example #16
0
        internal static CastResult CastTo(object value, Type targetType)
        {
            if (value == null)
            {
                return(new CastResult((object)null, CastFlag.Undefined));
            }

            Guard.ArgumentNotNull(targetType, nameof(targetType));

            var sourceType     = value.GetType();
            var sourceTypeInfo = value.GetType().GetTypeInfo();
            var targetTypeInfo = targetType.GetTypeInfo();

            if (targetTypeInfo.IsGenericType && !targetTypeInfo.GenericTypeArguments.Any())
            {
                return
                    (new CastResult(
                         ConversionNotSupportedException.Create(
                             sourceType,
                             targetType,
                             string.Format("The target type {0} does not have sufficient generic type arguments specified.", targetType.GetFormattedName())),
                         CastFlag.Undefined));
            }

            CastResult castResult = null;
            CastFlag   castFlag   = CastFlag.Undefined;

            try
            {
                // explicit conversion always works if to : from OR if there's an implicit conversion
                if (targetType.IsSameOrParent(sourceType))
                {
                    castFlag = CastFlag.Implicit;
                    var castedValue = GenericCast(() => AttemptImplicitCast <object, object>(null), sourceType, targetType, value);
                    castResult = new CastResult(castedValue, castFlag);
                }
                // for nullable types, we can simply strip off the nullability and evaluate the underyling types
                else if (Nullable.GetUnderlyingType(targetType) != null)
                {
                    castResult = CastTo(value, Nullable.GetUnderlyingType(targetType));
                }
                else if (sourceTypeInfo.IsValueType)
                {
                    castFlag = CastFlag.Explicit;
                    var castedValue = GenericCast(() => AttemptExplicitCast <object, object>(null), sourceType, targetType, value);
                    castResult = new CastResult(castedValue, castFlag);
                }
                else
                {
                    // Implicit cast operators have priority in favour of explicit operators
                    // since they should not lose precision. See C# language specification:
                    // https://msdn.microsoft.com/en-us/library/z5z9kes2.aspx
                    var conversionMethods =
                        GetCastOperatorMethods(sourceType, targetType)
                        .OrderByDescending(m => m.Name == "op_Implicit")
                        .ThenByDescending(m => m.ReturnType == targetType || m.ReturnType.GetTypeInfo().IsAssignableFrom(targetTypeInfo));

                    foreach (var conversionMethod in conversionMethods)
                    {
                        try
                        {
                            var convertedValue = conversionMethod.Invoke(null, new[] { value });
                            castResult = CastTo(convertedValue, targetType);
                            if (castResult.IsSuccessful)
                            {
                                break;
                            }
                            else
                            {
                                castResult = null;
                            }
                        }
                        catch
                        {
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                castResult = new CastResult(ConversionNotSupportedException.Create(sourceType, targetType, ex.InnerException), castFlag);
            }

            if (castResult == null)
            {
                castResult = new CastResult(ConversionNotSupportedException.Create(sourceType, targetType), castFlag);
            }

            return(castResult);
        }