1
- import numpy as np
2
- import pytest
1
+ import glob
2
+ import os
3
+ import shutil
3
4
import sys
5
+ import time
4
6
import unittest
5
-
6
7
from io import BytesIO , StringIO
7
8
from multiprocessing import get_context
8
9
from numbers import Number
9
- from numpy .testing import assert_array_equal , assert_array_almost_equal
10
+
11
+ import numpy as np
12
+ import pytest
10
13
# from threading import Thread, Event
11
14
from PIL import Image
15
+ from numpy .testing import assert_array_equal , assert_array_almost_equal
12
16
13
- from mujoco_py import (MjSim , load_model_from_xml ,
14
- load_model_from_path , MjSimState ,
15
- ignore_mujoco_warnings ,
16
- load_model_from_mjb )
17
+ from mujoco_py import (
18
+ MjSim , load_model_from_xml ,
19
+ load_model_from_path , MjSimState ,
20
+ ignore_mujoco_warnings ,
21
+ load_model_from_mjb
22
+ )
17
23
from mujoco_py import const , cymj , functions
18
24
from mujoco_py .tests .utils import compare_imgs
19
25
42
48
"""
43
49
44
50
51
+ def remove_mujoco_build ():
52
+ # Removes previously compiled mujoco_py files.
53
+ print ("Removing previously compiled mujoco_py files." )
54
+ path = os .path .join (os .path .dirname (__file__ ), "generated" )
55
+ for fname in glob .glob (f"{ path } /*.so" ):
56
+ os .remove (fname )
57
+ for dirname in glob .glob (f"{ path } /_pyxbld*" ):
58
+ shutil .rmtree (dirname , ignore_errors = True )
59
+ shutil .rmtree (f"{ path } /__pycache__" , ignore_errors = True )
60
+
61
+
62
+ def remove_mujoco_build_and_lock ():
63
+ # Removes previously compiled mujoco_py files.
64
+ remove_mujoco_build ()
65
+ path = os .path .join (os .path .dirname (__file__ ), ".." , "generated" )
66
+ fname = f"{ path } /mujocopy-buildlock.lock"
67
+ if os .path .exists (fname ):
68
+ os .remove (fname )
69
+
70
+
45
71
def test_nested ():
46
72
model = load_model_from_xml (BASIC_MODEL_XML )
47
73
model .vis .global_ .fovy
@@ -150,6 +176,7 @@ def udd_callback(sim):
150
176
with pytest .raises (AssertionError ):
151
177
sim .step ()
152
178
179
+
153
180
def test_data_attribute_getters ():
154
181
model = load_model_from_xml (BASIC_MODEL_XML )
155
182
sim = MjSim (model )
@@ -657,14 +684,15 @@ def test_high_res():
657
684
658
685
@pytest .mark .skipif (sys .platform .startswith ("win" ), reason = "This test fails on windows." )
659
686
def test_multiprocess ():
660
- '''
687
+ """
661
688
Tests for importing mujoco_py from multiple processes.
662
- '''
689
+ """
690
+ remove_mujoco_build_and_lock ()
663
691
ctx = get_context ('spawn' )
664
692
processes = []
665
693
times = 3
666
694
queue = ctx .Queue ()
667
- for idx in range (3 ):
695
+ for idx in range (5 ):
668
696
processes .append (ctx .Process (target = import_process , args = (queue , )))
669
697
for p in processes :
670
698
p .start ()
@@ -674,6 +702,32 @@ def test_multiprocess():
674
702
assert queue .get (), "One of processes failed."
675
703
676
704
705
+ @pytest .mark .skipif (sys .platform .startswith ("win" ), reason = "This test fails on windows." )
706
+ def test_multiprocess_with_killing ():
707
+ """
708
+ Kills a process in a middle of compilation and verifies that
709
+ other processes can resume compilation.
710
+ """
711
+ remove_mujoco_build_and_lock ()
712
+ ctx = get_context ('spawn' )
713
+ processes = []
714
+ times = 3
715
+ queue = ctx .Queue ()
716
+ for idx in range (times ):
717
+ processes .append (ctx .Process (target = import_process , args = (queue , )))
718
+ processes [0 ].start ()
719
+ # We wait 20s so the compilation already
720
+ # has started. Then we kill the process.
721
+ time .sleep (20 )
722
+ for p in processes [1 :]:
723
+ p .start ()
724
+ processes [0 ].terminate ()
725
+ for p in processes [1 :]:
726
+ p .join ()
727
+ for _ in range (times - 1 ):
728
+ assert queue .get (), "One of processes failed."
729
+
730
+
677
731
def import_process (queue ):
678
732
try :
679
733
from mujoco_py import builder
0 commit comments