1
# Copyright (C) 2005, 2006 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""Tests for the osutils wrapper."""
31
from bzrlib.errors import BzrBadParameterNotUnicode, InvalidURL
32
from bzrlib.tests import (
40
class TestOSUtils(TestCaseInTempDir):
42
def test_contains_whitespace(self):
43
self.failUnless(osutils.contains_whitespace(u' '))
44
self.failUnless(osutils.contains_whitespace(u'hello there'))
45
self.failUnless(osutils.contains_whitespace(u'hellothere\n'))
46
self.failUnless(osutils.contains_whitespace(u'hello\nthere'))
47
self.failUnless(osutils.contains_whitespace(u'hello\rthere'))
48
self.failUnless(osutils.contains_whitespace(u'hello\tthere'))
50
# \xa0 is "Non-breaking-space" which on some python locales thinks it
51
# is whitespace, but we do not.
52
self.failIf(osutils.contains_whitespace(u''))
53
self.failIf(osutils.contains_whitespace(u'hellothere'))
54
self.failIf(osutils.contains_whitespace(u'hello\xa0there'))
56
def test_fancy_rename(self):
57
# This should work everywhere
59
osutils.fancy_rename(a, b,
60
rename_func=os.rename,
61
unlink_func=os.unlink)
63
open('a', 'wb').write('something in a\n')
65
self.failIfExists('a')
66
self.failUnlessExists('b')
67
self.check_file_contents('b', 'something in a\n')
69
open('a', 'wb').write('new something in a\n')
72
self.check_file_contents('a', 'something in a\n')
74
def test_rename(self):
75
# Rename should be semi-atomic on all platforms
76
open('a', 'wb').write('something in a\n')
77
osutils.rename('a', 'b')
78
self.failIfExists('a')
79
self.failUnlessExists('b')
80
self.check_file_contents('b', 'something in a\n')
82
open('a', 'wb').write('new something in a\n')
83
osutils.rename('b', 'a')
85
self.check_file_contents('a', 'something in a\n')
87
# TODO: test fancy_rename using a MemoryTransport
89
def test_01_rand_chars_empty(self):
90
result = osutils.rand_chars(0)
91
self.assertEqual(result, '')
93
def test_02_rand_chars_100(self):
94
result = osutils.rand_chars(100)
95
self.assertEqual(len(result), 100)
96
self.assertEqual(type(result), str)
97
self.assertContainsRe(result, r'^[a-z0-9]{100}$')
99
def test_is_inside(self):
100
is_inside = osutils.is_inside
101
self.assertTrue(is_inside('src', 'src/foo.c'))
102
self.assertFalse(is_inside('src', 'srccontrol'))
103
self.assertTrue(is_inside('src', 'src/a/a/a/foo.c'))
104
self.assertTrue(is_inside('foo.c', 'foo.c'))
105
self.assertFalse(is_inside('foo.c', ''))
106
self.assertTrue(is_inside('', 'foo.c'))
108
def test_rmtree(self):
109
# Check to remove tree with read-only files/dirs
111
f = file('dir/file', 'w')
114
# would like to also try making the directory readonly, but at the
115
# moment python shutil.rmtree doesn't handle that properly - it would
116
# need to chmod the directory before removing things inside it - deferred
117
# for now -- mbp 20060505
118
# osutils.make_readonly('dir')
119
osutils.make_readonly('dir/file')
121
osutils.rmtree('dir')
123
self.failIfExists('dir/file')
124
self.failIfExists('dir')
126
def test_file_kind(self):
127
self.build_tree(['file', 'dir/'])
128
self.assertEquals('file', osutils.file_kind('file'))
129
self.assertEquals('directory', osutils.file_kind('dir/'))
130
if osutils.has_symlinks():
131
os.symlink('symlink', 'symlink')
132
self.assertEquals('symlink', osutils.file_kind('symlink'))
134
# TODO: jam 20060529 Test a block device
136
os.lstat('/dev/null')
138
if e.errno not in (errno.ENOENT,):
141
self.assertEquals('chardev', osutils.file_kind('/dev/null'))
143
mkfifo = getattr(os, 'mkfifo', None)
147
self.assertEquals('fifo', osutils.file_kind('fifo'))
151
AF_UNIX = getattr(socket, 'AF_UNIX', None)
153
s = socket.socket(AF_UNIX)
156
self.assertEquals('socket', osutils.file_kind('socket'))
160
def test_get_umask(self):
161
if sys.platform == 'win32':
162
# umask always returns '0', no way to set it
163
self.assertEqual(0, osutils.get_umask())
166
orig_umask = osutils.get_umask()
169
self.assertEqual(0222, osutils.get_umask())
171
self.assertEqual(0022, osutils.get_umask())
173
self.assertEqual(0002, osutils.get_umask())
175
self.assertEqual(0027, osutils.get_umask())
179
def assertFormatedDelta(self, expected, seconds):
180
"""Assert osutils.format_delta formats as expected"""
181
actual = osutils.format_delta(seconds)
182
self.assertEqual(expected, actual)
184
def test_format_delta(self):
185
self.assertFormatedDelta('0 seconds ago', 0)
186
self.assertFormatedDelta('1 second ago', 1)
187
self.assertFormatedDelta('10 seconds ago', 10)
188
self.assertFormatedDelta('59 seconds ago', 59)
189
self.assertFormatedDelta('89 seconds ago', 89)
190
self.assertFormatedDelta('1 minute, 30 seconds ago', 90)
191
self.assertFormatedDelta('3 minutes, 0 seconds ago', 180)
192
self.assertFormatedDelta('3 minutes, 1 second ago', 181)
193
self.assertFormatedDelta('10 minutes, 15 seconds ago', 615)
194
self.assertFormatedDelta('30 minutes, 59 seconds ago', 1859)
195
self.assertFormatedDelta('31 minutes, 0 seconds ago', 1860)
196
self.assertFormatedDelta('60 minutes, 0 seconds ago', 3600)
197
self.assertFormatedDelta('89 minutes, 59 seconds ago', 5399)
198
self.assertFormatedDelta('1 hour, 30 minutes ago', 5400)
199
self.assertFormatedDelta('2 hours, 30 minutes ago', 9017)
200
self.assertFormatedDelta('10 hours, 0 minutes ago', 36000)
201
self.assertFormatedDelta('24 hours, 0 minutes ago', 86400)
202
self.assertFormatedDelta('35 hours, 59 minutes ago', 129599)
203
self.assertFormatedDelta('36 hours, 0 minutes ago', 129600)
204
self.assertFormatedDelta('36 hours, 0 minutes ago', 129601)
205
self.assertFormatedDelta('36 hours, 1 minute ago', 129660)
206
self.assertFormatedDelta('36 hours, 1 minute ago', 129661)
207
self.assertFormatedDelta('84 hours, 10 minutes ago', 303002)
209
# We handle when time steps the wrong direction because computers
210
# don't have synchronized clocks.
211
self.assertFormatedDelta('84 hours, 10 minutes in the future', -303002)
212
self.assertFormatedDelta('1 second in the future', -1)
213
self.assertFormatedDelta('2 seconds in the future', -2)
215
def test_dereference_path(self):
216
if not osutils.has_symlinks():
217
raise TestSkipped('Symlinks are not supported on this platform')
218
cwd = osutils.realpath('.')
220
bar_path = osutils.pathjoin(cwd, 'bar')
221
# Using './' to avoid bug #1213894 (first path component not
222
# dereferenced) in Python 2.4.1 and earlier
223
self.assertEqual(bar_path, osutils.realpath('./bar'))
224
os.symlink('bar', 'foo')
225
self.assertEqual(bar_path, osutils.realpath('./foo'))
227
# Does not dereference terminal symlinks
228
foo_path = osutils.pathjoin(cwd, 'foo')
229
self.assertEqual(foo_path, osutils.dereference_path('./foo'))
231
# Dereferences parent symlinks
233
baz_path = osutils.pathjoin(bar_path, 'baz')
234
self.assertEqual(baz_path, osutils.dereference_path('./foo/baz'))
236
# Dereferences parent symlinks that are the first path element
237
self.assertEqual(baz_path, osutils.dereference_path('foo/baz'))
239
# Dereferences parent symlinks in absolute paths
240
foo_baz_path = osutils.pathjoin(foo_path, 'baz')
241
self.assertEqual(baz_path, osutils.dereference_path(foo_baz_path))
244
class TestSafeUnicode(TestCase):
246
def test_from_ascii_string(self):
247
self.assertEqual(u'foobar', osutils.safe_unicode('foobar'))
249
def test_from_unicode_string_ascii_contents(self):
250
self.assertEqual(u'bargam', osutils.safe_unicode(u'bargam'))
252
def test_from_unicode_string_unicode_contents(self):
253
self.assertEqual(u'bargam\xae', osutils.safe_unicode(u'bargam\xae'))
255
def test_from_utf8_string(self):
256
self.assertEqual(u'foo\xae', osutils.safe_unicode('foo\xc2\xae'))
258
def test_bad_utf8_string(self):
259
self.assertRaises(BzrBadParameterNotUnicode,
260
osutils.safe_unicode,
264
class TestSafeUtf8(TestCase):
266
def test_from_ascii_string(self):
268
self.assertEqual('foobar', osutils.safe_utf8(f))
270
def test_from_unicode_string_ascii_contents(self):
271
self.assertEqual('bargam', osutils.safe_utf8(u'bargam'))
273
def test_from_unicode_string_unicode_contents(self):
274
self.assertEqual('bargam\xc2\xae', osutils.safe_utf8(u'bargam\xae'))
276
def test_from_utf8_string(self):
277
self.assertEqual('foo\xc2\xae', osutils.safe_utf8('foo\xc2\xae'))
279
def test_bad_utf8_string(self):
280
self.assertRaises(BzrBadParameterNotUnicode,
281
osutils.safe_utf8, '\xbb\xbb')
284
class TestSafeRevisionId(TestCase):
286
def test_from_ascii_string(self):
288
self.assertEqual('foobar', osutils.safe_revision_id(f))
289
self.assertIs(osutils.safe_utf8(f), f)
291
def test_from_unicode_string_ascii_contents(self):
292
self.assertEqual('bargam', osutils.safe_revision_id(u'bargam'))
294
def test_from_unicode_string_unicode_contents(self):
295
self.assertEqual('bargam\xc2\xae',
296
osutils.safe_revision_id(u'bargam\xae'))
298
def test_from_utf8_string(self):
299
self.assertEqual('foo\xc2\xae',
300
osutils.safe_revision_id('foo\xc2\xae'))
302
def test_bad_utf8_string(self):
303
# This check may eventually go away
304
self.assertRaises(BzrBadParameterNotUnicode,
305
osutils.safe_utf8, '\xbb\xbb')
308
"""Currently, None is a valid revision_id"""
309
self.assertEqual(None, osutils.safe_revision_id(None))
312
class TestWin32Funcs(TestCase):
313
"""Test that the _win32 versions of os utilities return appropriate paths."""
315
def test_abspath(self):
316
self.assertEqual('C:/foo', osutils._win32_abspath('C:\\foo'))
317
self.assertEqual('C:/foo', osutils._win32_abspath('C:/foo'))
318
self.assertEqual('//HOST/path', osutils._win32_abspath(r'\\HOST\path'))
319
self.assertEqual('//HOST/path', osutils._win32_abspath('//HOST/path'))
321
def test_realpath(self):
322
self.assertEqual('C:/foo', osutils._win32_realpath('C:\\foo'))
323
self.assertEqual('C:/foo', osutils._win32_realpath('C:/foo'))
325
def test_pathjoin(self):
326
self.assertEqual('path/to/foo', osutils._win32_pathjoin('path', 'to', 'foo'))
327
self.assertEqual('C:/foo', osutils._win32_pathjoin('path\\to', 'C:\\foo'))
328
self.assertEqual('C:/foo', osutils._win32_pathjoin('path/to', 'C:/foo'))
329
self.assertEqual('path/to/foo', osutils._win32_pathjoin('path/to/', 'foo'))
330
self.assertEqual('/foo', osutils._win32_pathjoin('C:/path/to/', '/foo'))
331
self.assertEqual('/foo', osutils._win32_pathjoin('C:\\path\\to\\', '\\foo'))
333
def test_normpath(self):
334
self.assertEqual('path/to/foo', osutils._win32_normpath(r'path\\from\..\to\.\foo'))
335
self.assertEqual('path/to/foo', osutils._win32_normpath('path//from/../to/./foo'))
337
def test_getcwd(self):
338
cwd = osutils._win32_getcwd()
339
os_cwd = os.getcwdu()
340
self.assertEqual(os_cwd[1:].replace('\\', '/'), cwd[1:])
341
# win32 is inconsistent whether it returns lower or upper case
342
# and even if it was consistent the user might type the other
343
# so we force it to uppercase
344
# running python.exe under cmd.exe return capital C:\\
345
# running win32 python inside a cygwin shell returns lowercase
346
self.assertEqual(os_cwd[0].upper(), cwd[0])
348
def test_fixdrive(self):
349
self.assertEqual('H:/foo', osutils._win32_fixdrive('h:/foo'))
350
self.assertEqual('H:/foo', osutils._win32_fixdrive('H:/foo'))
351
self.assertEqual('C:\\foo', osutils._win32_fixdrive('c:\\foo'))
353
def test_win98_abspath(self):
355
self.assertEqual('C:/foo', osutils._win98_abspath('C:\\foo'))
356
self.assertEqual('C:/foo', osutils._win98_abspath('C:/foo'))
358
self.assertEqual('//HOST/path', osutils._win98_abspath(r'\\HOST\path'))
359
self.assertEqual('//HOST/path', osutils._win98_abspath('//HOST/path'))
361
cwd = osutils.getcwd().rstrip('/')
362
drive = osutils._nt_splitdrive(cwd)[0]
363
self.assertEqual(cwd+'/path', osutils._win98_abspath('path'))
364
self.assertEqual(drive+'/path', osutils._win98_abspath('/path'))
367
self.assertEqual(cwd+'/'+u, osutils._win98_abspath(u))
370
class TestWin32FuncsDirs(TestCaseInTempDir):
371
"""Test win32 functions that create files."""
373
def test_getcwd(self):
374
if win32utils.winver == 'Windows 98':
375
raise TestSkipped('Windows 98 cannot handle unicode filenames')
376
# Make sure getcwd can handle unicode filenames
380
raise TestSkipped("Unable to create Unicode filename")
383
# TODO: jam 20060427 This will probably fail on Mac OSX because
384
# it will change the normalization of B\xe5gfors
385
# Consider using a different unicode character, or make
386
# osutils.getcwd() renormalize the path.
387
self.assertEndsWith(osutils._win32_getcwd(), u'mu-\xb5')
389
def test_mkdtemp(self):
390
tmpdir = osutils._win32_mkdtemp(dir='.')
391
self.assertFalse('\\' in tmpdir)
393
def test_rename(self):
401
osutils._win32_rename('b', 'a')
402
self.failUnlessExists('a')
403
self.failIfExists('b')
404
self.assertFileEqual('baz\n', 'a')
406
def test_rename_missing_file(self):
412
osutils._win32_rename('b', 'a')
413
except (IOError, OSError), e:
414
self.assertEqual(errno.ENOENT, e.errno)
415
self.assertFileEqual('foo\n', 'a')
417
def test_rename_missing_dir(self):
420
osutils._win32_rename('b', 'a')
421
except (IOError, OSError), e:
422
self.assertEqual(errno.ENOENT, e.errno)
424
def test_rename_current_dir(self):
427
# You can't rename the working directory
428
# doing rename non-existant . usually
429
# just raises ENOENT, since non-existant
432
osutils._win32_rename('b', '.')
433
except (IOError, OSError), e:
434
self.assertEqual(errno.ENOENT, e.errno)
436
def test_splitpath(self):
437
def check(expected, path):
438
self.assertEqual(expected, osutils.splitpath(path))
441
check(['a', 'b'], 'a/b')
442
check(['a', 'b'], 'a/./b')
443
check(['a', '.b'], 'a/.b')
444
check(['a', '.b'], 'a\\.b')
446
self.assertRaises(errors.BzrError, osutils.splitpath, 'a/../b')
449
class TestMacFuncsDirs(TestCaseInTempDir):
450
"""Test mac special functions that require directories."""
452
def test_getcwd(self):
453
# On Mac, this will actually create Ba\u030agfors
454
# but chdir will still work, because it accepts both paths
456
os.mkdir(u'B\xe5gfors')
458
raise TestSkipped("Unable to create Unicode filename")
460
os.chdir(u'B\xe5gfors')
461
self.assertEndsWith(osutils._mac_getcwd(), u'B\xe5gfors')
463
def test_getcwd_nonnorm(self):
464
# Test that _mac_getcwd() will normalize this path
466
os.mkdir(u'Ba\u030agfors')
468
raise TestSkipped("Unable to create Unicode filename")
470
os.chdir(u'Ba\u030agfors')
471
self.assertEndsWith(osutils._mac_getcwd(), u'B\xe5gfors')
474
class TestSplitLines(TestCase):
476
def test_split_unicode(self):
477
self.assertEqual([u'foo\n', u'bar\xae'],
478
osutils.split_lines(u'foo\nbar\xae'))
479
self.assertEqual([u'foo\n', u'bar\xae\n'],
480
osutils.split_lines(u'foo\nbar\xae\n'))
482
def test_split_with_carriage_returns(self):
483
self.assertEqual(['foo\rbar\n'],
484
osutils.split_lines('foo\rbar\n'))
487
class TestWalkDirs(TestCaseInTempDir):
489
def test_walkdirs(self):
498
self.build_tree(tree)
499
expected_dirblocks = [
501
[('0file', '0file', 'file'),
502
('1dir', '1dir', 'directory'),
503
('2file', '2file', 'file'),
507
[('1dir/0file', '0file', 'file'),
508
('1dir/1dir', '1dir', 'directory'),
511
(('1dir/1dir', './1dir/1dir'),
518
for dirdetail, dirblock in osutils.walkdirs('.'):
519
if len(dirblock) and dirblock[0][1] == '.bzr':
520
# this tests the filtering of selected paths
523
result.append((dirdetail, dirblock))
525
self.assertTrue(found_bzrdir)
526
self.assertEqual(expected_dirblocks,
527
[(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
528
# you can search a subdir only, with a supplied prefix.
530
for dirblock in osutils.walkdirs('./1dir', '1dir'):
531
result.append(dirblock)
532
self.assertEqual(expected_dirblocks[1:],
533
[(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
535
def assertPathCompare(self, path_less, path_greater):
536
"""check that path_less and path_greater compare correctly."""
537
self.assertEqual(0, osutils.compare_paths_prefix_order(
538
path_less, path_less))
539
self.assertEqual(0, osutils.compare_paths_prefix_order(
540
path_greater, path_greater))
541
self.assertEqual(-1, osutils.compare_paths_prefix_order(
542
path_less, path_greater))
543
self.assertEqual(1, osutils.compare_paths_prefix_order(
544
path_greater, path_less))
546
def test_compare_paths_prefix_order(self):
547
# root before all else
548
self.assertPathCompare("/", "/a")
550
self.assertPathCompare("/a", "/b")
551
self.assertPathCompare("/b", "/z")
552
# high dirs before lower.
553
self.assertPathCompare("/z", "/a/a")
554
# except if the deeper dir should be output first
555
self.assertPathCompare("/a/b/c", "/d/g")
556
# lexical betwen dirs of the same height
557
self.assertPathCompare("/a/z", "/z/z")
558
self.assertPathCompare("/a/c/z", "/a/d/e")
560
# this should also be consistent for no leading / paths
561
# root before all else
562
self.assertPathCompare("", "a")
564
self.assertPathCompare("a", "b")
565
self.assertPathCompare("b", "z")
566
# high dirs before lower.
567
self.assertPathCompare("z", "a/a")
568
# except if the deeper dir should be output first
569
self.assertPathCompare("a/b/c", "d/g")
570
# lexical betwen dirs of the same height
571
self.assertPathCompare("a/z", "z/z")
572
self.assertPathCompare("a/c/z", "a/d/e")
574
def test_path_prefix_sorting(self):
575
"""Doing a sort on path prefix should match our sample data."""
606
sorted(original_paths, key=osutils.path_prefix_key))
607
# using the comparison routine shoudl work too:
610
sorted(original_paths, cmp=osutils.compare_paths_prefix_order))
613
class TestCopyTree(TestCaseInTempDir):
615
def test_copy_basic_tree(self):
616
self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
617
osutils.copy_tree('source', 'target')
618
self.assertEqual(['a', 'b'], sorted(os.listdir('target')))
619
self.assertEqual(['c'], os.listdir('target/b'))
621
def test_copy_tree_target_exists(self):
622
self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c',
624
osutils.copy_tree('source', 'target')
625
self.assertEqual(['a', 'b'], sorted(os.listdir('target')))
626
self.assertEqual(['c'], os.listdir('target/b'))
628
def test_copy_tree_symlinks(self):
629
if not osutils.has_symlinks():
631
self.build_tree(['source/'])
632
os.symlink('a/generic/path', 'source/lnk')
633
osutils.copy_tree('source', 'target')
634
self.assertEqual(['lnk'], os.listdir('target'))
635
self.assertEqual('a/generic/path', os.readlink('target/lnk'))
637
def test_copy_tree_handlers(self):
640
def file_handler(from_path, to_path):
641
processed_files.append(('f', from_path, to_path))
642
def dir_handler(from_path, to_path):
643
processed_files.append(('d', from_path, to_path))
644
def link_handler(from_path, to_path):
645
processed_links.append((from_path, to_path))
646
handlers = {'file':file_handler,
647
'directory':dir_handler,
648
'symlink':link_handler,
651
self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
652
if osutils.has_symlinks():
653
os.symlink('a/generic/path', 'source/lnk')
654
osutils.copy_tree('source', 'target', handlers=handlers)
656
self.assertEqual([('d', 'source', 'target'),
657
('f', 'source/a', 'target/a'),
658
('d', 'source/b', 'target/b'),
659
('f', 'source/b/c', 'target/b/c'),
661
self.failIfExists('target')
662
if osutils.has_symlinks():
663
self.assertEqual([('source/lnk', 'target/lnk')], processed_links)
666
#class TestTerminalEncoding has been moved to test_osutils_encodings.py
667
# [bialix] 2006/12/26
670
class TestSetUnsetEnv(TestCase):
671
"""Test updating the environment"""
674
super(TestSetUnsetEnv, self).setUp()
676
self.assertEqual(None, os.environ.get('BZR_TEST_ENV_VAR'),
677
'Environment was not cleaned up properly.'
678
' Variable BZR_TEST_ENV_VAR should not exist.')
680
if 'BZR_TEST_ENV_VAR' in os.environ:
681
del os.environ['BZR_TEST_ENV_VAR']
683
self.addCleanup(cleanup)
686
"""Test that we can set an env variable"""
687
old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'foo')
688
self.assertEqual(None, old)
689
self.assertEqual('foo', os.environ.get('BZR_TEST_ENV_VAR'))
691
def test_double_set(self):
692
"""Test that we get the old value out"""
693
osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'foo')
694
old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'bar')
695
self.assertEqual('foo', old)
696
self.assertEqual('bar', os.environ.get('BZR_TEST_ENV_VAR'))
698
def test_unicode(self):
699
"""Environment can only contain plain strings
701
So Unicode strings must be encoded.
703
# Try a few different characters, to see if we can get
704
# one that will be valid in the user_encoding
705
possible_vals = [u'm\xb5', u'\xe1', u'\u0410']
706
for uni_val in possible_vals:
708
env_val = uni_val.encode(bzrlib.user_encoding)
709
except UnicodeEncodeError:
710
# Try a different character
715
raise TestSkipped('Cannot find a unicode character that works in'
716
' encoding %s' % (bzrlib.user_encoding,))
718
old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', uni_val)
719
self.assertEqual(env_val, os.environ.get('BZR_TEST_ENV_VAR'))
721
def test_unset(self):
722
"""Test that passing None will remove the env var"""
723
osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'foo')
724
old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', None)
725
self.assertEqual('foo', old)
726
self.assertEqual(None, os.environ.get('BZR_TEST_ENV_VAR'))
727
self.failIf('BZR_TEST_ENV_VAR' in os.environ)
730
class TestLocalTimeOffset(TestCase):
732
def test_local_time_offset(self):
733
"""Test that local_time_offset() returns a sane value."""
734
offset = osutils.local_time_offset()
735
self.assertTrue(isinstance(offset, int))
736
# Test that the offset is no more than a eighteen hours in
738
# Time zone handling is system specific, so it is difficult to
739
# do more specific tests, but a value outside of this range is
741
eighteen_hours = 18 * 3600
742
self.assertTrue(-eighteen_hours < offset < eighteen_hours)
744
def test_local_time_offset_with_timestamp(self):
745
"""Test that local_time_offset() works with a timestamp."""
746
offset = osutils.local_time_offset(1000000000.1234567)
747
self.assertTrue(isinstance(offset, int))
748
eighteen_hours = 18 * 3600
749
self.assertTrue(-eighteen_hours < offset < eighteen_hours)