11902Szelenkov@nginx.comimport socket 21902Szelenkov@nginx.com 31596Szelenkov@nginx.comimport pytest 41019Szelenkov@nginx.comfrom unit.control import TestControl 5484Szelenkov@nginx.com 61017Szelenkov@nginx.com 71019Szelenkov@nginx.comclass TestConfiguration(TestControl): 81467Szelenkov@nginx.com prerequisites = {'modules': {'python': 'any'}} 9484Szelenkov@nginx.com 10*1913Szelenkov@nginx.com def try_addr(self, addr): 11*1913Szelenkov@nginx.com return self.conf( 12*1913Szelenkov@nginx.com { 13*1913Szelenkov@nginx.com "listeners": {addr: {"pass": "routes"}}, 14*1913Szelenkov@nginx.com "routes": [{"action": {"return": 200}}], 15*1913Szelenkov@nginx.com "applications": {}, 16*1913Szelenkov@nginx.com } 17*1913Szelenkov@nginx.com ) 18*1913Szelenkov@nginx.com 19719Szelenkov@nginx.com def test_json_empty(self): 201596Szelenkov@nginx.com assert 'error' in self.conf(''), 'empty' 21719Szelenkov@nginx.com 22495Szelenkov@nginx.com def test_json_leading_zero(self): 231596Szelenkov@nginx.com assert 'error' in self.conf('00'), 'leading zero' 24484Szelenkov@nginx.com 25495Szelenkov@nginx.com def test_json_unicode(self): 261596Szelenkov@nginx.com assert 'success' in self.conf( 271635Szelenkov@nginx.com u""" 28495Szelenkov@nginx.com { 29495Szelenkov@nginx.com "ap\u0070": { 30495Szelenkov@nginx.com "type": "\u0070ython", 31507Smax.romanov@nginx.com "processes": { "spare": 0 }, 32495Szelenkov@nginx.com "path": "\u002Fapp", 33495Szelenkov@nginx.com "module": "wsgi" 34495Szelenkov@nginx.com } 35495Szelenkov@nginx.com } 361017Szelenkov@nginx.com """, 371596Szelenkov@nginx.com 'applications', 381596Szelenkov@nginx.com ), 'unicode' 39484Szelenkov@nginx.com 401596Szelenkov@nginx.com assert self.conf_get('applications') == { 411596Szelenkov@nginx.com "app": { 421596Szelenkov@nginx.com "type": "python", 431596Szelenkov@nginx.com "processes": {"spare": 0}, 441596Szelenkov@nginx.com "path": "/app", 451596Szelenkov@nginx.com "module": "wsgi", 461596Szelenkov@nginx.com } 471596Szelenkov@nginx.com }, 'unicode get' 481596Szelenkov@nginx.com 491596Szelenkov@nginx.com def test_json_unicode_2(self): 501596Szelenkov@nginx.com assert 'success' in self.conf( 511017Szelenkov@nginx.com { 521596Szelenkov@nginx.com "приложение": { 531017Szelenkov@nginx.com "type": "python", 541017Szelenkov@nginx.com "processes": {"spare": 0}, 551017Szelenkov@nginx.com "path": "/app", 561017Szelenkov@nginx.com "module": "wsgi", 571017Szelenkov@nginx.com } 581017Szelenkov@nginx.com }, 591596Szelenkov@nginx.com 'applications', 601596Szelenkov@nginx.com ), 'unicode 2' 61555Szelenkov@nginx.com 621596Szelenkov@nginx.com assert 'приложение' in self.conf_get('applications'), 'unicode 2 get' 63555Szelenkov@nginx.com 64495Szelenkov@nginx.com def test_json_unicode_number(self): 651635Szelenkov@nginx.com assert 'success' in self.conf( 661635Szelenkov@nginx.com u""" 67495Szelenkov@nginx.com { 68495Szelenkov@nginx.com "app": { 69495Szelenkov@nginx.com "type": "python", 70507Smax.romanov@nginx.com "processes": { "spare": \u0030 }, 71495Szelenkov@nginx.com "path": "/app", 72495Szelenkov@nginx.com "module": "wsgi" 73495Szelenkov@nginx.com } 74495Szelenkov@nginx.com } 751017Szelenkov@nginx.com """, 761596Szelenkov@nginx.com 'applications', 771596Szelenkov@nginx.com ), 'unicode number' 78495Szelenkov@nginx.com 791426Szelenkov@nginx.com def test_json_utf8_bom(self): 801596Szelenkov@nginx.com assert 'success' in self.conf( 811596Szelenkov@nginx.com b"""\xEF\xBB\xBF 821426Szelenkov@nginx.com { 831426Szelenkov@nginx.com "app": { 841426Szelenkov@nginx.com "type": "python", 851426Szelenkov@nginx.com "processes": {"spare": 0}, 861426Szelenkov@nginx.com "path": "/app", 871426Szelenkov@nginx.com "module": "wsgi" 881426Szelenkov@nginx.com } 891426Szelenkov@nginx.com } 901426Szelenkov@nginx.com """, 911596Szelenkov@nginx.com 'applications', 921596Szelenkov@nginx.com ), 'UTF-8 BOM' 931426Szelenkov@nginx.com 941427Szelenkov@nginx.com def test_json_comment_single_line(self): 951596Szelenkov@nginx.com assert 'success' in self.conf( 961596Szelenkov@nginx.com b""" 971427Szelenkov@nginx.com // this is bridge 981427Szelenkov@nginx.com { 991427Szelenkov@nginx.com "//app": { 1001427Szelenkov@nginx.com "type": "python", // end line 1011427Szelenkov@nginx.com "processes": {"spare": 0}, 1021427Szelenkov@nginx.com // inside of block 1031427Szelenkov@nginx.com "path": "/app", 1041427Szelenkov@nginx.com "module": "wsgi" 1051427Szelenkov@nginx.com } 1061427Szelenkov@nginx.com // double // 1071427Szelenkov@nginx.com } 1081427Szelenkov@nginx.com // end of json \xEF\t 1091427Szelenkov@nginx.com """, 1101596Szelenkov@nginx.com 'applications', 1111596Szelenkov@nginx.com ), 'single line comments' 1121427Szelenkov@nginx.com 1131427Szelenkov@nginx.com def test_json_comment_multi_line(self): 1141596Szelenkov@nginx.com assert 'success' in self.conf( 1151596Szelenkov@nginx.com b""" 1161427Szelenkov@nginx.com /* this is bridge */ 1171427Szelenkov@nginx.com { 1181427Szelenkov@nginx.com "/*app": { 1191427Szelenkov@nginx.com /** 1201427Szelenkov@nginx.com * multiple lines 1211427Szelenkov@nginx.com **/ 1221427Szelenkov@nginx.com "type": "python", 1231427Szelenkov@nginx.com "processes": /* inline */ {"spare": 0}, 1241427Szelenkov@nginx.com "path": "/app", 1251427Szelenkov@nginx.com "module": "wsgi" 1261427Szelenkov@nginx.com /* 1271427Szelenkov@nginx.com // end of block */ 1281427Szelenkov@nginx.com } 1291427Szelenkov@nginx.com /* blah * / blah /* blah */ 1301427Szelenkov@nginx.com } 1311427Szelenkov@nginx.com /* end of json \xEF\t\b */ 1321427Szelenkov@nginx.com """, 1331596Szelenkov@nginx.com 'applications', 1341596Szelenkov@nginx.com ), 'multi line comments' 1351427Szelenkov@nginx.com 1361427Szelenkov@nginx.com def test_json_comment_invalid(self): 1371596Szelenkov@nginx.com assert 'error' in self.conf(b'/{}', 'applications'), 'slash' 1381596Szelenkov@nginx.com assert 'error' in self.conf(b'//{}', 'applications'), 'comment' 1391596Szelenkov@nginx.com assert 'error' in self.conf(b'{} /', 'applications'), 'slash end' 1401596Szelenkov@nginx.com assert 'error' in self.conf(b'/*{}', 'applications'), 'slash star' 1411596Szelenkov@nginx.com assert 'error' in self.conf(b'{} /*', 'applications'), 'slash star end' 1421427Szelenkov@nginx.com 143495Szelenkov@nginx.com def test_applications_open_brace(self): 1441596Szelenkov@nginx.com assert 'error' in self.conf('{', 'applications'), 'open brace' 145495Szelenkov@nginx.com 146495Szelenkov@nginx.com def test_applications_string(self): 1471596Szelenkov@nginx.com assert 'error' in self.conf('"{}"', 'applications'), 'string' 148495Szelenkov@nginx.com 1491596Szelenkov@nginx.com @pytest.mark.skip('not yet, unsafe') 150495Szelenkov@nginx.com def test_applications_type_only(self): 1511596Szelenkov@nginx.com assert 'error' in self.conf( 1521596Szelenkov@nginx.com {"app": {"type": "python"}}, 'applications' 1531596Szelenkov@nginx.com ), 'type only' 154484Szelenkov@nginx.com 155495Szelenkov@nginx.com def test_applications_miss_quote(self): 1561596Szelenkov@nginx.com assert 'error' in self.conf( 1571596Szelenkov@nginx.com """ 158484Szelenkov@nginx.com { 159484Szelenkov@nginx.com app": { 160484Szelenkov@nginx.com "type": "python", 161507Smax.romanov@nginx.com "processes": { "spare": 0 }, 162484Szelenkov@nginx.com "path": "/app", 163484Szelenkov@nginx.com "module": "wsgi" 164484Szelenkov@nginx.com } 165484Szelenkov@nginx.com } 1661017Szelenkov@nginx.com """, 1671596Szelenkov@nginx.com 'applications', 1681596Szelenkov@nginx.com ), 'miss quote' 169484Szelenkov@nginx.com 170495Szelenkov@nginx.com def test_applications_miss_colon(self): 1711596Szelenkov@nginx.com assert 'error' in self.conf( 1721596Szelenkov@nginx.com """ 173484Szelenkov@nginx.com { 174484Szelenkov@nginx.com "app" { 175484Szelenkov@nginx.com "type": "python", 176507Smax.romanov@nginx.com "processes": { "spare": 0 }, 177484Szelenkov@nginx.com "path": "/app", 178484Szelenkov@nginx.com "module": "wsgi" 179484Szelenkov@nginx.com } 180484Szelenkov@nginx.com } 1811017Szelenkov@nginx.com """, 1821596Szelenkov@nginx.com 'applications', 1831596Szelenkov@nginx.com ), 'miss colon' 184484Szelenkov@nginx.com 185495Szelenkov@nginx.com def test_applications_miss_comma(self): 1861596Szelenkov@nginx.com assert 'error' in self.conf( 1871596Szelenkov@nginx.com """ 188484Szelenkov@nginx.com { 189484Szelenkov@nginx.com "app": { 190484Szelenkov@nginx.com "type": "python" 191507Smax.romanov@nginx.com "processes": { "spare": 0 }, 192484Szelenkov@nginx.com "path": "/app", 193484Szelenkov@nginx.com "module": "wsgi" 194484Szelenkov@nginx.com } 195484Szelenkov@nginx.com } 1961017Szelenkov@nginx.com """, 1971596Szelenkov@nginx.com 'applications', 1981596Szelenkov@nginx.com ), 'miss comma' 199484Szelenkov@nginx.com 200495Szelenkov@nginx.com def test_applications_skip_spaces(self): 2011596Szelenkov@nginx.com assert 'success' in self.conf( 2021596Szelenkov@nginx.com b'{ \n\r\t}', 'applications' 2031596Szelenkov@nginx.com ), 'skip spaces' 204484Szelenkov@nginx.com 205495Szelenkov@nginx.com def test_applications_relative_path(self): 2061596Szelenkov@nginx.com assert 'success' in self.conf( 2071596Szelenkov@nginx.com { 2081596Szelenkov@nginx.com "app": { 2091596Szelenkov@nginx.com "type": "python", 2101596Szelenkov@nginx.com "processes": {"spare": 0}, 2111596Szelenkov@nginx.com "path": "../app", 2121596Szelenkov@nginx.com "module": "wsgi", 2131596Szelenkov@nginx.com } 2141596Szelenkov@nginx.com }, 2151596Szelenkov@nginx.com 'applications', 2161596Szelenkov@nginx.com ), 'relative path' 2171596Szelenkov@nginx.com 2181596Szelenkov@nginx.com @pytest.mark.skip('not yet, unsafe') 2191596Szelenkov@nginx.com def test_listeners_empty(self): 2201596Szelenkov@nginx.com assert 'error' in self.conf( 2211596Szelenkov@nginx.com {"*:7080": {}}, 'listeners' 2221596Szelenkov@nginx.com ), 'listener empty' 2231596Szelenkov@nginx.com 2241596Szelenkov@nginx.com def test_listeners_no_app(self): 2251596Szelenkov@nginx.com assert 'error' in self.conf( 2261596Szelenkov@nginx.com {"*:7080": {"pass": "applications/app"}}, 'listeners' 2271596Szelenkov@nginx.com ), 'listeners no app' 2281596Szelenkov@nginx.com 229*1913Szelenkov@nginx.com def test_listeners_addr(self): 230*1913Szelenkov@nginx.com assert 'success' in self.try_addr("*:7080"), 'wildcard' 231*1913Szelenkov@nginx.com assert 'success' in self.try_addr("127.0.0.1:7081"), 'explicit' 232*1913Szelenkov@nginx.com assert 'success' in self.try_addr("[::1]:7082"), 'explicit ipv6' 233495Szelenkov@nginx.com 234*1913Szelenkov@nginx.com def test_listeners_addr_error(self): 235*1913Szelenkov@nginx.com assert 'error' in self.try_addr("127.0.0.1"), 'no port' 236484Szelenkov@nginx.com 237*1913Szelenkov@nginx.com def test_listeners_addr_error_2(self, skip_alert): 238*1913Szelenkov@nginx.com skip_alert(r'bind.*failed', r'failed to apply new conf') 239*1913Szelenkov@nginx.com 240*1913Szelenkov@nginx.com assert 'error' in self.try_addr( 241*1913Szelenkov@nginx.com "[f607:7403:1e4b:6c66:33b2:843f:2517:da27]:7080" 242*1913Szelenkov@nginx.com ) 243495Szelenkov@nginx.com 2441871Szelenkov@nginx.com def test_listeners_port_release(self): 2451871Szelenkov@nginx.com for i in range(10): 2461871Szelenkov@nginx.com fail = False 2471871Szelenkov@nginx.com with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: 2481871Szelenkov@nginx.com s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 2491871Szelenkov@nginx.com 2501871Szelenkov@nginx.com self.conf( 2511871Szelenkov@nginx.com { 2521871Szelenkov@nginx.com "listeners": {"127.0.0.1:7080": {"pass": "routes"}}, 2531871Szelenkov@nginx.com "routes": [], 2541871Szelenkov@nginx.com } 2551871Szelenkov@nginx.com ) 2561871Szelenkov@nginx.com 2571871Szelenkov@nginx.com resp = self.conf({"listeners": {}, "applications": {}}) 2581871Szelenkov@nginx.com 2591871Szelenkov@nginx.com try: 2601871Szelenkov@nginx.com s.bind(('127.0.0.1', 7080)) 2611871Szelenkov@nginx.com s.listen() 2621871Szelenkov@nginx.com 2631871Szelenkov@nginx.com except OSError: 2641871Szelenkov@nginx.com fail = True 2651871Szelenkov@nginx.com 2661871Szelenkov@nginx.com if fail: 2671871Szelenkov@nginx.com pytest.fail('cannot bind or listen to the address') 2681871Szelenkov@nginx.com 2691871Szelenkov@nginx.com assert 'success' in resp, 'port release' 2701871Szelenkov@nginx.com 271917Szelenkov@nginx.com def test_json_application_name_large(self): 272917Szelenkov@nginx.com name = "X" * 1024 * 1024 273917Szelenkov@nginx.com 2741596Szelenkov@nginx.com assert 'success' in self.conf( 2751596Szelenkov@nginx.com { 2761596Szelenkov@nginx.com "listeners": {"*:7080": {"pass": "applications/" + name}}, 2771596Szelenkov@nginx.com "applications": { 2781596Szelenkov@nginx.com name: { 2791596Szelenkov@nginx.com "type": "python", 2801596Szelenkov@nginx.com "processes": {"spare": 0}, 2811596Szelenkov@nginx.com "path": "/app", 2821596Szelenkov@nginx.com "module": "wsgi", 2831596Szelenkov@nginx.com } 2841596Szelenkov@nginx.com }, 2851596Szelenkov@nginx.com } 2861017Szelenkov@nginx.com ) 287917Szelenkov@nginx.com 2881596Szelenkov@nginx.com @pytest.mark.skip('not yet') 289917Szelenkov@nginx.com def test_json_application_many(self): 290946Szelenkov@nginx.com apps = 999 291917Szelenkov@nginx.com 292917Szelenkov@nginx.com conf = { 2931017Szelenkov@nginx.com "applications": { 2941017Szelenkov@nginx.com "app-" 2951017Szelenkov@nginx.com + str(a): { 296917Szelenkov@nginx.com "type": "python", 2971017Szelenkov@nginx.com "processes": {"spare": 0}, 298917Szelenkov@nginx.com "path": "/app", 2991017Szelenkov@nginx.com "module": "wsgi", 3001017Szelenkov@nginx.com } 3011017Szelenkov@nginx.com for a in range(apps) 302917Szelenkov@nginx.com }, 303917Szelenkov@nginx.com "listeners": { 3041041Svbart@nginx.com "*:" + str(7000 + a): {"pass": "applications/app-" + str(a)} 3051017Szelenkov@nginx.com for a in range(apps) 3061017Szelenkov@nginx.com }, 307917Szelenkov@nginx.com } 308917Szelenkov@nginx.com 3091596Szelenkov@nginx.com assert 'success' in self.conf(conf) 310917Szelenkov@nginx.com 3111006Smax.romanov@nginx.com def test_json_application_many2(self): 3121006Smax.romanov@nginx.com conf = { 3131017Szelenkov@nginx.com "applications": { 3141017Szelenkov@nginx.com "app-" 3151017Szelenkov@nginx.com + str(a): { 3161006Smax.romanov@nginx.com "type": "python", 3171017Szelenkov@nginx.com "processes": {"spare": 0}, 3181006Smax.romanov@nginx.com "path": "/app", 3191017Szelenkov@nginx.com "module": "wsgi", 3201017Szelenkov@nginx.com } 3211551Smax.romanov@nginx.com # Larger number of applications can cause test fail with default 3221551Smax.romanov@nginx.com # open files limit due to the lack of file descriptors. 3231551Smax.romanov@nginx.com for a in range(100) 3241006Smax.romanov@nginx.com }, 3251232Szelenkov@nginx.com "listeners": {"*:7080": {"pass": "applications/app-1"}}, 3261006Smax.romanov@nginx.com } 3271006Smax.romanov@nginx.com 3281596Szelenkov@nginx.com assert 'success' in self.conf(conf) 3291006Smax.romanov@nginx.com 3301736Szelenkov@nginx.com def test_unprivileged_user_error(self, is_su, skip_alert): 3311596Szelenkov@nginx.com skip_alert(r'cannot set user "root"', r'failed to apply new conf') 3321596Szelenkov@nginx.com if is_su: 3331596Szelenkov@nginx.com pytest.skip('unprivileged tests') 3341569St.nateldemoura@f5.com 3351596Szelenkov@nginx.com assert 'error' in self.conf( 3361596Szelenkov@nginx.com { 3371596Szelenkov@nginx.com "app": { 3381596Szelenkov@nginx.com "type": "external", 3391596Szelenkov@nginx.com "processes": 1, 3401596Szelenkov@nginx.com "executable": "/app", 3411596Szelenkov@nginx.com "user": "root", 3421596Szelenkov@nginx.com } 3431596Szelenkov@nginx.com }, 3441596Szelenkov@nginx.com 'applications', 3451596Szelenkov@nginx.com ), 'setting user' 346