2021-09-27 05:53:36 +08:00
|
|
|
import gc
|
2016-04-27 08:00:58 -07:00
|
|
|
import os
|
2021-09-27 05:53:36 +08:00
|
|
|
import time
|
2016-04-27 08:00:58 -07:00
|
|
|
|
|
|
|
import gym
|
2021-09-27 05:53:36 +08:00
|
|
|
from gym.wrappers.monitoring.video_recorder import VideoRecorder
|
2016-04-27 08:00:58 -07:00
|
|
|
|
2021-07-29 02:26:34 +02:00
|
|
|
|
2022-01-11 18:12:05 +01:00
|
|
|
class BrokenRecordableEnv:
|
2022-02-28 15:54:03 -05:00
|
|
|
metadata = {"render_modes": [None, "rgb_array"]}
|
2016-04-27 08:00:58 -07:00
|
|
|
|
|
|
|
def render(self, mode=None):
|
|
|
|
pass
|
|
|
|
|
2021-07-29 02:26:34 +02:00
|
|
|
|
2022-01-11 18:12:05 +01:00
|
|
|
class UnrecordableEnv:
|
2022-02-28 15:54:03 -05:00
|
|
|
metadata = {"render_modes": [None]}
|
2016-04-27 08:00:58 -07:00
|
|
|
|
|
|
|
def render(self, mode=None):
|
|
|
|
pass
|
|
|
|
|
2021-07-29 02:26:34 +02:00
|
|
|
|
2016-08-30 01:12:29 +02:00
|
|
|
def test_record_simple():
|
|
|
|
env = gym.make("CartPole-v1")
|
|
|
|
rec = VideoRecorder(env)
|
|
|
|
env.reset()
|
|
|
|
rec.capture_frame()
|
2021-09-27 05:53:36 +08:00
|
|
|
proc = rec.encoder.proc
|
|
|
|
|
|
|
|
assert proc.poll() is None # subprocess is running
|
|
|
|
|
2016-08-30 01:12:29 +02:00
|
|
|
rec.close()
|
2021-09-27 05:53:36 +08:00
|
|
|
|
|
|
|
assert proc.poll() is not None # subprocess is terminated
|
2016-08-30 01:12:29 +02:00
|
|
|
assert not rec.empty
|
|
|
|
assert not rec.broken
|
|
|
|
assert os.path.exists(rec.path)
|
|
|
|
f = open(rec.path)
|
|
|
|
assert os.fstat(f.fileno()).st_size > 100
|
2016-04-27 08:00:58 -07:00
|
|
|
|
2021-07-29 02:26:34 +02:00
|
|
|
|
2021-08-26 23:48:18 +08:00
|
|
|
def test_autoclose():
|
|
|
|
def record():
|
|
|
|
env = gym.make("CartPole-v1")
|
|
|
|
rec = VideoRecorder(env)
|
|
|
|
env.reset()
|
|
|
|
rec.capture_frame()
|
|
|
|
|
|
|
|
rec_path = rec.path
|
|
|
|
proc = rec.encoder.proc
|
|
|
|
|
|
|
|
assert proc.poll() is None # subprocess is running
|
|
|
|
|
|
|
|
# The function ends without an explicit `rec.close()` call
|
|
|
|
# The Python interpreter will implicitly do `del rec` on garbage cleaning
|
|
|
|
return rec_path, proc
|
|
|
|
|
|
|
|
rec_path, proc = record()
|
2021-09-27 05:53:36 +08:00
|
|
|
|
|
|
|
gc.collect() # do explicit garbage collection for test
|
|
|
|
time.sleep(5) # wait for subprocess exiting
|
|
|
|
|
|
|
|
assert proc.poll() is not None # subprocess is terminated
|
2021-08-26 23:48:18 +08:00
|
|
|
assert os.path.exists(rec_path)
|
|
|
|
f = open(rec_path)
|
|
|
|
assert os.fstat(f.fileno()).st_size > 100
|
|
|
|
|
|
|
|
|
2016-04-27 08:00:58 -07:00
|
|
|
def test_no_frames():
|
|
|
|
env = BrokenRecordableEnv()
|
|
|
|
rec = VideoRecorder(env)
|
|
|
|
rec.close()
|
|
|
|
assert rec.empty
|
|
|
|
assert rec.functional
|
|
|
|
assert not os.path.exists(rec.path)
|
|
|
|
|
2021-07-29 02:26:34 +02:00
|
|
|
|
2016-04-27 08:00:58 -07:00
|
|
|
def test_record_unrecordable_method():
|
|
|
|
env = UnrecordableEnv()
|
|
|
|
rec = VideoRecorder(env)
|
|
|
|
assert not rec.enabled
|
|
|
|
rec.close()
|
|
|
|
|
2021-07-29 02:26:34 +02:00
|
|
|
|
2016-04-27 08:00:58 -07:00
|
|
|
def test_record_breaking_render_method():
|
|
|
|
env = BrokenRecordableEnv()
|
|
|
|
rec = VideoRecorder(env)
|
|
|
|
rec.capture_frame()
|
|
|
|
rec.close()
|
|
|
|
assert rec.empty
|
|
|
|
assert rec.broken
|
|
|
|
assert not os.path.exists(rec.path)
|
|
|
|
|
2021-07-29 02:26:34 +02:00
|
|
|
|
2016-04-27 08:00:58 -07:00
|
|
|
def test_text_envs():
|
2021-08-13 00:18:42 -04:00
|
|
|
env = gym.make("FrozenLake-v1")
|
2016-04-27 08:00:58 -07:00
|
|
|
video = VideoRecorder(env)
|
|
|
|
try:
|
|
|
|
env.reset()
|
|
|
|
video.capture_frame()
|
|
|
|
video.close()
|
|
|
|
finally:
|
|
|
|
os.remove(video.path)
|