Coverage for tests / test_consdbClient.py: 28%

76 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-05-05 19:02 +0000

1# This file is part of summit_utils. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (http://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 <http://www.gnu.org/licenses/>. 

21 

22import pytest 

23import responses 

24from requests import HTTPError 

25 

26from lsst.summit.utils import ConsDbClient, FlexibleMetadataInfo 

27 

28 

29@pytest.fixture 

30def client(): 

31 """Initialize client with a fake url 

32 Requires mocking connection with @responses.activate decorator 

33 """ 

34 return ConsDbClient("http://example.com/consdb") 

35 

36 

37def test_table_name(): 

38 instrument = "latiss" 

39 obs_type = "exposure" 

40 assert ( 

41 ConsDbClient.compute_flexible_metadata_table_name(instrument, obs_type) 

42 == "cdb_latiss.exposure_flexdata" 

43 ) 

44 

45 

46@responses.activate 

47def test_add_flexible_metadata_key(client): 

48 instrument = "latiss" 

49 obs_type = "exposure" 

50 responses.post( 

51 "http://example.com/consdb/flex/latiss/exposure/addkey", 

52 json={ 

53 "message": "Key added to flexible metadata", 

54 "key": "foo", 

55 "instrument": "latiss", 

56 "obs_type": "exposure", 

57 }, 

58 match=[ 

59 responses.matchers.json_params_matcher({"key": "foo", "dtype": "bool", "doc": "bool key"}), 

60 ], 

61 ) 

62 responses.post( 

63 "http://example.com/consdb/flex/latiss/exposure/addkey", 

64 json={ 

65 "message": "Key added to flexible metadata", 

66 "key": "bar", 

67 "instrument": "latiss", 

68 "obs_type": "exposure", 

69 }, 

70 match=[ 

71 responses.matchers.json_params_matcher({"key": "bar", "dtype": "int", "doc": "int key"}), 

72 ], 

73 ) 

74 responses.post( 

75 "http://example.com/consdb/flex/bad_instrument/exposure/addkey", 

76 status=404, 

77 json={"message": "Unknown instrument", "value": "bad_instrument", "valid": ["latiss"]}, 

78 ) 

79 responses.post( 

80 "http://example.com/consdb/flex/latiss/bad_obs_type/addkey", 

81 status=404, 

82 json={"message": "Unknown observation type", "value": "bad_obs_type", "valid": ["exposure"]}, 

83 ) 

84 

85 assert ( 

86 client.add_flexible_metadata_key(instrument, obs_type, "foo", "bool", "bool key").json()["key"] 

87 == "foo" 

88 ) 

89 assert ( 

90 client.add_flexible_metadata_key(instrument, obs_type, "bar", "int", "int key").json()["instrument"] 

91 == "latiss" 

92 ) 

93 with pytest.raises(HTTPError, match="404") as e: 

94 client.add_flexible_metadata_key("bad_instrument", obs_type, "error", "int", "instrument error") 

95 assert "Unknown instrument" in str(e.value.__notes__) 

96 json_data = e.value.response.json() 

97 assert json_data["message"] == "Unknown instrument" 

98 assert json_data["value"] == "bad_instrument" 

99 assert json_data["valid"] == ["latiss"] 

100 with pytest.raises(HTTPError, match="404"): 

101 client.add_flexible_metadata_key(instrument, "bad_obs_type", "error", "int", "obs_type error") 

102 

103 

104@responses.activate 

105def test_get_flexible_metadata_keys(client): 

106 description = {"foo": ["bool", "a", None, None], "bar": ["float", "b", "deg", "pos.eq.ra"]} 

107 responses.get( 

108 "http://example.com/consdb/flex/latiss/exposure/schema", 

109 json=description, 

110 ) 

111 instrument = "latiss" 

112 obs_type = "exposure" 

113 assert client.get_flexible_metadata_keys(instrument, obs_type) == { 

114 "foo": FlexibleMetadataInfo("bool", "a"), 

115 "bar": FlexibleMetadataInfo("float", "b", "deg", "pos.eq.ra"), 

116 } 

117 

118 

119@responses.activate 

120def test_get_flexible_metadata(client): 

121 results = {"bool_key": True, "int_key": 42, "float_key": 3.14159, "str_key": "foo"} 

122 responses.get( 

123 "http://example.com/consdb/flex/latiss/exposure/obs/271828", 

124 json=results, 

125 ) 

126 responses.get( 

127 "http://example.com/consdb/flex/latiss/exposure/obs/271828?k=float_key", json={"float_key": 3.14159} 

128 ) 

129 responses.get( 

130 "http://example.com/consdb/flex/latiss/exposure/obs/271828?k=int_key&k=float_key", 

131 json={"float_key": 3.14159, "int_key": 42}, 

132 ) 

133 instrument = "latiss" 

134 obs_type = "exposure" 

135 obs_id = 271828 

136 assert client.get_flexible_metadata(instrument, obs_type, obs_id) == results 

137 assert client.get_flexible_metadata(instrument, obs_type, obs_id, ["float_key"]) == { 

138 "float_key": results["float_key"] 

139 } 

140 assert client.get_flexible_metadata(instrument, obs_type, obs_id, ["int_key", "float_key"]) == { 

141 "int_key": results["int_key"], 

142 "float_key": results["float_key"], 

143 } 

144 

145 

146@responses.activate 

147def test_insert_flexible_metadata(client): 

148 instrument = "latiss" 

149 obs_type = "exposure" 

150 with pytest.raises(ValueError): 

151 client.insert_flexible_metadata(instrument, obs_type, 271828) 

152 # TODO: more POST tests 

153 

154 

155@responses.activate 

156def test_schema(client): 

157 description = {"foo": ("bool", "a"), "bar": ("int", "b")} 

158 responses.get( 

159 "http://example.com/consdb/schema/latiss/misc_table", 

160 json=description, 

161 ) 

162 instrument = "latiss" 

163 table = "misc_table" 

164 assert client.schema(instrument, table) == description 

165 

166 

167@responses.activate 

168@pytest.mark.parametrize( 

169 "secret, redacted", 

170 [ 

171 ("usdf:v987wefVMPz", "us***:v9***"), 

172 ("u:v", "u***:v***"), 

173 ("ulysses", "ul***"), 

174 (":alberta94", "***:al***"), 

175 ], 

176) 

177def test_clean_token_url_response(secret, redacted): 

178 """Test tokens URL is cleaned when an error is thrown from requests 

179 Use with pytest raises assert an error' 

180 assert that url does not contain tokens 

181 """ 

182 domain = "@usdf-fake.slackers.stanford.edu/consdb" 

183 complex_client = ConsDbClient(f"https://{secret}{domain}") 

184 

185 obs_type = "exposure" 

186 responses.post( 

187 f"https://{secret}{domain}/flex/bad_instrument/exposure/addkey", 

188 status=404, 

189 ) 

190 with pytest.raises(HTTPError, match="404") as error: 

191 complex_client.add_flexible_metadata_key( 

192 "bad_instrument", obs_type, "error", "int", "instrument error" 

193 ) 

194 

195 url = error.value.args[0].split()[-1] 

196 sanitized = f"https://{redacted}{domain}/flex/bad_instrument/exposure/addkey" 

197 assert url == sanitized 

198 

199 

200def test_client(client): 

201 """Test ConsDbClient is initialized properly""" 

202 assert "clean_url" in str(client.session.hooks["response"]) 

203 

204 

205# TODO: more POST tests 

206# client.insert(instrument, table, obs_id, values, allow_update) 

207# client.insert_multiple(instrument, table, obs_dict, allow_update) 

208# client.query(query)