Skip to content

Commit ab2cd2d

Browse files
committed
test: port comprehensive conformance tests from kin-openapi
Port all request-validation-relevant test cases from kin-openapi: - test_issue267: oneOf/anyOf/allOf body validation (JSON + form-urlencoded) - test_issue624: content-encoded query params with anyOf - test_issue625: array query params with composite items - test_issue641: string query params with pattern constraints - test_issue689: readOnly/writeOnly property validation - test_issue733: large integer (int64) body values - test_issue789: anyOf/oneOf/allOf word boundary patterns - test_issue884: allOf with $ref enum in query params - test_issue991: array query params with enum items - test_issue1045: allOf with nested $ref body validation - test_issue1100: POST with no requestBody in spec - test_issue1110: form-urlencoded with optional properties - test_validate_request: TestValidateRequest, deepObject, exclude params - test_components_path_items: OAS 3.1 components/pathItems (PR#1) Fix composite schema coercion in params.lua for anyOf/oneOf/allOf items without a direct type field. Fix deepObject nil result handling for optional parameters. Remove old monolithic test_kin_openapi.lua (superseded). Total: 302 assertions across 18 conformance + 8 unit test files.
1 parent 8c1a221 commit ab2cd2d

15 files changed

Lines changed: 1797 additions & 694 deletions
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#!/usr/bin/env resty
2+
--- Conformance test ported from api7/kin-openapi PR#1 components_path_items_test.go
3+
-- Tests OAS 3.1 components/pathItems with $ref resolution.
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 spec = cjson.encode({
11+
openapi = "3.1.0",
12+
info = { title = "OAS 3.1 Gap Tests", version = "1.0.0" },
13+
paths = {
14+
["/widget"] = {
15+
["$ref"] = "#/components/pathItems/WidgetPath",
16+
},
17+
},
18+
components = {
19+
pathItems = {
20+
WidgetPath = {
21+
post = {
22+
operationId = "createWidget",
23+
requestBody = {
24+
required = true,
25+
content = {
26+
["application/json"] = {
27+
schema = { ["$ref"] = "#/components/schemas/Widget" },
28+
},
29+
},
30+
},
31+
responses = { ["200"] = { description = "ok" } },
32+
},
33+
},
34+
},
35+
schemas = {
36+
Widget = {
37+
type = "object",
38+
required = { "name" },
39+
properties = {
40+
name = { type = "string" },
41+
},
42+
},
43+
},
44+
},
45+
})
46+
47+
local v = ov.compile(spec)
48+
assert(v, "compile failed")
49+
50+
T.describe("PR#1: components/pathItems - valid body (valid)", function()
51+
local ok, err = v:validate_request({
52+
method = "POST",
53+
path = "/widget",
54+
body = '{"name": "foo"}',
55+
content_type = "application/json",
56+
headers = { ["content-type"] = "application/json" },
57+
})
58+
T.ok(ok, "should pass: " .. tostring(err))
59+
end)
60+
61+
T.describe("PR#1: components/pathItems - missing required 'name' (fail)", function()
62+
local ok, err = v:validate_request({
63+
method = "POST",
64+
path = "/widget",
65+
body = '{"notaname": "foo"}',
66+
content_type = "application/json",
67+
headers = { ["content-type"] = "application/json" },
68+
})
69+
T.ok(not ok, "should fail")
70+
T.ok(err and err:find("name", 1, true), "error should mention 'name': " .. tostring(err))
71+
end)
72+
73+
T.done()

t/conformance/test_issue1045.lua

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#!/usr/bin/env resty
2+
--- Conformance test ported from kin-openapi issue1045_test.go
3+
-- Tests allOf with $ref body validation for both JSON and form-urlencoded.
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 spec = cjson.encode({
11+
openapi = "3.0.3",
12+
info = { title = "sample api", version = "1.0.0" },
13+
paths = {
14+
["/api/path"] = {
15+
post = {
16+
requestBody = {
17+
required = true,
18+
content = {
19+
["application/json"] = {
20+
schema = { ["$ref"] = "#/components/schemas/PathRequest" },
21+
},
22+
["application/x-www-form-urlencoded"] = {
23+
schema = { ["$ref"] = "#/components/schemas/PathRequest" },
24+
},
25+
},
26+
},
27+
responses = { ["200"] = { description = "Ok" } },
28+
},
29+
},
30+
},
31+
components = {
32+
schemas = {
33+
Msg_Opt = {
34+
properties = {
35+
msg = { type = "string" },
36+
},
37+
},
38+
Msg = {
39+
allOf = {
40+
{ ["$ref"] = "#/components/schemas/Msg_Opt" },
41+
{ required = { "msg" } },
42+
},
43+
},
44+
Name = {
45+
properties = {
46+
name = { type = "string" },
47+
},
48+
required = { "name" },
49+
},
50+
PathRequest = {
51+
type = "object",
52+
allOf = {
53+
{ ["$ref"] = "#/components/schemas/Msg" },
54+
{ ["$ref"] = "#/components/schemas/Name" },
55+
},
56+
},
57+
},
58+
},
59+
})
60+
61+
local v = ov.compile(spec)
62+
assert(v, "compile failed")
63+
64+
T.describe("issue1045: JSON - both msg and name present (valid)", function()
65+
local ok, err = v:validate_request({
66+
method = "POST",
67+
path = "/api/path",
68+
body = '{"msg":"message","name":"some+name"}',
69+
content_type = "application/json",
70+
headers = { ["content-type"] = "application/json" },
71+
})
72+
T.ok(ok, "should pass: " .. tostring(err))
73+
end)
74+
75+
T.describe("issue1045: JSON - missing msg (fail)", function()
76+
local ok, err = v:validate_request({
77+
method = "POST",
78+
path = "/api/path",
79+
body = '{"name":"some+name"}',
80+
content_type = "application/json",
81+
headers = { ["content-type"] = "application/json" },
82+
})
83+
T.ok(not ok, "should fail")
84+
end)
85+
86+
T.describe("issue1045: form - both msg and name present (valid)", function()
87+
local ok, err = v:validate_request({
88+
method = "POST",
89+
path = "/api/path",
90+
body = "msg=message&name=some+name",
91+
content_type = "application/x-www-form-urlencoded",
92+
headers = { ["content-type"] = "application/x-www-form-urlencoded" },
93+
})
94+
T.ok(ok, "should pass: " .. tostring(err))
95+
end)
96+
97+
T.describe("issue1045: form - missing msg (fail)", function()
98+
local ok, err = v:validate_request({
99+
method = "POST",
100+
path = "/api/path",
101+
body = "name=some+name",
102+
content_type = "application/x-www-form-urlencoded",
103+
headers = { ["content-type"] = "application/x-www-form-urlencoded" },
104+
})
105+
T.ok(not ok, "should fail")
106+
end)
107+
108+
T.done()

t/conformance/test_issue1100.lua

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/env resty
2+
--- Conformance test ported from kin-openapi issue1100_test.go (in testdata/)
3+
-- Tests POST endpoint with no requestBody defined in spec but body sent.
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 spec = cjson.encode({
11+
openapi = "3.0.3",
12+
info = { title = "sample api", version = "1.0.0" },
13+
paths = {
14+
["/api/path"] = {
15+
post = {
16+
responses = { ["200"] = { description = "Ok" } },
17+
},
18+
},
19+
},
20+
})
21+
22+
local v = ov.compile(spec)
23+
assert(v, "compile failed")
24+
25+
T.describe("issue1100: empty body, no requestBody in spec (valid)", function()
26+
local ok, err = v:validate_request({
27+
method = "POST",
28+
path = "/api/path",
29+
content_type = "application/json",
30+
headers = { ["content-type"] = "application/json" },
31+
})
32+
T.ok(ok, "should pass: " .. tostring(err))
33+
end)
34+
35+
T.describe("issue1100: body present but no requestBody in spec (valid - lenient)", function()
36+
local ok, err = v:validate_request({
37+
method = "POST",
38+
path = "/api/path",
39+
body = '{"data":"some+unexpected+data"}',
40+
content_type = "application/json",
41+
headers = { ["content-type"] = "application/json" },
42+
})
43+
T.ok(ok, "should pass (no schema to validate against): " .. tostring(err))
44+
end)
45+
46+
T.done()

t/conformance/test_issue1110.lua

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#!/usr/bin/env resty
2+
--- Conformance test ported from kin-openapi issue1110_test.go
3+
-- Tests POST with form-urlencoded body where all properties are optional.
4+
-- Absent optional properties should not cause validation errors.
5+
dofile("t/lib/test_bootstrap.lua")
6+
7+
local T = require("test_helper")
8+
local cjson = require("cjson.safe")
9+
local ov = require("resty.openapi_validator")
10+
11+
local spec = cjson.encode({
12+
openapi = "3.0.3",
13+
info = { title = "Test API", version = "1.0.0" },
14+
paths = {
15+
["/test"] = {
16+
post = {
17+
requestBody = {
18+
content = {
19+
["application/x-www-form-urlencoded"] = {
20+
schema = {
21+
type = "object",
22+
properties = {
23+
param1 = { type = "string" },
24+
param2 = { type = "string" },
25+
},
26+
},
27+
},
28+
},
29+
},
30+
responses = { ["200"] = { description = "OK" } },
31+
},
32+
},
33+
},
34+
})
35+
36+
local v = ov.compile(spec)
37+
assert(v, "compile failed")
38+
39+
T.describe("issue1110: empty body (valid - no required fields)", function()
40+
local ok, err = v:validate_request({
41+
method = "POST",
42+
path = "/test",
43+
body = "",
44+
content_type = "application/x-www-form-urlencoded",
45+
headers = { ["content-type"] = "application/x-www-form-urlencoded" },
46+
})
47+
T.ok(ok, "should pass: " .. tostring(err))
48+
end)
49+
50+
T.describe("issue1110: only param1 present (valid)", function()
51+
local ok, err = v:validate_request({
52+
method = "POST",
53+
path = "/test",
54+
body = "param1=value1",
55+
content_type = "application/x-www-form-urlencoded",
56+
headers = { ["content-type"] = "application/x-www-form-urlencoded" },
57+
})
58+
T.ok(ok, "should pass: " .. tostring(err))
59+
end)
60+
61+
T.describe("issue1110: only param2 present (valid)", function()
62+
local ok, err = v:validate_request({
63+
method = "POST",
64+
path = "/test",
65+
body = "param2=value2",
66+
content_type = "application/x-www-form-urlencoded",
67+
headers = { ["content-type"] = "application/x-www-form-urlencoded" },
68+
})
69+
T.ok(ok, "should pass: " .. tostring(err))
70+
end)
71+
72+
T.describe("issue1110: both params present (valid)", function()
73+
local ok, err = v:validate_request({
74+
method = "POST",
75+
path = "/test",
76+
body = "param1=value1&param2=value2",
77+
content_type = "application/x-www-form-urlencoded",
78+
headers = { ["content-type"] = "application/x-www-form-urlencoded" },
79+
})
80+
T.ok(ok, "should pass: " .. tostring(err))
81+
end)
82+
83+
T.done()

0 commit comments

Comments
 (0)