1from pathlib import Path 2 3import pytest 4 5from unit.applications.proto import ApplicationProto 6from unit.option import option 7from unit.utils import waitforfiles 8 9prerequisites = {'modules': {'njs': 'any'}} 10 11client = ApplicationProto() 12 13 14@pytest.fixture(autouse=True) 15def setup_method_fixture(temp_dir): 16 assert 'success' in client.conf( 17 { 18 "listeners": {"*:8080": {"pass": "routes"}}, 19 "routes": [{"action": {"share": f"{temp_dir}/assets$uri"}}], 20 } 21 ) 22 23 24def create_files(*files): 25 assets_dir = f'{option.temp_dir}/assets/' 26 Path(assets_dir).mkdir(exist_ok=True) 27 28 _ = [Path(assets_dir + f).touch() for f in files] 29 waitforfiles(*[assets_dir + f for f in files]) 30 31 32def set_share(share): 33 assert 'success' in client.conf(share, 'routes/0/action/share') 34 35 36def check_expression(expression, url='/'): 37 set_share(f'"`{option.temp_dir}/assets{expression}`"') 38 assert client.get(url=url)['status'] == 200 39 40 41def test_njs_template_string(temp_dir): 42 create_files('str', '`string`', '`backtick', 'l1\nl2') 43 44 check_expression('/str') 45 check_expression('/\\\\`backtick') 46 check_expression('/l1\\nl2') 47 48 set_share(f'"{temp_dir}/assets/`string`"') 49 assert client.get()['status'] == 200 50 51 52def test_njs_template_expression(): 53 create_files('str', 'localhost') 54 55 check_expression('${uri}', '/str') 56 check_expression('${uri}${host}') 57 check_expression('${uri + host}') 58 check_expression('${uri + `${host}`}') 59 60 61def test_njs_iteration(): 62 create_files('Connection,Host', 'close,localhost') 63 64 check_expression('/${Object.keys(headers).sort().join()}') 65 check_expression('/${Object.values(headers).sort().join()}') 66 67 68def test_njs_variables(temp_dir): 69 create_files('str', 'localhost', '127.0.0.1') 70 71 check_expression('/${host}') 72 check_expression('/${remoteAddr}') 73 check_expression('/${headers.Host}') 74 75 set_share(f'"`{temp_dir}/assets/${{cookies.foo}}`"') 76 assert ( 77 client.get(headers={'Cookie': 'foo=str', 'Connection': 'close'})[ 78 'status' 79 ] 80 == 200 81 ), 'cookies' 82 83 set_share(f'"`{temp_dir}/assets/${{args.foo}}`"') 84 assert client.get(url='/?foo=str')['status'] == 200, 'args' 85 86 check_expression('/${vars.header_host}') 87 88 set_share(f'"`{temp_dir}/assets/${{vars[\\"arg_foo\\"]}}`"') 89 assert client.get(url='/?foo=str')['status'] == 200, 'vars' 90 91 set_share(f'"`{temp_dir}/assets/${{vars.non_exist}}`"') 92 assert client.get()['status'] == 404, 'undefined' 93 94 create_files('undefined') 95 assert client.get()['status'] == 200, 'undefined 2' 96 97 98def test_njs_variables_cacheable(temp_dir): 99 create_files('str') 100 101 def check_rewrite(rewrite, uri): 102 assert 'success' in client.conf( 103 [ 104 { 105 "action": { 106 "rewrite": rewrite, 107 "share": f"`{temp_dir}/assets{uri}`", 108 }, 109 }, 110 ], 111 'routes', 112 ) 113 assert client.get()['status'] == 200 114 115 check_rewrite('/str', '${uri}') 116 check_rewrite('/str', '${vars.uri}') 117 118 119def test_njs_invalid(skip_alert): 120 skip_alert(r'js exception:') 121 122 def check_invalid(template): 123 assert 'error' in client.conf(template, 'routes/0/action/share') 124 125 check_invalid('"`a"') 126 check_invalid('"`a``"') 127 check_invalid('"`a`/"') 128 check_invalid('"`${vars.}`"') 129 130 def check_invalid_resolve(template): 131 assert 'success' in client.conf(template, 'routes/0/action/share') 132 assert client.get()['status'] == 500 133 134 check_invalid_resolve('"`${a}`"') 135 check_invalid_resolve('"`${uri.a.a}`"') 136 check_invalid_resolve('"`${vars.a.a}`"') 137