1# Copyright 2013 Christoph Reiter 2# 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. 7 8import os 9import stat 10import shutil 11 12from tests import TestCase, mkdtemp 13 14from quodlibet.util.atomic import atomic_save 15 16 17class Tatomic_save(TestCase): 18 19 def setUp(self): 20 self.dir = mkdtemp() 21 22 def tearDown(self): 23 shutil.rmtree(self.dir) 24 25 def test_basic(self): 26 filename = os.path.join(self.dir, "foo.txt") 27 28 with open(filename, "wb") as fobj: 29 fobj.write(b"nope") 30 31 with atomic_save(filename, "wb") as fobj: 32 fobj.write(b"foo") 33 temp_name = fobj.name 34 35 with open(filename, "rb") as fobj: 36 self.assertEqual(fobj.read(), b"foo") 37 38 self.assertFalse(os.path.exists(temp_name)) 39 self.assertEqual(os.listdir(self.dir), [os.path.basename(filename)]) 40 41 def test_non_exist(self): 42 filename = os.path.join(self.dir, "foo.txt") 43 44 with atomic_save(filename, "wb") as fobj: 45 fobj.write(b"foo") 46 temp_name = fobj.name 47 48 with open(filename, "rb") as fobj: 49 self.assertEqual(fobj.read(), b"foo") 50 51 self.assertFalse(os.path.exists(temp_name)) 52 self.assertEqual(os.listdir(self.dir), [os.path.basename(filename)]) 53 54 def test_readonly(self): 55 filename = os.path.join(self.dir, "foo.txt") 56 57 with open(filename, "wb") as fobj: 58 fobj.write(b"nope") 59 60 dir_mode = os.stat(self.dir).st_mode 61 file_mode = os.stat(filename).st_mode 62 # setting directory permissions doesn't work under Windows, so make 63 # the file read only, so the rename fails. On the other hand marking 64 # the file read only doesn't make rename fail on unix, so make the 65 # directory read only as well. 66 os.chmod(filename, stat.S_IREAD) 67 os.chmod(self.dir, stat.S_IREAD) 68 try: 69 with self.assertRaises(OSError): 70 with atomic_save(filename, "wb") as fobj: 71 fobj.write(b"foo") 72 finally: 73 # restore permissions 74 os.chmod(self.dir, dir_mode) 75 os.chmod(filename, file_mode) 76 77 with open(filename, "rb") as fobj: 78 self.assertEqual(fobj.read(), b"nope") 79 80 self.assertEqual(os.listdir(self.dir), [os.path.basename(filename)]) 81