118 lines
3.7 KiB
Python
118 lines
3.7 KiB
Python
import threading
|
|
import unittest
|
|
|
|
import ray
|
|
from ray.tune import CheckpointConfig, register_trainable
|
|
from ray.tune.error import TuneError
|
|
from ray.tune.experiment import Experiment, _convert_to_experiment_list
|
|
from ray.tune.utils import diagnose_serialization
|
|
|
|
|
|
class ExperimentTest(unittest.TestCase):
|
|
def tearDown(self):
|
|
ray.shutdown()
|
|
|
|
def setUp(self):
|
|
def train_fn(config):
|
|
for i in range(100):
|
|
ray.tune.report(dict(timesteps_total=i))
|
|
|
|
register_trainable("f1", train_fn)
|
|
|
|
def testConvertExperimentFromExperiment(self):
|
|
exp1 = Experiment(
|
|
**{"name": "foo", "run": "f1", "config": {"script_min_iter_time_s": 0}}
|
|
)
|
|
result = _convert_to_experiment_list(exp1)
|
|
self.assertEqual(len(result), 1)
|
|
self.assertEqual(type(result), list)
|
|
|
|
def testConvertExperimentNone(self):
|
|
result = _convert_to_experiment_list(None)
|
|
self.assertEqual(len(result), 0)
|
|
self.assertEqual(type(result), list)
|
|
|
|
def testConvertExperimentList(self):
|
|
exp1 = Experiment(
|
|
**{"name": "foo", "run": "f1", "config": {"script_min_iter_time_s": 0}}
|
|
)
|
|
result = _convert_to_experiment_list([exp1, exp1])
|
|
self.assertEqual(len(result), 2)
|
|
self.assertEqual(type(result), list)
|
|
|
|
def testConvertExperimentJSON(self):
|
|
experiment = {
|
|
"name": {"run": "f1", "config": {"script_min_iter_time_s": 0}},
|
|
"named": {"run": "f1", "config": {"script_min_iter_time_s": 0}},
|
|
}
|
|
result = _convert_to_experiment_list(experiment)
|
|
self.assertEqual(len(result), 2)
|
|
self.assertEqual(type(result), list)
|
|
|
|
def testConvertExperimentIncorrect(self):
|
|
self.assertRaises(TuneError, lambda: _convert_to_experiment_list("hi"))
|
|
|
|
def testFuncTrainableCheckpointConfigValidation(self):
|
|
"""Raise an error when trying to specify checkpoint_at_end/checkpoint_frequency
|
|
with a function trainable."""
|
|
with self.assertRaises(ValueError):
|
|
Experiment(
|
|
name="foo",
|
|
run="f1", # Will point to a wrapped function trainable
|
|
checkpoint_config=CheckpointConfig(checkpoint_at_end=True),
|
|
)
|
|
with self.assertRaises(ValueError):
|
|
Experiment(
|
|
name="foo",
|
|
run="f1",
|
|
checkpoint_config=CheckpointConfig(checkpoint_frequency=1),
|
|
)
|
|
with self.assertRaises(ValueError):
|
|
Experiment(
|
|
name="foo",
|
|
run=lambda config: 1,
|
|
checkpoint_config=CheckpointConfig(checkpoint_at_end=True),
|
|
)
|
|
|
|
def testInvalidExperimentConfig(self):
|
|
with self.assertRaises(ValueError):
|
|
Experiment(name="foo", run="f1", config="invalid")
|
|
|
|
class InvalidClass:
|
|
def to_dict(self):
|
|
return {"valid": 1}
|
|
|
|
with self.assertRaises(ValueError):
|
|
Experiment(name="foo", run="f1", config=InvalidClass())
|
|
|
|
Experiment(name="foo", run="f1", config=InvalidClass().to_dict())
|
|
|
|
|
|
class ValidateUtilTest(unittest.TestCase):
|
|
def testDiagnoseSerialization(self):
|
|
# this is not serializable
|
|
e = threading.Event()
|
|
|
|
def test(config):
|
|
print(e)
|
|
|
|
assert diagnose_serialization(test) is not True
|
|
|
|
# should help identify that 'e' should be moved into
|
|
# the `test` scope.
|
|
|
|
# correct implementation
|
|
def test(config):
|
|
e = threading.Event()
|
|
print(e)
|
|
|
|
assert diagnose_serialization(test) is True
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import sys
|
|
|
|
import pytest
|
|
|
|
sys.exit(pytest.main(["-v", __file__]))
|