2017-03-29 13:44:02 +00:00
|
|
|
## @package test_util
|
|
|
|
|
# Module caffe2.python.test_util
|
2020-09-24 00:55:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-05-13 21:43:48 +00:00
|
|
|
import numpy as np
|
2017-08-30 00:34:04 +00:00
|
|
|
from caffe2.python import core, workspace
|
2016-05-13 21:43:48 +00:00
|
|
|
|
2018-10-09 00:07:57 +00:00
|
|
|
import os
|
2021-02-12 18:53:49 +00:00
|
|
|
import pathlib
|
|
|
|
|
import shutil
|
|
|
|
|
import tempfile
|
|
|
|
|
import unittest
|
|
|
|
|
from typing import Any, Callable, Tuple, Type
|
|
|
|
|
from types import TracebackType
|
2016-05-13 21:43:48 +00:00
|
|
|
|
2019-03-25 23:55:30 +00:00
|
|
|
|
2016-05-13 21:43:48 +00:00
|
|
|
def rand_array(*dims):
|
|
|
|
|
# np.random.rand() returns float instead of 0-dim array, that's why need to
|
|
|
|
|
# do some tricks
|
|
|
|
|
return np.array(np.random.rand(*dims) - 0.5).astype(np.float32)
|
|
|
|
|
|
|
|
|
|
|
2018-09-25 17:48:02 +00:00
|
|
|
def randBlob(name, type, *dims, **kwargs):
|
|
|
|
|
offset = kwargs['offset'] if 'offset' in kwargs else 0.0
|
|
|
|
|
workspace.FeedBlob(name, np.random.rand(*dims).astype(type) + offset)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def randBlobFloat32(name, *dims, **kwargs):
|
|
|
|
|
randBlob(name, np.float32, *dims, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def randBlobsFloat32(names, *dims, **kwargs):
|
|
|
|
|
for name in names:
|
|
|
|
|
randBlobFloat32(name, *dims, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
2018-10-01 18:10:15 +00:00
|
|
|
def numOps(net):
|
|
|
|
|
return len(net.Proto().op)
|
|
|
|
|
|
|
|
|
|
|
2018-09-25 17:48:02 +00:00
|
|
|
def str_compare(a, b, encoding="utf8"):
|
|
|
|
|
if isinstance(a, bytes):
|
|
|
|
|
a = a.decode(encoding)
|
|
|
|
|
if isinstance(b, bytes):
|
|
|
|
|
b = b.decode(encoding)
|
|
|
|
|
return a == b
|
|
|
|
|
|
|
|
|
|
|
2018-12-15 00:20:37 +00:00
|
|
|
def get_default_test_flags():
|
|
|
|
|
return [
|
|
|
|
|
'caffe2',
|
|
|
|
|
'--caffe2_log_level=0',
|
|
|
|
|
'--caffe2_cpu_allocator_do_zero_fill=0',
|
|
|
|
|
'--caffe2_cpu_allocator_do_junk_fill=1',
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
2019-03-25 23:55:30 +00:00
|
|
|
def caffe2_flaky(test_method):
|
|
|
|
|
# This decorator is used to mark a test method as flaky.
|
|
|
|
|
# This is used in conjunction with the environment variable
|
|
|
|
|
# CAFFE2_RUN_FLAKY_TESTS that specifies "flaky tests" mode
|
|
|
|
|
# If flaky tests mode are on, only flaky tests are run
|
|
|
|
|
# If flaky tests mode are off, only non-flaky tests are run
|
|
|
|
|
# NOTE: the decorator should be applied as the top-level decorator
|
|
|
|
|
# in a test method.
|
|
|
|
|
test_method.__caffe2_flaky__ = True
|
|
|
|
|
return test_method
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_flaky_test_mode():
|
|
|
|
|
return os.getenv('CAFFE2_RUN_FLAKY_TESTS', '0') == '1'
|
|
|
|
|
|
|
|
|
|
|
2016-05-13 21:43:48 +00:00
|
|
|
class TestCase(unittest.TestCase):
|
2016-07-21 17:16:42 +00:00
|
|
|
@classmethod
|
|
|
|
|
def setUpClass(cls):
|
2018-12-15 00:20:37 +00:00
|
|
|
workspace.GlobalInit(get_default_test_flags())
|
2017-08-30 00:34:04 +00:00
|
|
|
# clear the default engines settings to separate out its
|
|
|
|
|
# affect from the ops tests
|
|
|
|
|
core.SetEnginePref({}, {})
|
2016-07-21 17:16:42 +00:00
|
|
|
|
2016-05-13 21:43:48 +00:00
|
|
|
def setUp(self):
|
2019-03-25 23:55:30 +00:00
|
|
|
# Skip tests based on whether we're in flaky test mode and
|
|
|
|
|
# the test is decorated as a flaky test.
|
|
|
|
|
test_method = getattr(self, self._testMethodName)
|
|
|
|
|
is_flaky_test = getattr(test_method, "__caffe2_flaky__", False)
|
|
|
|
|
if (is_flaky_test_mode() and not is_flaky_test):
|
|
|
|
|
raise unittest.SkipTest("Non-flaky tests are skipped in flaky test mode")
|
|
|
|
|
elif (not is_flaky_test_mode() and is_flaky_test):
|
|
|
|
|
raise unittest.SkipTest("Flaky tests are skipped in regular test mode")
|
|
|
|
|
|
2016-09-06 22:54:56 +00:00
|
|
|
self.ws = workspace.C.Workspace()
|
2016-05-13 21:43:48 +00:00
|
|
|
workspace.ResetWorkspace()
|
|
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
|
workspace.ResetWorkspace()
|
2021-02-12 18:53:49 +00:00
|
|
|
|
|
|
|
|
def make_tempdir(self) -> pathlib.Path:
|
|
|
|
|
tmp_folder = pathlib.Path(tempfile.mkdtemp(prefix="caffe2_test."))
|
|
|
|
|
self.addCleanup(self._remove_tempdir, tmp_folder)
|
|
|
|
|
return tmp_folder
|
|
|
|
|
|
|
|
|
|
def _remove_tempdir(self, path: pathlib.Path) -> None:
|
|
|
|
|
def _onerror(
|
|
|
|
|
fn: Callable[..., Any],
|
|
|
|
|
path: str,
|
|
|
|
|
exc_info: Tuple[Type[BaseException], BaseException, TracebackType],
|
|
|
|
|
) -> None:
|
|
|
|
|
# Ignore FileNotFoundError, but re-raise anything else
|
|
|
|
|
if not isinstance(exc_info[1], FileNotFoundError):
|
|
|
|
|
raise exc_info[1].with_traceback(exc_info[2])
|
|
|
|
|
|
|
|
|
|
shutil.rmtree(str(path), onerror=_onerror)
|