5
5
import os , random , collections
6
6
import unittest
7
7
import subprocess
8
+ import multiprocessing
8
9
import util .misc
9
10
import util .file
10
11
import pytest
@@ -284,15 +285,76 @@ def test_chk():
284
285
285
286
def test_available_cpu_count (monkeypatch_function_result ):
286
287
reported_cpu_count = util .misc .available_cpu_count ()
287
-
288
288
assert reported_cpu_count >= int (os .environ .get ('PYTEST_XDIST_WORKER_COUNT' , '1' ))
289
+ assert util .misc .available_cpu_count () == reported_cpu_count
289
290
290
- with monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu/cpu.cfs_quota_us' , patch_result = '1' ), \
291
- monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu/cpu.cfs_period_us' , patch_result = '1' ):
291
+ # cgroup v2 limited to 1 cpu
292
+ with monkeypatch_function_result (os .path .exists , "/sys/fs/cgroup/cgroup.controllers" , patch_result = True , patch_module = os .path ), \
293
+ monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu.max' , patch_result = "100000 100000" ):
292
294
assert util .misc .available_cpu_count () == 1
293
295
294
- assert util .misc .available_cpu_count () == reported_cpu_count
296
+ # cgroup v2 limited to 2 cpu
297
+ with monkeypatch_function_result (os .path .exists , "/sys/fs/cgroup/cgroup.controllers" , patch_result = True , patch_module = os .path ), \
298
+ monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu.max' , patch_result = "200000 100000" ):
299
+ assert util .misc .available_cpu_count () == 2
300
+
301
+ # cgroup v2 with no CPU limit imposed on cgroup
302
+ # (fall back to /proc/self/status method, with limit imposed there):
303
+ # 'Cpus_allowed: d' = 0b1101 bitmask (meaning execution allowed on 3 CPUs)
304
+ with monkeypatch_function_result (os .path .exists , "/sys/fs/cgroup/cgroup.controllers" , patch_result = True , patch_module = os .path ), \
305
+ monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu.max' , patch_result = "max 100000" ), \
306
+ monkeypatch_function_result (util .file .slurp_file , '/proc/self/status' , patch_result = 'Cpus_allowed: d' ):
307
+ assert util .misc .available_cpu_count () == 3
308
+
309
+ # cgroup v1 limited to 2 CPUs
310
+ with monkeypatch_function_result (os .path .exists , "/sys/fs/cgroup/cgroup.controllers" , patch_result = False , patch_module = os .path ), \
311
+ monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu/cpu.cfs_quota_us' , patch_result = '200000' ), \
312
+ monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu/cpu.cfs_period_us' , patch_result = '100000' ):
313
+
314
+ assert util .misc .available_cpu_count () == 2
315
+
316
+ # cgroup v1 limited to 1 CPU
317
+ with monkeypatch_function_result (os .path .exists , "/sys/fs/cgroup/cgroup.controllers" , patch_result = False , patch_module = os .path ), \
318
+ monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu/cpu.cfs_quota_us' , patch_result = '1' ), \
319
+ monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu/cpu.cfs_period_us' , patch_result = '1' ):
320
+
321
+ assert util .misc .available_cpu_count () == 1
295
322
296
- with monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu/cpu.cfs_quota_us' , patch_result = '-1' ), \
323
+ # cgroup v1 with no limit imposed on the cgroup
324
+ # (fall back to /proc/self/status method, with limit imposed there):
325
+ # 'Cpus_allowed: c' = 0b1100 bitmask (meaning execution allowed on 2 CPUs)
326
+ with monkeypatch_function_result (os .path .exists , "/sys/fs/cgroup/cgroup.controllers" , patch_result = False , patch_module = os .path ), \
327
+ monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu/cpu.cfs_quota_us' , patch_result = '-1' ), \
328
+ monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu/cpu.cfs_period_us' , patch_result = '1' ), \
329
+ monkeypatch_function_result (util .file .slurp_file , '/proc/self/status' , patch_result = 'Cpus_allowed: c' ):
330
+
331
+ assert util .misc .available_cpu_count () == 2
332
+
333
+ # cgroup v1 with no limit imposed on the cgoup or via /proc/self/status
334
+ # (fall back to /proc/self/status method, with no limit imposed there)
335
+ with monkeypatch_function_result (os .path .exists , "/sys/fs/cgroup/cgroup.controllers" , patch_result = False , patch_module = os .path ), \
336
+ monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu/cpu.cfs_quota_us' , patch_result = '-1' ), \
297
337
monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu/cpu.cfs_period_us' , patch_result = '1' ):
338
+
339
+ assert util .misc .available_cpu_count () == reported_cpu_count
340
+
341
+ # cgroup v1 with no limit imposed on the cgoup
342
+ # with 'Cpus_allowed' not present in /proc/self/status
343
+ # (fall back to multiprocessing.cpu_count() method)
344
+ with monkeypatch_function_result (os .path .exists , "/sys/fs/cgroup/cgroup.controllers" , patch_result = False , patch_module = os .path ), \
345
+ monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu/cpu.cfs_quota_us' , patch_result = '-1' ), \
346
+ monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu/cpu.cfs_period_us' , patch_result = '1' ), \
347
+ monkeypatch_function_result (util .file .slurp_file , '/proc/self/status' , patch_result = 'unexpected_key: 1' ):
348
+
298
349
assert util .misc .available_cpu_count () == reported_cpu_count
350
+
351
+ # cgroup v1 with no limit imposed on the cgoup
352
+ # with 'Cpus_allowed' not present in /proc/self/status
353
+ # (fall back to multiprocessing.cpu_count() method with CPU count of 2 reported)
354
+ with monkeypatch_function_result (os .path .exists , "/sys/fs/cgroup/cgroup.controllers" , patch_result = False , patch_module = os .path ), \
355
+ monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu/cpu.cfs_quota_us' , patch_result = '-1' ), \
356
+ monkeypatch_function_result (util .file .slurp_file , '/sys/fs/cgroup/cpu/cpu.cfs_period_us' , patch_result = '1' ), \
357
+ monkeypatch_function_result (util .file .slurp_file , '/proc/self/status' , patch_result = 'unexpected_key: 1' ), \
358
+ monkeypatch_function_result (multiprocessing .cpu_count , patch_result = 2 , patch_module = multiprocessing ):
359
+
360
+ assert util .misc .available_cpu_count () == 2
0 commit comments