diff --git a/src/Hl7.Fhir.Base/CompatibilitySuppressions.xml b/src/Hl7.Fhir.Base/CompatibilitySuppressions.xml index c5bb7b18b9..864efe3716 100644 --- a/src/Hl7.Fhir.Base/CompatibilitySuppressions.xml +++ b/src/Hl7.Fhir.Base/CompatibilitySuppressions.xml @@ -8,6 +8,13 @@ lib/net8.0/Hl7.Fhir.Base.dll true + + CP0001 + T:Hl7.Fhir.ElementModel.Types.MetricConfiguration + lib/net8.0/Hl7.Fhir.Base.dll + lib/net8.0/Hl7.Fhir.Base.dll + true + CP0001 T:Hl7.Fhir.Introspection.BackboneTypeAttribute @@ -28,6 +35,13 @@ lib/netstandard2.0/Hl7.Fhir.Base.dll true + + CP0001 + T:Hl7.Fhir.ElementModel.Types.MetricConfiguration + lib/netstandard2.0/Hl7.Fhir.Base.dll + lib/netstandard2.0/Hl7.Fhir.Base.dll + true + CP0001 T:Hl7.Fhir.Introspection.BackboneTypeAttribute diff --git a/src/Hl7.Fhir.Base/ElementModel/Types/Quantity.cs b/src/Hl7.Fhir.Base/ElementModel/Types/Quantity.cs index 025ce1c198..8804fe72b6 100644 --- a/src/Hl7.Fhir.Base/ElementModel/Types/Quantity.cs +++ b/src/Hl7.Fhir.Base/ElementModel/Types/Quantity.cs @@ -32,7 +32,12 @@ public enum QuantityUnitSystem /// /// Unit is taken from the set of calendar units (year or month) /// - CalendarDuration + CalendarDuration, + + /// + /// Unit is not specified to be part of any coding system. + /// + Unknown } @@ -73,16 +78,16 @@ public static Quantity ForCalendarDuration(decimal value, string calendarUnit) } private static readonly string QUANTITY_BASE_REGEX = - @"(?'value'(\+|-)?\d+(\.\d+)?)\s*(('(?'unit'[^\']+)')|(?'time'[a-zA-Z]+))"; + @"(?'value'(\+|-)?\d+(\.\d+)?)\s*(('(?'unit'[^\']+)')|(?'time'[a-zA-Z]+))"; public static readonly Regex QUANTITYREGEX = - new(QUANTITY_BASE_REGEX, RegexOptions.ExplicitCapture | RegexOptions.Compiled); + new(QUANTITY_BASE_REGEX, RegexOptions.ExplicitCapture | RegexOptions.Compiled); internal static readonly Regex QUANTITYREGEX_FOR_PARSE = new($"^{QUANTITY_BASE_REGEX}?$", RegexOptions.ExplicitCapture | RegexOptions.Compiled); public static Quantity Parse(string representation) => - TryParse(representation, out var result) ? result : throw new FormatException($"String '{representation}' was not recognized as a valid quantity."); + TryParse(representation, out var result) ? result : throw new FormatException($"String '{representation}' was not recognized as a valid quantity."); public static bool TryParse(string representation, [NotNullWhen(true)] out Quantity? quantity) { @@ -105,7 +110,8 @@ public static bool TryParse(string representation, [NotNullWhen(true)] out Quant { if (TryParseTimeUnit(result.Groups["time"].Value, out var tv, out var isCalendarUnit)) { - quantity = isCalendarUnit ? ForCalendarDuration(value, tv) + quantity = isCalendarUnit + ? ForCalendarDuration(value, tv) : new Quantity(value, tv); return true; } @@ -200,18 +206,16 @@ public bool Equals(Any other, QuantityComparison comparisonType) => /// /// For time-valued quantities, the comparison of /// calendar durations and definite quantity durations above seconds is determined by the - public Result TryEquals(Any other, QuantityComparison comparisonType) => other is Quantity ? - TryCompareTo(other, comparisonType).Select(i => i == 0) : false; + public Result TryEquals(Any other, QuantityComparison comparisonType) => other is Quantity ? TryCompareTo(other, comparisonType).Select(i => i == 0) : false; - public static bool operator ==(Quantity a, Quantity b) => Equals(a, b); - public static bool operator !=(Quantity a, Quantity b) => !Equals(a, b); + public static bool operator ==(Quantity a, Quantity b) => a.CompareTo(b) == 0; + public static bool operator !=(Quantity a, Quantity b) => a.CompareTo(b) != 0; /// /// Compare two datetimes based on CQL equivalence rules /// /// See for more details. - public int CompareTo(object? obj) => obj is Quantity q ? - TryCompareTo(q, CQL_EQUIVALENCE_COMPARISON).ValueOrThrow() : throw NotSameTypeComparison(this, obj); + public int CompareTo(object? obj) => obj is Quantity q ? TryCompareTo(q, CQL_EQUIVALENCE_COMPARISON).ValueOrThrow() : throw NotSameTypeComparison(this, obj); public static bool operator <(Quantity a, Quantity b) => a.CompareTo(b) < 0; public static bool operator <=(Quantity a, Quantity b) => a.CompareTo(b) <= 0; @@ -236,24 +240,17 @@ public Result TryCompareTo(Any? other, QuantityComparison comparisonType) if (IsDuration && otherQ.IsDuration) return doDurationComparison(otherQ, comparisonType); - if (System != QuantityUnitSystem.UCUM || otherQ.System != QuantityUnitSystem.UCUM) + if (System != otherQ.System) { - return Fail(Error.NotSupported("Comparing quantities with system other than UCUM is not supported")); + return Fail(Error.NotSupported("Comparing a UCUM quantity with a non-UCUM quantity is not supported.")); } - Quantity? left = this; - Quantity? right = otherQ; - - if (Unit != otherQ.Unit) - { - // align units with each other - if (!this.TryCanonicalize(out left)) left = this; - if (!otherQ.TryCanonicalize(out right)) right = otherQ; - } + Quantity left = this; + Quantity right = otherQ; return (left.Unit == right.Unit) - ? decimal.Compare(Math.Round(left.Value, 8), Math.Round(right.Value, 8)) // aligns with Decimal - : Fail(Error.InvalidOperation($"UCUM quanties with unit '{left.Unit}' and '{right.Unit}' cannot be compared.")); + ? decimal.Compare(Math.Round(left.Value, 8), Math.Round(right.Value, 8)) // aligns with Decimal + : Fail(Error.InvalidOperation($"Quantities with differing units '{left.Unit}' and '{right.Unit}' cannot be compared.")); } private Result doDurationComparison(Quantity other, QuantityComparison comparisonType) @@ -264,7 +261,7 @@ private Result doDurationComparison(Quantity other, QuantityComparison comp if (l.Unit != r.Unit) return Fail(Error.InvalidOperation($"Durations of {l.Unit} and {r.Unit} cannot be compared,")); else - return decimal.Compare(Math.Round(l.Value, 8), Math.Round(r.Value, 8)); // aligns with Decimal + return decimal.Compare(Math.Round(l.Value, 8), Math.Round(r.Value, 8)); // aligns with Decimal Quantity normalizeToUcum(Quantity orig) { @@ -305,27 +302,6 @@ Quantity normalizeToUcum(Quantity orig) /// to specify comparison behaviour for date comparisons. public Result TryCompareTo(Any other) => TryCompareTo(other, CQL_EQUIVALENCE_COMPARISON); - - private static (Quantity, Quantity) alignQuantityUnits(Quantity a, Quantity b) - { - if (a.System != QuantityUnitSystem.UCUM || b.System != QuantityUnitSystem.UCUM) - { - Error.NotSupported("Arithmetic operations on quantities using systems other than UCUM are not supported."); - } - - Quantity? left = a; - Quantity? right = b; - - if (a.Unit != b.Unit) - { - // align units with each other - if (!a.TryCanonicalize(out left)) left = a; - if (!b.TryCanonicalize(out right)) right = b; - } - - return (left, right); - } - public static Quantity? operator +(Quantity a, Quantity b) => Add(a, b).ValueOrDefault(); @@ -338,48 +314,30 @@ private static (Quantity, Quantity) alignQuantityUnits(Quantity a, Quantity b) public static Quantity? operator /(Quantity a, Quantity b) => Divide(a, b).ValueOrDefault(); - internal static Result Add(Quantity a, Quantity b) + internal static Result Add(Quantity left, Quantity right) { - var (left, right) = alignQuantityUnits(a, b); - return (left.Unit == right.Unit) ? Ok(new(left.Value + right.Value, left.Unit)) - : Fail(Error.InvalidOperation($"The add operation cannot be performed on quantities with units '{left.Unit}' and '{right.Unit}'.")); + : Fail(Error.InvalidOperation($"The add operation cannot be performed on quantities with differing units '{left.Unit}' and '{right.Unit}'.")); } - internal static Result Substract(Quantity a, Quantity b) + internal static Result Substract(Quantity left, Quantity right) { - var (left, right) = alignQuantityUnits(a, b); - return (left.Unit == right.Unit) ? Ok(new(left.Value - right.Value, left.Unit)) - : Fail(Error.InvalidOperation($"The substract operation cannot be performed on quantities with units '{left.Unit}' and '{right.Unit}'.")); + : Fail(Error.InvalidOperation($"The substract operation cannot be performed on quantities with differing units '{left.Unit}' and '{right.Unit}'.")); } - internal static Result Multiply(Quantity a, Quantity b) + internal static Result Multiply(Quantity left, Quantity right) { - var (left, right) = alignQuantityUnits(a, b); - - if (!left.TryMultiply(right, out var result)) - { - return Fail(Error.InvalidOperation($"The multiply operation cannot be performed on quantities with units '{left.Unit}' and '{right.Unit}'.")); - } - - return Ok(result); + return Ok(new(left.Value * right.Value, $"({left.Unit}).({right.Unit})")); } - internal static Result Divide(Quantity a, Quantity b) + internal static Result Divide(Quantity left, Quantity right) { - if (b.Value == 0) return Fail(Error.InvalidOperation("Cannot divide by zero.")); + if (right.Value == 0) return Fail(Error.InvalidOperation("Cannot divide by zero.")); - var (left, right) = alignQuantityUnits(a, b); - - if (!left.TryDivide(right, out var result)) - { - return Fail(Error.InvalidOperation($"The divide operation cannot be performed on quantities with units '{left.Unit}' and '{right.Unit}'.")); - } - - return Ok(result); + return Ok(new(left.Value / right.Value, $"({left.Unit})/({right.Unit})")); } public override int GetHashCode() => (Unit, Value).GetHashCode(); diff --git a/src/Hl7.Fhir.Base/ElementModel/Types/Ucum.cs b/src/Hl7.Fhir.Base/ElementModel/Types/Ucum.cs deleted file mode 100644 index f16280ddcb..0000000000 --- a/src/Hl7.Fhir.Base/ElementModel/Types/Ucum.cs +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2019, Firely (info@fire.ly) and contributors - * See the file CONTRIBUTORS for details. - * - * This file is licensed under the BSD 3-Clause license - * available at https://raw.githubusercontent.com/FirelyTeam/firely-net-sdk/master/LICENSE - */ - -#nullable enable - -using Fhir.Metrics; -using M = Fhir.Metrics; -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; - -namespace Hl7.Fhir.ElementModel.Types -{ - public static class MetricConfiguration - { - [CLSCompliant(false)] - public static Lazy MetricService { get; set; } = new(() => FhirMetricService.Instance.Value); - } - - internal static class Ucum - { - private static readonly IMetricService METRIC_SERVICE = MetricConfiguration.MetricService.Value; - - /// - /// Try to canonicalize the system type quantity to Umum base quantity. So a 1,000 cm will be 10 m. Or an inch will be converted to a meter. - /// - /// A system type Quantity of system Ucum - /// The converted system type Quantity when the conversion was a success. - /// true when the conversion succeeded. Or false otherwise. - internal static bool TryCanonicalize(this Quantity quantity, [NotNullWhen(true)] out Quantity? canonicalizedQuantity) - { - var qtyTuple = ( - quantity.Value.ToString(CultureInfo.InvariantCulture), - quantity.Unit, - quantity.System == QuantityUnitSystem.UCUM ? "http://unitsofmeasure.org" : "" - ); - - if (!METRIC_SERVICE.TryCanonicalize(qtyTuple, out var canonicalized)) - { - canonicalizedQuantity = null; - return false; - } - - canonicalizedQuantity = quantityFromTuple(canonicalized!.Value); - - return true; - } - - internal static bool TryMultiply(this Quantity quantity, Quantity multiplier, [NotNullWhen(true)] out Quantity? result) - { - var qty1 = ( - quantity.Value.ToString(CultureInfo.InvariantCulture), - quantity.Unit, - quantity.System == QuantityUnitSystem.UCUM ? "http://unitsofmeasure.org" : "" - ); - var qty2 = ( - multiplier.Value.ToString(CultureInfo.InvariantCulture), - multiplier.Unit, - multiplier.System == QuantityUnitSystem.UCUM ? "http://unitsofmeasure.org" : "" - ); - - if (!METRIC_SERVICE.TryMultiply(qty1, qty2, out var resultTuple)) - { - result = null; - return false; - } - - result = quantityFromTuple(resultTuple!.Value); - - return true; - } - - internal static bool TryDivide(this Quantity quantity, Quantity divisor, [NotNullWhen(true)] out Quantity? result) - { - var qty1 = ( - quantity.Value.ToString(CultureInfo.InvariantCulture), - quantity.Unit, - quantity.System == QuantityUnitSystem.UCUM ? "http://unitsofmeasure.org" : "" - ); - var qty2 = ( - divisor.Value.ToString(CultureInfo.InvariantCulture), - divisor.Unit, - divisor.System == QuantityUnitSystem.UCUM ? "http://unitsofmeasure.org" : "" - ); - - if (!METRIC_SERVICE.TryDivide(qty1, qty2, out var resultTuple)) - { - result = null; - return false; - } - - result = quantityFromTuple(resultTuple!.Value); - - return true; - } - - private static Quantity quantityFromTuple((string value, string unit, string codesystem) quantity) - { - return new Quantity( - decimal.Parse(quantity.value, NumberStyles.Any, CultureInfo.InvariantCulture), - quantity.unit == "" ? "1" : quantity.unit, - QuantityUnitSystem.UCUM - ); - } - } -} - -#nullable restore diff --git a/src/Hl7.Fhir.Base/Hl7.Fhir.Base.csproj b/src/Hl7.Fhir.Base/Hl7.Fhir.Base.csproj index 44011e9614..2a197046d4 100644 --- a/src/Hl7.Fhir.Base/Hl7.Fhir.Base.csproj +++ b/src/Hl7.Fhir.Base/Hl7.Fhir.Base.csproj @@ -16,7 +16,6 @@ - diff --git a/src/Hl7.Fhir.Support.Tests/ElementModel/QuantityTests.cs b/src/Hl7.Fhir.Support.Tests/ElementModel/QuantityTests.cs index fa8a62c93e..b76e14a5bf 100644 --- a/src/Hl7.Fhir.Support.Tests/ElementModel/QuantityTests.cs +++ b/src/Hl7.Fhir.Support.Tests/ElementModel/QuantityTests.cs @@ -95,12 +95,11 @@ public void DifferentUnitsNotSupported() { var a = new Quantity(3.14m, "kg"); var b = new Quantity(30.5m, "g"); - /* + Func func = () => a < b; - ExceptionAssert.Throws); - Assert.IsFalse(a == b); - ExceptionAssert.Throws(() => a >= b); - Assert.IsFalse(a.Equals(b));*/ + func.Should().Throw(); + func = () => a == b; + func.Should().Throw(); } public enum Comparison @@ -110,67 +109,24 @@ public enum Comparison GreaterThan } - [DataTestMethod] - [DataRow("1 'm'", "1 'm'", Comparison.Equals)] - [DataRow("1 'm'", "2 'm'", Comparison.LessThan)] - [DataRow("1 'cm'", "1 'm'", Comparison.LessThan)] - [DataRow("30.0 'g'", "0.03 'kg'", Comparison.Equals)] - [DataRow("1 '[in_i]'", "2 'cm'", Comparison.GreaterThan)] // 1 inch is greater than 2 - [DataRow("1 '[stone_av]'", "6350.29318 'g'", Comparison.Equals)] - [DataRow("3 'hr'", "3 'h'", Comparison.Equals, true)] - [DataRow("3 'a'", "3 year", Comparison.Equals)] - [DataRow("3 'a'", "3 years", Comparison.Equals)] - [DataRow("3 'mo'", "3 months", Comparison.Equals)] - [DataRow("3 'd'", "3 days", Comparison.Equals)] - [DataRow("1 'd'", "3 days", Comparison.LessThan)] - public void QuantityCompareTests(string left, string right, Comparison expectedResult, bool shouldThrowException = false) - { - Quantity.TryParse(left, out var a).Should().BeTrue(); - Quantity.TryParse(right, out var b).Should().BeTrue(); - - Func func = () => a!.CompareTo(b); - - if (shouldThrowException) - { - func.Should().Throw(); - return; - } - var result = func(); - - switch (expectedResult) - { - case Comparison.LessThan: - result.Should().BeNegative(); - break; - case Comparison.Equals: - result.Should().Be(0); - break; - case Comparison.GreaterThan: - result.Should().BePositive(); - break; - } - } - public static IEnumerable ArithmeticTestdata => new[] { ["25 'kg'", "5 'kg'", "30 'kg'" , (object)Quantity.Add], - ["25 'kg'", "1000 'g'", "26000 'g'", (object)Quantity.Add], + ["25000 'g'", "1000 'g'", "26000 'g'", (object)Quantity.Add], ["3 '[in_i]'", "2 '[in_i]'", "5 '[in_i]'", (object)Quantity.Add], - ["4.0 'kg.m/s2'", "2000 'g.m.s-2'", "6000 'g.m.s-2'", (object)Quantity.Add], - ["3 'm'", "3 'cm'", "303 'cm'", (object)Quantity.Add], - ["3 'm'", "0 'cm'","300 'cm'", (object)Quantity.Add], - ["3 'm'", "-80 'cm'", "220 'cm'", (object)Quantity.Add], + ["4.0 'kg.m/s2'", "2.0 'kg.m/s2'", "6.0 'kg.m/s2'", (object)Quantity.Add], + ["3 'm'", "0.03 'm'", "3.03 'm'", (object)Quantity.Add], + ["3 'm'", "0 'm'","3 'm'", (object)Quantity.Add], + ["3 'm'", "-0.8 'm'", "2.2 'm'", (object)Quantity.Add], ["3 'm'", "0 'kg'", null, (object)Quantity.Add], - ["25 'kg'", "500 'g'", "24500 'g'", (object)Quantity.Substract], - ["25 'kg'", "25001 'g'", "-1 'g'", (object)Quantity.Substract], - ["1 '[in_i]'", "2 'cm'", "0.005400 'm'", (object)Quantity.Substract], + ["25000 'g'", "500 'g'", "24500 'g'", (object)Quantity.Substract], + ["25000 'g'", "25001 'g'", "-1 'g'", (object)Quantity.Substract], ["1 '[in_i]'", "2 'kg'", null, (object)Quantity.Substract], - ["25 'km'", "20 'cm'", "5000 'm2'", (object)Quantity.Multiply], - ["2.0 'cm'", "2.0 'm'", "0.040 'm2'", (object)Quantity.Multiply], - ["2.0 'cm'", "9 'kg'", "180 'g.m'", (object)Quantity.Multiply], - ["14.4 'km'", "2.0 'h'", "2 'm.s-1'", (object)Quantity.Divide], - ["9 'm2'", "3 'm'", "3 'm'", (object)Quantity.Divide], - ["6 'm'", "3 'm'", "2 '1'", (object)Quantity.Divide], + ["25 'm'", "20 'm'", "500 '(m).(m)'", (object)Quantity.Multiply], + ["2.0 'cm'", "9 'kg'", "18 '(cm).(kg)'", (object)Quantity.Multiply], + ["14.4 'km'", "2.0 'h'", "7.2 '(km)/(h)'", (object)Quantity.Divide], + ["9 'm2'", "3 'm'", "3 '(m2)/(m)'", (object)Quantity.Divide], + ["6 'm'", "3 'm'", "2 '(m)/(m)'", (object)Quantity.Divide], new[] { "3 'm'", "0 'cm'", null, (object)Quantity.Divide } }; diff --git a/src/Hl7.Fhir.Support.Tests/ElementModel/UcumTests.cs b/src/Hl7.Fhir.Support.Tests/ElementModel/UcumTests.cs deleted file mode 100644 index 0406ef24c7..0000000000 --- a/src/Hl7.Fhir.Support.Tests/ElementModel/UcumTests.cs +++ /dev/null @@ -1,34 +0,0 @@ -#nullable enable - -using FluentAssertions; -using Hl7.Fhir.ElementModel.Types; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; - -namespace Hl7.Fhir.Support.Tests.ElementModel -{ - [TestClass] - public class UcumTests - { - [DataTestMethod] - [DataRow(1.0, "m", true, "m")] - [DataRow(1.0, "cm", true, "m")] - [DataRow(1.0, "mm", true, "m")] - [DataRow(1.0, "[in_i]", true, "m")] - [DataRow(1.0, "[stone_av]", true, "g")] //britisch stone - [DataRow(1.0, "m[H2O]", true, "g.m-1.s-2")] // meter of water column - [DataRow(1.0, "unknown", false, null)] - public void TryCanonicalizeTests(double val, string unit, bool exptectedResult, string? expectedUnit) - { - var input = new Quantity(Convert.ToDecimal(val), unit); - - var result = input.TryCanonicalize(out var convertedQuantity); - - result.Should().Be(exptectedResult); - var u = convertedQuantity?.Unit; - u.Should().Be(expectedUnit); - } - } -} - -#nullable restore \ No newline at end of file diff --git a/src/Hl7.Fhir.Support.Tests/FhirPath/FhirPathTests.cs b/src/Hl7.Fhir.Support.Tests/FhirPath/FhirPathTests.cs index c8f8e94ef1..e96465eed5 100644 --- a/src/Hl7.Fhir.Support.Tests/FhirPath/FhirPathTests.cs +++ b/src/Hl7.Fhir.Support.Tests/FhirPath/FhirPathTests.cs @@ -134,7 +134,7 @@ public static IEnumerable HighBoundaryTestCases() => public static IEnumerable ComparableTestCases() => new (string expression, bool expected)[] { - ("1 'cm'.comparable(1 '[in_i]')", true), + ("1 'cm'.comparable(1 '[in_i]')", false), ("1 week.comparable(1 'wk')", true), ("1 'cm'.comparable(1 's')", false), }.Select(t => new object[] { t.expression, t.expected }); diff --git a/src/Hl7.FhirPath.Tests/Functions/MathOperatorsTests.cs b/src/Hl7.FhirPath.Tests/Functions/MathOperatorsTests.cs index d91c9b506f..e3461354ad 100644 --- a/src/Hl7.FhirPath.Tests/Functions/MathOperatorsTests.cs +++ b/src/Hl7.FhirPath.Tests/Functions/MathOperatorsTests.cs @@ -29,70 +29,6 @@ public void Power() 2m.Power(2m).Should().BeOfType(typeof(decimal)); } - - private static IEnumerable QuantityAddOperations() => - new (string expression, bool expected, bool invalid)[] - { - ("25 'kg' + 5 'kg' = 30 'kg'", true, false), - ("3 '[in_i]' + 2 '[in_i]' = 5 '[in_i]'", true, false), - ("3 'm' + 0 'cm' = 300 'cm'", true, false), - ("(3 'm' + 0 'kg').empty()", true, false), - }.Select(t => new object[] { t.expression, t.expected, t.invalid }); - - private static IEnumerable QuantitySubstractOperations() => - new (string expression, bool expected, bool invalid)[] - { - ("25 'kg' - 500 'g' = 24500 'g'", true, false), - ("25 'kg' - 25001 'g' = -1 'g'", true, false), - ("1 '[in_i]' - 2 'cm' = 0.005400 'm'", true, false), - ("(3 '[in_i]' - 0 'kg').empty()", true, false), - }.Select(t => new object[] { t.expression, t.expected, t.invalid }); - - private static IEnumerable QuantityMultiplyOperations() => - new (string expression, bool expected, bool invalid)[] - { - ("25 'km' * 20 'cm' = 5000 'm2'", true, false), - ("2 'cm' * 2 'm' = 0.040 'm2'", true, false), - ("2 'cm' * 9 'kg' = 180 'g.m'", true, false), - }.Select(t => new object[] { t.expression, t.expected, t.invalid }); - - private static IEnumerable QuantityDivideOperations() => - new (string expression, bool expected, bool invalid)[] - { - ("14.4 'km' / 2 'h' = 2 'm.s-1'", true, false), - ("9 'm2' / 3 'm' = 3 'm'", true, false), - ("6 'm' / 3 'm' = 2 '1'", true, false), - ("(3 'm' / 0 'cm').empty()", true, false), - }.Select(t => new object[] { t.expression, t.expected, t.invalid }); - - public static IEnumerable AllQuantityOperations() - { - return - Enumerable.Empty() - .Union(QuantityAddOperations()) - .Union(QuantitySubstractOperations()) - .Union(QuantityMultiplyOperations()) - .Union(QuantityDivideOperations()) - ; - } - - [DataTestMethod] - [DynamicData(nameof(AllQuantityOperations), DynamicDataSourceType.Method)] - public void AssertTestcases(string expression, bool expected, bool invalid = false) - { - ITypedElement dummy = ElementNode.ForPrimitive(true); - - if (invalid) - { - Action act = () => dummy.IsBoolean(expression, expected); - act.Should().Throw(); - } - else - { - dummy.IsBoolean(expression, expected) - .Should().BeTrue(because: $"The expression was supposed to result in {expected}."); - } - } } diff --git a/src/Hl7.FhirPath.Tests/Functions/OperationsTests.cs b/src/Hl7.FhirPath.Tests/Functions/OperationsTests.cs index 6e9133d15c..7ffe3faeae 100644 --- a/src/Hl7.FhirPath.Tests/Functions/OperationsTests.cs +++ b/src/Hl7.FhirPath.Tests/Functions/OperationsTests.cs @@ -93,7 +93,6 @@ private static IEnumerable GreaterThanOperatorTestcases() => ("10 > 5.0", true, false), ("'abc' > 'ABC'", true, false), ("8 'm' > 4 'm'", true, false), - ("(4 'm' > 4 'cm')", true, false), ("@2018-03-01 > @2018-01-01", true, false), ("(@2018-03 > @2018-03-01).empty()", true, false), ("@2018-03-01T10:30:00 > @2018-03-01T10:00:00", true, false), @@ -111,7 +110,6 @@ private static IEnumerable LessThanOperatorTestcases() => ("10 < 5.0", false, false), ("'abc' < 'ABC'", false, false), ("8 'm' < 4 'm'", false, false), - ("(4 'm' < 4 'cm')", false, false), ("@2018-03-01 < @2018-01-01", false, false), ("(@2018-03 < @2018-03-01).empty()", true, false), ("@2018-03-01T10:30:00 < @2018-03-01T10:00:00", false, false), @@ -129,7 +127,6 @@ private static IEnumerable LessOrEqualOperatorTestcases() => ("10 <= 5.0", false, false), ("'abc' <= 'ABC'", false, false), ("8 'm' <= 4 'm'", false, false), - ("(4 'm' <= 4 'cm')", false, false), ("@2018-03-01 <= @2018-01-01", false, false), ("(@2018-03 <= @2018-03-01).empty()", true, false), ("@2018-03-01T10:30:00 <= @2018-03-01T10:00:00", false, false), @@ -147,7 +144,6 @@ private static IEnumerable GreaterOrEqualOperatorTestcases() => ("10 >= 5.0", true, false), ("'abc' >= 'ABC'", true, false), ("8 'm' >= 4 'm'", true, false), - ("(4 'm' >= 4 'cm')", true, false), ("@2018-03-01 >= @2018-01-01", true, false), ("(@2018-03 >= @2018-03-01).empty()", true, false), ("@2018-03-01T10:30:00 >= @2018-03-01T10:00:00", true, false),