import os
import os.path
import sys
import time
import unittest
from shutil import rmtree
from tempfile import mkdtemp
import mozunit
import nsinstall as nsinstall_module
import six
from mozprocess import processhandler
from nsinstall import nsinstall
NSINSTALL_PATH = nsinstall_module.__file__
# Run the non-ASCII tests on (a) Windows, or (b) any platform with
# sys.stdin.encoding set to UTF-8
import codecs
RUN_NON_ASCII_TESTS = sys.platform == "win32" or (
sys.stdin.encoding is not None
and codecs.lookup(sys.stdin.encoding) == codecs.lookup("utf-8")
)
class TestNsinstall(unittest.TestCase):
"""
Unit tests for nsinstall.py
"""
def setUp(self):
self.tmpdir = mkdtemp()
def tearDown(self):
# Unicode strings means non-ASCII children can be deleted properly on
# Windows
if sys.stdin.encoding is None:
tmpdir = six.ensure_text(self.tmpdir)
else:
tmpdir = six.ensure_text(self.tmpdir, sys.stdin.encoding)
rmtree(tmpdir)
# utility methods for tests
def touch(self, file, dir=None):
if dir is None:
dir = self.tmpdir
f = os.path.join(dir, file)
open(f, "w").close()
return f
def mkdirs(self, dir):
d = os.path.join(self.tmpdir, dir)
os.makedirs(d)
return d
def test_nsinstall_D(self):
"Test nsinstall -D
"
testdir = os.path.join(self.tmpdir, "test")
self.assertEqual(nsinstall(["-D", testdir]), 0)
self.assert_(os.path.isdir(testdir))
def test_nsinstall_basic(self):
"Test nsinstall "
testfile = self.touch("testfile")
testdir = self.mkdirs("testdir")
self.assertEqual(nsinstall([testfile, testdir]), 0)
self.assert_(os.path.isfile(os.path.join(testdir, "testfile")))
def test_nsinstall_basic_recursive(self):
"Test nsinstall "
sourcedir = self.mkdirs("sourcedir")
self.touch("testfile", sourcedir)
Xfile = self.touch("Xfile", sourcedir)
copieddir = self.mkdirs("sourcedir/copieddir")
self.touch("testfile2", copieddir)
Xdir = self.mkdirs("sourcedir/Xdir")
self.touch("testfile3", Xdir)
destdir = self.mkdirs("destdir")
self.assertEqual(nsinstall([sourcedir, destdir, "-X", Xfile, "-X", Xdir]), 0)
testdir = os.path.join(destdir, "sourcedir")
self.assert_(os.path.isdir(testdir))
self.assert_(os.path.isfile(os.path.join(testdir, "testfile")))
self.assert_(not os.path.exists(os.path.join(testdir, "Xfile")))
self.assert_(os.path.isdir(os.path.join(testdir, "copieddir")))
self.assert_(os.path.isfile(os.path.join(testdir, "copieddir", "testfile2")))
self.assert_(not os.path.exists(os.path.join(testdir, "Xdir")))
def test_nsinstall_multiple(self):
"Test nsinstall "
testfiles = [
self.touch("testfile1"),
self.touch("testfile2"),
self.touch("testfile3"),
]
testdir = self.mkdirs("testdir")
self.assertEqual(nsinstall(testfiles + [testdir]), 0)
for f in testfiles:
self.assert_(os.path.isfile(os.path.join(testdir, os.path.basename(f))))
def test_nsinstall_dir_exists(self):
"Test nsinstall , where / already exists"
srcdir = self.mkdirs("test")
destdir = self.mkdirs("testdir/test")
self.assertEqual(nsinstall([srcdir, os.path.dirname(destdir)]), 0)
self.assert_(os.path.isdir(destdir))
def test_nsinstall_t(self):
"Test that nsinstall -t works (preserve timestamp)"
testfile = self.touch("testfile")
testdir = self.mkdirs("testdir")
# set mtime to now - 30 seconds
t = int(time.time()) - 30
os.utime(testfile, (t, t))
self.assertEqual(nsinstall(["-t", testfile, testdir]), 0)
destfile = os.path.join(testdir, "testfile")
self.assert_(os.path.isfile(destfile))
self.assertEqual(os.stat(testfile).st_mtime, os.stat(destfile).st_mtime)
@unittest.skipIf(sys.platform == "win32", "Windows doesn't have real file modes")
def test_nsinstall_m(self):
"Test that nsinstall -m works (set mode)"
testfile = self.touch("testfile")
mode = 0o600
os.chmod(testfile, mode)
testdir = self.mkdirs("testdir")
self.assertEqual(
nsinstall(["-m", "{0:04o}".format(mode), testfile, testdir]), 0
)
destfile = os.path.join(testdir, "testfile")
self.assert_(os.path.isfile(destfile))
self.assertEqual(os.stat(testfile).st_mode, os.stat(destfile).st_mode)
def test_nsinstall_d(self):
"Test that nsinstall -d works (create directories in target)"
# -d makes no sense to me, but ok!
testfile = self.touch("testfile")
testdir = self.mkdirs("testdir")
destdir = os.path.join(testdir, "subdir")
self.assertEqual(nsinstall(["-d", testfile, destdir]), 0)
self.assert_(os.path.isdir(os.path.join(destdir, "testfile")))
@unittest.skipIf(not RUN_NON_ASCII_TESTS, "Skipping non ascii tests")
def test_nsinstall_non_ascii(self):
"Test that nsinstall handles non-ASCII files"
filename = u"\u2325\u3452\u2415\u5081"
testfile = self.touch(filename)
testdir = self.mkdirs(u"\u4241\u1D04\u1414")
self.assertEqual(
nsinstall([testfile.encode("utf-8"), testdir.encode("utf-8")]), 0
)
destfile = os.path.join(testdir, filename)
self.assert_(os.path.isfile(destfile))
# Executing nsinstall.py with python 2 is not supported.
@unittest.skipIf(
not RUN_NON_ASCII_TESTS or sys.version_info[0] == 2, "Skipping non ascii tests"
)
def test_nsinstall_non_ascii_subprocess(self):
"Test that nsinstall as a subprocess handles non-ASCII files"
filename = u"\u2325\u3452\u2415\u5081"
testfile = self.touch(filename)
testdir = self.mkdirs(u"\u4241\u1D04\u1414")
# We don't use subprocess because it can't handle Unicode on
# Windows . mozprocess calls
# CreateProcessW directly so it's perfect.
p = processhandler.ProcessHandlerMixin(
[sys.executable, NSINSTALL_PATH, testfile, testdir]
)
p.run()
rv = p.wait()
self.assertEqual(rv, 0)
destfile = os.path.join(testdir, filename)
self.assert_(os.path.isfile(destfile))
# TODO: implement -R, -l, -L and test them!
if __name__ == "__main__":
mozunit.main()