Skip to content

Commit

Permalink
Adjust tests for new Row.GetFloat() behavior. Add explicit range chec…
Browse files Browse the repository at this point in the history
…ks, to ensure no significant loss of information, when casting from double to float.

Signed-off-by: Laurents Meyer <laucomm@gmail.com>
  • Loading branch information
lauxjpn committed Sep 25, 2019
1 parent 3baee86 commit 4e97fee
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 3 deletions.
12 changes: 9 additions & 3 deletions src/MySqlConnector/Core/Row.cs
Original file line number Diff line number Diff line change
Expand Up @@ -353,9 +353,15 @@ public double GetDouble(int ordinal)
public float GetFloat(int ordinal)
{
var value = GetValue(ordinal);
return value is double doubleValue ? (float) doubleValue :
value is decimal decimalValue ? (float) decimalValue :
(float) value;

// Loss of precision is expected, significant loss of information is not.
// Use explicit range checks to guard against that.
return value switch
{
double doubleValue => (doubleValue >= float.MinValue && doubleValue <= float.MaxValue ? (float) doubleValue : throw new InvalidCastException("The value cannot be safely cast to Single.")),
decimal decimalValue => (float) decimalValue,
_ => (float) value
};
}

public MySqlDateTime GetMySqlDateTime(int ordinal)
Expand Down
8 changes: 8 additions & 0 deletions tests/Conformance.Tests/GetValueConversionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,13 @@ public GetValueConversionTests(SelectValueFixture fixture)
// the minimum date permitted by MySQL is 1000-01-01; override the minimum value for DateTime tests
public override void GetDateTime_for_minimum_Date() => TestGetValue(DbType.Date, ValueKind.Minimum, x => x.GetDateTime(0), new DateTime(1000, 1, 1));
public override void GetDateTime_for_minimum_DateTime() => TestGetValue(DbType.Date, ValueKind.Minimum, x => x.GetDateTime(0), new DateTime(1000, 1, 1));

// The GetFloat() implementation allows for conversions from double to float.
// The minimum tests for float and double do not test for the smallest possible value (as the tests for integer values do),
// but test for the largest value smaller than 0 (Epsilon).
// If double.Epsilon is converted to float, it will result in 0.
public override void GetFloat_throws_for_minimum_Double() => TestGetValue(DbType.Double, ValueKind.Minimum, x => x.GetFloat(0), 0);
public override void GetFloat_throws_for_one_Double() => TestGetValue(DbType.Double, ValueKind.One, x => x.GetFloat(0), 1);
public override void GetFloat_throws_for_zero_Double() => TestGetValue(DbType.Double, ValueKind.Zero, x => x.GetFloat(0), 0);
}
}

0 comments on commit 4e97fee

Please sign in to comment.