@@ -18,6 +18,7 @@ package ffapi
1818
1919import (
2020 "context"
21+ "encoding/json"
2122 "fmt"
2223 "io"
2324 "net/http"
@@ -112,6 +113,29 @@ var utAPIRoute2 = &Route{
112113 },
113114}
114115
116+ type testInputStruct struct {
117+ Input1 string `json:"input1,omitempty"`
118+ }
119+
120+ var utAPIRoute3 = & Route {
121+ Name : "utAPIRoute3" ,
122+ Path : "ut/utresource/{resourceid}/postbatch" ,
123+ Method : http .MethodPost ,
124+ Description : "post an array to check arrays go through ok" ,
125+ JSONInputDecoder : func (req * http.Request , body io.Reader ) (interface {}, error ) {
126+ var arrayInput []* testInputStruct
127+ err := json .NewDecoder (body ).Decode (& arrayInput )
128+ return arrayInput , err
129+ },
130+ JSONInputValue : func () interface {} { return []* testInputStruct {} },
131+ JSONOutputValue : func () interface {} { return []* testInputStruct {} },
132+ Extensions : & APIServerRouteExt [* utManager ]{
133+ JSONHandler : func (a * APIRequest , um * utManager ) (output interface {}, err error ) {
134+ return a .Input .([]* testInputStruct ), nil
135+ },
136+ },
137+ }
138+
115139func initUTConfig () (config.Section , config.Section , config.Section ) {
116140 config .RootConfigReset ()
117141 apiConfig := config .RootSection ("ut.api" )
@@ -129,7 +153,7 @@ func newTestAPIServer(t *testing.T, start bool) (*utManager, *apiServer[*utManag
129153 um := & utManager {t : t }
130154 as := NewAPIServer (ctx , APIServerOptions [* utManager ]{
131155 MetricsRegistry : metric .NewPrometheusMetricsRegistry ("ut" ),
132- Routes : []* Route {utAPIRoute1 , utAPIRoute2 },
156+ Routes : []* Route {utAPIRoute1 , utAPIRoute2 , utAPIRoute3 },
133157 EnrichRequest : func (r * APIRequest ) (* utManager , error ) {
134158 // This could be some dynamic object based on extra processing in the request,
135159 // but the most common case is you just have a "manager" that you inject into each
@@ -176,6 +200,50 @@ func TestAPIServerInvokeAPIRouteStream(t *testing.T) {
176200 assert .Equal (t , "a stream!" , string (res .Body ()))
177201}
178202
203+ func TestAPIServerInvokeAPIPostEmptyArray (t * testing.T ) {
204+ _ , as , done := newTestAPIServer (t , true )
205+ defer done ()
206+
207+ <- as .Started ()
208+
209+ var o []* testInputStruct
210+ res , err := resty .New ().R ().
211+ SetBody ([]* testInputStruct {}).
212+ SetResult (& o ).
213+ Post (fmt .Sprintf ("%s/api/v1/ut/utresource/id12345/postbatch" , as .APIPublicURL ()))
214+ assert .NoError (t , err )
215+ assert .Equal (t , 200 , res .StatusCode ())
216+ assert .Equal (t , []* testInputStruct {}, o )
217+
218+ res , err = resty .New ().R ().
219+ SetBody ([]* testInputStruct {{Input1 : "in1" }}).
220+ SetResult (& o ).
221+ Post (fmt .Sprintf ("%s/api/v1/ut/utresource/id12345/postbatch" , as .APIPublicURL ()))
222+ assert .NoError (t , err )
223+ assert .Equal (t , 200 , res .StatusCode ())
224+ assert .Equal (t , []* testInputStruct {{Input1 : "in1" }}, o )
225+ }
226+
227+ func TestAPIServerInvokeAPIRouteLiveness (t * testing.T ) {
228+ _ , as , done := newTestAPIServer (t , true )
229+ defer done ()
230+
231+ <- as .Started ()
232+
233+ res , err := resty .New ().R ().Get (fmt .Sprintf ("%s/livez" , as .MonitoringPublicURL ()))
234+ assert .NoError (t , err )
235+ assert .Equal (t , 204 , res .StatusCode ())
236+ }
237+
238+ func TestAPIServerPanicsMisConfig (t * testing.T ) {
239+ assert .Panics (t , func () {
240+ _ = NewAPIServer (context .Background (), APIServerOptions [any ]{})
241+ })
242+ assert .Panics (t , func () {
243+ _ = NewAPIServer (context .Background (), APIServerOptions [any ]{APIConfig : config .RootSection ("any" )})
244+ })
245+ }
246+
179247func TestAPIServerInvokeAPIRouteJSON (t * testing.T ) {
180248 um , as , done := newTestAPIServer (t , true )
181249 defer done ()
@@ -342,6 +410,19 @@ func TestAPIServerInvokeEnrichFailForm(t *testing.T) {
342410 assert .Equal (t , 500 , res .StatusCode ())
343411}
344412
413+ func TestAPIServerInvokeEnrichFailStream (t * testing.T ) {
414+ um , as , done := newTestAPIServer (t , true )
415+ defer done ()
416+
417+ um .mockEnrichErr = fmt .Errorf ("pop" )
418+ <- as .Started ()
419+
420+ res , err := resty .New ().R ().
421+ Get (fmt .Sprintf ("%s/api/v1/ut/utresource/id12345/getit" , as .APIPublicURL ()))
422+ assert .NoError (t , err )
423+ assert .Equal (t , 500 , res .StatusCode ())
424+ }
425+
345426func TestAPIServer404 (t * testing.T ) {
346427 _ , as , done := newTestAPIServer (t , true )
347428 defer done ()
@@ -397,6 +478,45 @@ func TestAPIServerFailServeMonitoring(t *testing.T) {
397478
398479}
399480
481+ func TestAPIServerFailServeMonitoringBadRouteSlash (t * testing.T ) {
482+ _ , as , done := newTestAPIServer (t , false )
483+ defer done ()
484+
485+ as .MonitoringConfig .Set (httpserver .HTTPConfAddress , "127.0.0.1:0" )
486+ as .MonitoringRoutes = []* Route {
487+ {Path : "right" , Extensions : & APIServerRouteExt [* utManager ]{}},
488+ {Path : "/wrong" },
489+ }
490+ err := as .Serve (context .Background ())
491+ assert .Regexp (t , "FF00255" , err )
492+
493+ // Check we still closed the started channel
494+ <- as .Started ()
495+
496+ }
497+
498+ func TestAPIServerFailServeBadRouteSlash (t * testing.T ) {
499+ _ , as , done := newTestAPIServer (t , false )
500+ defer done ()
501+
502+ as .Routes = []* Route {
503+ {
504+ Path : "/wrong" ,
505+ Extensions : & APIServerRouteExt [* utManager ]{
506+ JSONHandler : func (a * APIRequest , um * utManager ) (output interface {}, err error ) {
507+ return nil , nil
508+ },
509+ },
510+ },
511+ }
512+ err := as .Serve (context .Background ())
513+ assert .Regexp (t , "FF00255" , err )
514+
515+ // Check we still closed the started channel
516+ <- as .Started ()
517+
518+ }
519+
400520func TestWaitForServerStop (t * testing.T ) {
401521 _ , as , done := newTestAPIServer (t , false )
402522 defer done ()
@@ -611,6 +731,7 @@ func TestVersionedAPIInitErrors(t *testing.T) {
611731 err = as .Serve (ctx )
612732 assert .Error (t , err )
613733 assert .Regexp (t , "FF00253" , err )
734+
614735 as = NewAPIServer (ctx , APIServerOptions [* utManager ]{
615736 MetricsRegistry : metric .NewPrometheusMetricsRegistry ("ut" ),
616737 VersionedAPIs : & VersionedAPIs {
@@ -633,4 +754,32 @@ func TestVersionedAPIInitErrors(t *testing.T) {
633754 assert .Error (t , err )
634755 assert .Regexp (t , "FF00254" , err )
635756
757+ as = NewAPIServer (ctx , APIServerOptions [* utManager ]{
758+ MetricsRegistry : metric .NewPrometheusMetricsRegistry ("ut" ),
759+ VersionedAPIs : & VersionedAPIs {
760+ DefaultVersion : "unknown" ,
761+ APIVersions : map [string ]* APIVersion {
762+ "v1" : {
763+ Routes : []* Route {
764+ {
765+ Path : "/wrong" ,
766+ Extensions : & APIServerRouteExt [* utManager ]{
767+ JSONHandler : func (r * APIRequest , um * utManager ) (output interface {}, err error ) {
768+ return nil , nil
769+ },
770+ },
771+ },
772+ },
773+ },
774+ },
775+ },
776+ Description : "unit testing" ,
777+ APIConfig : apiConfig ,
778+ MonitoringConfig : monitoringConfig ,
779+ })
780+
781+ err = as .Serve (ctx )
782+ assert .Error (t , err )
783+ assert .Regexp (t , "FF00255" , err )
784+
636785}
0 commit comments