File: test_catalog.py

package info (click to toggle)
python-scipy 0.14.0-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 52,228 kB
  • ctags: 63,719
  • sloc: python: 112,726; fortran: 88,685; cpp: 86,979; ansic: 85,860; makefile: 530; sh: 236
file content (528 lines) | stat: -rw-r--r-- 18,251 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
from __future__ import absolute_import, print_function

import sys
import os
import re
import glob
import string
import stat
import tempfile

from distutils.dir_util import remove_tree

from numpy.testing import TestCase, assert_, dec, run_module_suite
from numpy.testing.noseclasses import KnownFailureTest

from scipy.weave import catalog
from weave_test_utils import (clear_temp_catalog, restore_temp_catalog,
                              empty_temp_dir, cleanup_temp_dir)


skip_on_windows = dec.skipif(sys.platform == 'win32',
                             "Test works only on posix")


def samefile(a, b):
    try:
        return os.path.samefile(a, b)
    except AttributeError:
        return os.path.realpath(a) == os.path.realpath(b)


class TestIntermediateDir(TestCase):
    """
    Tests for intermediate dir (store of .cpp and .o during builds).
    These tests test whether intermediate dir is safe. If it's not,
    new one should be created.
    """
    def dirs_are_valid(self, wrong_dir, tmpdir):
        # Test if new dir is created and is consistent.
        new_im_dir = catalog.intermediate_dir(tmpdir)
        assert_(not samefile(new_im_dir, wrong_dir))
        new_im_dir2 = catalog.intermediate_dir(tmpdir)
        assert_(samefile(new_im_dir, new_im_dir2))

    @skip_on_windows
    def test_ownership(self):
        # Test if intermediate dir is owned by correct user.
        im_dir = catalog.intermediate_dir()
        im_dir_stat = os.stat(im_dir)
        proc_uid = os.getuid()
        assert_(proc_uid == im_dir_stat.st_uid)
        r_im_dir_stat = os.stat(os.path.dirname(im_dir))
        assert_(proc_uid == r_im_dir_stat.st_uid)

    @skip_on_windows
    def test_incorrect_ownership(self):
        # Test if new intermediate dir is created when there is only one
        # im dir owned by improper user.
        import pwd
        tmpdir = tempfile.mkdtemp()
        try:
            im_dir = catalog.create_intermediate_dir(tmpdir)
            root_im_dir = os.path.dirname(im_dir)
            nobody = pwd.getpwnam('nobody')[2]
            nobody_g = pwd.getpwnam('nobody')[3]
            try:
                os.chown(root_im_dir, nobody, nobody_g)
            except OSError:
                raise KnownFailureTest("Can't change owner.")
            else:
                self.dirs_are_valid(im_dir, tmpdir)
        finally:
            remove_tree(tmpdir)

    @skip_on_windows
    def test_permissions(self):
        # im dir should have permissions 0700
        im_dir = catalog.intermediate_dir()
        im_dir_stat = os.stat(im_dir)
        assert_(stat.S_IMODE(im_dir_stat.st_mode) == 0o0700)
        r_im_dir_stat = os.stat(os.path.dirname(im_dir))
        assert_(stat.S_IMODE(r_im_dir_stat.st_mode) == 0o0700)

    @skip_on_windows
    def test_incorrect_permissions(self):
        # If permissions on existing im dir are not correct,
        # a new one should be created.
        tmpdir = tempfile.mkdtemp()
        try:
            im_dir = catalog.create_intermediate_dir(tmpdir)
            root_im_dir = os.path.dirname(im_dir)
            try:
                os.chmod(root_im_dir, 0o777)
            except OSError:
                raise KnownFailureTest("Can't set file permissions.")
            else:
                self.dirs_are_valid(im_dir, tmpdir)
        finally:
            remove_tree(tmpdir)

    @skip_on_windows
    def test_symlink(self):
        # im dir shouldn't be a symlink
        r_im_dir = os.path.dirname(catalog.intermediate_dir())
        assert_(os.path.islink(r_im_dir) is False)

    @skip_on_windows
    def test_symlink_raise(self):
        # If existing im dir is a symlink, new one should be created.
        tmpdir = tempfile.mkdtemp()
        try:
            im_dir = catalog.create_intermediate_dir(tmpdir)
            root_im_dir = os.path.dirname(im_dir)

            tempdir = tempfile.mkdtemp(prefix='scipy-test', dir=tmpdir)
            try:
                os.rename(root_im_dir, tempdir)
            except OSError:
                raise KnownFailureTest("Can't move intermediate dir.")

            try:
                os.symlink(tempdir, root_im_dir)
            except OSError:
                raise KnownFailureTest(
                    "Can't create symlink to intermediate dir.")
            else:
                self.dirs_are_valid(im_dir, tmpdir)
        finally:
            remove_tree(tmpdir)


