Skip to content

Temperature delta base dimensions? #777

Closed
@lipchev

Description

@lipchev

As a prelude to #709 I figure I'd run a test of the currently defined operators and see if there is mismatch between the dimensions of the operands and the result. To my great satisfaction- it found the faulty operator for Density / Mass (which I had previously annotated as obsolete- and completely forgotten about). The only other problem was with the TemperatureDelta which has no defined BaseDimensions- thus failing the dimensions multiplication (though I assume the operators are correct). Was there a reason for it not having the Temperature dimension defined?
Here is the test (I'd put it in the GeneratedQuantityCodeTests):


            [Fact]
            public void HasMultiplicationOperator_GivenMassAndVolume_ReturnsFalse()
            {
                Assert.False(HasMultiplicationOperator(typeof(Mass), typeof(Volume)));
                Assert.DoesNotContain(typeof(Volume), GetMultipliers(typeof(Mass)));
            }

            [Fact]
            public void HasMultiplicationOperator_GivenDensityAndVolume_ReturnsTrue()
            {
                Assert.True(HasMultiplicationOperator(typeof(Density), typeof(Volume)));
                Assert.Contains(typeof(Volume), GetMultipliers(typeof(Density)));
                Assert.Equal(typeof(Mass), GetMultiplicationResult(typeof(Density), typeof(Volume)));
            }

            [Fact]
            public void HasDivisionOperator_GivenDensityAndVolume_ReturnsFalse()
            {
                Assert.False(HasDivisionOperator(typeof(Density), typeof(Volume)));
                Assert.DoesNotContain(typeof(Volume), GetDivisors(typeof(Density)));
            }

            [Fact]
            public void HasDivisionOperator_GivenMassAndVolume_ReturnsTrue()
            {
                Assert.True(HasDivisionOperator(typeof(Mass), typeof(Volume)));
                Assert.Contains(typeof(Volume), GetDivisors(typeof(Mass)));
                Assert.Equal(typeof(Density), GetDivisionResult(typeof(Mass), typeof(Volume)));
            }

            [Fact]
            public void HasMultiplicationOperator_GivenTwoQuantities_ReturnsTrueIfDimensionsMultiplicationIsValid()
            {
                var failed = new List<Tuple<QuantityInfo, QuantityInfo, QuantityInfo>>();
                foreach (QuantityInfo firstQuantity in Quantity.Infos)
                {
                    foreach (Type divisor in GetMultipliers(firstQuantity.ValueType))
                    {
                        QuantityInfo secondQuantity = Quantity.Infos.FirstOrDefault(x => x.ValueType == divisor);
                        if (secondQuantity == null)
                        {
                            continue; // scalers
                        }
                        BaseDimensions resultDimensions = firstQuantity.BaseDimensions * secondQuantity.BaseDimensions;
                        Type resultingType = GetMultiplicationResult(firstQuantity.ValueType, secondQuantity.ValueType);
                        QuantityInfo resultQuantity = Quantity.Infos.FirstOrDefault(x => x.ValueType == resultingType);
                        if (resultQuantity == null)
                        {
                            continue; // scalers
                        }
                        if (resultQuantity.BaseDimensions != resultDimensions)
                        {
                            failed.Add(new Tuple<QuantityInfo, QuantityInfo, QuantityInfo>(firstQuantity, secondQuantity, resultQuantity));
                        }
//                        Assert.Equal(resultQuantity.BaseDimensions, resultDimensions);
                    }
                }
                Assert.Empty(failed);
            }

            [Fact]
            public void HasDivisionOperator_GivenTwoQuantities_ReturnsTrueIfDimensionsDivisionIsValid()
            {
                var failed = new List<Tuple<QuantityInfo, QuantityInfo, QuantityInfo>>();
                foreach (QuantityInfo firstQuantity in Quantity.Infos)
                {
                    foreach (Type divisor in GetDivisors(firstQuantity.ValueType))
                    {
                        QuantityInfo secondQuantity = Quantity.Infos.FirstOrDefault(x => x.ValueType == divisor);
                        if (secondQuantity == null)
                        {
                            continue; // scalers
                        }
                        BaseDimensions resultDimensions = firstQuantity.BaseDimensions / secondQuantity.BaseDimensions;
                        Type resultingType = GetDivisionResult(firstQuantity.ValueType, secondQuantity.ValueType);
                        QuantityInfo resultQuantity = Quantity.Infos.FirstOrDefault(x => x.ValueType == resultingType);
                        if (resultQuantity == null)
                        {
                            continue; // scalers
                        }
                        if (resultQuantity.BaseDimensions != resultDimensions)
                        {
                            failed.Add(new Tuple<QuantityInfo, QuantityInfo, QuantityInfo>(firstQuantity, secondQuantity, resultQuantity));
                        }
//                        Assert.Equal(resultQuantity.BaseDimensions, resultDimensions);
                    }
                }
                Assert.Empty(failed);
            }

            private static bool HasMultiplicationOperator(Type t, Type operandType)
            {
                var operation = t.GetMethod("op_Multiply", new[] { t, operandType });
                return operation != null && operation.IsSpecialName;
            }

            private static bool HasDivisionOperator(Type t, Type operandType)
            {
                var operation = t.GetMethod("op_Division", new[] { t, operandType });
                return operation != null && operation.IsSpecialName;
            }

            private static Type GetMultiplicationResult(Type t, Type operandType)
            {
                var operation = t.GetMethod("op_Multiply", new[] { t, operandType });
                return operation != null && operation.IsSpecialName ? operation.ReturnType : null;
            }

            private static Type GetDivisionResult(Type t, Type operandType)
            {
                var operation = t.GetMethod("op_Division", new[] { t, operandType });
                return operation != null && operation.IsSpecialName ? operation.ReturnType : null;
            }

            private static IEnumerable<Type> GetMultipliers(Type t)
            {
                return t.GetMethods().Where(x => x.IsSpecialName && x.Name == "op_Multiply" && x.CustomAttributes.All(a => a.AttributeType != typeof(ObsoleteAttribute)))
                    .SelectMany(x => x.GetParameters().Skip(1).Select(p => p.ParameterType));
            }

            private static IEnumerable<Type> GetDivisors(Type t)
            {
                return t.GetMethods().Where(x => x.IsSpecialName && x.Name == "op_Division" && x.CustomAttributes.All(a => a.AttributeType != typeof(ObsoleteAttribute)))
                    .SelectMany(x => x.GetParameters().Skip(1).Select(p => p.ParameterType));
            }

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions