Closed
Description
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));
}