debian-koji/tests/test_builder/test_buildroot_logs.py
Yuming Zhu ca05418fb5 unittest: use unittest.mock instead of mock
because the absence of unittest.mock on python2.7, we still fallback to
mock
2024-10-23 16:35:30 +00:00

194 lines
6 KiB
Python

from __future__ import absolute_import
import logging
import os
import shutil
import tempfile
import unittest
try:
from unittest import mock
except ImportError:
import mock
from .loadkojid import kojid
class TestBuildRootLogs(unittest.TestCase):
def setUp(self):
self.broot = mock.MagicMock()
self.broot.logger = logging.getLogger("koji.build.buildroot")
self.broot.incremental_log.side_effect = self.my_incremental_log
self.offsets = {}
self.contents = {}
self.session = mock.MagicMock()
self.tempdir = tempfile.mkdtemp()
def tearDown(self):
shutil.rmtree(self.tempdir)
mock.patch.stopall()
def my_incremental_log(self, fname, fd):
self.offsets.setdefault(fname, []).append(fd.tell())
self.contents.setdefault(fname, []).append(fd.read())
def test_simple(self):
patterns = ['%s/*.log' % self.tempdir]
mylogs = ['%s/test-%02i.log' % (self.tempdir, i) for i in range(4)]
for fn in mylogs:
with open(fn, 'wt') as fo:
fo.write('hello\n')
notlogs = ['%s/test-%02i.rpm' % (self.tempdir, i) for i in range(4)]
for fn in notlogs:
with open(fn, 'wt') as fo:
fo.write('this is not a log')
logs = kojid.BuildRootLogs(self.broot, patterns)
# first sync
logs.sync_logs()
self.assertEqual(logs.ts_logs, {})
self.assertEqual(sorted(logs.loginfo.keys()), mylogs)
self.assertEqual(len(self.broot.incremental_log.mock_calls), 4)
# sync again, no file changes
self.broot.reset_mock()
logs.sync_logs()
self.assertEqual(logs.ts_logs, {})
self.assertEqual(sorted(logs.loginfo.keys()), mylogs)
self.assertEqual(len(self.broot.incremental_log.mock_calls), 4)
# new file
mylogs.append('%s/test-new-file.log' % self.tempdir)
with open(mylogs[-1], 'wt') as fo:
fo.write('hello')
self.broot.reset_mock()
logs.sync_logs()
self.assertEqual(logs.ts_logs, {})
self.assertEqual(sorted(logs.loginfo.keys()), mylogs)
self.assertEqual(len(self.broot.incremental_log.mock_calls), 5)
logs.close_logs()
def test_timestamp(self):
patterns = ['%s/*.log' % self.tempdir]
mylog = '%s/test.log' % (self.tempdir)
with open(mylog, 'wt') as fo:
fo.write('hello\n')
workdir = '%s/work' % self.tempdir
os.makedirs(workdir)
self.broot.workdir = workdir
logs = kojid.BuildRootLogs(self.broot, patterns, with_ts=True)
# first sync
with mock.patch('time.time', return_value=100):
logs.sync_logs()
self.assertEqual(sorted(logs.loginfo.keys()), [mylog])
ts_log = '%s/test.log-ts.log' % workdir
self.assertEqual(sorted(logs.ts_logs.keys()), [ts_log])
self.assertEqual(len(self.broot.incremental_log.mock_calls), 2)
# sync again with file update
self.broot.reset_mock()
with open(mylog, 'at') as fo:
fo.write('hello\n')
with mock.patch('time.time', return_value=200):
logs.sync_logs()
logs.close_logs()
with open(ts_log, 'rt') as fo:
contents = fo.read()
self.assertEqual(contents, '100 0\n100 6\n200 12\n')
def test_truncate(self):
patterns = ['%s/*.log' % self.tempdir]
mylog = '%s/test.log' % (self.tempdir)
with open(mylog, 'wt') as fo:
fo.write('hello\n')
logs = kojid.BuildRootLogs(self.broot, patterns)
# first sync
logs.sync_logs()
self.assertEqual(sorted(logs.loginfo.keys()), [mylog])
# truncate and rsync again
with open(mylog, 'wt') as fo:
pass
logs.sync_logs()
# append and sync again
with open(mylog, 'at') as fo:
fo.write('...\n')
logs.sync_logs()
self.assertEqual(self.contents['test.log'], [b'hello\n', b'', b'...\n'])
def test_log_disappears(self):
patterns = ['%s/*.log' % self.tempdir]
mylog = '%s/test.log' % (self.tempdir)
with open(mylog, 'wt') as fo:
fo.write('hello\n')
logs = kojid.BuildRootLogs(self.broot, patterns)
# first sync
logs.sync_logs()
self.assertEqual(sorted(logs.loginfo.keys()), [mylog])
# delete and sync again
os.unlink(mylog)
logs.sync_logs()
self.assertEqual(self.contents['test.log'], [b'hello\n'])
# and again
logs.sync_logs()
self.assertEqual(self.contents['test.log'], [b'hello\n'])
# re-create and sync
with open(mylog, 'wt') as fo:
fo.write('world\n')
logs.sync_logs()
self.assertEqual(self.contents['test.log'], [b'hello\n', b'world\n'])
def test_no_workdir(self):
patterns = ['%s/*.log' % self.tempdir]
self.broot.workdir = None
logs = kojid.BuildRootLogs(self.broot, patterns, with_ts=True)
self.assertEqual(logs.with_ts, False)
def test_name_overlap(self):
mylog = '%s/test.log' % (self.tempdir)
os.mkdir('%s/dup' % self.tempdir)
mydup = '%s/dup/test.log' % (self.tempdir)
for fn in mylog, mydup:
with open(fn, 'wt') as fo:
fo.write('hello\n')
patterns = [
'%s/*.log' % self.tempdir,
'%s/*/*.log' % self.tempdir,
]
logs = kojid.BuildRootLogs(self.broot, patterns)
# first sync
logs.sync_logs()
self.assertEqual(sorted(logs.loginfo.keys()), [mydup, mylog])
self.assertEqual(logs.loginfo[mylog]['name'], 'test.log')
self.assertEqual(logs.loginfo[mydup]['name'], 'test.DUP00.log')
def test_stray_ts_log(self):
logs = kojid.BuildRootLogs(self.broot, [])
stray = '%s/test.log-ts.log' % (self.tempdir)
logs.add_log(stray)
if stray not in logs.ignored:
raise Exception('stray log not ignored')
if stray in logs.loginfo:
raise Exception('stray log not ignored')