class TestDefaultDir(TestCase):
    """
    Tests for 'catalog.default_dir()'.
    These should verified posix and win default_dir function.
    """
    def test_win(self):
        # test if default_dir for Windows platform is accessible
        #
        # since default_dir_win() does not have any Windows specific code,
        # let's test it everywhere
        d = catalog.default_dir_win()
        assert_(catalog.is_writable(d))

    @skip_on_windows
    def test_posix(self):
        # test if posix default_dir is writable
        d = catalog.default_dir_posix()
        assert_(catalog.is_writable(d))

    @skip_on_windows
    def test_posix_home_inaccessible(self):
        # what happens when home catalog dir is innaccessible
        tmpdir = tempfile.mkdtemp()
        try:
            d_dir = catalog.default_dir_posix(tmpdir)

            try:
                os.chmod(d_dir, 0o000)
            except OSError:
                raise KnownFailureTest("Can't change permissions of default_dir.")

            new_ddir = catalog.default_dir_posix(tmpdir)
            assert_(not os.path.samefile(new_ddir, d_dir))
            new_ddir2 = catalog.default_dir_posix(tmpdir)
            assert_(os.path.samefile(new_ddir, new_ddir2))
        finally:
            os.chmod(d_dir, 0o700)
            remove_tree(tmpdir)

    @skip_on_windows
    def test_posix_dirs_inaccessible(self):
        # test if new dir is created if both implicit dirs are not valid
        tmpdir = tempfile.mkdtemp()
        try:
            d_dir = catalog.default_dir_posix(tmpdir)

            try:
                os.chmod(d_dir, 0o000)
            except OSError:
                raise KnownFailureTest("Can't change permissions of default_dir.")

            d_dir2 = catalog.default_dir_posix(tmpdir)

            try:
                os.chmod(d_dir2, 0o000)
            except OSError:
                raise KnownFailureTest("Can't change permissions of default_dir.")

            new_ddir = catalog.default_dir_posix(tmpdir)
            assert_(not (os.path.samefile(new_ddir, d_dir) or os.path.samefile(new_ddir, d_dir2)))
            new_ddir2 = catalog.default_dir_posix(tmpdir)
            assert_(os.path.samefile(new_ddir, new_ddir2))
        finally:
            os.chmod(d_dir, 0o700)
            os.chmod(d_dir2, 0o700)
            remove_tree(tmpdir)

    def test_is_writable(self):
        # default_dir has to be writable
        path = catalog.default_dir()
        name = os.path.join(path,'dummy_catalog')
        test_file = open(name,'w')
        try:
            test_file.write('making sure default location is writable\n')
        finally:
            test_file.close()
            os.remove(name)


class TestOsDependentCatalogName(TestCase):
    pass


class TestCatalogPath(TestCase):

    def test_default(self):
        in_path = catalog.default_dir()
        path = catalog.catalog_path(in_path)
        d,f = os.path.split(path)
        assert_(d == in_path)
        assert_(f == catalog.os_dependent_catalog_name())

    def test_current(self):
        in_path = '.'
        path = catalog.catalog_path(in_path)
        d,f = os.path.split(path)
        assert_(d == os.path.abspath(in_path))
        assert_(f == catalog.os_dependent_catalog_name())

    @skip_on_windows
    def test_user(path):
        in_path = '~'
        path = catalog.catalog_path(in_path)
        d,f = os.path.split(path)
        assert_(d == os.path.expanduser(in_path))
        assert_(f == catalog.os_dependent_catalog_name())

    def test_module(self):
        # hand it a module and see if it uses the parent directory
        # of the module.
        path = catalog.catalog_path(os.__file__)
        d,f = os.path.split(os.__file__)
        d2,f = os.path.split(path)
        assert_(d2 == d)

    def test_path(self):
        # use os.__file__ to get a usable directory.
        in_path,f = os.path.split(os.__file__)
        path = catalog.catalog_path(in_path)
        d,f = os.path.split(path)
        assert_(d == in_path)

    def test_bad_path(self):
        # stupid_path_name
        in_path = 'stupid_path_name'
        path = catalog.catalog_path(in_path)
        assert_(path is None)


