194 lines
6 KiB
Python
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')
|
|
|
|
|