go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/lucicfg/testdata/misc/validators.star (about) 1 load("@stdlib//internal/time.star", "time") 2 load("@stdlib//internal/validate.star", "validate") 3 4 def test_validate_string(): 5 call = validate.string 6 assert.eq(call("a", "zzz"), "zzz") 7 assert.eq(call("a", "abc", regexp = "a.c$"), "abc") 8 assert.eq(call("a", "", default = "zzz", allow_empty = True, required = False), "") 9 assert.eq(call("a", None, default = "zzz", allow_empty = True, required = False), "zzz") 10 assert.eq(call("a", None, required = False), None) 11 assert.fails(lambda: call("a", None), 'missing required field "a"') 12 assert.fails(lambda: call("a", 1), 'bad "a": got int, want string') 13 assert.fails(lambda: call("a", []), 'bad "a": got list, want string') 14 assert.fails(lambda: call("a", None, default = 1, required = False), 'bad "a": got int, want string') 15 assert.fails(lambda: call("a", "abcd", regexp = "a.c$"), r'bad "a": "abcd" should match "a\.c\$"') 16 assert.fails(lambda: call("a", "", default = "zzz", required = False), 'bad "a": must not be empty') 17 18 def test_validate_hostname(): 19 call = validate.hostname 20 assert.eq(call("a", "zzz"), "zzz") 21 assert.eq(call("a", "test-domain.example.com"), "test-domain.example.com") 22 assert.eq(call("a", "xn--ls8h.example.com"), "xn--ls8h.example.com") 23 assert.eq(call("a", None, default = "zzz", required = False), "zzz") 24 assert.eq(call("a", None, required = False), None) 25 26 assert.fails(lambda: call("a", None), 'missing required field "a"') 27 assert.fails(lambda: call("a", 1), 'bad "a": got int, want string') 28 assert.fails(lambda: call("a", []), 'bad "a": got list, want string') 29 assert.fails(lambda: call("a", None, default = 1, required = False), 'bad "a": got int, want string') 30 assert.fails(lambda: call("a", "!notdomain"), r'bad "a": "!notdomain" is not valid RFC1123 hostname') 31 assert.fails( 32 lambda: call("a", "https://i.am.a.url.example.com"), 33 r'bad "a": "https://i.am.a.url.example.com" is not valid RFC1123 hostname', 34 ) 35 assert.fails(lambda: call("a", "", default = "zzz", required = False), 'bad "a": must not be empty') 36 37 def test_validate_int(): 38 call = validate.int 39 assert.eq(call("a", 123, min = 123, max = 123), 123) 40 assert.eq(call("a", 0, default = 123, required = False), 0) 41 assert.eq(call("a", None, default = 123, required = False), 123) 42 assert.eq(call("a", None, required = False), None) 43 assert.fails(lambda: call("a", None), 'missing required field "a"') 44 assert.fails(lambda: call("a", "1"), 'bad "a": got string, want int') 45 assert.fails(lambda: call("a", []), 'bad "a": got list, want int') 46 assert.fails(lambda: call("a", None, default = "1", required = False), 'bad "a": got string, want int') 47 assert.fails(lambda: call("a", 123, min = 124), 'bad "a": 123 should be >= 124') 48 assert.fails(lambda: call("a", 123, max = 122), 'bad "a": 123 should be <= 122') 49 50 def test_validate_float(): 51 call = validate.float 52 assert.eq(call("a", 123.4, min = 123, max = 123.5), 123.4) 53 assert.eq(call("a", 123, min = 123, max = 123), 123.0) 54 assert.eq(call("a", 0, default = 123, required = False), 0.0) 55 assert.eq(call("a", None, default = 123, required = False), 123.0) 56 assert.eq(call("a", None, required = False), None) 57 assert.fails(lambda: call("a", None), 'missing required field "a"') 58 assert.fails(lambda: call("a", "1"), 'bad "a": got string, want float or int') 59 assert.fails(lambda: call("a", []), 'bad "a": got list, want float or int') 60 assert.fails(lambda: call("a", None, default = "1", required = False), 'bad "a": got string, want float or int') 61 assert.fails(lambda: call("a", 123, min = 124.5), 'bad "a": 123.0 should be >= 124.5') 62 assert.fails(lambda: call("a", 123, max = 122.5), 'bad "a": 123.0 should be <= 122.5') 63 64 def test_validate_bool(): 65 call = validate.bool 66 assert.eq(call("a", True), True) 67 assert.eq(call("a", 1), True) 68 assert.eq(call("a", [1]), True) 69 assert.eq(call("a", []), False) 70 assert.eq(call("a", None, default = True, required = False), True) 71 assert.eq(call("a", None, default = False, required = False), False) 72 assert.eq(call("a", None, required = False), None) 73 assert.fails(lambda: call("a", None), 'missing required field "a"') 74 75 def test_validate_duration(): 76 call = validate.duration 77 m = time.minute 78 assert.eq(call("a", m), m) 79 assert.eq(call("a", None, default = m, required = False), m) 80 assert.eq(call("a", None, required = False), None) 81 assert.fails(lambda: call("a", None), 'missing required field "a"') 82 assert.fails(lambda: call("a", 1), 'bad "a": got int, want duration') 83 assert.fails(lambda: call("a", []), 'bad "a": got list, want duration') 84 assert.fails(lambda: call("a", -m), 'bad "a": -1m0s should be >= 0s') 85 assert.fails(lambda: call("a", 2 * m, max = m), 'bad "a": 2m0s should be <= 1m0s') 86 assert.fails( 87 lambda: call("a", 500 * time.millisecond), 88 'bad "a": losing precision when truncating 500ms to 1s units, use ' + 89 r"time.truncate\(\.\.\.\) to acknowledge", 90 ) 91 92 def test_validate_list(): 93 call = validate.list 94 assert.eq(call("a", [1, "a"]), [1, "a"]) 95 assert.eq(call("a", []), []) 96 assert.eq(call("a", None), []) 97 assert.fails(lambda: call("a", 0), 'bad "a": got int, want list') 98 assert.fails(lambda: call("a", {}), 'bad "a": got dict, want list') 99 assert.fails(lambda: call("a", None, required = True), 'missing required field "a"') 100 assert.fails(lambda: call("a", [], required = True), 'missing required field "a"') 101 102 def test_validate_str_dict(): 103 call = validate.str_dict 104 assert.eq(call("a", {"k": 1}), {"k": 1}) 105 assert.eq(call("a", {}), {}) 106 assert.eq(call("a", None), {}) 107 assert.fails(lambda: call("a", 0), 'bad "a": got int, want dict') 108 assert.fails(lambda: call("a", []), 'bad "a": got list, want dict') 109 assert.fails(lambda: call("a", {1: 1}), 'bad "a": got int key, want string') 110 assert.fails(lambda: call("a", {"": 1}), 'bad "a": got empty key') 111 assert.fails(lambda: call("a", None, required = True), 'missing required field "a"') 112 assert.fails(lambda: call("a", {}, required = True), 'missing required field "a"') 113 114 def test_validate_struct(): 115 call = validate.struct 116 s = struct(a = 1, b = 2) 117 assert.eq(call("a", s, "struct"), s) 118 assert.eq(call("a", None, "struct", default = s, required = False), s) 119 assert.eq(call("a", None, "struct", required = False), None) 120 assert.fails(lambda: call("a", None, "struct"), 'missing required field "a"') 121 assert.fails(lambda: call("a", 1, "struct"), 'bad "a": got int, want struct') 122 assert.fails(lambda: call("a", [], "struct"), 'bad "a": got list, want struct') 123 assert.fails(lambda: call("a", None, "struct", default = 1, required = False), 'bad "a": got int, want struct') 124 125 def test_validate_type(): 126 call = validate.type 127 assert.eq(call("a", 1, 0), 1) 128 assert.eq(call("a", None, 0, default = 123, required = False), 123) 129 assert.eq(call("a", None, 0, required = False), None) 130 assert.fails(lambda: call("a", None, 0), 'missing required field "a"') 131 assert.fails(lambda: call("a", "sss", 0), 'bad "a": got string, want int') 132 assert.fails(lambda: call("a", [], 0), 'bad "a": got list, want int') 133 134 def test_validate_relative_path(): 135 call = validate.relative_path 136 assert.eq(call("a", "./abc/def//./zzz/../yyy/."), "abc/def/yyy") 137 assert.eq(call("a", "."), ".") 138 assert.eq(call("a", "./../abc", allow_dots = True), "../abc") 139 assert.eq(call("a", None, required = False), None) 140 assert.fails(lambda: call("a", None), 'missing required field "a"') 141 assert.fails(lambda: call("a", "./../abc"), 'must not start with "../"') 142 assert.fails(lambda: call("a", "a/../../abc"), 'must not start with "../"') 143 144 # Rebasing. 145 assert.eq(call("a", "./abc", base = "./a/b"), "a/b/abc") 146 assert.eq(call("a", "../abc", base = "./a/b"), "a/abc") 147 assert.eq(call("a", "../../abc", base = "./a/b"), "abc") 148 assert.eq(call("a", "../../../abc", base = "./a/b", allow_dots = True), "../abc") 149 assert.fails( 150 lambda: call("a", "../../../abc", base = "./a/b", allow_dots = False), 151 'must not start with "../"', 152 ) 153 assert.fails( 154 lambda: call("a", "a/../../../../abc", base = "./a/b", allow_dots = False), 155 'must not start with "../"', 156 ) 157 158 def test_validate_regex_list(): 159 call = validate.regex_list 160 161 assert.fails(lambda: call("a", 123), 'bad "a": got int, want string or list') 162 assert.fails(lambda: call("a", [123]), 'bad "a": got list element of type int, want string') 163 assert.fails(lambda: call("a", None, required = True), 'missing required field "a"') 164 assert.fails(lambda: call("a", "", required = True), 'missing required field "a"') 165 assert.fails(lambda: call("a", [], required = True), 'missing required field "a"') 166 assert.fails(lambda: call("a", "("), 'bad "a": error parsing regexp: missing closing \\): `\\(`') 167 assert.fails(lambda: call("a", ["(ab", "bc)"]), 'bad "a": error parsing regexp: missing closing \\): `\\(ab`') 168 169 assert.eq(call("a", ""), "") 170 assert.eq(call("a", []), "") 171 assert.eq(call("a", "abc.*def"), "abc.*def") 172 assert.eq(call("a", "abcdef", required = True), "abcdef") 173 assert.eq(call("a", ["xyz", "abc"]), "xyz|abc") 174 assert.eq(call("a", ["xyz", "abc"], required = True), "xyz|abc") 175 assert.eq(call("a", ["x.*yz", "defg", "abc"]), "x.*yz|defg|abc") 176 177 def test_validate_str_list(): 178 call = validate.str_list 179 assert.eq(call("a", ["a", "b"]), ["a", "b"]) 180 assert.eq(call("a", []), []) 181 assert.eq(call("a", None), []) 182 assert.fails(lambda: call("a", 0), 'bad "a": got int, want list') 183 assert.fails(lambda: call("a", {}), 'bad "a": got dict, want list') 184 assert.fails(lambda: call("a", [100]), 'bad "a": got list element of type int, want string') 185 assert.fails(lambda: call("a", None, required = True), 'missing required field "a"') 186 assert.fails(lambda: call("a", [], required = True), 'missing required field "a"') 187 188 test_validate_string() 189 test_validate_hostname() 190 test_validate_int() 191 test_validate_float() 192 test_validate_bool() 193 test_validate_duration() 194 test_validate_list() 195 test_validate_str_dict() 196 test_validate_struct() 197 test_validate_type() 198 test_validate_relative_path() 199 test_validate_regex_list() 200 test_validate_str_list()