Skip to content

Commit 279e47d

Browse files
authored
test: port conformance tests from lua-resty-openapi-validate (#1)
1 parent ab2cd2d commit 279e47d

14 files changed

Lines changed: 747 additions & 0 deletions
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#!/usr/bin/env resty
2+
--- Conformance test ported from lua-resty-openapi-validate: body.t
3+
-- Validates request body for OpenAPI 3.0 spec.
4+
dofile("t/lib/test_bootstrap.lua")
5+
6+
local T = require("test_helper")
7+
local cjson = require("cjson.safe")
8+
local ov = require("resty.openapi_validator")
9+
10+
local function read_file(path)
11+
local f = io.open(path, "r")
12+
assert(f, "cannot open " .. path)
13+
local data = f:read("*a")
14+
f:close()
15+
return data
16+
end
17+
18+
local spec_str = read_file("t/specs/body.json")
19+
local validator, compile_err = ov.compile(spec_str)
20+
assert(validator, "compile failed: " .. tostring(compile_err))
21+
22+
-- TEST 1: valid body
23+
T.describe("body: valid request body", function()
24+
local ok, err = validator:validate_request({
25+
method = "POST",
26+
path = "/user",
27+
body = cjson.encode({
28+
username = "alphabeta",
29+
email = "alphabeta@gamma.zeta",
30+
}),
31+
content_type = "application/json",
32+
})
33+
T.ok(ok, "valid body passes: " .. tostring(err))
34+
end)
35+
36+
-- TEST 2: missing required field 'username'
37+
T.describe("body: missing required field username", function()
38+
local ok, err = validator:validate_request({
39+
method = "POST",
40+
path = "/user",
41+
body = cjson.encode({
42+
email = "alphabeta@gamma.zeta",
43+
}),
44+
content_type = "application/json",
45+
})
46+
T.ok(not ok, "missing username fails")
47+
T.like(err, "username", "error mentions username")
48+
end)
49+
50+
-- TEST 3: skip body validation (empty body)
51+
T.describe("body: skip body validation", function()
52+
local ok, err = validator:validate_request({
53+
method = "POST",
54+
path = "/user",
55+
content_type = "application/json",
56+
}, { body = true })
57+
T.ok(ok, "skip body passes: " .. tostring(err))
58+
end)
59+
60+
T.done()
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/usr/bin/env resty
2+
--- Conformance test ported from lua-resty-openapi-validate: body_31.t
3+
-- Validates request body for OpenAPI 3.1 features: type arrays (nullable), const.
4+
dofile("t/lib/test_bootstrap.lua")
5+
6+
local T = require("test_helper")
7+
local cjson = require("cjson.safe")
8+
local ov = require("resty.openapi_validator")
9+
10+
local function read_file(path)
11+
local f = io.open(path, "r")
12+
assert(f, "cannot open " .. path)
13+
local data = f:read("*a")
14+
f:close()
15+
return data
16+
end
17+
18+
local spec_str = read_file("t/specs/body_31.json")
19+
local validator, compile_err = ov.compile(spec_str, { strict = false })
20+
assert(validator, "compile failed: " .. tostring(compile_err))
21+
22+
-- TEST 1: valid body (basic 3.1 compatibility)
23+
T.describe("body_31: valid request body", function()
24+
local ok, err = validator:validate_request({
25+
method = "POST",
26+
path = "/user",
27+
body = cjson.encode({
28+
username = "alphabeta",
29+
email = "alphabeta@gamma.zeta",
30+
}),
31+
content_type = "application/json",
32+
})
33+
T.ok(ok, "valid body passes: " .. tostring(err))
34+
end)
35+
36+
-- TEST 2: nullable field with null value (3.1 type array ["string", "null"])
37+
T.describe("body_31: nullable email with null", function()
38+
local ok, err = validator:validate_request({
39+
method = "POST",
40+
path = "/user",
41+
body = cjson.encode({
42+
username = "alphabeta",
43+
email = cjson.null,
44+
}),
45+
content_type = "application/json",
46+
})
47+
T.ok(ok, "nullable email with null passes: " .. tostring(err))
48+
end)
49+
50+
-- TEST 3: missing required field 'username'
51+
T.describe("body_31: missing required username", function()
52+
local ok, err = validator:validate_request({
53+
method = "POST",
54+
path = "/user",
55+
body = cjson.encode({
56+
email = "alphabeta@gamma.zeta",
57+
}),
58+
content_type = "application/json",
59+
})
60+
T.ok(not ok, "missing username fails")
61+
T.like(err, "username", "error mentions username")
62+
end)
63+
64+
-- TEST 4: correct const value
65+
T.describe("body_31: correct const value", function()
66+
local ok, err = validator:validate_request({
67+
method = "POST",
68+
path = "/user",
69+
body = cjson.encode({
70+
username = "alphabeta",
71+
role = "admin",
72+
}),
73+
content_type = "application/json",
74+
})
75+
T.ok(ok, "correct const value passes: " .. tostring(err))
76+
end)
77+
78+
-- TEST 5: wrong const value
79+
T.describe("body_31: wrong const value", function()
80+
local ok, err = validator:validate_request({
81+
method = "POST",
82+
path = "/user",
83+
body = cjson.encode({
84+
username = "alphabeta",
85+
role = "user",
86+
}),
87+
content_type = "application/json",
88+
})
89+
T.ok(not ok, "wrong const value fails")
90+
T.like(err, "const", "error mentions const")
91+
end)
92+
93+
T.done()
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#!/usr/bin/env resty
2+
--- Conformance test ported from lua-resty-openapi-validate: header.t
3+
-- Validates header parameters with pattern constraints.
4+
dofile("t/lib/test_bootstrap.lua")
5+
6+
local T = require("test_helper")
7+
local ov = require("resty.openapi_validator")
8+
9+
local function read_file(path)
10+
local f = io.open(path, "r")
11+
assert(f, "cannot open " .. path)
12+
local data = f:read("*a")
13+
f:close()
14+
return data
15+
end
16+
17+
local spec_str = read_file("t/specs/header.json")
18+
local validator, compile_err = ov.compile(spec_str)
19+
assert(validator, "compile failed: " .. tostring(compile_err))
20+
21+
-- TEST 1: valid headers
22+
T.describe("header: valid Authorization and Content-Type", function()
23+
local ok, err = validator:validate_request({
24+
method = "GET",
25+
path = "/validateHeaders",
26+
headers = {
27+
["authorization"] = "Bearer dGVzdA==.dGVzdA==.dGVzdA==",
28+
["content-type"] = "application/json",
29+
},
30+
})
31+
T.ok(ok, "valid headers pass: " .. tostring(err))
32+
end)
33+
34+
-- TEST 2: missing required headers
35+
T.describe("header: missing required headers", function()
36+
local ok, err = validator:validate_request({
37+
method = "GET",
38+
path = "/validateHeaders",
39+
headers = {
40+
["no-authorization"] = "wrong",
41+
["no-content-type"] = "wrong",
42+
},
43+
})
44+
T.ok(not ok, "missing required headers fails")
45+
T.like(err, "[Aa]uthorization", "error mentions Authorization")
46+
T.like(err, "[Cc]ontent%-[Tt]ype", "error mentions Content-Type")
47+
end)
48+
49+
-- TEST 3: skip header validation
50+
T.describe("header: skip header validation", function()
51+
local ok, err = validator:validate_request({
52+
method = "GET",
53+
path = "/validateHeaders",
54+
headers = {
55+
["no-authorization"] = "wrong",
56+
["no-content-type"] = "wrong",
57+
},
58+
}, { header = true })
59+
T.ok(ok, "skip header passes: " .. tostring(err))
60+
end)
61+
62+
T.done()
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/usr/bin/env resty
2+
--- Conformance test ported from lua-resty-openapi-validate: path_items_31.t
3+
-- Validates OAS 3.1 components/pathItems with $ref.
4+
dofile("t/lib/test_bootstrap.lua")
5+
6+
local T = require("test_helper")
7+
local ov = require("resty.openapi_validator")
8+
9+
local function read_file(path)
10+
local f = io.open(path, "r")
11+
assert(f, "cannot open " .. path)
12+
local data = f:read("*a")
13+
f:close()
14+
return data
15+
end
16+
17+
local spec_str = read_file("t/specs/path_items_31.json")
18+
local validator, compile_err = ov.compile(spec_str, { strict = false })
19+
assert(validator, "compile failed: " .. tostring(compile_err))
20+
21+
-- TEST 1: valid GET with userId 420
22+
T.describe("path_items_31: valid GET /users/420", function()
23+
local ok, err = validator:validate_request({
24+
method = "GET",
25+
path = "/users/420",
26+
})
27+
T.ok(ok, "valid GET passes: " .. tostring(err))
28+
end)
29+
30+
-- TEST 2: userId exceeds maximum (4200 > 1000)
31+
T.describe("path_items_31: userId exceeds max", function()
32+
local ok, err = validator:validate_request({
33+
method = "GET",
34+
path = "/users/4200",
35+
})
36+
T.ok(not ok, "exceeding maximum fails")
37+
T.like(err, "userId", "error mentions userId")
38+
end)
39+
40+
-- TEST 3: non-integer path param
41+
T.describe("path_items_31: non-integer userId", function()
42+
local ok, err = validator:validate_request({
43+
method = "GET",
44+
path = "/users/not-an-integer",
45+
})
46+
T.ok(not ok, "non-integer fails")
47+
T.like(err, "userId", "error mentions userId")
48+
end)
49+
50+
-- TEST 4: valid DELETE with userId 5
51+
T.describe("path_items_31: valid DELETE /users/5", function()
52+
local ok, err = validator:validate_request({
53+
method = "DELETE",
54+
path = "/users/5",
55+
})
56+
T.ok(ok, "valid DELETE passes: " .. tostring(err))
57+
end)
58+
59+
T.done()
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/usr/bin/env resty
2+
--- Conformance test ported from lua-resty-openapi-validate: path_params.t
3+
-- Validates path parameters with type and range constraints.
4+
dofile("t/lib/test_bootstrap.lua")
5+
6+
local T = require("test_helper")
7+
local ov = require("resty.openapi_validator")
8+
9+
local function read_file(path)
10+
local f = io.open(path, "r")
11+
assert(f, "cannot open " .. path)
12+
local data = f:read("*a")
13+
f:close()
14+
return data
15+
end
16+
17+
local spec_str = read_file("t/specs/path_params.json")
18+
local validator, compile_err = ov.compile(spec_str)
19+
assert(validator, "compile failed: " .. tostring(compile_err))
20+
21+
-- TEST 1: valid path param
22+
T.describe("path_params: valid userId 420", function()
23+
local ok, err = validator:validate_request({
24+
method = "GET",
25+
path = "/users/420",
26+
})
27+
T.ok(ok, "valid path param passes: " .. tostring(err))
28+
end)
29+
30+
-- TEST 2: path param exceeds maximum (4200 > 1000)
31+
T.describe("path_params: userId exceeds maximum", function()
32+
local ok, err = validator:validate_request({
33+
method = "GET",
34+
path = "/users/4200",
35+
})
36+
T.ok(not ok, "exceeding maximum fails")
37+
T.like(err, "userId", "error mentions userId")
38+
end)
39+
40+
-- TEST 3: wrong type (string instead of integer)
41+
T.describe("path_params: wrong type for userId", function()
42+
local ok, err = validator:validate_request({
43+
method = "GET",
44+
path = "/users/wrong_path_param",
45+
})
46+
T.ok(not ok, "string for integer param fails")
47+
T.like(err, "userId", "error mentions userId")
48+
end)
49+
50+
-- TEST 4: skip path params validation
51+
T.describe("path_params: skip path params", function()
52+
local ok, err = validator:validate_request({
53+
method = "GET",
54+
path = "/users/this-is-wrong-but-it-should-pass",
55+
}, { path = true })
56+
T.ok(ok, "skip path params passes: " .. tostring(err))
57+
end)
58+
59+
T.done()
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/usr/bin/env resty
2+
--- Conformance test ported from lua-resty-openapi-validate: query_params.t
3+
-- Validates query parameters with required, type, and range constraints.
4+
dofile("t/lib/test_bootstrap.lua")
5+
6+
local T = require("test_helper")
7+
local ov = require("resty.openapi_validator")
8+
9+
local function read_file(path)
10+
local f = io.open(path, "r")
11+
assert(f, "cannot open " .. path)
12+
local data = f:read("*a")
13+
f:close()
14+
return data
15+
end
16+
17+
local spec_str = read_file("t/specs/query_params.json")
18+
local validator, compile_err = ov.compile(spec_str)
19+
assert(validator, "compile failed: " .. tostring(compile_err))
20+
21+
-- TEST 1: valid query params
22+
T.describe("query_params: valid page=1 limit=10", function()
23+
local ok, err = validator:validate_request({
24+
method = "GET",
25+
path = "/users",
26+
query = { page = "1", limit = "10" },
27+
})
28+
T.ok(ok, "valid query params pass: " .. tostring(err))
29+
end)
30+
31+
-- TEST 2: missing required query params
32+
T.describe("query_params: missing required params", function()
33+
local ok, err = validator:validate_request({
34+
method = "GET",
35+
path = "/users",
36+
query = { not_page = "1", unlimited = "10" },
37+
})
38+
T.ok(not ok, "missing required params fails")
39+
T.like(err, "page", "error mentions page")
40+
T.like(err, "limit", "error mentions limit")
41+
end)
42+
43+
-- TEST 3: skip query params validation
44+
T.describe("query_params: skip query params", function()
45+
local ok, err = validator:validate_request({
46+
method = "GET",
47+
path = "/users",
48+
query = { page = "1", limit = "wrong" },
49+
}, { query = true })
50+
T.ok(ok, "skip query params passes: " .. tostring(err))
51+
end)
52+
53+
T.done()

0 commit comments

Comments
 (0)