普通文本  |  83行  |  2.36 KB

#!/usr/bin/env python2

# Copyright 2016 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Unit tests for apache_log_metrics.py"""

from __future__ import print_function

import StringIO
import subprocess
import tempfile
import threading
import time
import unittest

import tail_until_writer_finished


class TestTailUntilWriterFinished(unittest.TestCase):
    """Tests tail_until_writer_finished."""

    def SkipIfMissingInotifyTools(self):
        """The tail_until_writer_finished module requires 'inotifywait'."""
        try:
          subprocess.call(['inotifywait'], stderr=subprocess.PIPE)
        except OSError:
          raise unittest.SkipTest('inotify-tools must be installed.')

    def testTail(self):
        """Tests reading a file from the end."""
        self.GetsEntireInput(seek_to_end=True)

    def testRead(self):
        """Tests reading a file from the beginning."""
        self.GetsEntireInput(seek_to_end=False)

    def GetsEntireInput(self, seek_to_end):
        """Tails a temp file in a thread.

        Check that it read the file correctly.

        @param seek_to_end: Whether to .seek to the end of the file before
            reading.
        """
        self.SkipIfMissingInotifyTools()

        f = tempfile.NamedTemporaryFile()
        output = StringIO.StringIO()

        f.write('This line will not get read if we seek to end.\n')
        f.flush()

        def Tail():
            """Tails the file into |output| with a 64k chunk size."""
            tail_until_writer_finished.TailFile(
                f.name, 0.1, 64000, outfile=output, seek_to_end=seek_to_end)

        thread = threading.Thread(target=Tail)
        thread.start()

        # There is a race here: the thread must start the inotify process before
        # we close the file. This shouldn't take long at all, so add a small
        # sleep.
        time.sleep(0.3)

        for i in range(100):
            f.write(str(i) + '\n')
            f.flush()
        f.close()
        thread.join()

        expected = ''.join([str(i) + '\n' for i in range(100)])
        if not seek_to_end:
            expected = ('This line will not get read if we seek to end.\n'
                        + expected)
        self.assertEqual(output.getvalue(), expected)


if __name__ == '__main__':
    unittest.main()