forked from GoCodeAlone/modular
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbdd_tls_ssl_test.go
More file actions
278 lines (230 loc) · 12.4 KB
/
bdd_tls_ssl_test.go
File metadata and controls
278 lines (230 loc) · 12.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
package httpserver
import (
"fmt"
"testing"
"time"
"github.com/cucumber/godog"
)
// TLS/SSL configuration step implementations
func (ctx *HTTPServerBDDTestContext) iHaveAnHTTPSServerConfigurationWithTLSEnabled() error {
ctx.resetContext()
// Create HTTPS server configuration
ctx.serverConfig = &HTTPServerConfig{
Host: "127.0.0.1",
Port: 8443, // Fixed HTTPS port for testing
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 30 * time.Second,
TLS: &TLSConfig{
Enabled: true,
AutoGenerate: true,
Domains: []string{"localhost"},
},
}
ctx.isHTTPS = true
return ctx.setupApplicationWithConfig()
}
func (ctx *HTTPServerBDDTestContext) theHTTPSServerIsStarted() error {
return ctx.theHTTPServerIsStarted()
}
func (ctx *HTTPServerBDDTestContext) theServerShouldListenOnTheConfiguredTLSPort() error {
return ctx.theServerShouldListenOnTheConfiguredAddress()
}
func (ctx *HTTPServerBDDTestContext) theServerShouldAcceptHTTPSRequests() error {
if ctx.service == nil || ctx.service.server == nil {
return fmt.Errorf("server not configured")
}
if !ctx.isHTTPS {
return fmt.Errorf("server not configured for HTTPS")
}
// Verify TLS configuration is properly applied
if ctx.service.config == nil || ctx.service.config.TLS == nil {
return fmt.Errorf("TLS configuration not available")
}
if !ctx.service.config.TLS.Enabled {
return fmt.Errorf("TLS not enabled in server configuration")
}
// Verify server address and handler are configured for HTTPS
if ctx.service.server.Addr == "" {
return fmt.Errorf("HTTPS server has no address configured")
}
if ctx.service.server.Handler == nil {
return fmt.Errorf("HTTPS server has no handler configured")
}
// For HTTPS, verify that either auto-generate is enabled, UseService is enabled, or cert files are specified
if !ctx.service.config.TLS.AutoGenerate && !ctx.service.config.TLS.UseService &&
(ctx.service.config.TLS.CertFile == "" || ctx.service.config.TLS.KeyFile == "") {
return fmt.Errorf("TLS enabled but no certificate method configured (auto-generate, service, or cert files)")
}
// If auto-generate is enabled, verify domains are configured
if ctx.service.config.TLS.AutoGenerate && len(ctx.service.config.TLS.Domains) == 0 {
// This is acceptable - the implementation defaults to localhost
// Configuration allows for this fallback behavior
_ = ctx.service.config.TLS.Domains // Empty domains array is acceptable for auto-generation
}
return nil
}
func (ctx *HTTPServerBDDTestContext) iHaveATLSConfigurationWithoutCertificateFiles() error {
// Debug: print that this method is being called
ctx.resetContext()
ctx.serverConfig = &HTTPServerConfig{
Host: "127.0.0.1",
Port: 8444, // Fixed port for TLS testing
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 30 * time.Second,
TLS: &TLSConfig{
Enabled: true,
AutoGenerate: true,
CertFile: "", // No cert file
KeyFile: "", // No key file
Domains: []string{"localhost"},
},
}
ctx.isHTTPS = true
err := ctx.setupApplicationWithConfig()
// Debug: test config integrity after setup
_ = ctx.serverConfig.TLS // TLS config available after setup
return err
}
func (ctx *HTTPServerBDDTestContext) theHTTPSServerIsStartedWithAutoGeneration() error {
// Debug: TLS config available before server start
_ = ctx.serverConfig.TLS // TLS config check before server start
if false { // Unreachable code to maintain structure
}
return ctx.theHTTPServerIsStarted()
}
func (ctx *HTTPServerBDDTestContext) theServerShouldGenerateSelfSignedCertificates() error {
if ctx.service == nil {
return fmt.Errorf("server service not available")
}
// Debug: print the test config to see what was set up
if ctx.serverConfig.TLS == nil {
return fmt.Errorf("debug: test config TLS is nil")
}
// Debug: Let's check what config section we can get from the app
configSection, err := ctx.app.GetConfigSection("httpserver")
if err != nil {
return fmt.Errorf("debug: cannot get config section: %v", err)
}
actualConfig := configSection.GetConfig().(*HTTPServerConfig)
if actualConfig.TLS == nil {
return fmt.Errorf("debug: actual config TLS is nil (test config TLS.Enabled=%v, TLS.AutoGenerate=%v)",
ctx.serverConfig.TLS.Enabled, ctx.serverConfig.TLS.AutoGenerate)
}
if !actualConfig.TLS.AutoGenerate {
return fmt.Errorf("auto-TLS not enabled: AutoGenerate is %v", actualConfig.TLS.AutoGenerate)
}
return nil
}
func (ctx *HTTPServerBDDTestContext) theServerShouldUseTheGeneratedCertificates() error {
if ctx.service == nil || ctx.service.server == nil {
return fmt.Errorf("server not configured")
}
if !ctx.isHTTPS {
return fmt.Errorf("server not configured for HTTPS")
}
// Verify TLS configuration supports certificate generation
if ctx.service.config == nil || ctx.service.config.TLS == nil {
return fmt.Errorf("TLS configuration not available for certificate validation")
}
if !ctx.service.config.TLS.AutoGenerate {
return fmt.Errorf("auto-generate not enabled, certificates should not be auto-generated")
}
// Verify certificate files are not required when auto-generate is enabled
if ctx.service.config.TLS.CertFile != "" || ctx.service.config.TLS.KeyFile != "" {
return fmt.Errorf("certificate files specified, auto-generation may not be used")
}
// Verify the server is configured properly for auto-generated certificates
// The actual TLS setup happens asynchronously in the Start() method
// We validate that the configuration is correct for certificate generation
// Check if domains are configured, but allow empty (defaults to localhost in implementation)
if ctx.service.config.TLS.Domains == nil {
// Nil domains slice is acceptable, will default to localhost
_ = ctx.service.config.TLS.Domains // Nil domains acceptable for auto-generation
}
// Verify server configuration is compatible with certificate generation
if ctx.service.server.Addr == "" {
return fmt.Errorf("server has no address configured for certificate generation")
}
// The actual TLSConfig is set asynchronously in the server Start goroutine
// For BDD validation, we confirm the configuration is set up correctly
// to allow certificate generation to occur
return nil
}
// TestHTTPServerModuleTLS runs the TLS/SSL BDD tests for the HTTP server module
func TestHTTPServerModuleTLS(t *testing.T) {
suite := godog.TestSuite{
ScenarioInitializer: func(ctx *godog.ScenarioContext) {
testCtx := &HTTPServerBDDTestContext{}
// Use common scenario setup to reduce duplication
setupCommonBDDScenarios(ctx, testCtx)
// TLS/SSL specific steps
ctx.Given(`^I have an HTTPS server configuration with TLS enabled$`, testCtx.iHaveAnHTTPSServerConfigurationWithTLSEnabled)
ctx.When(`^the HTTPS server is started$`, testCtx.theHTTPSServerIsStarted)
ctx.Then(`^the server should listen on the configured TLS port$`, testCtx.theServerShouldListenOnTheConfiguredTLSPort)
ctx.Then(`^the server should accept HTTPS requests$`, testCtx.theServerShouldAcceptHTTPSRequests)
// Steps for TLS auto-generation
ctx.Given(`^I have a TLS configuration without certificate files$`, testCtx.iHaveATLSConfigurationWithoutCertificateFiles)
ctx.When(`^the HTTPS server is started with auto-generation$`, testCtx.theHTTPSServerIsStartedWithAutoGeneration)
ctx.Then(`^the server should generate self-signed certificates$`, testCtx.theServerShouldGenerateSelfSignedCertificates)
ctx.Then(`^the server should use the generated certificates$`, testCtx.theServerShouldUseTheGeneratedCertificates)
// Additional steps needed for full coverage
ctx.Given(`^I have an HTTP server with custom timeout settings$`, testCtx.iHaveAnHTTPServerWithCustomTimeoutSettings)
ctx.Given(`^I have a running HTTP server$`, testCtx.iHaveARunningHTTPServer)
ctx.Given(`^I have an HTTP server running$`, testCtx.iHaveAnHTTPServerRunning)
ctx.Given(`^I have an HTTP server with health checks enabled$`, testCtx.iHaveAnHTTPServerWithHealthChecksEnabled)
ctx.Given(`^I have an HTTP server service available$`, testCtx.iHaveAnHTTPServerServiceAvailable)
ctx.Given(`^I have an HTTP server with middleware configured$`, testCtx.iHaveAnHTTPServerWithMiddlewareConfigured)
ctx.Given(`^I have an HTTP server with monitoring enabled$`, testCtx.iHaveAnHTTPServerWithMonitoringEnabled)
ctx.Given(`^I have an httpserver with event observation enabled$`, testCtx.iHaveAnHTTPServerWithEventObservationEnabled)
ctx.Given(`^I have an httpserver with TLS and event observation enabled$`, testCtx.iHaveAnHTTPServerWithTLSAndEventObservationEnabled)
// Additional When steps
ctx.When(`^the server processes requests$`, testCtx.theServerProcessesRequests)
ctx.When(`^the server shutdown is initiated$`, testCtx.theServerShutdownIsInitiated)
ctx.When(`^I request the health check endpoint$`, testCtx.iRequestTheHealthCheckEndpoint)
ctx.When(`^I register custom handlers with the server$`, testCtx.iRegisterCustomHandlersWithTheServer)
ctx.When(`^requests are processed through the server$`, testCtx.requestsAreProcessedThroughTheServer)
ctx.When(`^an error occurs during request processing$`, testCtx.anErrorOccursDuringRequestProcessing)
ctx.When(`^the httpserver module starts$`, func() error { return nil })
ctx.When(`^the TLS server module starts$`, func() error { return nil })
ctx.When(`^the httpserver processes a request$`, testCtx.theHTTPServerProcessesARequest)
// Additional Then steps
ctx.Then(`^the read timeout should be respected$`, testCtx.theReadTimeoutShouldBeRespected)
ctx.Then(`^the write timeout should be respected$`, testCtx.theWriteTimeoutShouldBeRespected)
ctx.Then(`^the idle timeout should be respected$`, testCtx.theIdleTimeoutShouldBeRespected)
ctx.Then(`^the server should stop accepting new connections$`, testCtx.theServerShouldStopAcceptingNewConnections)
ctx.Then(`^existing connections should be allowed to complete$`, testCtx.existingConnectionsShouldBeAllowedToComplete)
ctx.Then(`^the shutdown should complete within the timeout$`, testCtx.theShutdownShouldCompleteWithinTheTimeout)
ctx.Then(`^the health check should return server status$`, testCtx.theHealthCheckShouldReturnServerStatus)
ctx.Then(`^the response should indicate server health$`, testCtx.theResponseShouldIndicateServerHealth)
ctx.Then(`^the handlers should be available for requests$`, testCtx.theHandlersShouldBeAvailableForRequests)
ctx.Then(`^the server should route requests to the correct handlers$`, testCtx.theServerShouldRouteRequestsToTheCorrectHandlers)
ctx.Then(`^the middleware should be applied to requests$`, testCtx.theMiddlewareShouldBeAppliedToRequests)
ctx.Then(`^the middleware chain should execute in order$`, testCtx.theMiddlewareChainShouldExecuteInOrder)
ctx.Then(`^the server should handle errors gracefully$`, testCtx.theServerShouldHandleErrorsGracefully)
ctx.Then(`^appropriate error responses should be returned$`, testCtx.appropriateErrorResponsesShouldBeReturned)
ctx.Then(`^server metrics should be collected$`, testCtx.serverMetricsShouldBeCollected)
ctx.Then(`^the metrics should include request counts and response times$`, testCtx.theMetricsShouldIncludeRequestCountsAndResponseTimes)
ctx.Then(`^a server started event should be emitted$`, testCtx.aServerStartedEventShouldBeEmitted)
ctx.Then(`^a config loaded event should be emitted$`, testCtx.aConfigLoadedEventShouldBeEmitted)
ctx.Then(`^the events should contain server configuration details$`, testCtx.theEventsShouldContainServerConfigurationDetails)
ctx.Then(`^a TLS enabled event should be emitted$`, testCtx.aTLSEnabledEventShouldBeEmitted)
ctx.Then(`^a TLS configured event should be emitted$`, testCtx.aTLSConfiguredEventShouldBeEmitted)
ctx.Then(`^the events should contain TLS configuration details$`, testCtx.theEventsShouldContainTLSConfigurationDetails)
ctx.Then(`^a request received event should be emitted$`, testCtx.aRequestReceivedEventShouldBeEmitted)
ctx.Then(`^a request handled event should be emitted$`, testCtx.aRequestHandledEventShouldBeEmitted)
ctx.Then(`^the events should contain request details$`, testCtx.theEventsShouldContainRequestDetails)
ctx.Then(`^all registered events should be emitted during testing$`, testCtx.allRegisteredEventsShouldBeEmittedDuringTesting)
},
Options: &godog.Options{
Format: "pretty",
Paths: []string{"features"},
TestingT: t,
Strict: true,
},
}
if suite.Run() != 0 {
t.Fatal("non-zero status returned, failed to run TLS feature tests")
}
}