From 19464940acd5c44385f961c82f1529744c64b908 Mon Sep 17 00:00:00 2001 From: Nick Guletskii Date: Sat, 25 Apr 2020 02:54:03 +0300 Subject: [PATCH 01/11] Load the user's locale before performing tests --- conftest.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/conftest.py b/conftest.py index dad6854ee30c..caabaf9d74b9 100644 --- a/conftest.py +++ b/conftest.py @@ -108,6 +108,11 @@ def pytest_configure(): logging.warning('*** test-level seed set: all "@with_seed()" ' 'tests run deterministically ***') + # Load the user's locale settings to verify that MXNet works correctly when the C locale is set + # to anything other than the default value. Please see #16134 for an example of a bug caused by + # incorrect handling of C locales. + import locale + locale.setlocale(locale.LC_ALL, "") @pytest.hookimpl(tryfirst=True, hookwrapper=True) def pytest_runtest_makereport(item, call): From 1bc49a1419c25e4ca5fc439d5145c14bb5655c34 Mon Sep 17 00:00:00 2001 From: Nick Guletskii Date: Sat, 25 Apr 2020 02:54:44 +0300 Subject: [PATCH 02/11] Change the locale for the CentOS CI jobs to weed out locale-related bugs --- ci/docker/Dockerfile.build.centos7 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ci/docker/Dockerfile.build.centos7 b/ci/docker/Dockerfile.build.centos7 index eef3f90cbd2a..5214c6dad587 100644 --- a/ci/docker/Dockerfile.build.centos7 +++ b/ci/docker/Dockerfile.build.centos7 @@ -111,6 +111,10 @@ COPY install/docker_filepermissions.sh /work/ RUN /work/docker_filepermissions.sh ENV PYTHONPATH=./python/ +# Verify that MXNet works correctly when the C locale is set to a locale that uses a comma as the +# decimal separator. Please see #16134 for an example of a bug caused by incorrect handling of +# number serialization and deserialization. +ENV LC_NUMERIC=en_DK.UTF-8 WORKDIR /work/mxnet COPY runtime_functions.sh /work/ From 0ebbc4fcc59fba0ad34f57a375291c0722b68ff3 Mon Sep 17 00:00:00 2001 From: Nick Guletskii Date: Tue, 5 May 2020 21:08:04 +0300 Subject: [PATCH 03/11] Mark tests that fail due to the decimal point with xfail --- tests/python/unittest/common.py | 7 +++++++ tests/python/unittest/test_autograd.py | 3 ++- tests/python/unittest/test_contrib_autograd.py | 3 ++- tests/python/unittest/test_contrib_operator.py | 4 +++- .../python/unittest/test_contrib_optimizer.py | 4 +++- tests/python/unittest/test_contrib_stes_op.py | 4 +++- tests/python/unittest/test_gluon.py | 4 +++- .../python/unittest/test_gluon_data_vision.py | 4 +++- tests/python/unittest/test_gluon_trainer.py | 4 +++- .../python/unittest/test_higher_order_grad.py | 6 ++++-- tests/python/unittest/test_image.py | 3 ++- tests/python/unittest/test_loss.py | 5 ++++- tests/python/unittest/test_metric.py | 3 ++- tests/python/unittest/test_numpy_ndarray.py | 3 ++- tests/python/unittest/test_operator.py | 6 +++++- tests/python/unittest/test_optimizer.py | 18 +++++++++++++++++- tests/python/unittest/test_sparse_ndarray.py | 3 ++- 17 files changed, 67 insertions(+), 17 deletions(-) diff --git a/tests/python/unittest/common.py b/tests/python/unittest/common.py index 7f0f232b69e2..46513b29b7f9 100644 --- a/tests/python/unittest/common.py +++ b/tests/python/unittest/common.py @@ -31,6 +31,13 @@ from contextlib import contextmanager import pytest from tempfile import TemporaryDirectory +import locale + +xfail_when_nonstandard_decimal_point = pytest.mark.xfail( + locale.localeconv()["decimal_point"] != ".", + reason="Some operators break when the decimal point is set to anything other than \".\". These " + "operators should be rewritten to utilize the new FFI. Please see #18097 for more information." +) def assertRaises(expected_exception, func, *args, **kwargs): try: diff --git a/tests/python/unittest/test_autograd.py b/tests/python/unittest/test_autograd.py index 69b61b47d4c9..cb021dcb4ea5 100644 --- a/tests/python/unittest/test_autograd.py +++ b/tests/python/unittest/test_autograd.py @@ -20,7 +20,7 @@ from mxnet.ndarray import zeros_like from mxnet.autograd import * from mxnet.test_utils import * -from common import setup_module, with_seed, teardown_module +from common import setup_module, with_seed, teardown_module, xfail_when_nonstandard_decimal_point from mxnet.test_utils import EnvManager @@ -107,6 +107,7 @@ def autograd_assert(*args, **kwargs): for a, b in zip(grad_vals, grad_res): assert same(a.asnumpy(), b.asnumpy()) +@xfail_when_nonstandard_decimal_point @with_seed() def test_unary_func(): def check_unary_func(x): diff --git a/tests/python/unittest/test_contrib_autograd.py b/tests/python/unittest/test_contrib_autograd.py index c376eb7794f8..c8bce819421a 100644 --- a/tests/python/unittest/test_contrib_autograd.py +++ b/tests/python/unittest/test_contrib_autograd.py @@ -18,7 +18,7 @@ import mxnet.ndarray as nd from mxnet.contrib.autograd import * from mxnet.test_utils import * -from common import setup_module, with_seed, teardown_module +from common import setup_module, with_seed, teardown_module, xfail_when_nonstandard_decimal_point def autograd_assert(*args, **kwargs): func = kwargs["func"] @@ -34,6 +34,7 @@ def autograd_assert(*args, **kwargs): for a, b in zip(grad_vals, grad_res): assert same(a.asnumpy(), b.asnumpy()) +@xfail_when_nonstandard_decimal_point @with_seed() def test_unary_func(): x = nd.uniform(shape=(4, 5)) diff --git a/tests/python/unittest/test_contrib_operator.py b/tests/python/unittest/test_contrib_operator.py index 717ce7f20f95..3826a8fa476d 100644 --- a/tests/python/unittest/test_contrib_operator.py +++ b/tests/python/unittest/test_contrib_operator.py @@ -23,7 +23,8 @@ import itertools from numpy.testing import assert_allclose, assert_array_equal from mxnet.test_utils import * -from common import with_seed, assert_raises_cudnn_not_satisfied +from common import with_seed, assert_raises_cudnn_not_satisfied, \ + xfail_when_nonstandard_decimal_point import unittest def test_box_nms_op(): @@ -285,6 +286,7 @@ def test_multibox_target_op(): assert_array_equal(loc_mask.asnumpy(), expected_loc_mask) assert_array_equal(cls_target.asnumpy(), expected_cls_target) +@xfail_when_nonstandard_decimal_point def test_gradient_multiplier_op(): # We use the quadratic function in combination with gradient multiplier def f(x, a, b, c): diff --git a/tests/python/unittest/test_contrib_optimizer.py b/tests/python/unittest/test_contrib_optimizer.py index 9facfb2cc26c..7d858cccb462 100644 --- a/tests/python/unittest/test_contrib_optimizer.py +++ b/tests/python/unittest/test_contrib_optimizer.py @@ -23,9 +23,10 @@ curr_path = os.path.dirname(os.path.abspath(os.path.expanduser(__file__))) sys.path.insert(0, os.path.join(curr_path, '../unittest')) -from common import with_seed +from common import with_seed, xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_point def test_group_adagrad(): mx.random.seed(0) opt1 = mx.optimizer.contrib.GroupAdaGrad @@ -61,6 +62,7 @@ def test_group_adagrad(): g_stype='row_sparse') +@xfail_when_nonstandard_decimal_point @with_seed() @pytest.mark.serial def test_adamw(): diff --git a/tests/python/unittest/test_contrib_stes_op.py b/tests/python/unittest/test_contrib_stes_op.py index 163ab4a7c9f8..da5658cc2998 100644 --- a/tests/python/unittest/test_contrib_stes_op.py +++ b/tests/python/unittest/test_contrib_stes_op.py @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -from common import with_seed +from common import with_seed, xfail_when_nonstandard_decimal_point import mxnet as mx from mxnet import nd, autograd, gluon from mxnet.test_utils import default_context @@ -98,6 +98,7 @@ def check_ste(net_type_str, w_init, hybridize, in_data, ctx=None): str(net.w.grad()) + " but expected " + \ str(net.expected_grads(in_data, w_init)) +@xfail_when_nonstandard_decimal_point @with_seed() def test_contrib_round_ste(): # Test with random data @@ -119,6 +120,7 @@ def test_contrib_round_ste(): check_ste(net_type_str="RoundSTENET", w_init=w_init, hybridize=False, in_data=in_data) +@xfail_when_nonstandard_decimal_point @with_seed() def test_contrib_sign_ste(): in_data = nd.uniform(-10, 10, shape=30) # 10 and 30 are arbitrary numbers diff --git a/tests/python/unittest/test_gluon.py b/tests/python/unittest/test_gluon.py index 9a6eb83780fb..50e8e90610fd 100644 --- a/tests/python/unittest/test_gluon.py +++ b/tests/python/unittest/test_gluon.py @@ -27,7 +27,7 @@ from mxnet.test_utils import use_np import mxnet.numpy as _mx_np from common import (setup_module, with_seed, assertRaises, teardown_module, - assert_raises_cudnn_not_satisfied) + assert_raises_cudnn_not_satisfied, xfail_when_nonstandard_decimal_point) import numpy as np from numpy.testing import assert_array_equal import pytest @@ -754,6 +754,7 @@ def test_batchnorm(): check_layer_forward(layer, (2, 10, 10, 10)) +@xfail_when_nonstandard_decimal_point @with_seed() def test_sync_batchnorm(): def _check_batchnorm_result(input, num_devices=1, cuda=False): @@ -1377,6 +1378,7 @@ def test_inline(): assert len_1 == len_2 + 2 +@xfail_when_nonstandard_decimal_point @with_seed() def test_activations(): point_to_validate = mx.nd.array([-0.1, 0.1] * 3) diff --git a/tests/python/unittest/test_gluon_data_vision.py b/tests/python/unittest/test_gluon_data_vision.py index 8ffb0d15952a..d14b4585dff6 100644 --- a/tests/python/unittest/test_gluon_data_vision.py +++ b/tests/python/unittest/test_gluon_data_vision.py @@ -25,7 +25,8 @@ from mxnet.gluon.data.vision import transforms from mxnet import image from mxnet.test_utils import * -from common import assertRaises, setup_module, with_seed, teardown_module +from common import assertRaises, setup_module, with_seed, teardown_module, \ + xfail_when_nonstandard_decimal_point import numpy as np @@ -318,6 +319,7 @@ def test_random_rotation(): assert_almost_equal(data, transformer(data)) +@xfail_when_nonstandard_decimal_point @with_seed() def test_rotate(): transformer = transforms.Rotate(10.) diff --git a/tests/python/unittest/test_gluon_trainer.py b/tests/python/unittest/test_gluon_trainer.py index 7622c9d710ad..958a80d7e2c1 100644 --- a/tests/python/unittest/test_gluon_trainer.py +++ b/tests/python/unittest/test_gluon_trainer.py @@ -22,7 +22,7 @@ from mxnet import gluon from mxnet.gluon import nn from mxnet.test_utils import assert_almost_equal -from common import setup_module, with_seed, assertRaises +from common import setup_module, with_seed, assertRaises, xfail_when_nonstandard_decimal_point from copy import deepcopy import pytest @@ -217,6 +217,7 @@ def check_init(ctxes): check_init([mx.cpu(1), mx.cpu(2)]) check_init([mx.cpu(1)]) +@xfail_when_nonstandard_decimal_point @with_seed() def test_trainer_reset_kv(): def check_trainer_reset_kv(kv): @@ -250,6 +251,7 @@ def check_trainer_reset_kv(kv): for kv in kvs: check_trainer_reset_kv(kv) +@xfail_when_nonstandard_decimal_point @with_seed() def test_trainer_sparse_kv(): def check_trainer_sparse_kv(kv, stype, grad_stype, update_on_kv, expected): diff --git a/tests/python/unittest/test_higher_order_grad.py b/tests/python/unittest/test_higher_order_grad.py index 28357360bc41..e9d5864c430f 100644 --- a/tests/python/unittest/test_higher_order_grad.py +++ b/tests/python/unittest/test_higher_order_grad.py @@ -22,7 +22,7 @@ from operator import mul import random -from common import with_seed +from common import with_seed, xfail_when_nonstandard_decimal_point import mxnet from mxnet import nd, autograd, gluon from mxnet.test_utils import ( @@ -276,6 +276,7 @@ def grad_grad_op(x): check_nth_order_unary(array, log, [grad_op, grad_grad_op], [1, 2]) +@xfail_when_nonstandard_decimal_point @with_seed() def test_log2(): def log2(x): @@ -289,7 +290,7 @@ def grad_grad_op(x): array = random_arrays(shape) check_second_order_unary(array, log2, grad_grad_op) - +@xfail_when_nonstandard_decimal_point @with_seed() def test_log10(): def log10(x): @@ -415,6 +416,7 @@ def grad_grad_op(x): check_nth_order_unary(array, sigmoid, grad_grad_op, 2) +@xfail_when_nonstandard_decimal_point @with_seed() def test_sqrt(): def sqrt(x): diff --git a/tests/python/unittest/test_image.py b/tests/python/unittest/test_image.py index 7cd81460ac52..6a69d47e94da 100644 --- a/tests/python/unittest/test_image.py +++ b/tests/python/unittest/test_image.py @@ -20,7 +20,7 @@ import numpy as np import scipy.ndimage from mxnet.test_utils import * -from common import assertRaises, with_seed +from common import assertRaises, with_seed, xfail_when_nonstandard_decimal_point import shutil import tempfile import unittest @@ -366,6 +366,7 @@ def test_random_size_crop(self): assert ratio[0] - epsilon <= float(new_w)/new_h <= ratio[1] + epsilon, \ 'ration of new width and height out of the bound{}/{}={}'.format(new_w, new_h, float(new_w)/new_h) + @xfail_when_nonstandard_decimal_point @with_seed() def test_imrotate(self): # test correctness diff --git a/tests/python/unittest/test_loss.py b/tests/python/unittest/test_loss.py index e779fd672701..efd4f1e994d9 100644 --- a/tests/python/unittest/test_loss.py +++ b/tests/python/unittest/test_loss.py @@ -19,10 +19,11 @@ import numpy as np from mxnet import gluon, autograd from mxnet.test_utils import assert_almost_equal, default_context -from common import setup_module, with_seed, teardown_module +from common import setup_module, with_seed, teardown_module, xfail_when_nonstandard_decimal_point import unittest +@xfail_when_nonstandard_decimal_point @with_seed() def test_loss_ndarray(): output = mx.nd.array([1, 2, 3, 4]) @@ -348,6 +349,7 @@ def test_triplet_loss(): optimizer='adam') assert mod.score(data_iter, eval_metric=mx.metric.Loss())[0][1] < 0.05 +@xfail_when_nonstandard_decimal_point @with_seed() def test_sdml_loss(): @@ -399,6 +401,7 @@ def test_cosine_loss(): mx.nd.broadcast_maximum(mx.nd.array([0]), numerator/denominator, axis=1)) assert_almost_equal(loss.asnumpy(), numpy_loss.asnumpy(), rtol=1e-3, atol=1e-5) +@xfail_when_nonstandard_decimal_point def test_poisson_nllloss(): shape=(3, 4) not_axis0 = tuple(range(1, len(shape))) diff --git a/tests/python/unittest/test_metric.py b/tests/python/unittest/test_metric.py index d1e1c5a35fb3..2a9cd8eaeba0 100644 --- a/tests/python/unittest/test_metric.py +++ b/tests/python/unittest/test_metric.py @@ -21,7 +21,7 @@ from scipy.stats import pearsonr import json import math -from common import with_seed +from common import with_seed, xfail_when_nonstandard_decimal_point from copy import deepcopy def check_metric(metric, *args, **kwargs): @@ -387,6 +387,7 @@ def test_pcc(): met_pcc.update(l, p) assert pcc == met_pcc.get()[1] +@xfail_when_nonstandard_decimal_point def test_single_array_input(): pred = mx.nd.array([[1,2,3,4]]) label = pred + 0.1 diff --git a/tests/python/unittest/test_numpy_ndarray.py b/tests/python/unittest/test_numpy_ndarray.py index b4de9f7ba5d3..527e4f80c18b 100644 --- a/tests/python/unittest/test_numpy_ndarray.py +++ b/tests/python/unittest/test_numpy_ndarray.py @@ -27,7 +27,7 @@ from mxnet import np, npx, autograd from mxnet.gluon import HybridBlock from mxnet.test_utils import same, assert_almost_equal, rand_shape_nd, rand_ndarray, use_np -from common import with_seed, retry, TemporaryDirectory +from common import with_seed, retry, TemporaryDirectory, xfail_when_nonstandard_decimal_point from mxnet.test_utils import verify_generator, gen_buckets_probs_with_ppf, assert_exception, is_op_runnable, collapse_sum_like from mxnet.ndarray.ndarray import py_slice from mxnet.base import integer_types @@ -261,6 +261,7 @@ def check_identity_array_creation(shape, dtype): assert type(y[1]) == np.ndarray +@xfail_when_nonstandard_decimal_point @with_seed() @pytest.mark.serial def test_np_ndarray_binary_element_wise_ops(): diff --git a/tests/python/unittest/test_operator.py b/tests/python/unittest/test_operator.py index ceb8e75d7c27..5e402f7f93fa 100644 --- a/tests/python/unittest/test_operator.py +++ b/tests/python/unittest/test_operator.py @@ -30,7 +30,7 @@ from mxnet.operator import * from mxnet.base import py_str, MXNetError, _as_list from common import setup_module, with_seed, teardown_module, assert_raises_cudnn_not_satisfied, assert_raises_cuda_not_satisfied, assertRaises -from common import run_in_spawned_process +from common import run_in_spawned_process, xfail_when_nonstandard_decimal_point import pytest import unittest import os @@ -772,6 +772,7 @@ def test_swapaxes(): assert_almost_equal(out, ret_np) +@xfail_when_nonstandard_decimal_point @with_seed() def test_scalarop(): data = mx.symbol.Variable('data') @@ -1836,6 +1837,7 @@ def check_batchnorm_training(stype): check_batchnorm_training('default') +@xfail_when_nonstandard_decimal_point @with_seed() def test_batchnorm(): momentum = 0.9 @@ -6485,6 +6487,7 @@ def _make_triangle_symm(a, ndims, m, lower, dtype=np.float32): # @ankkhedia: Getting rid of fixed seed as flakiness could not be reproduced # tracked at https://github.com/apache/incubator-mxnet/issues/11718 +@xfail_when_nonstandard_decimal_point @with_seed() def test_laop(): dtype = np.float64 @@ -7535,6 +7538,7 @@ def test_softmax(): check_smoothed_softmax_grad(default_context()) +@xfail_when_nonstandard_decimal_point @with_seed() def test_softmax_output_normalization(): def _softmaxoutput_normalization(multi_output, use_ignore, normalization): diff --git a/tests/python/unittest/test_optimizer.py b/tests/python/unittest/test_optimizer.py index 6223c1e39f87..b16f02e868a9 100644 --- a/tests/python/unittest/test_optimizer.py +++ b/tests/python/unittest/test_optimizer.py @@ -25,7 +25,8 @@ import pytest import math from mxnet.test_utils import * -from common import setup_module, with_seed, teardown_module, retry +from common import setup_module, with_seed, teardown_module, retry, \ + xfail_when_nonstandard_decimal_point @with_seed() def test_learning_rate(): @@ -79,6 +80,7 @@ def test_lr_wd_mult(): assert not mx.test_utils.almost_equal(args1['fc2_weight'], args2['fc2_weight'], 1e-1) +@xfail_when_nonstandard_decimal_point @with_seed() def test_sgd(): opt1 = mx.optimizer.SGD @@ -184,6 +186,7 @@ def step(self, indices, weights, grads, states): weight[row] += mom[row] +@xfail_when_nonstandard_decimal_point @with_seed() def test_sparse_sgd(): opt1 = PySparseSGD @@ -207,6 +210,7 @@ def test_sparse_sgd(): w_stype='default', g_stype='row_sparse') +@xfail_when_nonstandard_decimal_point @with_seed() def test_std_sparse_sgd(): opt1 = mx.optimizer.SGD @@ -231,6 +235,7 @@ def test_std_sparse_sgd(): w_stype='default', g_stype='row_sparse') +@xfail_when_nonstandard_decimal_point @with_seed() def test_nag(): opt1 = mx.optimizer.NAG @@ -256,6 +261,7 @@ def test_nag(): shapes, dtype, rtol=1e-3, atol=1e-4) +@xfail_when_nonstandard_decimal_point @with_seed() def test_lars(): opt1 = mx.optimizer.LARS @@ -337,6 +343,7 @@ def test_sgld(): shapes, dtype, seed, atol=atol, rtol=rtol) +@xfail_when_nonstandard_decimal_point @with_seed() def test_ftml(): opt1 = mx.optimizer.FTML @@ -437,6 +444,7 @@ def step(self, indices, weights, grads, states): weight[row] -= lr * mean[row] / (mx.nd.sqrt(variance[row]) + self.epsilon) +@xfail_when_nonstandard_decimal_point @with_seed() def test_adam(): opt1 = mx.optimizer.Adam @@ -463,6 +471,7 @@ def test_adam(): rtol=1e-4, atol=2e-5) +@xfail_when_nonstandard_decimal_point @with_seed() def test_sparse_adam(): opt1 = PySparseAdam @@ -506,6 +515,7 @@ def test_sparse_adam(): rtol=1e-4, atol=2e-5) +@xfail_when_nonstandard_decimal_point @with_seed() @retry(3) def test_adamax(): @@ -530,6 +540,7 @@ def test_adamax(): compare_optimizer(opt1(**kwarg), opt2(**kwarg), shapes, dtype) +@xfail_when_nonstandard_decimal_point @with_seed() def test_signum(): opt1 = mx.optimizer.Signum @@ -558,6 +569,7 @@ def test_signum(): rtol=rtol, atol=atol) +@xfail_when_nonstandard_decimal_point @with_seed() def test_rms(): opt1 = mx.optimizer.RMSProp @@ -669,6 +681,7 @@ def step(self, indices, weights, grads, states): weight[row] = - d / denom +@xfail_when_nonstandard_decimal_point @with_seed() @retry(3) def test_ftrl(): @@ -696,6 +709,7 @@ def test_ftrl(): rtol=rtol, atol=atol) +@xfail_when_nonstandard_decimal_point @with_seed() def test_sparse_ftrl(): opt1 = PySparseFtrl @@ -722,6 +736,7 @@ def test_sparse_ftrl(): rtol=rtol, atol=atol) +@xfail_when_nonstandard_decimal_point @with_seed() def test_nadam(): opt1 = mx.optimizer.Nadam @@ -835,6 +850,7 @@ def test_adagrad(): opt2(use_fused_step=True, **kwarg), shapes, dtype) +@xfail_when_nonstandard_decimal_point @with_seed() def test_sparse_adagrad(): opt1 = PySparseAdaGrad diff --git a/tests/python/unittest/test_sparse_ndarray.py b/tests/python/unittest/test_sparse_ndarray.py index de06c7be0777..00c8dc5e716c 100644 --- a/tests/python/unittest/test_sparse_ndarray.py +++ b/tests/python/unittest/test_sparse_ndarray.py @@ -24,7 +24,7 @@ from numpy.testing import assert_allclose import numpy.random as rnd import numpy as np -from common import assertRaises +from common import assertRaises, xfail_when_nonstandard_decimal_point from mxnet.ndarray.sparse import RowSparseNDArray, CSRNDArray @@ -318,6 +318,7 @@ def check_binary(fn, stype): check_binary(lambda x, y: x == y, stype) +@xfail_when_nonstandard_decimal_point @with_seed() def test_sparse_nd_binary_scalar_op(): N = 3 From a5234a3d4114828e36859b76d2184eea87b126dc Mon Sep 17 00:00:00 2001 From: Nick Guletskii Date: Wed, 6 May 2020 00:53:34 +0300 Subject: [PATCH 04/11] Run localedef when generating the CentOS CI image --- ci/docker/Dockerfile.build.centos7 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci/docker/Dockerfile.build.centos7 b/ci/docker/Dockerfile.build.centos7 index 5214c6dad587..49693af407d4 100644 --- a/ci/docker/Dockerfile.build.centos7 +++ b/ci/docker/Dockerfile.build.centos7 @@ -106,6 +106,9 @@ RUN pip3 install --no-cache-dir --upgrade pip && \ protobuf==3.5.2 \ tabulate==0.7.5 +# Fix the en_DK.UTF-8 locale to test locale invariance +RUN localedef -i en_DK -f UTF-8 en_DK.UTF-8 + ARG USER_ID=0 COPY install/docker_filepermissions.sh /work/ RUN /work/docker_filepermissions.sh From 18633fce51bf76dd19eda2309e4297878e18c3e9 Mon Sep 17 00:00:00 2001 From: Nick Guletskii Date: Thu, 7 May 2020 19:00:27 +0300 Subject: [PATCH 05/11] Cancel some Scala tests when C locale uses a non-standard decimal sep. --- .../scala/org/apache/mxnet/ModuleSuite.scala | 2 ++ .../org/apache/mxnet/OperatorSuite.scala | 4 +++ .../scala/org/apache/mxnet/TestUtil.scala | 36 +++++++++++++++++++ .../org/apache/mxnet/train/ConvSuite.scala | 1 + 4 files changed, 43 insertions(+) diff --git a/scala-package/core/src/test/scala/org/apache/mxnet/ModuleSuite.scala b/scala-package/core/src/test/scala/org/apache/mxnet/ModuleSuite.scala index 5aed01bde693..5ac7c0034d6e 100644 --- a/scala-package/core/src/test/scala/org/apache/mxnet/ModuleSuite.scala +++ b/scala-package/core/src/test/scala/org/apache/mxnet/ModuleSuite.scala @@ -167,6 +167,8 @@ class ModuleSuite extends FunSuite with BeforeAndAfterAll { } test ("module reshape") { + TestUtil.assumeStandardDecimalSeparator() + var sym = Symbol.Variable("data") sym = Symbol.FullyConnected("fc")()(Map("data" -> sym, "num_hidden" -> 20)) diff --git a/scala-package/core/src/test/scala/org/apache/mxnet/OperatorSuite.scala b/scala-package/core/src/test/scala/org/apache/mxnet/OperatorSuite.scala index 3bb1b2b5b3bc..1997c58e0ca2 100644 --- a/scala-package/core/src/test/scala/org/apache/mxnet/OperatorSuite.scala +++ b/scala-package/core/src/test/scala/org/apache/mxnet/OperatorSuite.scala @@ -191,6 +191,8 @@ class OperatorSuite extends FunSuite with BeforeAndAfterAll } test("scalar op") { + TestUtil.assumeStandardDecimalSeparator() + val data = Symbol.Variable("data") val shape = Shape(3, 4) val dataTmp = NDArray.ones(shape) * 5 @@ -277,6 +279,8 @@ class OperatorSuite extends FunSuite with BeforeAndAfterAll } test("pow fn") { + TestUtil.assumeStandardDecimalSeparator() + val shape = Shape(3, 4) val exp = Symbol.Variable("exp") import SymbolConversions._ diff --git a/scala-package/core/src/test/scala/org/apache/mxnet/TestUtil.scala b/scala-package/core/src/test/scala/org/apache/mxnet/TestUtil.scala index 4fc8ec9826c1..0a071cdf6c5b 100644 --- a/scala-package/core/src/test/scala/org/apache/mxnet/TestUtil.scala +++ b/scala-package/core/src/test/scala/org/apache/mxnet/TestUtil.scala @@ -17,6 +17,12 @@ package org.apache.mxnet +import java.text.DecimalFormatSymbols +import java.util.Locale + +import org.scalatest.Assertions + + class TestUtil { /** @@ -45,3 +51,33 @@ class TestUtil { } } + +object TestUtil { + + /** + * Cancel the test if the system's locale uses a decimal separator other than '.'. Please see + * #18097 for more information. + */ + def assumeStandardDecimalSeparator() = { + val lcNumeric = System.getenv("LC_NUMERIC"); + + val decimalFormatSymbols = if (lcNumeric != null) { + val localeName = lcNumeric.stripSuffix(".UTF-8".stripSuffix(".utf-8")) + val locale = Locale.forLanguageTag(localeName) + DecimalFormatSymbols.getInstance(locale) + } else { + DecimalFormatSymbols.getInstance() + } + + val isStandardDecimalPoint = (decimalFormatSymbols.getDecimalSeparator == '.') && + (lcNumeric != null && lcNumeric.toLowerCase != "en_dk.utf-8") // Java doesn't seem to respect + // the decimal separator + // set in en_DK.UTF8, which is + // used in CentOS CI jobs. + if (!isStandardDecimalPoint) { + Assertions.cancel("Some operators " + + "break when the decimal separator is set to anything other than \".\". These operators " + + "should be rewritten to utilize the new FFI. Please see #18097 for more information.") + } + } +} \ No newline at end of file diff --git a/scala-package/core/src/test/scala/org/apache/mxnet/train/ConvSuite.scala b/scala-package/core/src/test/scala/org/apache/mxnet/train/ConvSuite.scala index eb6d5b7d7175..4cd1ce27dbd9 100644 --- a/scala-package/core/src/test/scala/org/apache/mxnet/train/ConvSuite.scala +++ b/scala-package/core/src/test/scala/org/apache/mxnet/train/ConvSuite.scala @@ -32,6 +32,7 @@ class ConvSuite extends FunSuite with BeforeAndAfterAll { private var tu = new TestUtil test("train mnist") { + TestUtil.assumeStandardDecimalSeparator() // symbol net val batchSize = 100 From 6641b4a92f66a0764898903b31ab994ecb96ac65 Mon Sep 17 00:00:00 2001 From: Nick Guletskii Date: Thu, 7 May 2020 19:04:15 +0300 Subject: [PATCH 06/11] Rename xfail helper to xfail_when_nonstandard_decimal_separator --- tests/python/unittest/common.py | 7 ++-- tests/python/unittest/test_autograd.py | 4 +-- .../python/unittest/test_contrib_autograd.py | 4 +-- .../python/unittest/test_contrib_operator.py | 4 +-- .../python/unittest/test_contrib_optimizer.py | 6 ++-- tests/python/unittest/test_contrib_stes_op.py | 6 ++-- tests/python/unittest/test_gluon.py | 6 ++-- .../python/unittest/test_gluon_data_vision.py | 4 +-- tests/python/unittest/test_gluon_trainer.py | 6 ++-- .../python/unittest/test_higher_order_grad.py | 8 ++--- tests/python/unittest/test_image.py | 4 +-- tests/python/unittest/test_loss.py | 8 ++--- tests/python/unittest/test_metric.py | 4 +-- tests/python/unittest/test_numpy_ndarray.py | 4 +-- tests/python/unittest/test_operator.py | 10 +++--- tests/python/unittest/test_optimizer.py | 32 +++++++++---------- tests/python/unittest/test_sparse_ndarray.py | 4 +-- 17 files changed, 61 insertions(+), 60 deletions(-) diff --git a/tests/python/unittest/common.py b/tests/python/unittest/common.py index 46513b29b7f9..021961646f3c 100644 --- a/tests/python/unittest/common.py +++ b/tests/python/unittest/common.py @@ -33,10 +33,11 @@ from tempfile import TemporaryDirectory import locale -xfail_when_nonstandard_decimal_point = pytest.mark.xfail( +xfail_when_nonstandard_decimal_separator = pytest.mark.xfail( locale.localeconv()["decimal_point"] != ".", - reason="Some operators break when the decimal point is set to anything other than \".\". These " - "operators should be rewritten to utilize the new FFI. Please see #18097 for more information." + reason="Some operators break when the decimal separator is set to anything other than \".\". " + "These operators should be rewritten to utilize the new FFI. Please see #18097 for more " + "information." ) def assertRaises(expected_exception, func, *args, **kwargs): diff --git a/tests/python/unittest/test_autograd.py b/tests/python/unittest/test_autograd.py index cb021dcb4ea5..148325c9af3a 100644 --- a/tests/python/unittest/test_autograd.py +++ b/tests/python/unittest/test_autograd.py @@ -20,7 +20,7 @@ from mxnet.ndarray import zeros_like from mxnet.autograd import * from mxnet.test_utils import * -from common import setup_module, with_seed, teardown_module, xfail_when_nonstandard_decimal_point +from common import setup_module, with_seed, teardown_module, xfail_when_nonstandard_decimal_separator from mxnet.test_utils import EnvManager @@ -107,7 +107,7 @@ def autograd_assert(*args, **kwargs): for a, b in zip(grad_vals, grad_res): assert same(a.asnumpy(), b.asnumpy()) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_unary_func(): def check_unary_func(x): diff --git a/tests/python/unittest/test_contrib_autograd.py b/tests/python/unittest/test_contrib_autograd.py index c8bce819421a..c383744a69a4 100644 --- a/tests/python/unittest/test_contrib_autograd.py +++ b/tests/python/unittest/test_contrib_autograd.py @@ -18,7 +18,7 @@ import mxnet.ndarray as nd from mxnet.contrib.autograd import * from mxnet.test_utils import * -from common import setup_module, with_seed, teardown_module, xfail_when_nonstandard_decimal_point +from common import setup_module, with_seed, teardown_module, xfail_when_nonstandard_decimal_separator def autograd_assert(*args, **kwargs): func = kwargs["func"] @@ -34,7 +34,7 @@ def autograd_assert(*args, **kwargs): for a, b in zip(grad_vals, grad_res): assert same(a.asnumpy(), b.asnumpy()) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_unary_func(): x = nd.uniform(shape=(4, 5)) diff --git a/tests/python/unittest/test_contrib_operator.py b/tests/python/unittest/test_contrib_operator.py index 3826a8fa476d..6f8b415c648e 100644 --- a/tests/python/unittest/test_contrib_operator.py +++ b/tests/python/unittest/test_contrib_operator.py @@ -24,7 +24,7 @@ from numpy.testing import assert_allclose, assert_array_equal from mxnet.test_utils import * from common import with_seed, assert_raises_cudnn_not_satisfied, \ - xfail_when_nonstandard_decimal_point + xfail_when_nonstandard_decimal_separator import unittest def test_box_nms_op(): @@ -286,7 +286,7 @@ def test_multibox_target_op(): assert_array_equal(loc_mask.asnumpy(), expected_loc_mask) assert_array_equal(cls_target.asnumpy(), expected_cls_target) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator def test_gradient_multiplier_op(): # We use the quadratic function in combination with gradient multiplier def f(x, a, b, c): diff --git a/tests/python/unittest/test_contrib_optimizer.py b/tests/python/unittest/test_contrib_optimizer.py index 7d858cccb462..cb90f429c864 100644 --- a/tests/python/unittest/test_contrib_optimizer.py +++ b/tests/python/unittest/test_contrib_optimizer.py @@ -23,10 +23,10 @@ curr_path = os.path.dirname(os.path.abspath(os.path.expanduser(__file__))) sys.path.insert(0, os.path.join(curr_path, '../unittest')) -from common import with_seed, xfail_when_nonstandard_decimal_point +from common import with_seed, xfail_when_nonstandard_decimal_separator -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator def test_group_adagrad(): mx.random.seed(0) opt1 = mx.optimizer.contrib.GroupAdaGrad @@ -62,7 +62,7 @@ def test_group_adagrad(): g_stype='row_sparse') -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() @pytest.mark.serial def test_adamw(): diff --git a/tests/python/unittest/test_contrib_stes_op.py b/tests/python/unittest/test_contrib_stes_op.py index da5658cc2998..9b09033ed522 100644 --- a/tests/python/unittest/test_contrib_stes_op.py +++ b/tests/python/unittest/test_contrib_stes_op.py @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -from common import with_seed, xfail_when_nonstandard_decimal_point +from common import with_seed, xfail_when_nonstandard_decimal_separator import mxnet as mx from mxnet import nd, autograd, gluon from mxnet.test_utils import default_context @@ -98,7 +98,7 @@ def check_ste(net_type_str, w_init, hybridize, in_data, ctx=None): str(net.w.grad()) + " but expected " + \ str(net.expected_grads(in_data, w_init)) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_contrib_round_ste(): # Test with random data @@ -120,7 +120,7 @@ def test_contrib_round_ste(): check_ste(net_type_str="RoundSTENET", w_init=w_init, hybridize=False, in_data=in_data) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_contrib_sign_ste(): in_data = nd.uniform(-10, 10, shape=30) # 10 and 30 are arbitrary numbers diff --git a/tests/python/unittest/test_gluon.py b/tests/python/unittest/test_gluon.py index 50e8e90610fd..3bfe4f30ef4b 100644 --- a/tests/python/unittest/test_gluon.py +++ b/tests/python/unittest/test_gluon.py @@ -27,7 +27,7 @@ from mxnet.test_utils import use_np import mxnet.numpy as _mx_np from common import (setup_module, with_seed, assertRaises, teardown_module, - assert_raises_cudnn_not_satisfied, xfail_when_nonstandard_decimal_point) + assert_raises_cudnn_not_satisfied, xfail_when_nonstandard_decimal_separator) import numpy as np from numpy.testing import assert_array_equal import pytest @@ -754,7 +754,7 @@ def test_batchnorm(): check_layer_forward(layer, (2, 10, 10, 10)) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_sync_batchnorm(): def _check_batchnorm_result(input, num_devices=1, cuda=False): @@ -1378,7 +1378,7 @@ def test_inline(): assert len_1 == len_2 + 2 -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_activations(): point_to_validate = mx.nd.array([-0.1, 0.1] * 3) diff --git a/tests/python/unittest/test_gluon_data_vision.py b/tests/python/unittest/test_gluon_data_vision.py index d14b4585dff6..c4fd7344df35 100644 --- a/tests/python/unittest/test_gluon_data_vision.py +++ b/tests/python/unittest/test_gluon_data_vision.py @@ -26,7 +26,7 @@ from mxnet import image from mxnet.test_utils import * from common import assertRaises, setup_module, with_seed, teardown_module, \ - xfail_when_nonstandard_decimal_point + xfail_when_nonstandard_decimal_separator import numpy as np @@ -319,7 +319,7 @@ def test_random_rotation(): assert_almost_equal(data, transformer(data)) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_rotate(): transformer = transforms.Rotate(10.) diff --git a/tests/python/unittest/test_gluon_trainer.py b/tests/python/unittest/test_gluon_trainer.py index 958a80d7e2c1..892b2e33eaed 100644 --- a/tests/python/unittest/test_gluon_trainer.py +++ b/tests/python/unittest/test_gluon_trainer.py @@ -22,7 +22,7 @@ from mxnet import gluon from mxnet.gluon import nn from mxnet.test_utils import assert_almost_equal -from common import setup_module, with_seed, assertRaises, xfail_when_nonstandard_decimal_point +from common import setup_module, with_seed, assertRaises, xfail_when_nonstandard_decimal_separator from copy import deepcopy import pytest @@ -217,7 +217,7 @@ def check_init(ctxes): check_init([mx.cpu(1), mx.cpu(2)]) check_init([mx.cpu(1)]) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_trainer_reset_kv(): def check_trainer_reset_kv(kv): @@ -251,7 +251,7 @@ def check_trainer_reset_kv(kv): for kv in kvs: check_trainer_reset_kv(kv) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_trainer_sparse_kv(): def check_trainer_sparse_kv(kv, stype, grad_stype, update_on_kv, expected): diff --git a/tests/python/unittest/test_higher_order_grad.py b/tests/python/unittest/test_higher_order_grad.py index e9d5864c430f..8ccadd02f0a2 100644 --- a/tests/python/unittest/test_higher_order_grad.py +++ b/tests/python/unittest/test_higher_order_grad.py @@ -22,7 +22,7 @@ from operator import mul import random -from common import with_seed, xfail_when_nonstandard_decimal_point +from common import with_seed, xfail_when_nonstandard_decimal_separator import mxnet from mxnet import nd, autograd, gluon from mxnet.test_utils import ( @@ -276,7 +276,7 @@ def grad_grad_op(x): check_nth_order_unary(array, log, [grad_op, grad_grad_op], [1, 2]) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_log2(): def log2(x): @@ -290,7 +290,7 @@ def grad_grad_op(x): array = random_arrays(shape) check_second_order_unary(array, log2, grad_grad_op) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_log10(): def log10(x): @@ -416,7 +416,7 @@ def grad_grad_op(x): check_nth_order_unary(array, sigmoid, grad_grad_op, 2) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_sqrt(): def sqrt(x): diff --git a/tests/python/unittest/test_image.py b/tests/python/unittest/test_image.py index 6a69d47e94da..9cb287a50b11 100644 --- a/tests/python/unittest/test_image.py +++ b/tests/python/unittest/test_image.py @@ -20,7 +20,7 @@ import numpy as np import scipy.ndimage from mxnet.test_utils import * -from common import assertRaises, with_seed, xfail_when_nonstandard_decimal_point +from common import assertRaises, with_seed, xfail_when_nonstandard_decimal_separator import shutil import tempfile import unittest @@ -366,7 +366,7 @@ def test_random_size_crop(self): assert ratio[0] - epsilon <= float(new_w)/new_h <= ratio[1] + epsilon, \ 'ration of new width and height out of the bound{}/{}={}'.format(new_w, new_h, float(new_w)/new_h) - @xfail_when_nonstandard_decimal_point + @xfail_when_nonstandard_decimal_separator @with_seed() def test_imrotate(self): # test correctness diff --git a/tests/python/unittest/test_loss.py b/tests/python/unittest/test_loss.py index efd4f1e994d9..1f54066a0d90 100644 --- a/tests/python/unittest/test_loss.py +++ b/tests/python/unittest/test_loss.py @@ -19,11 +19,11 @@ import numpy as np from mxnet import gluon, autograd from mxnet.test_utils import assert_almost_equal, default_context -from common import setup_module, with_seed, teardown_module, xfail_when_nonstandard_decimal_point +from common import setup_module, with_seed, teardown_module, xfail_when_nonstandard_decimal_separator import unittest -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_loss_ndarray(): output = mx.nd.array([1, 2, 3, 4]) @@ -349,7 +349,7 @@ def test_triplet_loss(): optimizer='adam') assert mod.score(data_iter, eval_metric=mx.metric.Loss())[0][1] < 0.05 -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_sdml_loss(): @@ -401,7 +401,7 @@ def test_cosine_loss(): mx.nd.broadcast_maximum(mx.nd.array([0]), numerator/denominator, axis=1)) assert_almost_equal(loss.asnumpy(), numpy_loss.asnumpy(), rtol=1e-3, atol=1e-5) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator def test_poisson_nllloss(): shape=(3, 4) not_axis0 = tuple(range(1, len(shape))) diff --git a/tests/python/unittest/test_metric.py b/tests/python/unittest/test_metric.py index 2a9cd8eaeba0..4dd2b48ff2fb 100644 --- a/tests/python/unittest/test_metric.py +++ b/tests/python/unittest/test_metric.py @@ -21,7 +21,7 @@ from scipy.stats import pearsonr import json import math -from common import with_seed, xfail_when_nonstandard_decimal_point +from common import with_seed, xfail_when_nonstandard_decimal_separator from copy import deepcopy def check_metric(metric, *args, **kwargs): @@ -387,7 +387,7 @@ def test_pcc(): met_pcc.update(l, p) assert pcc == met_pcc.get()[1] -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator def test_single_array_input(): pred = mx.nd.array([[1,2,3,4]]) label = pred + 0.1 diff --git a/tests/python/unittest/test_numpy_ndarray.py b/tests/python/unittest/test_numpy_ndarray.py index 527e4f80c18b..b43d0e1433fc 100644 --- a/tests/python/unittest/test_numpy_ndarray.py +++ b/tests/python/unittest/test_numpy_ndarray.py @@ -27,7 +27,7 @@ from mxnet import np, npx, autograd from mxnet.gluon import HybridBlock from mxnet.test_utils import same, assert_almost_equal, rand_shape_nd, rand_ndarray, use_np -from common import with_seed, retry, TemporaryDirectory, xfail_when_nonstandard_decimal_point +from common import with_seed, retry, TemporaryDirectory, xfail_when_nonstandard_decimal_separator from mxnet.test_utils import verify_generator, gen_buckets_probs_with_ppf, assert_exception, is_op_runnable, collapse_sum_like from mxnet.ndarray.ndarray import py_slice from mxnet.base import integer_types @@ -261,7 +261,7 @@ def check_identity_array_creation(shape, dtype): assert type(y[1]) == np.ndarray -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() @pytest.mark.serial def test_np_ndarray_binary_element_wise_ops(): diff --git a/tests/python/unittest/test_operator.py b/tests/python/unittest/test_operator.py index 5e402f7f93fa..8d843cf16b8c 100644 --- a/tests/python/unittest/test_operator.py +++ b/tests/python/unittest/test_operator.py @@ -30,7 +30,7 @@ from mxnet.operator import * from mxnet.base import py_str, MXNetError, _as_list from common import setup_module, with_seed, teardown_module, assert_raises_cudnn_not_satisfied, assert_raises_cuda_not_satisfied, assertRaises -from common import run_in_spawned_process, xfail_when_nonstandard_decimal_point +from common import run_in_spawned_process, xfail_when_nonstandard_decimal_separator import pytest import unittest import os @@ -772,7 +772,7 @@ def test_swapaxes(): assert_almost_equal(out, ret_np) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_scalarop(): data = mx.symbol.Variable('data') @@ -1837,7 +1837,7 @@ def check_batchnorm_training(stype): check_batchnorm_training('default') -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_batchnorm(): momentum = 0.9 @@ -6487,7 +6487,7 @@ def _make_triangle_symm(a, ndims, m, lower, dtype=np.float32): # @ankkhedia: Getting rid of fixed seed as flakiness could not be reproduced # tracked at https://github.com/apache/incubator-mxnet/issues/11718 -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_laop(): dtype = np.float64 @@ -7538,7 +7538,7 @@ def test_softmax(): check_smoothed_softmax_grad(default_context()) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_softmax_output_normalization(): def _softmaxoutput_normalization(multi_output, use_ignore, normalization): diff --git a/tests/python/unittest/test_optimizer.py b/tests/python/unittest/test_optimizer.py index b16f02e868a9..9202184f6b6d 100644 --- a/tests/python/unittest/test_optimizer.py +++ b/tests/python/unittest/test_optimizer.py @@ -26,7 +26,7 @@ import math from mxnet.test_utils import * from common import setup_module, with_seed, teardown_module, retry, \ - xfail_when_nonstandard_decimal_point + xfail_when_nonstandard_decimal_separator @with_seed() def test_learning_rate(): @@ -80,7 +80,7 @@ def test_lr_wd_mult(): assert not mx.test_utils.almost_equal(args1['fc2_weight'], args2['fc2_weight'], 1e-1) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_sgd(): opt1 = mx.optimizer.SGD @@ -186,7 +186,7 @@ def step(self, indices, weights, grads, states): weight[row] += mom[row] -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_sparse_sgd(): opt1 = PySparseSGD @@ -210,7 +210,7 @@ def test_sparse_sgd(): w_stype='default', g_stype='row_sparse') -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_std_sparse_sgd(): opt1 = mx.optimizer.SGD @@ -235,7 +235,7 @@ def test_std_sparse_sgd(): w_stype='default', g_stype='row_sparse') -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_nag(): opt1 = mx.optimizer.NAG @@ -261,7 +261,7 @@ def test_nag(): shapes, dtype, rtol=1e-3, atol=1e-4) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_lars(): opt1 = mx.optimizer.LARS @@ -343,7 +343,7 @@ def test_sgld(): shapes, dtype, seed, atol=atol, rtol=rtol) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_ftml(): opt1 = mx.optimizer.FTML @@ -444,7 +444,7 @@ def step(self, indices, weights, grads, states): weight[row] -= lr * mean[row] / (mx.nd.sqrt(variance[row]) + self.epsilon) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_adam(): opt1 = mx.optimizer.Adam @@ -471,7 +471,7 @@ def test_adam(): rtol=1e-4, atol=2e-5) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_sparse_adam(): opt1 = PySparseAdam @@ -515,7 +515,7 @@ def test_sparse_adam(): rtol=1e-4, atol=2e-5) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() @retry(3) def test_adamax(): @@ -540,7 +540,7 @@ def test_adamax(): compare_optimizer(opt1(**kwarg), opt2(**kwarg), shapes, dtype) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_signum(): opt1 = mx.optimizer.Signum @@ -569,7 +569,7 @@ def test_signum(): rtol=rtol, atol=atol) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_rms(): opt1 = mx.optimizer.RMSProp @@ -681,7 +681,7 @@ def step(self, indices, weights, grads, states): weight[row] = - d / denom -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() @retry(3) def test_ftrl(): @@ -709,7 +709,7 @@ def test_ftrl(): rtol=rtol, atol=atol) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_sparse_ftrl(): opt1 = PySparseFtrl @@ -736,7 +736,7 @@ def test_sparse_ftrl(): rtol=rtol, atol=atol) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_nadam(): opt1 = mx.optimizer.Nadam @@ -850,7 +850,7 @@ def test_adagrad(): opt2(use_fused_step=True, **kwarg), shapes, dtype) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_sparse_adagrad(): opt1 = PySparseAdaGrad diff --git a/tests/python/unittest/test_sparse_ndarray.py b/tests/python/unittest/test_sparse_ndarray.py index 00c8dc5e716c..4e122453ff7b 100644 --- a/tests/python/unittest/test_sparse_ndarray.py +++ b/tests/python/unittest/test_sparse_ndarray.py @@ -24,7 +24,7 @@ from numpy.testing import assert_allclose import numpy.random as rnd import numpy as np -from common import assertRaises, xfail_when_nonstandard_decimal_point +from common import assertRaises, xfail_when_nonstandard_decimal_separator from mxnet.ndarray.sparse import RowSparseNDArray, CSRNDArray @@ -318,7 +318,7 @@ def check_binary(fn, stype): check_binary(lambda x, y: x == y, stype) -@xfail_when_nonstandard_decimal_point +@xfail_when_nonstandard_decimal_separator @with_seed() def test_sparse_nd_binary_scalar_op(): N = 3 From 3cdb93dbdeae4a0ec48b1ff5c5a5c3f193d04407 Mon Sep 17 00:00:00 2001 From: Nick Guletskii Date: Thu, 7 May 2020 22:08:10 +0300 Subject: [PATCH 07/11] Fix scalastyle errors --- .../core/src/test/scala/org/apache/mxnet/TestUtil.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scala-package/core/src/test/scala/org/apache/mxnet/TestUtil.scala b/scala-package/core/src/test/scala/org/apache/mxnet/TestUtil.scala index 0a071cdf6c5b..312c9d894f0d 100644 --- a/scala-package/core/src/test/scala/org/apache/mxnet/TestUtil.scala +++ b/scala-package/core/src/test/scala/org/apache/mxnet/TestUtil.scala @@ -58,7 +58,7 @@ object TestUtil { * Cancel the test if the system's locale uses a decimal separator other than '.'. Please see * #18097 for more information. */ - def assumeStandardDecimalSeparator() = { + def assumeStandardDecimalSeparator(): Unit = { val lcNumeric = System.getenv("LC_NUMERIC"); val decimalFormatSymbols = if (lcNumeric != null) { @@ -80,4 +80,4 @@ object TestUtil { "should be rewritten to utilize the new FFI. Please see #18097 for more information.") } } -} \ No newline at end of file +} From 4402d91ff3e4ecea038f921708c0347bf6ee0df9 Mon Sep 17 00:00:00 2001 From: Nick Guletskii Date: Fri, 8 May 2020 18:21:07 +0300 Subject: [PATCH 08/11] Disable more Python tests that fail due to locale-related issues --- tests/python/unittest/test_numpy_op.py | 4 +++- tests/python/unittest/test_optimizer.py | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/python/unittest/test_numpy_op.py b/tests/python/unittest/test_numpy_op.py index be759f6fa3d5..d440dc5c1dea 100644 --- a/tests/python/unittest/test_numpy_op.py +++ b/tests/python/unittest/test_numpy_op.py @@ -34,7 +34,7 @@ from mxnet.test_utils import check_numeric_gradient, use_np, collapse_sum_like from mxnet.test_utils import new_matrix_with_real_eigvals_nd from mxnet.test_utils import new_sym_matrix_with_real_eigvals_nd -from common import assertRaises, with_seed, retry +from common import assertRaises, with_seed, retry, xfail_when_nonstandard_decimal_separator import random from mxnet.test_utils import verify_generator, gen_buckets_probs_with_ppf from mxnet.numpy_op_signature import _get_builtin_op @@ -1732,6 +1732,7 @@ def hybrid_forward(self, F, x): rtol=1e-5, atol=1e-6, use_broadcast=False) +@xfail_when_nonstandard_decimal_separator @with_seed() @use_np def test_np_tri(): @@ -3932,6 +3933,7 @@ def hybrid_forward(self, F, a, *args, **kwargs): check_unary_func(func, ref_grad, shape, low, high) +@xfail_when_nonstandard_decimal_separator @with_seed() @use_np def test_np_random_grad(): diff --git a/tests/python/unittest/test_optimizer.py b/tests/python/unittest/test_optimizer.py index 9202184f6b6d..d664d06fd59b 100644 --- a/tests/python/unittest/test_optimizer.py +++ b/tests/python/unittest/test_optimizer.py @@ -287,6 +287,7 @@ def test_lars(): shapes, dtype, rtol=1e-3, atol=1e-3) +@xfail_when_nonstandard_decimal_separator @with_seed() def test_lamb(): opt1 = mx.optimizer.LAMB From 914fac640d8c9a0df8a30b00df47b73d4b4d63e5 Mon Sep 17 00:00:00 2001 From: Nick Guletskii Date: Fri, 8 May 2020 19:20:21 +0300 Subject: [PATCH 09/11] Move assumeStandardDecimalSeparator into separate object to fix scaladoc --- ci/docker/runtime_functions.sh | 4 +- .../org/apache/mxnet/CancelTestUtil.scala | 52 +++++++++++++++++++ .../scala/org/apache/mxnet/ModuleSuite.scala | 2 +- .../org/apache/mxnet/OperatorSuite.scala | 4 +- .../scala/org/apache/mxnet/TestUtil.scala | 36 ------------- .../org/apache/mxnet/train/ConvSuite.scala | 2 +- 6 files changed, 58 insertions(+), 42 deletions(-) create mode 100644 scala-package/core/src/test/scala/org/apache/mxnet/CancelTestUtil.scala diff --git a/ci/docker/runtime_functions.sh b/ci/docker/runtime_functions.sh index be3a04eaf96b..0cbba5786993 100755 --- a/ci/docker/runtime_functions.sh +++ b/ci/docker/runtime_functions.sh @@ -1678,7 +1678,7 @@ build_scala_docs() { pushd $scala_path - scala_doc_sources=`find . -type f -name "*.scala" | egrep "./core|./infer" | egrep -v "/javaapi" | egrep -v "Suite" | egrep -v "/mxnetexamples"` + scala_doc_sources=`find . -type f -name "*.scala" | egrep "./core|./infer" | egrep -v "/javaapi" | egrep -v "Suite" | egrep -v "CancelTestUtil" | egrep -v "/mxnetexamples"` jar_native=`find native -name "*.jar" | grep "target/lib/" | tr "\\n" ":" ` jar_macros=`find macros -name "*.jar" | tr "\\n" ":" ` jar_core=`find core -name "*.jar" | tr "\\n" ":" ` @@ -1753,7 +1753,7 @@ build_java_docs() { pushd $java_path - java_doc_sources=`find . -type f -name "*.scala" | egrep "./core|./infer" | egrep "/javaapi" | egrep -v "Suite" | egrep -v "/mxnetexamples"` + java_doc_sources=`find . -type f -name "*.scala" | egrep "./core|./infer" | egrep "/javaapi" | egrep -v "Suite" | egrep -v "CancelTestUtil" | egrep -v "/mxnetexamples"` jar_native=`find native -name "*.jar" | grep "target/lib/" | tr "\\n" ":" ` jar_macros=`find macros -name "*.jar" | tr "\\n" ":" ` jar_core=`find core -name "*.jar" | tr "\\n" ":" ` diff --git a/scala-package/core/src/test/scala/org/apache/mxnet/CancelTestUtil.scala b/scala-package/core/src/test/scala/org/apache/mxnet/CancelTestUtil.scala new file mode 100644 index 000000000000..5b1e9a4bec69 --- /dev/null +++ b/scala-package/core/src/test/scala/org/apache/mxnet/CancelTestUtil.scala @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.mxnet + +import java.text.DecimalFormatSymbols +import java.util.Locale + +import org.scalatest.Assertions + +object CancelTestUtil { + /** + * Cancel the test if the system's locale uses a decimal separator other than '.'. Please see + * #18097 for more information. + */ + def assumeStandardDecimalSeparator(): Unit = { + val lcNumeric = System.getenv("LC_NUMERIC"); + + val decimalFormatSymbols = if (lcNumeric != null) { + val localeName = lcNumeric.stripSuffix(".UTF-8".stripSuffix(".utf-8")) + val locale = Locale.forLanguageTag(localeName) + DecimalFormatSymbols.getInstance(locale) + } else { + DecimalFormatSymbols.getInstance() + } + + val isStandardDecimalPoint = (decimalFormatSymbols.getDecimalSeparator == '.') && + (lcNumeric != null && lcNumeric.toLowerCase != "en_dk.utf-8") // Java doesn't seem to respect + // the decimal separator + // set in en_DK.UTF8, which is + // used in CentOS CI jobs. + if (!isStandardDecimalPoint) { + Assertions.cancel("Some operators " + + "break when the decimal separator is set to anything other than \".\". These operators " + + "should be rewritten to utilize the new FFI. Please see #18097 for more information.") + } + } +} diff --git a/scala-package/core/src/test/scala/org/apache/mxnet/ModuleSuite.scala b/scala-package/core/src/test/scala/org/apache/mxnet/ModuleSuite.scala index 5ac7c0034d6e..4d95f43751ba 100644 --- a/scala-package/core/src/test/scala/org/apache/mxnet/ModuleSuite.scala +++ b/scala-package/core/src/test/scala/org/apache/mxnet/ModuleSuite.scala @@ -167,7 +167,7 @@ class ModuleSuite extends FunSuite with BeforeAndAfterAll { } test ("module reshape") { - TestUtil.assumeStandardDecimalSeparator() + CancelTestUtil.assumeStandardDecimalSeparator() var sym = Symbol.Variable("data") sym = Symbol.FullyConnected("fc")()(Map("data" -> sym, "num_hidden" -> 20)) diff --git a/scala-package/core/src/test/scala/org/apache/mxnet/OperatorSuite.scala b/scala-package/core/src/test/scala/org/apache/mxnet/OperatorSuite.scala index 1997c58e0ca2..f3c250cbfabb 100644 --- a/scala-package/core/src/test/scala/org/apache/mxnet/OperatorSuite.scala +++ b/scala-package/core/src/test/scala/org/apache/mxnet/OperatorSuite.scala @@ -191,7 +191,7 @@ class OperatorSuite extends FunSuite with BeforeAndAfterAll } test("scalar op") { - TestUtil.assumeStandardDecimalSeparator() + CancelTestUtil.assumeStandardDecimalSeparator() val data = Symbol.Variable("data") val shape = Shape(3, 4) @@ -279,7 +279,7 @@ class OperatorSuite extends FunSuite with BeforeAndAfterAll } test("pow fn") { - TestUtil.assumeStandardDecimalSeparator() + CancelTestUtil.assumeStandardDecimalSeparator() val shape = Shape(3, 4) val exp = Symbol.Variable("exp") diff --git a/scala-package/core/src/test/scala/org/apache/mxnet/TestUtil.scala b/scala-package/core/src/test/scala/org/apache/mxnet/TestUtil.scala index 312c9d894f0d..4fc8ec9826c1 100644 --- a/scala-package/core/src/test/scala/org/apache/mxnet/TestUtil.scala +++ b/scala-package/core/src/test/scala/org/apache/mxnet/TestUtil.scala @@ -17,12 +17,6 @@ package org.apache.mxnet -import java.text.DecimalFormatSymbols -import java.util.Locale - -import org.scalatest.Assertions - - class TestUtil { /** @@ -51,33 +45,3 @@ class TestUtil { } } - -object TestUtil { - - /** - * Cancel the test if the system's locale uses a decimal separator other than '.'. Please see - * #18097 for more information. - */ - def assumeStandardDecimalSeparator(): Unit = { - val lcNumeric = System.getenv("LC_NUMERIC"); - - val decimalFormatSymbols = if (lcNumeric != null) { - val localeName = lcNumeric.stripSuffix(".UTF-8".stripSuffix(".utf-8")) - val locale = Locale.forLanguageTag(localeName) - DecimalFormatSymbols.getInstance(locale) - } else { - DecimalFormatSymbols.getInstance() - } - - val isStandardDecimalPoint = (decimalFormatSymbols.getDecimalSeparator == '.') && - (lcNumeric != null && lcNumeric.toLowerCase != "en_dk.utf-8") // Java doesn't seem to respect - // the decimal separator - // set in en_DK.UTF8, which is - // used in CentOS CI jobs. - if (!isStandardDecimalPoint) { - Assertions.cancel("Some operators " + - "break when the decimal separator is set to anything other than \".\". These operators " + - "should be rewritten to utilize the new FFI. Please see #18097 for more information.") - } - } -} diff --git a/scala-package/core/src/test/scala/org/apache/mxnet/train/ConvSuite.scala b/scala-package/core/src/test/scala/org/apache/mxnet/train/ConvSuite.scala index 4cd1ce27dbd9..be6b6b983fe2 100644 --- a/scala-package/core/src/test/scala/org/apache/mxnet/train/ConvSuite.scala +++ b/scala-package/core/src/test/scala/org/apache/mxnet/train/ConvSuite.scala @@ -32,7 +32,7 @@ class ConvSuite extends FunSuite with BeforeAndAfterAll { private var tu = new TestUtil test("train mnist") { - TestUtil.assumeStandardDecimalSeparator() + CancelTestUtil.assumeStandardDecimalSeparator() // symbol net val batchSize = 100 From 22255cb10ed8fda7a68a1529a3b2d8d468c8d5bb Mon Sep 17 00:00:00 2001 From: Nick Guletskii Date: Fri, 8 May 2020 19:21:01 +0300 Subject: [PATCH 10/11] Disable the "symbol pow" test when running with non-standard decimal sep --- .../core/src/test/scala/org/apache/mxnet/OperatorSuite.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scala-package/core/src/test/scala/org/apache/mxnet/OperatorSuite.scala b/scala-package/core/src/test/scala/org/apache/mxnet/OperatorSuite.scala index f3c250cbfabb..7c0b009ac8e6 100644 --- a/scala-package/core/src/test/scala/org/apache/mxnet/OperatorSuite.scala +++ b/scala-package/core/src/test/scala/org/apache/mxnet/OperatorSuite.scala @@ -258,6 +258,8 @@ class OperatorSuite extends FunSuite with BeforeAndAfterAll } test("symbol pow") { + CancelTestUtil.assumeStandardDecimalSeparator() + val shape = Shape(1, 1) val data = Symbol.Variable("data") From 1c42d798ce02c66999f2983e8af015cb849729ef Mon Sep 17 00:00:00 2001 From: Nick Guletskii Date: Fri, 8 May 2020 22:31:12 +0300 Subject: [PATCH 11/11] Disable new tests that fail due to locale-related issues --- tests/python/unittest/test_gluon_data_vision.py | 1 + tests/python/unittest/test_numpy_gluon_data_vision.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/python/unittest/test_gluon_data_vision.py b/tests/python/unittest/test_gluon_data_vision.py index c4fd7344df35..0546eb11c875 100644 --- a/tests/python/unittest/test_gluon_data_vision.py +++ b/tests/python/unittest/test_gluon_data_vision.py @@ -391,6 +391,7 @@ def test_random_transforms(): num_apply += 1 assert_almost_equal(num_apply/float(iteration), 0.5, 0.1) +@xfail_when_nonstandard_decimal_separator @with_seed() def test_random_gray(): from mxnet.gluon.data.vision import transforms diff --git a/tests/python/unittest/test_numpy_gluon_data_vision.py b/tests/python/unittest/test_numpy_gluon_data_vision.py index 4deb15353678..ec82052eff50 100644 --- a/tests/python/unittest/test_numpy_gluon_data_vision.py +++ b/tests/python/unittest/test_numpy_gluon_data_vision.py @@ -26,7 +26,8 @@ import mxnet as mx from mxnet import gluon, autograd, np, npx from mxnet.test_utils import use_np, assert_almost_equal, check_gluon_hybridize_consistency, same, check_symbolic_backward -from common import assertRaises, setup_module, with_seed, teardown_module +from common import assertRaises, setup_module, with_seed, teardown_module, \ + xfail_when_nonstandard_decimal_separator import random from mxnet.base import MXNetError from mxnet.gluon.data.vision import transforms @@ -276,6 +277,7 @@ def test_hybrid_transformer(): transform(mx.np.ones((245, 480, 3), dtype='uint8')).wait_to_read() +@xfail_when_nonstandard_decimal_separator @with_seed() @use_np def test_rotate(): @@ -350,6 +352,7 @@ def test_random_transforms(): num_apply += 1 assert_almost_equal(num_apply/float(iteration), 0.5, 0.1) +@xfail_when_nonstandard_decimal_separator @with_seed() @use_np def test_random_gray():