Completed
Push — master ( 0b9edb...ab2b1a )
by Mathieu
10s
created

smartdispatch.tests.TestHeliosQueue   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 44
Duplicated Lines 0 %
Metric Value
dl 0
loc 44
rs 10
wmc 9

7 Methods

Rating   Name   Duplication   Size   Complexity  
A TestHeliosQueue.tearDown() 0 3 1
A TestHeliosQueue.test_generate_pbs_valid_group() 0 4 1
A TestHeliosQueue.test_generate_pbs_even_nb_commands() 0 2 1
A TestHeliosQueue.test_generate_pbs_invalid_group() 0 4 1
A TestHeliosQueue.setUp() 0 16 3
A TestHeliosQueue.test_generate_pbs_odd_nb_commands() 0 5 1
A TestHeliosQueue.test_generate_pbs_ppn_is_absent() 0 2 1
1
from nose.tools import assert_true, assert_false, assert_equal, assert_raises
2
3
import os
4
import unittest
5
import tempfile
6
import shutil
7
from smartdispatch.queue import Queue
8
from smartdispatch.job_generator import JobGenerator, job_generator_factory
9
from smartdispatch.job_generator import HeliosJobGenerator, HadesJobGenerator
10
from smartdispatch.job_generator import GuilliminJobGenerator, MammouthJobGenerator
11
12
13
class TestJobGenerator(unittest.TestCase):
14
15
    def setUp(self):
16
        self.testing_dir = tempfile.mkdtemp()
17
        self.cluster_name = "skynet"
18
        self.name = "9000@hal"
19
        self.walltime = "10:00"
20
        self.cores = 42
21
        self.gpus = 42
22
        self.mem_per_node = 32
23
        self.modules = ["cuda", "python"]
24
25
        self.queue = Queue(self.name, self.cluster_name, self.walltime, self.cores, 0, self.mem_per_node, self.modules)
26
        self.queue_gpu = Queue(self.name, self.cluster_name, self.walltime, self.cores, self.gpus, self.mem_per_node, self.modules)
27
28
    def tearDown(self):
29
        shutil.rmtree(self.testing_dir)
30
31
    def test_generate_pbs(self):
32
        commands = ["echo 1", "echo 2", "echo 3", "echo 4"]
33
34
        job_generator = JobGenerator(self.queue, commands)
35
36
        # Test nb_cores_per_command argument
37
        # Should needs one PBS file
38
        pbs_list = job_generator.generate_pbs()
39
        assert_equal(len(pbs_list), 1)
40
        assert_equal(pbs_list[0].commands, commands)
41
42
        # Should needs two PBS file
