1from __future__ import absolute_import 2import unittest 3 4import os 5import six 6import sys 7import os.path 8import time 9from tempfile import mkdtemp 10from shutil import rmtree 11import mozunit 12from mozprocess import processhandler 13 14from nsinstall import nsinstall 15import nsinstall as nsinstall_module 16 17NSINSTALL_PATH = nsinstall_module.__file__ 18 19# Run the non-ASCII tests on (a) Windows, or (b) any platform with 20# sys.stdin.encoding set to UTF-8 21import codecs 22 23RUN_NON_ASCII_TESTS = sys.platform == "win32" or ( 24 sys.stdin.encoding is not None 25 and codecs.lookup(sys.stdin.encoding) == codecs.lookup("utf-8") 26) 27 28 29class TestNsinstall(unittest.TestCase): 30 """ 31 Unit tests for nsinstall.py 32 """ 33 34 def setUp(self): 35 self.tmpdir = mkdtemp() 36 37 def tearDown(self): 38 # Unicode strings means non-ASCII children can be deleted properly on 39 # Windows 40 if sys.stdin.encoding is None: 41 tmpdir = six.ensure_text(self.tmpdir) 42 else: 43 tmpdir = six.ensure_text(self.tmpdir, sys.stdin.encoding) 44 rmtree(tmpdir) 45 46 # utility methods for tests 47 def touch(self, file, dir=None): 48 if dir is None: 49 dir = self.tmpdir 50 f = os.path.join(dir, file) 51 open(f, "w").close() 52 return f 53 54 def mkdirs(self, dir): 55 d = os.path.join(self.tmpdir, dir) 56 os.makedirs(d) 57 return d 58 59 def test_nsinstall_D(self): 60 "Test nsinstall -D <dir>" 61 testdir = os.path.join(self.tmpdir, "test") 62 self.assertEqual(nsinstall(["-D", testdir]), 0) 63 self.assert_(os.path.isdir(testdir)) 64 65 def test_nsinstall_basic(self): 66 "Test nsinstall <file> <dir>" 67 testfile = self.touch("testfile") 68 testdir = self.mkdirs("testdir") 69 self.assertEqual(nsinstall([testfile, testdir]), 0) 70 self.assert_(os.path.isfile(os.path.join(testdir, "testfile"))) 71 72 def test_nsinstall_basic_recursive(self): 73 "Test nsinstall <dir> <dest dir>" 74 sourcedir = self.mkdirs("sourcedir") 75 self.touch("testfile", sourcedir) 76 Xfile = self.touch("Xfile", sourcedir) 77 copieddir = self.mkdirs("sourcedir/copieddir") 78 self.touch("testfile2", copieddir) 79 Xdir = self.mkdirs("sourcedir/Xdir") 80 self.touch("testfile3", Xdir) 81 82 destdir = self.mkdirs("destdir") 83 84 self.assertEqual(nsinstall([sourcedir, destdir, "-X", Xfile, "-X", Xdir]), 0) 85 86 testdir = os.path.join(destdir, "sourcedir") 87 self.assert_(os.path.isdir(testdir)) 88 self.assert_(os.path.isfile(os.path.join(testdir, "testfile"))) 89 self.assert_(not os.path.exists(os.path.join(testdir, "Xfile"))) 90 self.assert_(os.path.isdir(os.path.join(testdir, "copieddir"))) 91 self.assert_(os.path.isfile(os.path.join(testdir, "copieddir", "testfile2"))) 92 self.assert_(not os.path.exists(os.path.join(testdir, "Xdir"))) 93 94 def test_nsinstall_multiple(self): 95 "Test nsinstall <three files> <dest dir>" 96 testfiles = [ 97 self.touch("testfile1"), 98 self.touch("testfile2"), 99 self.touch("testfile3"), 100 ] 101 testdir = self.mkdirs("testdir") 102 self.assertEqual(nsinstall(testfiles + [testdir]), 0) 103 for f in testfiles: 104 self.assert_(os.path.isfile(os.path.join(testdir, os.path.basename(f)))) 105 106 def test_nsinstall_dir_exists(self): 107 "Test nsinstall <dir> <dest dir>, where <dest dir>/<dir> already exists" 108 srcdir = self.mkdirs("test") 109 destdir = self.mkdirs("testdir/test") 110 self.assertEqual(nsinstall([srcdir, os.path.dirname(destdir)]), 0) 111 self.assert_(os.path.isdir(destdir)) 112 113 def test_nsinstall_t(self): 114 "Test that nsinstall -t works (preserve timestamp)" 115 testfile = self.touch("testfile") 116 testdir = self.mkdirs("testdir") 117 # set mtime to now - 30 seconds 118 t = int(time.time()) - 30 119 os.utime(testfile, (t, t)) 120 self.assertEqual(nsinstall(["-t", testfile, testdir]), 0) 121 destfile = os.path.join(testdir, "testfile") 122 self.assert_(os.path.isfile(destfile)) 123 self.assertEqual(os.stat(testfile).st_mtime, os.stat(destfile).st_mtime) 124 125 @unittest.skipIf(sys.platform == "win32", "Windows doesn't have real file modes") 126 def test_nsinstall_m(self): 127 "Test that nsinstall -m works (set mode)" 128 testfile = self.touch("testfile") 129 mode = 0o600 130 os.chmod(testfile, mode) 131 testdir = self.mkdirs("testdir") 132 self.assertEqual( 133 nsinstall(["-m", "{0:04o}".format(mode), testfile, testdir]), 0 134 ) 135 destfile = os.path.join(testdir, "testfile") 136 self.assert_(os.path.isfile(destfile)) 137 self.assertEqual(os.stat(testfile).st_mode, os.stat(destfile).st_mode) 138 139 def test_nsinstall_d(self): 140 "Test that nsinstall -d works (create directories in target)" 141 # -d makes no sense to me, but ok! 142 testfile = self.touch("testfile") 143 testdir = self.mkdirs("testdir") 144 destdir = os.path.join(testdir, "subdir") 145 self.assertEqual(nsinstall(["-d", testfile, destdir]), 0) 146 self.assert_(os.path.isdir(os.path.join(destdir, "testfile"))) 147 148 @unittest.skipIf(not RUN_NON_ASCII_TESTS, "Skipping non ascii tests") 149 def test_nsinstall_non_ascii(self): 150 "Test that nsinstall handles non-ASCII files" 151 filename = u"\u2325\u3452\u2415\u5081" 152 testfile = self.touch(filename) 153 testdir = self.mkdirs(u"\u4241\u1D04\u1414") 154 self.assertEqual( 155 nsinstall([testfile.encode("utf-8"), testdir.encode("utf-8")]), 0 156 ) 157 158 destfile = os.path.join(testdir, filename) 159 self.assert_(os.path.isfile(destfile)) 160 161 # Executing nsinstall.py with python 2 is not supported. 162 @unittest.skipIf( 163 not RUN_NON_ASCII_TESTS or sys.version_info[0] == 2, "Skipping non ascii tests" 164 ) 165 def test_nsinstall_non_ascii_subprocess(self): 166 "Test that nsinstall as a subprocess handles non-ASCII files" 167 filename = u"\u2325\u3452\u2415\u5081" 168 testfile = self.touch(filename) 169 testdir = self.mkdirs(u"\u4241\u1D04\u1414") 170 # We don't use subprocess because it can't handle Unicode on 171 # Windows <http://bugs.python.org/issue1759845>. mozprocess calls 172 # CreateProcessW directly so it's perfect. 173 p = processhandler.ProcessHandlerMixin( 174 [sys.executable, NSINSTALL_PATH, testfile, testdir] 175 ) 176 p.run() 177 rv = p.wait() 178 179 self.assertEqual(rv, 0) 180 destfile = os.path.join(testdir, filename) 181 self.assert_(os.path.isfile(destfile)) 182 183 # TODO: implement -R, -l, -L and test them! 184 185 186if __name__ == "__main__": 187 mozunit.main() 188