go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/server/quota/internal/luatest/testdata/test_fixtures.lua (about) 1 -- Copyright 2022 The LUCI Authors 2 -- 3 -- Licensed under the Apache License, Version 2.0 (the "License"); 4 -- you may not use this file except in compliance with the License. 5 -- You may obtain a copy of the License at 6 -- 7 -- http://www.apache.org/licenses/LICENSE-2.0 8 -- 9 -- Unless required by applicable law or agreed to in writing, software 10 -- distributed under the License is distributed on an "AS IS" BASIS, 11 -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 -- See the License for the specific language governing permissions and 13 -- limitations under the License. 14 15 lu = require 'luaunit/luaunit' 16 -- This makes tracebacks work correctly; otherwise they show the location inside 17 -- of the luaunit assertion function. Suspect something to do with Go lua impl. 18 lu.STRIP_EXTRA_ENTRIES_IN_STACK_TRACE = 1 19 20 21 function dumpTable(table, depth) 22 if depth == nil then 23 depth = 0 24 end 25 if (depth > 200) then 26 print("Error: Depth > 200 in dumpTable()") 27 return 28 end 29 for k,v in pairs(table) do 30 if (type(v) == "table") then 31 print(string.rep(" ", depth)..k..":") 32 dumpTable(v, depth+1) 33 else 34 print(string.rep(" ", depth)..k..": ",v) 35 end 36 end 37 end 38 39 KEYS = {"account_key~account_name", "policy_key"} 40 41 cmsgpack = require 'luamsgpack/MessagePack' 42 43 PB = loadfile('../../../quotapb/quotapb.lua')() 44 45 T0_SEC = 1670834486 46 T0_MSEC = 0 47 48 function DUMP(...) 49 local toprint = {} 50 for i, v in next, arg do 51 if type(v) == "table" then 52 v = cjson.encode(v) 53 end 54 toprint[i] = v 55 end 56 print(unpack(toprint)) 57 end 58 59 redis = { 60 DATA = {}, 61 TTL = {} 62 } 63 64 function redis.call(method, ...) 65 local function check(nameTypes) 66 if #nameTypes ~= arg.n then 67 error(string.format("TEST ERROR: redis:call: %s: wrong arg.n: %d != %d", method, #nameTypes, args.n)) 68 end 69 for i, nameType in ipairs(nameTypes) do 70 local t = type(arg[i]) 71 local name, want = unpack(nameType) 72 if t ~= want then 73 error(string.format("TEST ERROR: redis:call: %s: bad %s type: %s, wanted %s", method, name, t, want)) 74 end 75 end 76 return unpack(arg) 77 end 78 79 if method == "HGET" then 80 local key, field = check({{"key", "string"}, {"field", "string"}}) 81 return (redis.DATA[key] or {})[field] 82 end 83 84 if method == "HMGET" then 85 local key, field, field2, field3 = check({ 86 {"key", "string"}, 87 {"field", "string"}, 88 {"field2", "string"}, 89 {"field3", "string"}, 90 }) 91 local subCache = (redis.DATA[key] or {}) 92 return {subCache[field], subCache[field2], subCache[field3]} 93 end 94 95 if method == "HSET" and arg.n == 3 then 96 local key, field, value = check({ 97 {"key", "string"}, 98 {"field", "string"}, {"value", "string"}, 99 }) 100 local subCache = redis.DATA[key] 101 if subCache == nil then 102 subCache = {} 103 redis.DATA[key] = subCache 104 end 105 subCache[field] = tostring(value) 106 return 107 end 108 109 if method == "HSET" and arg.n == 5 then 110 local key, field, value, field2, value2 = check({ 111 {"key", "string"}, 112 {"field", "string"}, {"value", "string"}, 113 {"field2", "string"}, {"value2", "string"}, 114 }) 115 local subCache = redis.DATA[key] 116 if subCache == nil then 117 subCache = {} 118 redis.DATA[key] = subCache 119 end 120 subCache[field] = tostring(value) 121 subCache[field2] = tostring(value3) 122 return 123 end 124 125 if method == "HSET" then 126 local key, field, value, field2, value2, field3, value3 = check({ 127 {"key", "string"}, 128 {"field", "string"}, {"value", "string"}, 129 {"field2", "string"}, {"value2", "string"}, 130 {"field3", "string"}, {"value3", "string"}, 131 }) 132 local subCache = redis.DATA[key] 133 if subCache == nil then 134 subCache = {} 135 redis.DATA[key] = subCache 136 end 137 subCache[field] = tostring(value) 138 subCache[field2] = tostring(value2) 139 subCache[field3] = tostring(value3) 140 return 141 end 142 143 if method == "GET" then 144 local key = check({{"key", "string"}}) 145 return redis.DATA[key] 146 end 147 148 if method == "SET" and arg.n == 4 then 149 local key, value, PX, TTL = check({ 150 {"key", "string"}, {"value", "string"}, 151 {"PX", "string"}, {"TTL", "number"}, 152 }) 153 if PX ~= "PX" then 154 error(string.format("TEST ERROR: unexpected option %s != PX", PX)) 155 end 156 redis.DATA[key] = value 157 redis.TTL[key] = TTL 158 return 159 end 160 161 if method == "SET" then 162 local key, value = check({{"key", "string"}, {"value", "string"}}) 163 redis.DATA[key] = value 164 redis.TTL[key] = nil 165 return 166 end 167 168 if method == "PEXPIRE" then 169 local key, exp = check({{"key", "string"}, {"exp", "number"}}) 170 redis.TTL[key] = exp 171 return 172 end 173 174 if method == "TIME" then 175 check({}) 176 return {T0_SEC, T0_MSEC} 177 end 178 179 error(string.format("TEST ERROR: redis.call unsupported method %s", method)) 180 end 181 182 function redis.error_reply(msg) 183 return { error = "ERR "..msg } 184 end 185 186 function redis.status_reply(obj) 187 return { ok = obj } 188 end 189 190 local Utils = loadfile('../../lua/utils.lua')(PB, policyNames) 191 local Policy = loadfile('../../lua/policy.lua')(PB, Utils) 192 local Account = loadfile('../../lua/account.lua')(PB, Utils, Policy) 193 194 G = {} 195 G.Utils = Utils 196 G.Policy = Policy 197 G.Account = Account 198 199 -- This is a hack; we hook the output to reset global state. 200 -- The alternative would be to add a layer of 'test classes', but for our 201 -- purposes, this should be OK. 202 local realStartTest = lu.LuaUnit.outputType.startTest 203 lu.LuaUnit.outputType.startTest = function( self, testName ) 204 redis.DATA = {} 205 redis.TTL = {} 206 207 Policy.CACHE = {} 208 Account.CACHE = {} 209 Utils.NOW.seconds = T0_SEC 210 Utils.NOW.nanos = T0_MSEC * 1000000 211 212 realStartTest(self, testName) 213 end