From 1fd11d33cb56fd7eff4dce05edaba1c9d8a1dccd Mon Sep 17 00:00:00 2001 From: Lei Hou Date: Thu, 16 Nov 2023 12:53:02 -0500 Subject: [PATCH] GH-38652: [MATLAB] Add tests about time precision preservation when converting MATLAB duration to `arrow.array.Time32Array` and `arrow.array.Time64Array` (#38661) ### Rationale for this change The current conversion from MATLAB duration to `arrow.array.Time32Array` and `arrow.array.Time64Array` loses time precision, and there is no test to cover such limitation. It is best practice to have tests cover software design. In addition, such tests will be helpful to evaluate the impact in the future when we improve the design. ### What changes are included in this PR? I mainly added three test cases for each of `arrow.array.Time32Array` and `arrow.array.Time64Array`. - Updated the basic test case to verify both class and value. In the MATLAB interface tests, we would like to verify the value to make sure there is no precision loss. The basic test case will serve as a test example when people learn to write tests. Updating the basic test case will set a good example for contributors to learn. - Test the default value of "TimeUnit". - Test the functionality of "TimeUnit". ### Are these changes tested? No software change. The updated test files passed on my local machine. ### Are there any user-facing changes? No * Closes: #38652 Authored-by: Lei Hou Signed-off-by: Kevin Gurney --- matlab/test/arrow/array/tTime32Array.m | 33 +++++++++++ matlab/test/arrow/array/tTime64Array.m | 76 ++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) diff --git a/matlab/test/arrow/array/tTime32Array.m b/matlab/test/arrow/array/tTime32Array.m index cc2fad64b2a28..24c3508a86015 100644 --- a/matlab/test/arrow/array/tTime32Array.m +++ b/matlab/test/arrow/array/tTime32Array.m @@ -30,6 +30,15 @@ function Basic(tc) times = seconds(1:4); array = tc.ArrowArrayConstructorFcn(times); tc.verifyInstanceOf(array, "arrow.array.Time32Array"); + tc.verifyEqual(array.toMATLAB, times'); + end + + function TimeUnitDefaultValue(tc) + % Verify that the default value of "TimeUnit" is "second". + times = seconds([1.2 1.3 1.4 1.5 1.7]); + array = tc.ArrowArrayConstructorFcn(times); + tc.verifyEqual(array.Type.TimeUnit, arrow.type.TimeUnit.Second); + tc.verifyEqual(array.toMATLAB, seconds([1;1;1;2;2])); end function TypeIsTime32(tc) @@ -274,6 +283,30 @@ function TestIsEqualFalseTimeUnitMistmatch(tc) % arrays are not equal tc.verifyFalse(isequal(array1, array2)); end + + function RoundTimeBySpecifiedTimeUnit(tc) + % Verify that the input parameter "TimeUnit" is used to specify + % the time resolution. The value is rounded off based on the + % specified "TimeUnit". + + % TimeUnit="Second" + matlabTimes = seconds([1.1, 1.4, 1.5, 1.9, 2.001]); + arrowTimes = tc.ArrowArrayConstructorFcn(matlabTimes, TimeUnit="Second"); + tc.verifyEqual(arrowTimes.toMATLAB(),seconds([1, 1, 2, 2, 2])'); + + % TimeUnit="Millisecond" + matlabTimes = seconds([1.1, 1.99, 1.001, 1.0004, 1.0005, 2.001]); + arrowTimes = tc.ArrowArrayConstructorFcn(matlabTimes, TimeUnit="Millisecond"); + tc.verifyEqual(arrowTimes.toMATLAB(),seconds([1.1, 1.99, 1.001, 1, 1.001, 2.001])','AbsTol',seconds(1e-15)); + end + + function TimeUnitIsReadOnly(tc) + % Verify that arrowArray.Type.TimeUnit cannot be changed. + + matlabTimes = seconds([1.1, 1.4, 1.5, 1.9, 2.001]); + arrowArray = tc.ArrowArrayConstructorFcn(matlabTimes); + tc.verifyError(@()setfield(arrowArray.Type,"TimeUnit", "millisecond"),'MATLAB:class:SetProhibited'); + end end methods diff --git a/matlab/test/arrow/array/tTime64Array.m b/matlab/test/arrow/array/tTime64Array.m index a078c5e2173f3..3f66ebd638c65 100644 --- a/matlab/test/arrow/array/tTime64Array.m +++ b/matlab/test/arrow/array/tTime64Array.m @@ -30,6 +30,26 @@ function Basic(tc) times = seconds(1:4); array = tc.ArrowArrayConstructorFcn(times); tc.verifyInstanceOf(array, "arrow.array.Time64Array"); + tc.verifyEqual(array.toMATLAB, times'); + end + + function TimeUnitDefaultValue(tc) + % Verify that the default value of "TimeUnit" is "Microsecond". + matlabTimes = seconds([1; ... + 0.001; ... + 2.004521; ... + 3.1234564; ... + 4.1234566; ... + 5.000000123]); + arrowArray = tc.ArrowArrayConstructorFcn(matlabTimes); + tc.verifyEqual(arrowArray.Type.TimeUnit, arrow.type.TimeUnit.Microsecond); + tc.verifyEqual(arrowArray.toMATLAB(), ... + seconds([1;... + 0.001; ... + 2.004521; ... + 3.123456; ... + 4.123457; ... + 5])); end function TypeIsTime64(tc) @@ -290,6 +310,62 @@ function TestIsEqualFalseTimeUnitMistmatch(tc) % arrays are not equal tc.verifyFalse(isequal(array1, array2)); end + + function RoundTimeBySpecifiedTimeUnit(tc) + % Verify that the input parameter "TimeUnit" is used to specify + % the time resolution. The value is rounded off based on the + % specified "TimeUnit". + + % TimeUnit="Microsecond" + matlabTimes = seconds([1.000001, ... + 2.999999, ... + 0.0002004, ... + 0.0000035, ... + 10.123456499, ... + 9.999999543]); + arrowTimes = tc.ArrowArrayConstructorFcn(matlabTimes, TimeUnit="Microsecond"); + tc.verifyEqual(arrowTimes.toMATLAB(), ... + seconds([1.000001, ... + 2.999999, ... + 0.0002, ... + 0.000004, ... + 10.123456, ... + 10])', ... + 'AbsTol',seconds(1e-14)); + + % TimeUnit="Nanosecond" + matlabTimes = seconds([1, ... + 1.123, ... + 1.12345, ... + 1.123456, ... + 1.1234567, ... + 1.12345678, ... + 1.123456789, ... + 1.1234567894, ... + 1.1234567895, ... + 1.123456789009]); + arrowTimes = tc.ArrowArrayConstructorFcn(matlabTimes, TimeUnit="Nanosecond"); + tc.verifyEqual(arrowTimes.toMATLAB(),... + seconds([1, ... + 1.123, ... + 1.12345, ... + 1.123456, ... + 1.1234567, ... + 1.12345678, ... + 1.123456789, ... + 1.123456789, ... + 1.123456790, ... + 1.123456789])',... + 'AbsTol',seconds(1e-15)); + end + + function TimeUnitIsReadOnly(tc) + % Verify that arrowArray.Type.TimeUnit cannot be changed. + + matlabTimes = seconds([1.000001, 2.999999, 0.0002004]); + arrowArray = tc.ArrowArrayConstructorFcn(matlabTimes); + tc.verifyError(@()setfield(arrowArray.Type,"TimeUnit", "Nanosecond"),'MATLAB:class:SetProhibited'); + end end methods