Coverage for tests/test_getTempFilePath.py: 19%

85 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-05-01 15:14 -0700

1# This file is part of utils. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (https://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# This program is free software: you can redistribute it and/or modify 

10# it under the terms of the GNU General Public License as published by 

11# the Free Software Foundation, either version 3 of the License, or 

12# (at your option) any later version. 

13# 

14# This program is distributed in the hope that it will be useful, 

15# but WITHOUT ANY WARRANTY; without even the implied warranty of 

16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

17# GNU General Public License for more details. 

18# 

19# You should have received a copy of the GNU General Public License 

20# along with this program. If not, see <https://www.gnu.org/licenses/>. 

21 

22import os.path 

23import sys 

24import time 

25import unittest 

26 

27import lsst.utils.tests 

28 

29"""This file contains tests for lsst.utils.tests.getTempFilePath. 

30 

31The ``TestNameClashN`` classes are used to check that getTempFilePath 

32does not use the same name across different test classes in the same 

33file even if they have the same test methods. They are distinct classes 

34with the same test method in an attempt to trigger a race condition 

35whereby context managers use the same name and race to delete the file. 

36The sleeps are there to ensure the race condition occurs in older versions 

37of this package. This should not happen as of DM-13046. 

38""" 

39 

40 

41class GetTempFilePathTestCase(unittest.TestCase): 

42 """Tests for temporary file path creation.""" 

43 

44 def testBasics(self): 

45 with lsst.utils.tests.getTempFilePath(".txt") as tmpFile: 

46 # Path will have unique component so do not test full equality 

47 self.assertIn("test_getTempFilePath_testBasics", tmpFile) 

48 self.assertTrue(tmpFile.endswith(".txt")) 

49 with open(tmpFile, "w") as f: 

50 f.write("foo\n") 

51 self.assertFalse(os.path.exists(tmpFile)) 

52 

53 def testMultipleCallDepth(self): 

54 """Test getTempFile with multiple call depth.""" 

55 funcName = "testMultipleCallDepth" 

56 self.runGetTempFile(funcName) 

57 self.runLevel2(funcName) 

58 self.runLevel3(funcName) 

59 

60 def runGetTempFile(self, funcName): 

61 with lsst.utils.tests.getTempFilePath(".fits") as tmpFile: 

62 # Path will have unique component so do not test full equality 

63 self.assertIn(f"test_getTempFilePath_{funcName}", tmpFile) 

64 self.assertTrue(tmpFile.endswith(".fits")) 

65 with open(tmpFile, "w") as f: 

66 f.write("foo\n") 

67 self.assertFalse(os.path.exists(tmpFile)) 

68 

69 def runLevel2(self, funcName): 

70 """Call runGetTempFile.""" 

71 self.runGetTempFile(funcName) 

72 

73 def runLevel3(self, funcName): 

74 """Call runLevel2, which calls runGetTempFile.""" 

75 self.runLevel2(funcName) 

76 

77 

78class TestNested(unittest.TestCase): 

79 """Tests of the use of getTempFilePath in nested context managers.""" 

80 

81 def testNested(self): 

82 with lsst.utils.tests.getTempFilePath(".fits") as tmpFile1: 

83 with lsst.utils.tests.getTempFilePath(".fits") as tmpFile2: 

84 self.assertNotEqual(tmpFile1, tmpFile2) 

85 with open(tmpFile1, "w") as f1: 

86 f1.write("foo\n") 

87 with open(tmpFile2, "w") as f2: 

88 f2.write("foo\n") 

89 self.assertTrue(os.path.exists(tmpFile1)) 

90 self.assertFalse(os.path.exists(tmpFile2)) 

91 self.assertFalse(os.path.exists(tmpFile1)) 

92 

93 

94class TestExpected(unittest.TestCase): 

95 """Tests that we get files when we expect to get them and we get upset 

96 when we don't get them. 

97 """ 

98 

99 def testOutputExpected(self): 

100 with lsst.utils.tests.getTempFilePath(".txt") as tmpFile: 

101 with open(tmpFile, "w") as f: 

102 f.write("foo\n") 

103 self.assertFalse(os.path.exists(tmpFile)) 

104 

105 with self.assertRaises(RuntimeError): 

106 with lsst.utils.tests.getTempFilePath(".txt", expectOutput=True) as tmpFile: 

107 pass 

108 

109 with self.assertRaises(RuntimeError): 

110 with lsst.utils.tests.getTempFilePath(".txt") as tmpFile: 

111 pass 

112 

113 def testOutputUnexpected(self): 

114 with self.assertRaises(RuntimeError): 

115 with lsst.utils.tests.getTempFilePath(".txt", expectOutput=False) as tmpFile: 

116 with open(tmpFile, "w") as f: 

117 f.write("foo\n") 

118 

119 with lsst.utils.tests.getTempFilePath(".txt", expectOutput=False) as tmpFile: 

120 pass 

121 self.assertFalse(os.path.exists(tmpFile)) 

122 

123 

124class TestNameClash1(unittest.TestCase): 

125 """Test involving a potential clash of test method name.""" 

126 

127 def testClash(self): 

128 """Create the temp file and pause before trying to delete it.""" 

129 with lsst.utils.tests.getTempFilePath(".fits") as tmpFile: 

130 with open(tmpFile, "w") as f: 

131 f.write("foo\n") 

132 time.sleep(0.2) 

133 self.assertTrue(os.path.exists(tmpFile)) 

134 

135 

136class TestNameClash2(unittest.TestCase): 

137 """Test involving a potential clash of test method name.""" 

138 

139 def testClash(self): 

140 """Pause a little before trying to create the temp file. The pause 

141 time is less than the time that TestNameClash1 is pausing. 

142 """ 

143 with lsst.utils.tests.getTempFilePath(".fits") as tmpFile: 

144 time.sleep(0.1) 

145 with open(tmpFile, "w") as f: 

146 f.write("foo\n") 

147 self.assertTrue(os.path.exists(tmpFile)) 

148 

149 

150class TestNameClash3(unittest.TestCase): 

151 """Test involving a potential clash of test method name.""" 

152 

153 def testClash(self): 

154 """Create temp file and remove it without pauses.""" 

155 with lsst.utils.tests.getTempFilePath(".fits") as tmpFile: 

156 with open(tmpFile, "w") as f: 

157 f.write("foo\n") 

158 self.assertTrue(os.path.exists(tmpFile)) 

159 

160 

161class TestMemory(lsst.utils.tests.MemoryTestCase): 

162 """Test for file descriptor leaks.""" 

163 

164 

165def setup_module(module): 

166 """Initialize the pytest environment.""" 

167 lsst.utils.tests.init() 

168 

169 

170if __name__ == "__main__": 

171 setup_module(sys.modules[__name__]) 

172 unittest.main()