@voxgig/sdkgen 0.44.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/voxgig-sdkgen +1 -1
- package/dist/cmp/ReadmeEntity.js +9 -153
- package/dist/cmp/ReadmeEntity.js.map +1 -1
- package/dist/cmp/ReadmeIntro.js +9 -14
- package/dist/cmp/ReadmeIntro.js.map +1 -1
- package/dist/cmp/ReadmeModel.js +6 -4
- package/dist/cmp/ReadmeModel.js.map +1 -1
- package/dist/cmp/ReadmeOptions.js +9 -61
- package/dist/cmp/ReadmeOptions.js.map +1 -1
- package/dist/cmp/ReadmeRef.js +10 -1328
- package/dist/cmp/ReadmeRef.js.map +1 -1
- package/dist/sdkgen.d.ts +2 -2
- package/dist/sdkgen.js +2 -1
- package/dist/sdkgen.js.map +1 -1
- package/dist/utility.d.ts +2 -1
- package/dist/utility.js +9 -0
- package/dist/utility.js.map +1 -1
- package/package.json +3 -3
- package/project/.sdk/src/cmp/go/Config_go.ts +9 -4
- package/project/.sdk/src/cmp/go/Entity_go.ts +2 -2
- package/project/.sdk/src/cmp/go/Main_go.ts +8 -4
- package/project/.sdk/src/cmp/go/Package_go.ts +2 -2
- package/project/.sdk/src/cmp/go/ReadmeEntity_go.ts +138 -0
- package/project/.sdk/src/cmp/go/ReadmeExplanation_go.ts +2 -2
- package/project/.sdk/src/cmp/go/ReadmeHowto_go.ts +8 -5
- package/project/.sdk/src/cmp/go/ReadmeInstall_go.ts +2 -2
- package/project/.sdk/src/cmp/go/ReadmeIntro_go.ts +18 -0
- package/project/.sdk/src/cmp/go/ReadmeModel_go.ts +8 -5
- package/project/.sdk/src/cmp/go/ReadmeOptions_go.ts +58 -0
- package/project/.sdk/src/cmp/go/ReadmeQuick_go.ts +13 -9
- package/project/.sdk/src/cmp/go/ReadmeRef_go.ts +354 -0
- package/project/.sdk/src/cmp/go/ReadmeTopQuick_go.ts +8 -6
- package/project/.sdk/src/cmp/go/ReadmeTopTest_go.ts +2 -2
- package/project/.sdk/src/cmp/go/TestDirect_go.ts +222 -41
- package/project/.sdk/src/cmp/go/TestEntity_go.ts +142 -60
- package/project/.sdk/src/cmp/go/Test_go.ts +2 -2
- package/project/.sdk/src/cmp/go/fragment/Main.fragment.go +21 -4
- package/project/.sdk/src/cmp/js/Config_js.ts +18 -0
- package/project/.sdk/src/cmp/js/ReadmeEntity_js.ts +138 -0
- package/project/.sdk/src/cmp/js/ReadmeHowto_js.ts +11 -6
- package/project/.sdk/src/cmp/js/ReadmeIntro_js.ts +18 -0
- package/project/.sdk/src/cmp/js/ReadmeModel_js.ts +6 -3
- package/project/.sdk/src/cmp/js/ReadmeOptions_js.ts +58 -0
- package/project/.sdk/src/cmp/js/ReadmeQuick_js.ts +6 -4
- package/project/.sdk/src/cmp/js/ReadmeRef_js.ts +384 -0
- package/project/.sdk/src/cmp/js/ReadmeTopQuick_js.ts +6 -4
- package/project/.sdk/src/cmp/js/TestDirect_js.ts +23 -12
- package/project/.sdk/src/cmp/js/TestEntity_js.ts +107 -74
- package/project/.sdk/src/cmp/js/fragment/Config.fragment.js +1 -5
- package/project/.sdk/src/cmp/lua/Config_lua.ts +9 -4
- package/project/.sdk/src/cmp/lua/Package_lua.ts +9 -2
- package/project/.sdk/src/cmp/lua/ReadmeEntity_lua.ts +138 -0
- package/project/.sdk/src/cmp/lua/ReadmeHowto_lua.ts +6 -3
- package/project/.sdk/src/cmp/lua/ReadmeIntro_lua.ts +18 -0
- package/project/.sdk/src/cmp/lua/ReadmeModel_lua.ts +6 -3
- package/project/.sdk/src/cmp/lua/ReadmeOptions_lua.ts +58 -0
- package/project/.sdk/src/cmp/lua/ReadmeQuick_lua.ts +6 -4
- package/project/.sdk/src/cmp/lua/ReadmeRef_lua.ts +360 -0
- package/project/.sdk/src/cmp/lua/ReadmeTopQuick_lua.ts +6 -4
- package/project/.sdk/src/cmp/lua/TestDirect_lua.ts +172 -29
- package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +120 -52
- package/project/.sdk/src/cmp/lua/fragment/Main.fragment.lua +20 -4
- package/project/.sdk/src/cmp/php/Config_php.ts +10 -8
- package/project/.sdk/src/cmp/php/Package_php.ts +7 -1
- package/project/.sdk/src/cmp/php/ReadmeEntity_php.ts +138 -0
- package/project/.sdk/src/cmp/php/ReadmeHowto_php.ts +6 -3
- package/project/.sdk/src/cmp/php/ReadmeIntro_php.ts +18 -0
- package/project/.sdk/src/cmp/php/ReadmeModel_php.ts +6 -3
- package/project/.sdk/src/cmp/php/ReadmeOptions_php.ts +58 -0
- package/project/.sdk/src/cmp/php/ReadmeQuick_php.ts +6 -4
- package/project/.sdk/src/cmp/php/ReadmeRef_php.ts +358 -0
- package/project/.sdk/src/cmp/php/ReadmeTopQuick_php.ts +6 -4
- package/project/.sdk/src/cmp/php/TestDirect_php.ts +171 -28
- package/project/.sdk/src/cmp/php/TestEntity_php.ts +126 -55
- package/project/.sdk/src/cmp/php/fragment/Main.fragment.php +17 -3
- package/project/.sdk/src/cmp/py/Config_py.ts +9 -4
- package/project/.sdk/src/cmp/py/Package_py.ts +8 -1
- package/project/.sdk/src/cmp/py/ReadmeEntity_py.ts +138 -0
- package/project/.sdk/src/cmp/py/ReadmeHowto_py.ts +6 -3
- package/project/.sdk/src/cmp/py/ReadmeIntro_py.ts +18 -0
- package/project/.sdk/src/cmp/py/ReadmeModel_py.ts +6 -3
- package/project/.sdk/src/cmp/py/ReadmeOptions_py.ts +58 -0
- package/project/.sdk/src/cmp/py/ReadmeQuick_py.ts +9 -6
- package/project/.sdk/src/cmp/py/ReadmeRef_py.ts +356 -0
- package/project/.sdk/src/cmp/py/ReadmeTopQuick_py.ts +9 -6
- package/project/.sdk/src/cmp/py/TestDirect_py.ts +164 -27
- package/project/.sdk/src/cmp/py/TestEntity_py.ts +125 -51
- package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +19 -4
- package/project/.sdk/src/cmp/rb/Config_rb.ts +9 -4
- package/project/.sdk/src/cmp/rb/Package_rb.ts +9 -2
- package/project/.sdk/src/cmp/rb/ReadmeEntity_rb.ts +138 -0
- package/project/.sdk/src/cmp/rb/ReadmeHowto_rb.ts +6 -3
- package/project/.sdk/src/cmp/rb/ReadmeIntro_rb.ts +18 -0
- package/project/.sdk/src/cmp/rb/ReadmeModel_rb.ts +6 -3
- package/project/.sdk/src/cmp/rb/ReadmeOptions_rb.ts +58 -0
- package/project/.sdk/src/cmp/rb/ReadmeQuick_rb.ts +6 -4
- package/project/.sdk/src/cmp/rb/ReadmeRef_rb.ts +361 -0
- package/project/.sdk/src/cmp/rb/ReadmeTopQuick_rb.ts +6 -4
- package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +172 -29
- package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +120 -52
- package/project/.sdk/src/cmp/rb/fragment/Main.fragment.rb +19 -3
- package/project/.sdk/src/cmp/ts/Config_ts.ts +18 -0
- package/project/.sdk/src/cmp/ts/Package_ts.ts +1 -1
- package/project/.sdk/src/cmp/ts/ReadmeEntity_ts.ts +138 -0
- package/project/.sdk/src/cmp/ts/ReadmeHowto_ts.ts +11 -6
- package/project/.sdk/src/cmp/ts/ReadmeIntro_ts.ts +18 -0
- package/project/.sdk/src/cmp/ts/ReadmeModel_ts.ts +9 -5
- package/project/.sdk/src/cmp/ts/ReadmeOptions_ts.ts +58 -0
- package/project/.sdk/src/cmp/ts/ReadmeQuick_ts.ts +6 -4
- package/project/.sdk/src/cmp/ts/ReadmeRef_ts.ts +384 -0
- package/project/.sdk/src/cmp/ts/ReadmeTopQuick_ts.ts +6 -4
- package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +213 -42
- package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +168 -75
- package/project/.sdk/src/cmp/ts/fragment/Config.fragment.ts +1 -5
- package/project/.sdk/src/cmp/ts/fragment/Direct.test.fragment.ts +8 -1
- package/project/.sdk/src/cmp/ts/fragment/Entity.test.fragment.ts +8 -2
- package/project/.sdk/src/cmp/ts/fragment/Main.fragment.ts +21 -1
- package/project/.sdk/tm/go/feature/test_feature.go +51 -3
- package/project/.sdk/tm/go/test/runner_test.go +106 -6
- package/project/.sdk/tm/go/test/sdk-test-control.json +19 -0
- package/project/.sdk/tm/go/utility/fetcher.go +10 -0
- package/project/.sdk/tm/go/utility/make_url.go +12 -0
- package/project/.sdk/tm/go/utility/prepare_auth.go +15 -1
- package/project/.sdk/tm/js/src/utility/PrepareAuthUtility.js +7 -1
- package/project/.sdk/tm/lua/feature/test_feature.lua +41 -3
- package/project/.sdk/tm/lua/test/runner.lua +74 -0
- package/project/.sdk/tm/lua/test/sdk-test-control.json +19 -0
- package/project/.sdk/tm/lua/utility/fetcher.lua +13 -0
- package/project/.sdk/tm/lua/utility/make_url.lua +16 -0
- package/project/.sdk/tm/lua/utility/prepare_auth.lua +9 -1
- package/project/.sdk/tm/php/feature/TestFeature.php +185 -43
- package/project/.sdk/tm/php/test/Runner.php +62 -0
- package/project/.sdk/tm/php/test/sdk-test-control.json +19 -0
- package/project/.sdk/tm/php/utility/Fetcher.php +132 -9
- package/project/.sdk/tm/php/utility/MakeUrl.php +16 -0
- package/project/.sdk/tm/php/utility/PrepareAuth.php +11 -1
- package/project/.sdk/tm/py/feature/test_feature.py +35 -3
- package/project/.sdk/tm/py/test/runner.py +60 -0
- package/project/.sdk/tm/py/test/sdk-test-control.json +19 -0
- package/project/.sdk/tm/py/utility/fetcher.py +13 -0
- package/project/.sdk/tm/py/utility/make_url.py +13 -0
- package/project/.sdk/tm/py/utility/prepare_auth.py +10 -1
- package/project/.sdk/tm/rb/feature/test_feature.rb +36 -3
- package/project/.sdk/tm/rb/test/runner.rb +46 -0
- package/project/.sdk/tm/rb/test/sdk-test-control.json +19 -0
- package/project/.sdk/tm/rb/utility/fetcher.rb +49 -28
- package/project/.sdk/tm/rb/utility/make_url.rb +16 -0
- package/project/.sdk/tm/rb/utility/prepare_auth.rb +8 -1
- package/project/.sdk/tm/ts/src/utility/MakeUrlUtility.ts +7 -8
- package/project/.sdk/tm/ts/src/utility/PrepareAuthUtility.ts +7 -1
- package/project/.sdk/tm/ts/test/sdk-test-control.json +19 -0
- package/project/.sdk/tm/ts/test/utility.ts +120 -2
- package/src/cmp/ReadmeEntity.ts +11 -178
- package/src/cmp/ReadmeIntro.ts +11 -25
- package/src/cmp/ReadmeModel.ts +7 -5
- package/src/cmp/ReadmeOptions.ts +12 -74
- package/src/cmp/ReadmeRef.ts +11 -1372
- package/src/sdkgen.ts +2 -1
- package/src/utility.ts +12 -0
- /package/project/.sdk/tm/go/utility/{make_target.go → make_point.go} +0 -0
|
@@ -71,12 +71,112 @@ func envOverride(m map[string]any) map[string]any {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
type entityTestSetup struct {
|
|
74
|
-
client
|
|
75
|
-
data
|
|
76
|
-
idmap
|
|
77
|
-
env
|
|
78
|
-
explain
|
|
79
|
-
|
|
74
|
+
client *sdk.ProjectNameSDK
|
|
75
|
+
data map[string]any
|
|
76
|
+
idmap map[string]any
|
|
77
|
+
env map[string]any
|
|
78
|
+
explain bool
|
|
79
|
+
live bool
|
|
80
|
+
syntheticOnly bool
|
|
81
|
+
now int64
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
var (
|
|
85
|
+
cachedTestControl map[string]any
|
|
86
|
+
cachedTestControlOnce sync.Once
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
// loadTestControl reads sdk-test-control.json from this test dir; caches
|
|
90
|
+
// after first read. Returns an empty-skip default if the file is missing
|
|
91
|
+
// or invalid so tests never crash on a bad config.
|
|
92
|
+
func loadTestControl() map[string]any {
|
|
93
|
+
cachedTestControlOnce.Do(func() {
|
|
94
|
+
_, filename, _, _ := runtime.Caller(0)
|
|
95
|
+
dir := filepath.Dir(filename)
|
|
96
|
+
ctrlPath := filepath.Join(dir, "sdk-test-control.json")
|
|
97
|
+
def := map[string]any{
|
|
98
|
+
"version": 1,
|
|
99
|
+
"test": map[string]any{"skip": map[string]any{
|
|
100
|
+
"live": map[string]any{"direct": []any{}, "entityOp": []any{}},
|
|
101
|
+
"unit": map[string]any{"direct": []any{}, "entityOp": []any{}},
|
|
102
|
+
}},
|
|
103
|
+
}
|
|
104
|
+
data, err := os.ReadFile(ctrlPath)
|
|
105
|
+
if err != nil {
|
|
106
|
+
cachedTestControl = def
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
var parsed map[string]any
|
|
110
|
+
if err := json.Unmarshal(data, &parsed); err != nil {
|
|
111
|
+
cachedTestControl = def
|
|
112
|
+
return
|
|
113
|
+
}
|
|
114
|
+
cachedTestControl = parsed
|
|
115
|
+
})
|
|
116
|
+
return cachedTestControl
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// isControlSkipped checks sdk-test-control.json for a skip entry.
|
|
120
|
+
// Returns (skip, reason).
|
|
121
|
+
func isControlSkipped(kind, name, mode string) (bool, string) {
|
|
122
|
+
ctrl := loadTestControl()
|
|
123
|
+
test, _ := ctrl["test"].(map[string]any)
|
|
124
|
+
if test == nil {
|
|
125
|
+
return false, ""
|
|
126
|
+
}
|
|
127
|
+
skip, _ := test["skip"].(map[string]any)
|
|
128
|
+
if skip == nil {
|
|
129
|
+
return false, ""
|
|
130
|
+
}
|
|
131
|
+
modeMap, _ := skip[mode].(map[string]any)
|
|
132
|
+
if modeMap == nil {
|
|
133
|
+
return false, ""
|
|
134
|
+
}
|
|
135
|
+
items, _ := modeMap[kind].([]any)
|
|
136
|
+
for _, raw := range items {
|
|
137
|
+
item, _ := raw.(map[string]any)
|
|
138
|
+
if item == nil {
|
|
139
|
+
continue
|
|
140
|
+
}
|
|
141
|
+
reason, _ := item["reason"].(string)
|
|
142
|
+
if kind == "direct" {
|
|
143
|
+
if t, _ := item["test"].(string); t == name {
|
|
144
|
+
return true, reason
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if kind == "entityOp" {
|
|
148
|
+
ent, _ := item["entity"].(string)
|
|
149
|
+
op, _ := item["op"].(string)
|
|
150
|
+
if ent+"."+op == name {
|
|
151
|
+
return true, reason
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return false, ""
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// liveDelayMs returns the configured per-test live delay in ms; default 500.
|
|
159
|
+
func liveDelayMs() int {
|
|
160
|
+
ctrl := loadTestControl()
|
|
161
|
+
test, _ := ctrl["test"].(map[string]any)
|
|
162
|
+
if test == nil {
|
|
163
|
+
return 500
|
|
164
|
+
}
|
|
165
|
+
live, _ := test["live"].(map[string]any)
|
|
166
|
+
if live == nil {
|
|
167
|
+
return 500
|
|
168
|
+
}
|
|
169
|
+
switch v := live["delayMs"].(type) {
|
|
170
|
+
case float64:
|
|
171
|
+
if v >= 0 {
|
|
172
|
+
return int(v)
|
|
173
|
+
}
|
|
174
|
+
case int:
|
|
175
|
+
if v >= 0 {
|
|
176
|
+
return v
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return 500
|
|
80
180
|
}
|
|
81
181
|
|
|
82
182
|
var cachedTestSpec map[string]any
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"_doc": "Per-SDK test control. Lists tests/operations to skip in unit and live modes; tunes per-test pacing. Edit by hand. Loaded by go test runner.",
|
|
4
|
+
"test": {
|
|
5
|
+
"skip": {
|
|
6
|
+
"live": {
|
|
7
|
+
"direct": [],
|
|
8
|
+
"entityOp": []
|
|
9
|
+
},
|
|
10
|
+
"unit": {
|
|
11
|
+
"direct": [],
|
|
12
|
+
"entityOp": []
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"live": {
|
|
16
|
+
"delayMs": 500
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -27,13 +27,23 @@ func defaultHTTPFetch(fullurl string, fetchdef map[string]any) (map[string]any,
|
|
|
27
27
|
return nil, err
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
hasUA := false
|
|
30
31
|
if headers, ok := fetchdef["headers"].(map[string]any); ok {
|
|
31
32
|
for k, v := range headers {
|
|
32
33
|
if sv, ok := v.(string); ok {
|
|
34
|
+
if strings.EqualFold(k, "user-agent") {
|
|
35
|
+
hasUA = true
|
|
36
|
+
}
|
|
33
37
|
req.Header.Set(k, sv)
|
|
34
38
|
}
|
|
35
39
|
}
|
|
36
40
|
}
|
|
41
|
+
// Default User-Agent — Go's net/http defaults to "Go-http-client/1.1"
|
|
42
|
+
// which some CDNs block. Use a Mozilla-shaped UA unless the caller
|
|
43
|
+
// already set one.
|
|
44
|
+
if !hasUA {
|
|
45
|
+
req.Header.Set("User-Agent", "Mozilla/5.0 (compatible; ProjectNameSDK/1.0)")
|
|
46
|
+
}
|
|
37
47
|
|
|
38
48
|
resp, err := http.DefaultClient.Do(req)
|
|
39
49
|
if err != nil {
|
|
@@ -35,6 +35,18 @@ func makeUrlUtil(ctx *core.Context) (string, error) {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
// Append query string from spec.Query.
|
|
39
|
+
qsep := "?"
|
|
40
|
+
for _, item := range vs.Items(spec.Query) {
|
|
41
|
+
key, _ := item[0].(string)
|
|
42
|
+
val := item[1]
|
|
43
|
+
if val != nil {
|
|
44
|
+
url += qsep + vs.EscUrl(key) + "=" + vs.EscUrl(vs.Stringify(val))
|
|
45
|
+
qsep = "&"
|
|
46
|
+
resmatch[key] = val
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
38
50
|
result.Resmatch = resmatch
|
|
39
51
|
|
|
40
52
|
return url, nil
|
|
@@ -20,9 +20,23 @@ func prepareAuthUtil(ctx *core.Context) (*core.Spec, error) {
|
|
|
20
20
|
headers := spec.Headers
|
|
21
21
|
options := ctx.Client.OptionsMap()
|
|
22
22
|
|
|
23
|
+
// Public APIs that need no auth omit the options.auth block entirely.
|
|
24
|
+
if options["auth"] == nil {
|
|
25
|
+
delete(headers, headerAuth)
|
|
26
|
+
return spec, nil
|
|
27
|
+
}
|
|
28
|
+
|
|
23
29
|
apikey := vs.GetProp(options, optionApikey, notFound)
|
|
24
30
|
|
|
25
|
-
|
|
31
|
+
skip := false
|
|
32
|
+
if apikey == nil {
|
|
33
|
+
skip = true
|
|
34
|
+
} else if apikeyStr, ok := apikey.(string); ok &&
|
|
35
|
+
(apikeyStr == notFound || apikeyStr == "") {
|
|
36
|
+
skip = true
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if skip {
|
|
26
40
|
delete(headers, headerAuth)
|
|
27
41
|
} else {
|
|
28
42
|
authPrefix := ""
|
|
@@ -24,9 +24,15 @@ function prepareAuth(ctx) {
|
|
|
24
24
|
|
|
25
25
|
const options = client.options()
|
|
26
26
|
|
|
27
|
+
// Public APIs that need no auth omit the options.auth block entirely.
|
|
28
|
+
if (null == options.auth) {
|
|
29
|
+
delprop(headers, HEADER_auth)
|
|
30
|
+
return spec
|
|
31
|
+
}
|
|
32
|
+
|
|
27
33
|
const apikey = getprop(options, OPTION_apikey, NOTFOUND)
|
|
28
34
|
|
|
29
|
-
if (NOTFOUND === apikey) {
|
|
35
|
+
if (NOTFOUND === apikey || null == apikey || '' === apikey) {
|
|
30
36
|
delprop(headers, HEADER_auth)
|
|
31
37
|
}
|
|
32
38
|
else {
|
|
@@ -62,8 +62,27 @@ function TestFeature:init(ctx, options)
|
|
|
62
62
|
entmap = {}
|
|
63
63
|
end
|
|
64
64
|
|
|
65
|
+
-- For single-entity ops (load, remove) with an empty explicit match, fall
|
|
66
|
+
-- back to the id the entity client already knows from a prior create/load
|
|
67
|
+
-- (in fctx.match / fctx.data). Mirrors the TS mock where param() resolves
|
|
68
|
+
-- the id from that accumulated state.
|
|
69
|
+
local function resolve_match(explicit)
|
|
70
|
+
if type(explicit) == "table" and next(explicit) ~= nil then
|
|
71
|
+
return explicit
|
|
72
|
+
end
|
|
73
|
+
local function id_of(src)
|
|
74
|
+
if src == nil then return nil end
|
|
75
|
+
local v = vs.getprop(src, "id")
|
|
76
|
+
if v ~= nil and v ~= "__UNDEFINED__" then return v end
|
|
77
|
+
return nil
|
|
78
|
+
end
|
|
79
|
+
local v = id_of(fctx.match) or id_of(fctx.data)
|
|
80
|
+
if v ~= nil then return { id = v } end
|
|
81
|
+
return {}
|
|
82
|
+
end
|
|
83
|
+
|
|
65
84
|
if op.name == "load" then
|
|
66
|
-
local args = test_self:build_args(fctx, op, fctx.reqmatch)
|
|
85
|
+
local args = test_self:build_args(fctx, op, resolve_match(fctx.reqmatch))
|
|
67
86
|
local found = vs.select(entmap, args)
|
|
68
87
|
local ent = vs.getelem(found, 0)
|
|
69
88
|
if ent == nil then
|
|
@@ -88,9 +107,28 @@ function TestFeature:init(ctx, options)
|
|
|
88
107
|
return respond(200, out, nil)
|
|
89
108
|
|
|
90
109
|
elseif op.name == "update" then
|
|
91
|
-
|
|
110
|
+
-- Match the existing entity by id only (or its alias). reqdata also
|
|
111
|
+
-- contains the new field values, which would otherwise cause select
|
|
112
|
+
-- to filter out the entity we want to update. Falls back to first
|
|
113
|
+
-- entity when no match found, mirroring the TS mock.
|
|
114
|
+
local update_match = {}
|
|
115
|
+
if type(fctx.reqdata) == "table" then
|
|
116
|
+
if fctx.reqdata["id"] ~= nil then update_match["id"] = fctx.reqdata["id"] end
|
|
117
|
+
if op.alias_map ~= nil then
|
|
118
|
+
local alias_id = vs.getprop(op.alias_map, "id")
|
|
119
|
+
if alias_id ~= nil and fctx.reqdata[alias_id] ~= nil then
|
|
120
|
+
update_match[alias_id] = fctx.reqdata[alias_id]
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
local args = test_self:build_args(fctx, op, update_match)
|
|
92
125
|
local found = vs.select(entmap, args)
|
|
93
126
|
local ent = vs.getelem(found, 0)
|
|
127
|
+
if ent == nil and type(entmap) == "table" then
|
|
128
|
+
for _, e in pairs(entmap) do
|
|
129
|
+
if type(e) == "table" then ent = e; break end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
94
132
|
if ent == nil then
|
|
95
133
|
return respond(404, nil, { statusText = "Not found" })
|
|
96
134
|
end
|
|
@@ -107,7 +145,7 @@ function TestFeature:init(ctx, options)
|
|
|
107
145
|
return respond(200, out, nil)
|
|
108
146
|
|
|
109
147
|
elseif op.name == "remove" then
|
|
110
|
-
local args = test_self:build_args(fctx, op, fctx.reqmatch)
|
|
148
|
+
local args = test_self:build_args(fctx, op, resolve_match(fctx.reqmatch))
|
|
111
149
|
local found = vs.select(entmap, args)
|
|
112
150
|
local ent = vs.getelem(found, 0)
|
|
113
151
|
if ent == nil then
|
|
@@ -83,4 +83,78 @@ function runner.entity_list_to_data(list)
|
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
|
|
86
|
+
-- Load sdk-test-control.json from this test dir; cache. Returns an
|
|
87
|
+
-- empty-skip default if the file is missing or invalid.
|
|
88
|
+
runner._test_control = nil
|
|
89
|
+
|
|
90
|
+
function runner.load_test_control()
|
|
91
|
+
if runner._test_control ~= nil then
|
|
92
|
+
return runner._test_control
|
|
93
|
+
end
|
|
94
|
+
local this_dir = debug.getinfo(1, "S").source:match("^@(.+/)") or "./"
|
|
95
|
+
local ctrl_path = this_dir .. "sdk-test-control.json"
|
|
96
|
+
local f = io.open(ctrl_path, "r")
|
|
97
|
+
if f == nil then
|
|
98
|
+
runner._test_control = {
|
|
99
|
+
version = 1,
|
|
100
|
+
test = {
|
|
101
|
+
skip = {
|
|
102
|
+
live = { direct = {}, entityOp = {} },
|
|
103
|
+
unit = { direct = {}, entityOp = {} },
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
}
|
|
107
|
+
return runner._test_control
|
|
108
|
+
end
|
|
109
|
+
local content = f:read("*a")
|
|
110
|
+
f:close()
|
|
111
|
+
local parsed = json.decode(content)
|
|
112
|
+
if parsed == nil then
|
|
113
|
+
runner._test_control = {
|
|
114
|
+
version = 1,
|
|
115
|
+
test = {
|
|
116
|
+
skip = {
|
|
117
|
+
live = { direct = {}, entityOp = {} },
|
|
118
|
+
unit = { direct = {}, entityOp = {} },
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
}
|
|
122
|
+
else
|
|
123
|
+
runner._test_control = parsed
|
|
124
|
+
end
|
|
125
|
+
return runner._test_control
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
-- Check sdk-test-control.json for a skip entry. Returns (skip, reason).
|
|
130
|
+
function runner.is_control_skipped(kind, name, mode)
|
|
131
|
+
local ctrl = runner.load_test_control()
|
|
132
|
+
local skip = (((ctrl.test or {}).skip or {})[mode] or {})
|
|
133
|
+
local items = skip[kind] or {}
|
|
134
|
+
for _, item in ipairs(items) do
|
|
135
|
+
if kind == "direct" and item.test == name then
|
|
136
|
+
return true, item.reason
|
|
137
|
+
end
|
|
138
|
+
if kind == "entityOp" then
|
|
139
|
+
local key = (item.entity or "") .. "." .. (item.op or "")
|
|
140
|
+
if key == name then
|
|
141
|
+
return true, item.reason
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
return false, nil
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
-- Per-test live pacing delay (ms); default 500.
|
|
150
|
+
function runner.live_delay_ms()
|
|
151
|
+
local ctrl = runner.load_test_control()
|
|
152
|
+
local v = ((ctrl.test or {}).live or {}).delayMs
|
|
153
|
+
if type(v) == "number" and v >= 0 then
|
|
154
|
+
return v
|
|
155
|
+
end
|
|
156
|
+
return 500
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
|
|
86
160
|
return runner
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"_doc": "Per-SDK test control. Lists tests/operations to skip in unit and live modes; tunes per-test pacing. Edit by hand. Loaded by lua test runner.",
|
|
4
|
+
"test": {
|
|
5
|
+
"skip": {
|
|
6
|
+
"live": {
|
|
7
|
+
"direct": [],
|
|
8
|
+
"entityOp": []
|
|
9
|
+
},
|
|
10
|
+
"unit": {
|
|
11
|
+
"direct": [],
|
|
12
|
+
"entityOp": []
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"live": {
|
|
16
|
+
"delayMs": 500
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -25,6 +25,19 @@ local function default_http_fetch(fullurl, fetchdef)
|
|
|
25
25
|
headers["content-length"] = tostring(#body_str)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
-- Default User-Agent — many CDNs reject requests with no UA. Set a
|
|
29
|
+
-- Mozilla-shaped UA unless the caller already set one.
|
|
30
|
+
local has_ua = false
|
|
31
|
+
for k, _ in pairs(headers) do
|
|
32
|
+
if string.lower(k) == "user-agent" then
|
|
33
|
+
has_ua = true
|
|
34
|
+
break
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
if not has_ua then
|
|
38
|
+
headers["User-Agent"] = "Mozilla/5.0 (compatible; ProjectNameSDK/1.0)"
|
|
39
|
+
end
|
|
40
|
+
|
|
28
41
|
local response_body = {}
|
|
29
42
|
local res, code, response_headers = http.request({
|
|
30
43
|
url = fullurl,
|
|
@@ -38,6 +38,22 @@ local function make_url_util(ctx)
|
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
-- Append query string from spec.query.
|
|
42
|
+
local qsep = "?"
|
|
43
|
+
local query_items = vs.items(spec.query)
|
|
44
|
+
if query_items ~= nil then
|
|
45
|
+
for _, item in ipairs(query_items) do
|
|
46
|
+
local key = item[1]
|
|
47
|
+
local val = item[2]
|
|
48
|
+
if val ~= nil and type(key) == "string" then
|
|
49
|
+
local val_str = type(val) == "string" and val or tostring(val)
|
|
50
|
+
url = url .. qsep .. vs.escurl(key) .. "=" .. vs.escurl(val_str)
|
|
51
|
+
qsep = "&"
|
|
52
|
+
resmatch[key] = val
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
41
57
|
result.resmatch = resmatch
|
|
42
58
|
|
|
43
59
|
return url, nil
|
|
@@ -16,9 +16,17 @@ local function prepare_auth_util(ctx)
|
|
|
16
16
|
local headers = spec.headers
|
|
17
17
|
local options = ctx.client:options_map()
|
|
18
18
|
|
|
19
|
+
-- Public APIs that need no auth omit the options.auth block entirely.
|
|
20
|
+
if options.auth == nil then
|
|
21
|
+
headers[HEADER_AUTH] = nil
|
|
22
|
+
return spec, nil
|
|
23
|
+
end
|
|
24
|
+
|
|
19
25
|
local apikey = vs.getprop(options, OPTION_APIKEY, NOT_FOUND)
|
|
20
26
|
|
|
21
|
-
if
|
|
27
|
+
if apikey == nil
|
|
28
|
+
or (type(apikey) == "string" and (apikey == NOT_FOUND or apikey == ""))
|
|
29
|
+
then
|
|
22
30
|
headers[HEADER_AUTH] = nil
|
|
23
31
|
else
|
|
24
32
|
local auth_prefix = ""
|