1import unittest 2from unit.control import TestControl 3 4 5class TestConfiguration(TestControl): 6 prerequisites = ['python'] 7 8 def test_json_empty(self): 9 self.assertIn('error', self.conf(''), 'empty') 10 11 def test_json_leading_zero(self): 12 self.assertIn('error', self.conf('00'), 'leading zero') 13 14 def test_json_unicode(self): 15 self.assertIn( 16 'success', 17 self.conf( 18 b""" 19 { 20 "ap\u0070": { 21 "type": "\u0070ython", 22 "processes": { "spare": 0 }, 23 "path": "\u002Fapp", 24 "module": "wsgi" 25 } 26 } 27 """, 28 'applications', 29 ), 30 'unicode', 31 ) 32 33 self.assertDictEqual( 34 self.conf_get('applications'), 35 { 36 "app": { 37 "type": "python", 38 "processes": {"spare": 0}, 39 "path": "/app", 40 "module": "wsgi", 41 } 42 }, 43 'unicode get', 44 ) 45 46 def test_json_unicode_2(self): 47 self.assertIn( 48 'success', 49 self.conf( 50 { 51 "приложение": { 52 "type": "python", 53 "processes": {"spare": 0}, 54 "path": "/app", 55 "module": "wsgi", 56 } 57 }, 58 'applications', 59 ), 60 'unicode 2', 61 ) 62 63 self.assertIn( 64 'приложение', self.conf_get('applications'), 'unicode 2 get' 65 ) 66 67 def test_json_unicode_number(self): 68 self.assertIn( 69 'error', 70 self.conf( 71 b""" 72 { 73 "app": { 74 "type": "python", 75 "processes": { "spare": \u0030 }, 76 "path": "/app", 77 "module": "wsgi" 78 } 79 } 80 """, 81 'applications', 82 ), 83 'unicode number', 84 ) 85 86 def test_applications_open_brace(self): 87 self.assertIn('error', self.conf('{', 'applications'), 'open brace') 88 89 def test_applications_string(self): 90 self.assertIn('error', self.conf('"{}"', 'applications'), 'string') 91 92 def test_applications_type_only(self): 93 self.skip_alerts.extend( 94 [ 95 r'python module is empty', 96 r'failed to apply new conf', 97 r'process \d+ exited on signal', 98 ] 99 ) 100 101 self.assertIn( 102 'error', 103 self.conf({"app": {"type": "python"}}, 'applications'), 104 'type only', 105 ) 106 107 def test_applications_miss_quote(self): 108 self.assertIn( 109 'error', 110 self.conf( 111 """ 112 { 113 app": { 114 "type": "python", 115 "processes": { "spare": 0 }, 116 "path": "/app", 117 "module": "wsgi" 118 } 119 } 120 """, 121 'applications', 122 ), 123 'miss quote', 124 ) 125 126 def test_applications_miss_colon(self): 127 self.assertIn( 128 'error', 129 self.conf( 130 """ 131 { 132 "app" { 133 "type": "python", 134 "processes": { "spare": 0 }, 135 "path": "/app", 136 "module": "wsgi" 137 } 138 } 139 """, 140 'applications', 141 ), 142 'miss colon', 143 ) 144 145 def test_applications_miss_comma(self): 146 self.assertIn( 147 'error', 148 self.conf( 149 """ 150 { 151 "app": { 152 "type": "python" 153 "processes": { "spare": 0 }, 154 "path": "/app", 155 "module": "wsgi" 156 } 157 } 158 """, 159 'applications', 160 ), 161 'miss comma', 162 ) 163 164 def test_applications_skip_spaces(self): 165 self.assertIn( 166 'success', self.conf(b'{ \n\r\t}', 'applications'), 'skip spaces' 167 ) 168 169 def test_applications_relative_path(self): 170 self.assertIn( 171 'success', 172 self.conf( 173 { 174 "app": { 175 "type": "python", 176 "processes": {"spare": 0}, 177 "path": "../app", 178 "module": "wsgi", 179 } 180 }, 181 'applications', 182 ), 183 'relative path', 184 ) 185 186 @unittest.expectedFailure 187 def test_listeners_empty(self): 188 self.skip_sanitizer = True 189 self.skip_alerts.extend( 190 [ 191 r'failed to apply previous configuration', 192 r'process \d+ exited on signal', 193 ] 194 ) 195 196 self.assertIn( 197 'error', self.conf({"*:7080": {}}, 'listeners'), 'listener empty' 198 ) 199 200 def test_listeners_no_app(self): 201 self.assertIn( 202 'error', 203 self.conf({"*:7080": {"application": "app"}}, 'listeners'), 204 'listeners no app', 205 ) 206 207 def test_listeners_wildcard(self): 208 self.assertIn( 209 'success', 210 self.conf( 211 { 212 "listeners": {"*:7080": {"application": "app"}}, 213 "applications": { 214 "app": { 215 "type": "python", 216 "processes": {"spare": 0}, 217 "path": "/app", 218 "module": "wsgi", 219 } 220 }, 221 } 222 ), 223 'listeners wildcard', 224 ) 225 226 def test_listeners_explicit(self): 227 self.assertIn( 228 'success', 229 self.conf( 230 { 231 "listeners": {"127.0.0.1:7080": {"application": "app"}}, 232 "applications": { 233 "app": { 234 "type": "python", 235 "processes": {"spare": 0}, 236 "path": "/app", 237 "module": "wsgi", 238 } 239 }, 240 } 241 ), 242 'explicit', 243 ) 244 245 def test_listeners_explicit_ipv6(self): 246 self.assertIn( 247 'success', 248 self.conf( 249 { 250 "listeners": {"[::1]:7080": {"application": "app"}}, 251 "applications": { 252 "app": { 253 "type": "python", 254 "processes": {"spare": 0}, 255 "path": "/app", 256 "module": "wsgi", 257 } 258 }, 259 } 260 ), 261 'explicit ipv6', 262 ) 263 264 def test_listeners_no_port(self): 265 self.skip_alerts.extend( 266 [ 267 r'invalid listener "127\.0\.0\.1"', 268 r'failed to apply new conf', 269 r'process \d+ exited on signal', 270 ] 271 ) 272 273 self.assertIn( 274 'error', 275 self.conf( 276 { 277 "listeners": {"127.0.0.1": {"application": "app"}}, 278 "applications": { 279 "app": { 280 "type": "python", 281 "processes": {"spare": 0}, 282 "path": "/app", 283 "module": "wsgi", 284 } 285 }, 286 } 287 ), 288 'no port', 289 ) 290 291 def test_json_application_name_large(self): 292 name = "X" * 1024 * 1024 293 294 self.assertIn( 295 'success', 296 self.conf( 297 { 298 "listeners": {"*:7080": {"application": name}}, 299 "applications": { 300 name: { 301 "type": "python", 302 "processes": {"spare": 0}, 303 "path": "/app", 304 "module": "wsgi", 305 } 306 }, 307 } 308 ), 309 ) 310 311 @unittest.expectedFailure 312 def test_json_application_many(self): 313 self.skip_alerts.extend( 314 [r'eventfd.+failed', r'epoll.+failed', r'failed to apply'] 315 ) 316 apps = 999 317 318 conf = { 319 "applications": { 320 "app-" 321 + str(a): { 322 "type": "python", 323 "processes": {"spare": 0}, 324 "path": "/app", 325 "module": "wsgi", 326 } 327 for a in range(apps) 328 }, 329 "listeners": { 330 "*:" + str(7000 + a): {"application": "app-" + str(a)} 331 for a in range(apps) 332 }, 333 } 334 335 self.assertIn('success', self.conf(conf)) 336 337 def test_json_application_many2(self): 338 self.skip_alerts.extend( 339 [r'eventfd.+failed', r'epoll.+failed', r'failed to apply'] 340 ) 341 342 conf = { 343 "applications": { 344 "app-" 345 + str(a): { 346 "type": "python", 347 "processes": {"spare": 0}, 348 "path": "/app", 349 "module": "wsgi", 350 } 351 for a in range(999) 352 }, 353 "listeners": {"*:7001": {"application": "app-1"}}, 354 } 355 356 self.assertIn('success', self.conf(conf)) 357 358 359if __name__ == '__main__': 360 TestConfiguration.main() 361