Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/pkg/input/formats/openapi/downloader_test.go
2844 views
1
package openapi
2
3
import (
4
"encoding/json"
5
"net/http"
6
"net/http/httptest"
7
"os"
8
"strings"
9
"testing"
10
"time"
11
)
12
13
func TestOpenAPIDownloader_SupportedExtensions(t *testing.T) {
14
downloader := &OpenAPIDownloader{}
15
extensions := downloader.SupportedExtensions()
16
17
expected := []string{".json"}
18
if len(extensions) != len(expected) {
19
t.Errorf("Expected %d extensions, got %d", len(expected), len(extensions))
20
}
21
22
for i, ext := range extensions {
23
if ext != expected[i] {
24
t.Errorf("Expected extension %s, got %s", expected[i], ext)
25
}
26
}
27
}
28
29
func TestOpenAPIDownloader_Download_Success(t *testing.T) {
30
// Create a mock OpenAPI spec
31
mockSpec := map[string]interface{}{
32
"openapi": "3.0.0",
33
"info": map[string]interface{}{
34
"title": "Test API",
35
"version": "1.0.0",
36
},
37
"paths": map[string]interface{}{
38
"/test": map[string]interface{}{
39
"get": map[string]interface{}{
40
"summary": "Test endpoint",
41
},
42
},
43
},
44
}
45
46
// Create mock server
47
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
48
w.Header().Set("Content-Type", "application/json")
49
if err := json.NewEncoder(w).Encode(mockSpec); err != nil {
50
http.Error(w, "failed to encode response", http.StatusInternalServerError)
51
}
52
}))
53
defer server.Close()
54
55
// Create temp directory
56
tmpDir, err := os.MkdirTemp("", "openapi_test")
57
if err != nil {
58
t.Fatalf("Failed to create temp dir: %v", err)
59
}
60
61
defer func() {
62
if err := os.RemoveAll(tmpDir); err != nil {
63
t.Fatalf("Failed to remove temp dir: %v", err)
64
}
65
}()
66
67
// Test download
68
downloader := &OpenAPIDownloader{}
69
filePath, err := downloader.Download(server.URL+"/openapi.json", tmpDir, nil)
70
if err != nil {
71
t.Fatalf("Download failed: %v", err)
72
}
73
74
// Verify file exists
75
if !fileExists(filePath) {
76
t.Errorf("Downloaded file does not exist: %s", filePath)
77
}
78
79
// Verify file content
80
content, err := os.ReadFile(filePath)
81
if err != nil {
82
t.Fatalf("Failed to read downloaded file: %v", err)
83
}
84
85
var downloadedSpec map[string]interface{}
86
if err := json.Unmarshal(content, &downloadedSpec); err != nil {
87
t.Fatalf("Failed to parse downloaded JSON: %v", err)
88
}
89
90
// Verify servers field was added
91
servers, exists := downloadedSpec["servers"]
92
if !exists {
93
t.Error("Servers field was not added to the spec")
94
}
95
96
if serversList, ok := servers.([]interface{}); ok {
97
if len(serversList) == 0 {
98
t.Error("Servers list is empty")
99
}
100
} else {
101
t.Error("Servers field is not a list")
102
}
103
}
104
105
func TestOpenAPIDownloader_Download_NonJSONURL(t *testing.T) {
106
tmpDir, err := os.MkdirTemp("", "openapi_test")
107
if err != nil {
108
t.Fatalf("Failed to create temp dir: %v", err)
109
}
110
111
defer func() {
112
if err := os.RemoveAll(tmpDir); err != nil {
113
t.Fatalf("Failed to remove temp dir: %v", err)
114
}
115
}()
116
117
downloader := &OpenAPIDownloader{}
118
_, err = downloader.Download("http://example.com/spec.yaml", tmpDir, nil)
119
if err == nil {
120
t.Error("Expected error for non-JSON URL, but got none")
121
}
122
123
if !strings.Contains(err.Error(), "URL does not appear to be an OpenAPI JSON spec") {
124
t.Errorf("Unexpected error message: %v", err)
125
}
126
}
127
128
func TestOpenAPIDownloader_Download_HTTPError(t *testing.T) {
129
// Create mock server that returns 404
130
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
131
w.WriteHeader(http.StatusNotFound)
132
}))
133
defer server.Close()
134
135
tmpDir, err := os.MkdirTemp("", "openapi_test")
136
if err != nil {
137
t.Fatalf("Failed to create temp dir: %v", err)
138
}
139
140
defer func() {
141
if err := os.RemoveAll(tmpDir); err != nil {
142
t.Fatalf("Failed to remove temp dir: %v", err)
143
}
144
}()
145
146
downloader := &OpenAPIDownloader{}
147
_, err = downloader.Download(server.URL+"/openapi.json", tmpDir, nil)
148
if err == nil {
149
t.Error("Expected error for HTTP 404, but got none")
150
}
151
}
152
153
func TestOpenAPIDownloader_Download_InvalidJSON(t *testing.T) {
154
// Create mock server that returns invalid JSON
155
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
156
w.Header().Set("Content-Type", "application/json")
157
if _, err := w.Write([]byte("invalid json")); err != nil {
158
http.Error(w, "failed to write response", http.StatusInternalServerError)
159
}
160
}))
161
defer server.Close()
162
163
tmpDir, err := os.MkdirTemp("", "openapi_test")
164
if err != nil {
165
t.Fatalf("Failed to create temp dir: %v", err)
166
}
167
168
defer func() {
169
if err := os.RemoveAll(tmpDir); err != nil {
170
t.Fatalf("Failed to remove temp dir: %v", err)
171
}
172
}()
173
174
downloader := &OpenAPIDownloader{}
175
_, err = downloader.Download(server.URL+"/openapi.json", tmpDir, nil)
176
if err == nil {
177
t.Error("Expected error for invalid JSON, but got none")
178
}
179
}
180
181
func TestOpenAPIDownloader_Download_Timeout(t *testing.T) {
182
// Create mock server with delay
183
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
184
time.Sleep(35 * time.Second) // Longer than 30 second timeout
185
if err := json.NewEncoder(w).Encode(map[string]interface{}{"test": "data"}); err != nil {
186
http.Error(w, "failed to encode response", http.StatusInternalServerError)
187
}
188
}))
189
defer server.Close()
190
191
tmpDir, err := os.MkdirTemp("", "openapi_test")
192
if err != nil {
193
t.Fatalf("Failed to create temp dir: %v", err)
194
}
195
196
defer func() {
197
if err := os.RemoveAll(tmpDir); err != nil {
198
t.Fatalf("Failed to remove temp dir: %v", err)
199
}
200
}()
201
202
downloader := &OpenAPIDownloader{}
203
_, err = downloader.Download(server.URL+"/openapi.json", tmpDir, nil)
204
if err == nil {
205
t.Error("Expected timeout error, but got none")
206
}
207
}
208
209
func TestOpenAPIDownloader_Download_WithExistingServers(t *testing.T) {
210
// Create a mock OpenAPI spec with existing servers
211
mockSpec := map[string]interface{}{
212
"openapi": "3.0.0",
213
"info": map[string]interface{}{
214
"title": "Test API",
215
"version": "1.0.0",
216
},
217
"servers": []interface{}{
218
map[string]interface{}{
219
"url": "https://existing-server.com",
220
},
221
},
222
"paths": map[string]interface{}{},
223
}
224
225
// Create mock server
226
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
227
w.Header().Set("Content-Type", "application/json")
228
if err := json.NewEncoder(w).Encode(mockSpec); err != nil {
229
http.Error(w, "failed to encode response", http.StatusInternalServerError)
230
}
231
}))
232
defer server.Close()
233
234
tmpDir, err := os.MkdirTemp("", "openapi_test")
235
if err != nil {
236
t.Fatalf("Failed to create temp dir: %v", err)
237
}
238
239
defer func() {
240
if err := os.RemoveAll(tmpDir); err != nil {
241
t.Fatalf("Failed to remove temp dir: %v", err)
242
}
243
}()
244
245
downloader := &OpenAPIDownloader{}
246
filePath, err := downloader.Download(server.URL+"/openapi.json", tmpDir, nil)
247
if err != nil {
248
t.Fatalf("Download failed: %v", err)
249
}
250
251
// Verify existing servers are preserved
252
content, err := os.ReadFile(filePath)
253
if err != nil {
254
t.Fatalf("Failed to read downloaded file: %v", err)
255
}
256
257
var downloadedSpec map[string]interface{}
258
if err := json.Unmarshal(content, &downloadedSpec); err != nil {
259
t.Fatalf("Failed to parse downloaded JSON: %v", err)
260
}
261
262
servers, exists := downloadedSpec["servers"]
263
if !exists {
264
t.Error("Servers field was removed from the spec")
265
}
266
267
if serversList, ok := servers.([]interface{}); ok {
268
if len(serversList) != 1 {
269
t.Errorf("Expected 1 server, got %d", len(serversList))
270
}
271
}
272
}
273
274
// Helper function to check if file exists
275
func fileExists(filename string) bool {
276
_, err := os.Stat(filename)
277
return !os.IsNotExist(err)
278
}
279
280