python/mozbuild/mozbuild/test/controller/test_clobber.py
author Gregory Szorc <gps@mozilla.com>
Fri, 29 Mar 2013 10:34:58 -0700
changeset 138936 962ec303ced29c831230cfdd10494a126eeb7925
parent 137118 a61aa08ab4ac92a5f909a87f0aa717a05eb36df2
child 140807 b49b5f42be79bf9290a0beca397e4ec7fbe054f4
permissions -rw-r--r--
Bug 837323 - Automatically clobber when CLOBBER is updated; r=ted, glandium

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from __future__ import unicode_literals

import os
import shutil
import tempfile
import unittest

from StringIO import StringIO

from mozunit import main

from mozbuild.controller.clobber import Clobberer
from mozbuild.controller.clobber import main as clobber


class TestClobberer(unittest.TestCase):
    def setUp(self):
        self._temp_dirs = []

        return unittest.TestCase.setUp(self)

    def tearDown(self):
        for d in self._temp_dirs:
            shutil.rmtree(d, ignore_errors=True)

        return unittest.TestCase.tearDown(self)

    def get_tempdir(self):
        t = tempfile.mkdtemp()
        self._temp_dirs.append(t)
        return t

    def get_topsrcdir(self):
        t = self.get_tempdir()
        p = os.path.join(t, 'CLOBBER')
        with open(p, 'a'):
            pass

        return t

    def test_no_objdir(self):
        """If topobjdir does not exist, no clobber is needed."""

        tmp = os.path.join(self.get_tempdir(), 'topobjdir')
        self.assertFalse(os.path.exists(tmp))

        c = Clobberer(self.get_topsrcdir(), tmp)
        self.assertFalse(c.clobber_needed())

        # Side-effect is topobjdir is created with CLOBBER file touched.
        required, performed, reason = c.maybe_do_clobber(os.getcwd())
        self.assertFalse(required)
        self.assertFalse(performed)
        self.assertIsNone(reason)

        self.assertTrue(os.path.isdir(tmp))
        self.assertTrue(os.path.exists(os.path.join(tmp, 'CLOBBER')))

    def test_objdir_no_clobber_file(self):
        """If CLOBBER does not exist in topobjdir, treat as empty."""

        c = Clobberer(self.get_topsrcdir(), self.get_tempdir())
        self.assertFalse(c.clobber_needed())

        required, performed, reason = c.maybe_do_clobber(os.getcwd())
        self.assertFalse(required)
        self.assertFalse(performed)
        self.assertIsNone(reason)

        self.assertTrue(os.path.exists(os.path.join(c.topobjdir, 'CLOBBER')))

    def test_objdir_clobber_newer(self):
        """If CLOBBER in topobjdir is newer, do nothing."""

        c = Clobberer(self.get_topsrcdir(), self.get_tempdir())
        with open(c.obj_clobber, 'a'):
            pass

        required, performed, reason = c.maybe_do_clobber(os.getcwd())
        self.assertFalse(required)
        self.assertFalse(performed)
        self.assertIsNone(reason)

    def test_objdir_clobber_older(self):
        """If CLOBBER in topobjdir is older, we clobber."""

        c = Clobberer(self.get_topsrcdir(), self.get_tempdir())
        with open(c.obj_clobber, 'a'):
            pass

        dummy_path = os.path.join(c.topobjdir, 'foo')
        with open(dummy_path, 'a'):
            pass

        self.assertTrue(os.path.exists(dummy_path))

        old_time = os.path.getmtime(c.src_clobber) - 60
        os.utime(c.obj_clobber, (old_time, old_time))

        self.assertTrue(c.clobber_needed())

        required, performed, reason = c.maybe_do_clobber(os.getcwd(), False)
        self.assertTrue(required)
        self.assertFalse(performed)
        self.assertIn('Automatic clobbering has been disabled', reason)

        # Now let's actually do it.
        required, performed, reason = c.maybe_do_clobber(os.getcwd())
        self.assertTrue(required)
        self.assertTrue(performed)

        self.assertFalse(os.path.exists(dummy_path))
        self.assertTrue(os.path.exists(c.obj_clobber))
        self.assertGreaterEqual(os.path.getmtime(c.obj_clobber),
            os.path.getmtime(c.src_clobber))

    def test_objdir_is_srcdir(self):
        """If topobjdir is the topsrcdir, refuse to clobber."""

        tmp = self.get_topsrcdir()
        c = Clobberer(tmp, tmp)

        self.assertFalse(c.clobber_needed())

    def test_cwd_is_topobjdir(self):
        """If cwd is topobjdir, we can still clobber."""
        c = Clobberer(self.get_topsrcdir(), self.get_tempdir())

        with open(c.obj_clobber, 'a'):
            pass

        dummy_file = os.path.join(c.topobjdir, 'dummy_file')
        with open(dummy_file, 'a'):
            pass

        dummy_dir = os.path.join(c.topobjdir, 'dummy_dir')
        os.mkdir(dummy_dir)

        self.assertTrue(os.path.exists(dummy_file))
        self.assertTrue(os.path.isdir(dummy_dir))

        old_time = os.path.getmtime(c.src_clobber) - 60
        os.utime(c.obj_clobber, (old_time, old_time))

        self.assertTrue(c.clobber_needed())

        required, performed, reason = c.maybe_do_clobber(c.topobjdir)
        self.assertTrue(required)
        self.assertTrue(performed)

        self.assertFalse(os.path.exists(dummy_file))
        self.assertFalse(os.path.exists(dummy_dir))

    def test_cwd_under_topobjdir(self):
        """If cwd is under topobjdir, we can't clobber."""

        c = Clobberer(self.get_topsrcdir(), self.get_tempdir())

        with open(c.obj_clobber, 'a'):
            pass

        old_time = os.path.getmtime(c.src_clobber) - 60
        os.utime(c.obj_clobber, (old_time, old_time))

        d = os.path.join(c.topobjdir, 'dummy_dir')
        os.mkdir(d)

        required, performed, reason = c.maybe_do_clobber(d)
        self.assertTrue(required)
        self.assertFalse(performed)
        self.assertIn('Cannot clobber while the shell is inside', reason)


    def test_mozconfig_overrides_auto_clobber(self):
        """If NO_AUTOCLOBBER is in the environment, don't auto clobber."""

        topsrcdir = self.get_topsrcdir()
        topobjdir = self.get_tempdir()

        obj_clobber = os.path.join(topobjdir, 'CLOBBER')
        with open(obj_clobber, 'a'):
            pass

        dummy_file = os.path.join(topobjdir, 'dummy_file')
        with open(dummy_file, 'a'):
            pass

        self.assertTrue(os.path.exists(dummy_file))

        old_time = os.path.getmtime(os.path.join(topsrcdir, 'CLOBBER')) - 60
        os.utime(obj_clobber, (old_time, old_time))

        env = dict(os.environ)
        env['NO_AUTOCLOBBER'] = '1'

        s = StringIO()
        status = clobber([topsrcdir, topobjdir], env, os.getcwd(), s)
        self.assertEqual(status, 1)
        self.assertIn('Automatic clobbering has been disabled', s.getvalue())
        self.assertTrue(os.path.exists(dummy_file))


if __name__ == '__main__':
    main()