class TestGetCatalog(TestCase):
    """ This only tests whether new catalogs are created correctly.
        And whether non-existent return None correctly with read mode.
        Putting catalogs in the right place is all tested with
        catalog_dir tests.
    """

    def get_test_dir(self,erase=0):
        # make sure tempdir catalog doesn't exist
        pardir = tempfile.mkdtemp(suffix='cat_test')
        cat_glob = os.path.join(pardir,catalog.os_dependent_catalog_name()+'.*')
        cat_files = glob.glob(cat_glob)
        if erase:
            for cat_file in cat_files:
                os.remove(cat_file)
        return pardir

    def test_nonexistent_catalog_is_none(self):
        pardir = self.get_test_dir(erase=1)
        cat = catalog.get_catalog(pardir,'r')
        remove_tree(pardir)
        assert_(cat is None)

    def test_create_catalog(self):
        pardir = self.get_test_dir(erase=1)
        cat = catalog.get_catalog(pardir,'c')
        assert_(cat is not None)
        cat.close()
        remove_tree(pardir)


class TestCatalog(TestCase):

    def clear_environ(self):
        if 'PYTHONCOMPILED' in os.environ:
            self.old_PYTHONCOMPILED = os.environ['PYTHONCOMPILED']
            del os.environ['PYTHONCOMPILED']
        else:
            self.old_PYTHONCOMPILED = None

    def reset_environ(self):
        if self.old_PYTHONCOMPILED:
            os.environ['PYTHONCOMPILED'] = self.old_PYTHONCOMPILED
            self.old_PYTHONCOMPILED = None

    def setUp(self):
        self.clear_environ()

    def tearDown(self):
        self.reset_environ()

    def test_set_module_directory(self):
        q = catalog.catalog()
        q.set_module_directory('bob')
        r = q.get_module_directory()
        assert_(r == 'bob')

    def test_clear_module_directory(self):
        q = catalog.catalog()
        r = q.get_module_directory()
        assert_(r is None)
        q.set_module_directory('bob')
        r = q.clear_module_directory()
        assert_(r is None)

    def test_get_environ_path(self):
        if sys.platform == 'win32':
            sep = ';'
        else:
            sep = ':'
        os.environ['PYTHONCOMPILED'] = sep.join(('path1','path2','path3'))
        q = catalog.catalog()
        path = q.get_environ_path()
        assert_(path == ['path1','path2','path3'])

    def test_build_search_order1(self):
        # MODULE in search path should be replaced by module_dir.
        q = catalog.catalog(['first','MODULE','third'])
        q.set_module_directory('second')
        order = q.build_search_order()
        assert_(order == ['first','second','third',catalog.default_dir()])

    def test_build_search_order2(self):
        # MODULE in search path should be removed if module_dir==None.
        q = catalog.catalog(['first','MODULE','third'])
        order = q.build_search_order()
        assert_(order == ['first','third',catalog.default_dir()])

    def test_build_search_order3(self):
        # If MODULE is absent, module_dir shouldn't be in search path.
        q = catalog.catalog(['first','second'])
        q.set_module_directory('third')
        order = q.build_search_order()
        assert_(order == ['first','second',catalog.default_dir()])

    def test_build_search_order4(self):
        # Make sure environment variable is getting used.
        q = catalog.catalog(['first','second'])
        if sys.platform == 'win32':
            sep = ';'
        else:
            sep = ':'
        os.environ['PYTHONCOMPILED'] = sep.join(('MODULE','fourth','fifth'))
        q.set_module_directory('third')
        order = q.build_search_order()
        assert_(order == ['first','second','third','fourth','fifth',catalog.default_dir()])

    def test_catalog_files1(self):
        # Be sure we get at least one file even without specifying the path.
        q = catalog.catalog()
        files = q.get_catalog_files()
        assert_(len(files) == 1)

    def test_catalog_files2(self):
        # Ignore bad paths in the path.
        q = catalog.catalog()
        os.environ['PYTHONCOMPILED'] = '_some_bad_path_'
        files = q.get_catalog_files()
        assert_(len(files) == 1)

    def test_get_existing_files1(self):
        # Shouldn't get any files when temp doesn't exist and no path set.
        backup_dir = clear_temp_catalog()
        q = catalog.catalog()
        files = q.get_existing_files()
        restore_temp_catalog(backup_dir)
        assert_(len(files) == 0)

    def test_get_existing_files2(self):
        # Shouldn't get a single file from the temp dir.
        backup_dir = clear_temp_catalog()
        q = catalog.catalog()
        # create a dummy file
        q.add_function('code', os.getpid)
        del q
        q = catalog.catalog()
        files = q.get_existing_files()
        restore_temp_catalog(backup_dir)
        assert_(len(files) == 1)

    def test_access_writable_file(self):
        # There should always be a writable file -- even if it is in temp
        q = catalog.catalog()
        file = q.get_writable_file()
        try:
            f = open(file,'w')
            f.write('bob')
        finally:
            f.close()
            os.remove(file)

    def test_writable_with_bad_path(self):
        # There should always be a writable file -- even if search paths
        # contain bad values.
        if sys.platform == 'win32':
            sep = ';'
        else:
            sep = ':'
        os.environ['PYTHONCOMPILED'] = sep.join(('_bad_path_name_'))
        q = catalog.catalog()
        file = q.get_writable_file()
        try:
            f = open(file,'w')
            f.write('bob')
        finally:
            f.close()
        os.remove(file)

    def test_writable_dir(self):
        # Check that we can create a file in the writable directory
        q = catalog.catalog()
        d = q.get_writable_dir()
        file = os.path.join(d,'some_silly_file')
        try:
            f = open(file,'w')
            f.write('bob')
        finally:
            f.close()
            os.remove(file)

    def test_unique_module_name(self):
        # Check that we can create a file in the writable directory
        q = catalog.catalog()
        file = q.unique_module_name('bob')
        cfile1 = file+'.cpp'
        assert_(not os.path.exists(cfile1))
        # Make sure it is writable
        try:
            f = open(cfile1,'w')
            f.write('bob')
        finally:
            f.close()
        # try again with same code fragment -- should get unique name
        file = q.unique_module_name('bob')
        cfile2 = file+'.cpp'
        assert_(not os.path.exists(cfile2+'.cpp'))
        os.remove(cfile1)

    def test_add_function_persistent1(self):
        # Test persisting a function in the default catalog
        backup_dir = clear_temp_catalog()
        q = catalog.catalog()
        # just use some already available functions
        funcs = [string.upper, string.lower, string.find,string.replace]
        for i in funcs:
            q.add_function_persistent('code',i)
        pfuncs = q.get_cataloged_functions('code')
        # any way to clean modules???
        restore_temp_catalog(backup_dir)
        for i in funcs:
            assert_(i in pfuncs)

    def test_add_function_ordered(self):
        backup_dir = clear_temp_catalog()
        q = catalog.catalog()

        q.add_function('f',string.upper)
        q.add_function('f',string.lower)
        q.add_function('ff',string.find)
        q.add_function('ff',string.replace)
        q.add_function('fff',string.atof)
        q.add_function('fff',string.atoi)
        del q

        # now we're gonna make a new catalog with same code
        # but different functions in a specified module directory
        env_dir = empty_temp_dir()
        r = catalog.catalog(env_dir)
        r.add_function('ff',os.abort)
        r.add_function('ff',os.chdir)
        r.add_function('fff',os.access)
        r.add_function('fff',os.open)
        del r
        # now we're gonna make a new catalog with same code
        # but different functions in a user specified directory
        user_dir = empty_temp_dir()
        s = catalog.catalog(user_dir)
        s.add_function('fff',re.match)
        s.add_function('fff',re.purge)
        del s

        # open new catalog and make sure it retreives the functions
        # from d catalog instead of the temp catalog (made by q)
        os.environ['PYTHONCOMPILED'] = env_dir
        t = catalog.catalog(user_dir)
        funcs1 = t.get_functions('f')
        funcs2 = t.get_functions('ff')
        funcs3 = t.get_functions('fff')
        restore_temp_catalog(backup_dir)
        # make sure everything is read back in the correct order
        # a little cheating... I'm ignoring any functions that might have
        # been read in from a prior catalog file (such as the defualt one).
        # the test should really be made so that these aren't read in, but
        # until I get this figured out...
        #assert_(funcs1 == [string.lower,string.upper])
        #assert_(funcs2 == [os.chdir,os.abort,string.replace,string.find])
        #assert_(funcs3 == [re.purge,re.match,os.open,
        #                  os.access,string.atoi,string.atof])
        assert_(funcs1[:2] == [string.lower,string.upper]),repr(funcs1)
        assert_(funcs2[:4] == [os.chdir,os.abort,string.replace,string.find])
        assert_(funcs3[:6] == [re.purge,re.match,os.open,
                          os.access,string.atoi,string.atof])
        cleanup_temp_dir(user_dir)
        cleanup_temp_dir(env_dir)


if __name__ == '__main__':
    run_module_suite()