43
        command_params = {'nb_cores_per_command': self.cores // 2}
44
        job_generator = JobGenerator(self.queue, commands, command_params)
45
        pbs_list = job_generator.generate_pbs()
46
        assert_equal(len(pbs_list), 2)
47
        assert_equal(pbs_list[0].commands, commands[:2])
48
        assert_equal(pbs_list[1].commands, commands[2:])
49
50
        # Should needs four PBS file
51
        command_params = {'nb_cores_per_command': self.cores}
52
        job_generator = JobGenerator(self.queue, commands, command_params)
53
        pbs_list = job_generator.generate_pbs()
54
        assert_equal(len(pbs_list), 4)
55
        assert_equal([pbs.commands[0] for pbs in pbs_list], commands)
56
57
        # Since queue has no gpus it should not be specified in PBS resource `nodes`
58
        assert_true('gpus' not in pbs_list[0].resources['nodes'])
59
60
        # Test modules to load
61
        # Check if needed modules for this queue are included in the PBS file
62
        assert_equal(pbs_list[0].modules, self.modules)
63
64
        # Test nb_gpus_per_command argument
65
        # Should needs two PBS file
66
        command_params = {'nb_gpus_per_command': self.gpus // 2}
67
        job_generator = JobGenerator(self.queue_gpu, commands, command_params)
68
        pbs_list = job_generator.generate_pbs()
69
        assert_equal(len(pbs_list), 2)
70
        assert_equal(pbs_list[0].commands, commands[:2])
71
        assert_equal(pbs_list[1].commands, commands[2:])
72
73
        # Should needs four PBS files
74
        command_params = {'nb_gpus_per_command': self.gpus}
75
        job_generator = JobGenerator(self.queue_gpu, commands, command_params)
76
        pbs_list = job_generator.generate_pbs()
77
        assert_equal(len(pbs_list), 4)
78
        assert_equal([pbs.commands[0] for pbs in pbs_list], commands)
79
80
        # Since queue has gpus it should be specified in PBS resource `nodes`
81
        assert_true('gpus' in pbs_list[0].resources['nodes'])
82
83
        # Test modules to load
84
        # Check if needed modules for this queue are included in the PBS file
85
        assert_equal(pbs_list[0].modules, self.modules)
86
87
        # Test creating a simple job generator
88
        queue = {"queue_name": "qtest"}
89
        job_generator = JobGenerator(queue, commands=[])
90
91
    def test_write_pbs_files(self):
92
        commands = ["echo 1", "echo 2", "echo 3", "echo 4"]
93
        command_params = {'nb_cores_per_command': self.cores}
94
        job_generator = JobGenerator(self.queue, commands, command_params)
95
        filenames = job_generator.write_pbs_files(self.testing_dir)
96
        assert_equal(len(filenames), 4)
97
98
99
class TestGuilliminQueue(TestJobGenerator):
100
101
    def test_generate_pbs(self):
102
        commands = ["echo 1", "echo 2", "echo 3", "echo 4"]
103
        job_generator = GuilliminJobGenerator(self.queue, commands)
104
105
        bak_env_home_group = os.environ.get('HOME_GROUP')
106
        if bak_env_home_group is not None:
107
            del os.environ['HOME_GROUP']
108
109
        assert_raises(ValueError, job_generator.generate_pbs)
110
111
        os.environ['HOME_GROUP'] = "/path/to/group"
112
        pbs = job_generator.generate_pbs()[0]
113
        assert_true("-A" in pbs.options)
114
115
        if bak_env_home_group is not None:
116
            os.environ['HOME_GROUP'] = bak_env_home_group
117
118
119
class TestMammouthQueue(unittest.TestCase):
120
121
    def setUp(self):
122
        self.commands = ["echo 1", "echo 2", "echo 3", "echo 4"]
123
        self.queue = Queue("qtest@mp2", "mammouth")
124
125
    def test_generate_pbs(self):
126
        job_generator = MammouthJobGenerator(self.queue, self.commands)
127
128
        assert_true("ppn=1" in job_generator.generate_pbs()[0].__str__())
129
130
131
class TestHeliosQueue(unittest.TestCase):
132
133
    def setUp(self):
134
        self.commands = ["echo 1", "echo 2", "echo 3", "echo 4"]
135
        self.queue = Queue("gpu_8", "helios")
136
137
        self._home_backup = os.environ['HOME']
138
        os.environ['HOME'] = tempfile.mkdtemp()
139
140
        self.rap_filename = os.path.join(os.environ['HOME'], ".default_rap")
141
        if os.path.isfile(self.rap_filename):
142
            raise Exception("Test fail: {} should not be there.".format(self.rap_filename))
143
        else:
144
            self.rapid = 'asd-123-ab'
145
            with open(self.rap_filename, 'w+') as rap_file:
146
                rap_file.write(self.rapid)
147
148
        self.job_generator = HeliosJobGenerator(self.queue, self.commands)
149
150
    def tearDown(self):
151
        shutil.rmtree(os.environ['HOME'])
152
        os.environ['HOME'] = self._home_backup
153
154
    def test_generate_pbs_invalid_group(self):
155
        os.remove(self.rap_filename)
156
157
        assert_raises(ValueError, self.job_generator.generate_pbs)
158
159
    def test_generate_pbs_valid_group(self):
160
        pbs = self.job_generator.generate_pbs()[0]
161
162
        assert_equal(pbs.options['-A'], self.rapid)
163
164
    def test_generate_pbs_ppn_is_absent(self):
165
        assert_false("ppn=" in self.job_generator.generate_pbs()[0].__str__())
166
167
    def test_generate_pbs_even_nb_commands(self):
168
        assert_true("gpus=4" in self.job_generator.generate_pbs()[0].__str__())
169
170
    def test_generate_pbs_odd_nb_commands(self):
171
        commands = ["echo 1", "echo 2", "echo 3", "echo 4", "echo 5"]
172
        job_generator = HeliosJobGenerator(self.queue, commands)
173
174
        assert_true("gpus=5" in job_generator.generate_pbs()[0].__str__())
175
176
177
class TestHadesQueue(unittest.TestCase):
178
179
    def setUp(self):
180
        self.queue = Queue("@hades", "hades")
181
182
        self.commands4 = ["echo 1", "echo 2", "echo 3", "echo 4"]
183
        self.pbs4 = HadesJobGenerator(self.queue, self.commands4).generate_pbs()
184
185
        # 8 commands chosen because there is 8 cores but still should be split because there is 6 gpu
186
        self.commands8 = ["echo 1", "echo 2", "echo 3", "echo 4", "echo 5", "echo 6", "echo 7", "echo 8"]
187
        self.pbs8 = HadesJobGenerator(self.queue, self.commands8).generate_pbs()
188
189
    def test_generate_pbs_ppn(self):
190
        assert_true("ppn={}".format(len(self.commands4)) in self.pbs4[0].__str__())
191
192
    def test_generate_pbs_no_gpus_used(self):
193
        # Hades use ppn instead og the gpus flag and breaks if gpus is there
194
        assert_false("gpus=" in self.pbs4[0].__str__())
195
196
    def test_pbs_split_1_job(self):
197
        assert_equal(len(self.pbs4), 1)
198
199
    def test_pbs_split_2_job(self):
200
        assert_equal(len(self.pbs8), 2)
201
202
    def test_pbs_split_2_job_nb_commands(self):
203
        assert_true("ppn=6" in self.pbs8[0].__str__())
204
        assert_true("ppn=2" in self.pbs8[1].__str__())
205
206
207
def test_job_generator_factory():
208
    queue = {"queue_name": "qtest"}
209
    commands = []
210
    job_generator = job_generator_factory(queue, commands, cluster_name="guillimin")
211
    assert_true(isinstance(job_generator, GuilliminJobGenerator))
212
213
    job_generator = job_generator_factory(queue, commands, cluster_name="mammouth")
214
    assert_true(isinstance(job_generator, MammouthJobGenerator))
215
216
    job_generator = job_generator_factory(queue, commands, cluster_name="helios")
217
    assert_true(isinstance(job_generator, HeliosJobGenerator))
218
219
    job_generator = job_generator_factory(queue, commands, cluster_name="hades")
220
    assert_true(isinstance(job_generator, HadesJobGenerator))
221
222
    job_generator = job_generator_factory(queue, commands, cluster_name=None)
223
    assert_true(isinstance(job_generator, JobGenerator))
224
    assert_true(not isinstance(job_generator, GuilliminJobGenerator))
225
    assert_true(not isinstance(job_generator, MammouthJobGenerator))
226
    assert_true(not isinstance(job_generator, HeliosJobGenerator))
227
    assert_true(not isinstance(job_generator, HadesJobGenerator))
228