blob: e12846d29b3f9b2059f6e92af6e9a37686c56650 [file] [log] [blame]
Clint Byrumdc8a0902017-07-20 16:36:27 -07001# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
Clark Boylan5ac76382018-02-06 15:18:45 -080013import fixtures
Clint Byrumdc8a0902017-07-20 16:36:27 -070014import os
15import tempfile
16import time
17
18from tests.base import BaseTestCase
19
20from zuul.executor.server import DiskAccountant
21
22
23class FakeExecutor(object):
24 def __init__(self):
25 self.stopped_jobs = set()
26 self.used = {}
27
28 def stopJobByJobDir(self, jobdir):
29 self.stopped_jobs.add(jobdir)
30
31 def usage(self, dirname, used):
32 self.used[dirname] = used
33
34
35class TestDiskAccountant(BaseTestCase):
Clark Boylan5ac76382018-02-06 15:18:45 -080036 def setUp(self):
37 super(TestDiskAccountant, self).setUp()
38 self.useFixture(fixtures.NestedTempfile())
39
Clint Byrumdc8a0902017-07-20 16:36:27 -070040 def test_disk_accountant(self):
Tobias Henkel683f10c2017-07-31 22:13:29 +020041 jobs_dir = tempfile.mkdtemp(
42 dir=os.environ.get("ZUUL_TEST_ROOT", None))
Clint Byrumdc8a0902017-07-20 16:36:27 -070043 cache_dir = tempfile.mkdtemp()
44 executor_server = FakeExecutor()
45 da = DiskAccountant(jobs_dir, 1, executor_server.stopJobByJobDir,
46 cache_dir)
47 da.start()
48
Tobias Henkel227c5512017-07-31 21:44:40 +020049 try:
Tobias Henkel8f016532017-08-01 07:42:44 +020050 jobdir = os.path.join(jobs_dir, '012345')
51 os.mkdir(jobdir)
52 testfile = os.path.join(jobdir, 'tfile')
53 with open(testfile, 'w') as tf:
54 tf.write(2 * 1024 * 1024 * '.')
Clark Boyland688a622018-02-06 15:02:16 -080055 tf.flush()
56 os.fsync(tf.fileno())
Tobias Henkel8f016532017-08-01 07:42:44 +020057
58 # da should catch over-limit dir within 5 seconds
59 for i in range(0, 50):
60 if jobdir in executor_server.stopped_jobs:
61 break
62 time.sleep(0.1)
Tobias Henkel227c5512017-07-31 21:44:40 +020063 self.assertEqual(set([jobdir]), executor_server.stopped_jobs)
64 finally:
65 da.stop()
Clint Byrumdc8a0902017-07-20 16:36:27 -070066 self.assertFalse(da.thread.is_alive())
67
68 def test_cache_hard_links(self):
Tobias Henkel683f10c2017-07-31 22:13:29 +020069 root_dir = tempfile.mkdtemp(
70 dir=os.environ.get("ZUUL_TEST_ROOT", None))
Clint Byrumdc8a0902017-07-20 16:36:27 -070071 jobs_dir = os.path.join(root_dir, 'jobs')
72 os.mkdir(jobs_dir)
73 cache_dir = os.path.join(root_dir, 'cache')
74 os.mkdir(cache_dir)
75
76 executor_server = FakeExecutor()
77 da = DiskAccountant(jobs_dir, 1, executor_server.stopJobByJobDir,
78 cache_dir, executor_server.usage)
79 da.start()
Tobias Henkel8f016532017-08-01 07:42:44 +020080 self.addCleanup(da.stop)
Clint Byrumdc8a0902017-07-20 16:36:27 -070081
82 jobdir = os.path.join(jobs_dir, '012345')
83 os.mkdir(jobdir)
84
85 repo_dir = os.path.join(cache_dir, 'a.repo')
86 os.mkdir(repo_dir)
87 source_file = os.path.join(repo_dir, 'big_file')
88 with open(source_file, 'w') as tf:
89 tf.write(2 * 1024 * 1024 * '.')
90 dest_link = os.path.join(jobdir, 'big_file')
91 os.link(source_file, dest_link)
92
93 # da should _not_ count this file. Wait for 5s to get noticed
94 for i in range(0, 50):
95 if jobdir in executor_server.used:
96 break
97 time.sleep(0.1)
Tobias Henkel8f016532017-08-01 07:42:44 +020098 self.assertEqual(set(), executor_server.stopped_jobs)
99 self.assertIn(jobdir, executor_server.used)
100 self.assertTrue(executor_server.used[jobdir] <= 1)