mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
503 lines
12 KiB
Go
503 lines
12 KiB
Go
package tests
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"reflect"
|
|
|
|
"github.com/fnproject/fn/api/id"
|
|
"github.com/fnproject/fn_go/client/apps"
|
|
"github.com/fnproject/fn_go/client/routes"
|
|
"github.com/fnproject/fn_go/models"
|
|
)
|
|
|
|
func TestShouldRejectEmptyRouteType(t *testing.T) {
|
|
t.Parallel()
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
|
|
s.GivenAppExists(t, &models.App{Name: s.AppName})
|
|
|
|
_, err := s.PostRoute(s.AppName, &models.Route{
|
|
Path: s.RoutePath,
|
|
Image: s.Image,
|
|
Type: "v",
|
|
Format: s.Format,
|
|
})
|
|
|
|
if err == nil {
|
|
t.Errorf("Should fail with Invalid route Type.")
|
|
}
|
|
}
|
|
|
|
func TestCanCreateRoute(t *testing.T) {
|
|
t.Parallel()
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
|
|
s.GivenAppExists(t, &models.App{Name: s.AppName})
|
|
_, err := s.PostRoute(s.AppName, &models.Route{
|
|
Path: s.RoutePath,
|
|
Image: s.Image,
|
|
Format: s.Format,
|
|
})
|
|
|
|
if err != nil {
|
|
t.Errorf("expected route success, got %v", err)
|
|
}
|
|
// TODO validate route returned matches request
|
|
}
|
|
|
|
func TestListRoutes(t *testing.T) {
|
|
t.Parallel()
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
|
|
s.GivenAppExists(t, &models.App{Name: s.AppName})
|
|
s.GivenRouteExists(t, s.AppName, s.BasicRoute())
|
|
|
|
cfg := &routes.GetAppsAppRoutesParams{
|
|
App: s.AppName,
|
|
Context: s.Context,
|
|
}
|
|
|
|
routesResponse, err := s.Client.Routes.GetAppsAppRoutes(cfg)
|
|
|
|
if err != nil {
|
|
t.Fatalf("Expecting list routes to be successful, got %v", err)
|
|
}
|
|
if !assertContainsRoute(routesResponse.Payload.Routes, s.RoutePath) {
|
|
t.Errorf("Unable to find corresponding route `%v` in list", s.RoutePath)
|
|
}
|
|
}
|
|
|
|
func TestInspectRoute(t *testing.T) {
|
|
t.Parallel()
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
|
|
s.GivenAppExists(t, &models.App{Name: s.AppName})
|
|
newRt := s.BasicRoute()
|
|
s.GivenRouteExists(t, s.AppName, newRt)
|
|
|
|
resp, err := s.Client.Routes.GetAppsAppRoutesRoute(&routes.GetAppsAppRoutesRouteParams{
|
|
App: s.AppName,
|
|
Route: newRt.Path[1:],
|
|
Context: s.Context,
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("Failed to get route %s, %v", s.RoutePath, err)
|
|
}
|
|
|
|
gotRt := resp.Payload.Route
|
|
|
|
AssertRouteMatches(t, newRt, gotRt)
|
|
|
|
}
|
|
|
|
var validRouteUpdates = []struct {
|
|
name string
|
|
update *models.Route
|
|
extract func(*models.Route) interface{}
|
|
}{
|
|
{"route type (sync)", &models.Route{Type: "sync"}, func(m *models.Route) interface{} { return m.Type }},
|
|
{"route type (async)", &models.Route{Type: "async"}, func(m *models.Route) interface{} { return m.Type }},
|
|
{"format (json)", &models.Route{Format: "json"}, func(m *models.Route) interface{} { return m.Format }},
|
|
{"format (default)", &models.Route{Format: "default"}, func(m *models.Route) interface{} { return m.Format }},
|
|
// ...
|
|
}
|
|
|
|
func TestCanUpdateRouteAttributes(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
for _, tci := range validRouteUpdates {
|
|
tc := tci
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
|
|
s.GivenAppExists(t, &models.App{Name: s.AppName})
|
|
s.GivenRouteExists(t, s.AppName, s.BasicRoute())
|
|
|
|
routeResp, err := s.Client.Routes.PatchAppsAppRoutesRoute(
|
|
&routes.PatchAppsAppRoutesRouteParams{
|
|
App: s.AppName,
|
|
Context: s.Context,
|
|
Route: s.RoutePath,
|
|
Body: &models.RouteWrapper{
|
|
Route: tc.update,
|
|
},
|
|
},
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("Failed to patch route, got %v", err)
|
|
}
|
|
|
|
got := tc.extract(routeResp.Payload.Route)
|
|
change := tc.extract(tc.update)
|
|
if !reflect.DeepEqual(got, change) {
|
|
t.Errorf("Expected value in response tobe %v but was %v", change, got)
|
|
}
|
|
})
|
|
}
|
|
|
|
}
|
|
|
|
func TestRoutePatchConfig(t *testing.T) {
|
|
t.Parallel()
|
|
for _, tci := range updateConfigCases {
|
|
tc := tci
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
s.GivenAppExists(t, &models.App{Name: s.AppName})
|
|
route := s.BasicRoute()
|
|
route.Config = tc.intialConfig
|
|
|
|
s.GivenRouteExists(t, s.AppName, route)
|
|
|
|
routeResp, err := s.Client.Routes.PatchAppsAppRoutesRoute(
|
|
&routes.PatchAppsAppRoutesRouteParams{
|
|
App: s.AppName,
|
|
Route: s.RoutePath,
|
|
Body: &models.RouteWrapper{
|
|
Route: &models.Route{
|
|
Config: tc.change,
|
|
},
|
|
},
|
|
Context: s.Context,
|
|
},
|
|
)
|
|
|
|
if err != nil {
|
|
t.Fatalf("Failed to patch route, got %v", err)
|
|
}
|
|
actual := routeResp.Payload.Route.Config
|
|
if !ConfigEquivalent(actual, tc.expected) {
|
|
t.Errorf("Expected config : %v after update, got %v", tc.expected, actual)
|
|
}
|
|
|
|
})
|
|
}
|
|
|
|
}
|
|
|
|
func TestSetRouteAnnotationsOnCreate(t *testing.T) {
|
|
t.Parallel()
|
|
for _, tci := range createAnnotationsValidCases {
|
|
// iterator mutation meets parallelism... pfft
|
|
tc := tci
|
|
t.Run("valid_"+tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
|
|
s.GivenAppExists(t, &models.App{
|
|
Name: s.AppName,
|
|
})
|
|
rt := s.BasicRoute()
|
|
rt.Annotations = tc.annotations
|
|
|
|
route, err := s.Client.Routes.PostAppsAppRoutes(&routes.PostAppsAppRoutesParams{
|
|
App: s.AppName,
|
|
Context: s.Context,
|
|
Body: &models.RouteWrapper{
|
|
Route: rt,
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("Failed to create route with valid annotations %v got error %v", tc.annotations, err)
|
|
}
|
|
|
|
gotMd := route.Payload.Route.Annotations
|
|
if !AnnotationsEquivalent(gotMd, tc.annotations) {
|
|
t.Errorf("Returned annotations %v does not match set annotations %v", gotMd, tc.annotations)
|
|
}
|
|
|
|
getRoute := s.RouteMustExist(t, s.AppName, s.RoutePath)
|
|
|
|
if !AnnotationsEquivalent(getRoute.Annotations, tc.annotations) {
|
|
t.Errorf("GET annotations '%v' does not match set annotations %v", getRoute.Annotations, tc.annotations)
|
|
}
|
|
|
|
})
|
|
}
|
|
|
|
for _, tci := range createAnnotationsErrorCases {
|
|
// iterator mutation meets parallelism... pfft
|
|
tc := tci
|
|
t.Run("invalid_"+tc.name, func(ti *testing.T) {
|
|
ti.Parallel()
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
|
|
_, err := s.PostApp(&models.App{
|
|
Name: s.AppName,
|
|
Annotations: tc.annotations,
|
|
})
|
|
|
|
if err == nil {
|
|
t.Fatalf("Created app with invalid annotations %v but expected error", tc.annotations)
|
|
}
|
|
|
|
if _, ok := err.(*apps.PostAppsBadRequest); !ok {
|
|
t.Errorf("Expecting bad request for invalid annotations, got %v", err)
|
|
}
|
|
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSetRouteMetadataOnPatch(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
for _, tci := range updateAnnotationsValidCases {
|
|
// iterator mutation meets parallelism... pfft
|
|
tc := tci
|
|
t.Run("valid_"+tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
|
|
s.GivenAppExists(t, &models.App{Name: s.AppName})
|
|
rt := s.BasicRoute()
|
|
rt.Annotations = tc.initial
|
|
s.GivenRouteExists(t, s.AppName, rt)
|
|
|
|
res, err := s.Client.Routes.PatchAppsAppRoutesRoute(&routes.PatchAppsAppRoutesRouteParams{
|
|
App: s.AppName,
|
|
Route: s.RoutePath[1:],
|
|
Context: s.Context,
|
|
Body: &models.RouteWrapper{
|
|
Route: &models.Route{
|
|
Annotations: tc.change,
|
|
},
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("Failed to patch annotations with %v on route: %v", tc.change, err)
|
|
}
|
|
|
|
gotMd := res.Payload.Route.Annotations
|
|
if !AnnotationsEquivalent(gotMd, tc.expected) {
|
|
t.Errorf("Returned annotations %v does not match set annotations %v", gotMd, tc.expected)
|
|
}
|
|
|
|
getRoute := s.RouteMustExist(t, s.AppName, s.RoutePath)
|
|
|
|
if !AnnotationsEquivalent(getRoute.Annotations, tc.expected) {
|
|
t.Errorf("GET annotations '%v' does not match set annotations %v", getRoute.Annotations, tc.expected)
|
|
}
|
|
})
|
|
}
|
|
|
|
for _, tci := range updateAnnotationsErrorCases {
|
|
// iterator mutation meets parallelism... pfft
|
|
tc := tci
|
|
t.Run("invalid_"+tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
|
|
s.GivenAppExists(t, &models.App{
|
|
Name: s.AppName,
|
|
})
|
|
rt := s.BasicRoute()
|
|
rt.Annotations = tc.initial
|
|
s.GivenRouteExists(t, s.AppName, rt)
|
|
|
|
_, err := s.Client.Routes.PatchAppsAppRoutesRoute(&routes.PatchAppsAppRoutesRouteParams{
|
|
App: s.AppName,
|
|
Route: s.RoutePath[1:],
|
|
Context: s.Context,
|
|
Body: &models.RouteWrapper{
|
|
Route: &models.Route{
|
|
Annotations: tc.change,
|
|
},
|
|
},
|
|
})
|
|
|
|
if err == nil {
|
|
t.Errorf("patched route with invalid annotations %v but expected error", tc.change)
|
|
}
|
|
if _, ok := err.(*routes.PatchAppsAppRoutesRouteBadRequest); !ok {
|
|
t.Errorf("Expecting bad request for invalid annotations, got %v", err)
|
|
}
|
|
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCantUpdateRoutePath(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
|
|
s.GivenAppExists(t, &models.App{Name: s.AppName})
|
|
s.GivenRouteExists(t, s.AppName, s.BasicRoute())
|
|
|
|
_, err := s.Client.Routes.PatchAppsAppRoutesRoute(
|
|
&routes.PatchAppsAppRoutesRouteParams{
|
|
App: s.AppName,
|
|
Route: s.RoutePath,
|
|
Body: &models.RouteWrapper{
|
|
Route: &models.Route{
|
|
Path: id.New().String(),
|
|
},
|
|
},
|
|
})
|
|
if err == nil {
|
|
t.Fatalf("Expected error when patching route")
|
|
}
|
|
if _, ok := err.(*routes.PatchAppsAppRoutesRouteBadRequest); ok {
|
|
t.Errorf("Error should be bad request when updating route path ")
|
|
}
|
|
|
|
}
|
|
|
|
func TestRoutePreventsDuplicate(t *testing.T) {
|
|
t.Parallel()
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
|
|
s.GivenAppExists(t, &models.App{Name: s.AppName})
|
|
s.GivenRouteExists(t, s.AppName, s.BasicRoute())
|
|
|
|
_, err := s.PostRoute(s.AppName, s.BasicRoute())
|
|
|
|
if err == nil {
|
|
t.Errorf("Route duplicate error should appear, but it didn't")
|
|
}
|
|
if _, ok := err.(*routes.PostAppsAppRoutesConflict); !ok {
|
|
t.Errorf("Error should be a conflict when creating a new route, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestCanDeleteRoute(t *testing.T) {
|
|
t.Parallel()
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
|
|
s.GivenAppExists(t, &models.App{Name: s.AppName})
|
|
s.GivenRouteExists(t, s.AppName, s.BasicRoute())
|
|
|
|
_, err := s.Client.Routes.DeleteAppsAppRoutesRoute(&routes.DeleteAppsAppRoutesRouteParams{
|
|
App: s.AppName,
|
|
Route: s.RoutePath,
|
|
Context: s.Context,
|
|
})
|
|
|
|
if err != nil {
|
|
t.Errorf("Expected success when deleting existing route, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestCantDeleteMissingRoute(t *testing.T) {
|
|
t.Parallel()
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
|
|
s.GivenAppExists(t, &models.App{Name: s.AppName})
|
|
|
|
_, err := s.Client.Routes.DeleteAppsAppRoutesRoute(&routes.DeleteAppsAppRoutesRouteParams{
|
|
App: s.AppName,
|
|
Route: s.RoutePath,
|
|
Context: s.Context,
|
|
})
|
|
|
|
if err == nil {
|
|
t.Fatalf("Expected error when deleting non-existing route, got none")
|
|
}
|
|
|
|
if _, ok := err.(*routes.DeleteAppsAppRoutesRouteNotFound); !ok {
|
|
t.Fatalf("Expected not-found when deleting non-existing route, got %v", err)
|
|
|
|
}
|
|
}
|
|
|
|
func TestPutRouteCreatesNewApp(t *testing.T) {
|
|
t.Parallel()
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
|
|
_, err := s.PutRoute(s.AppName, s.RoutePath, s.BasicRoute())
|
|
|
|
if err != nil {
|
|
t.Fatalf("Expected new route to be created, got %v", err)
|
|
}
|
|
|
|
s.AppMustExist(t, s.AppName)
|
|
s.RouteMustExist(t, s.AppName, s.RoutePath)
|
|
|
|
}
|
|
|
|
func TestPutRouteToExistingApp(t *testing.T) {
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
|
|
s.GivenAppExists(t, &models.App{Name: s.AppName})
|
|
_, err := s.PutRoute(s.AppName, s.RoutePath, s.BasicRoute())
|
|
if err != nil {
|
|
t.Fatalf("Failed to create route, got error %v", err)
|
|
}
|
|
s.AppMustExist(t, s.AppName)
|
|
s.RouteMustExist(t, s.AppName, s.RoutePath)
|
|
}
|
|
|
|
func TestPutRouteUpdatesRoute(t *testing.T) {
|
|
newRouteType := "sync"
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
|
|
s.GivenAppExists(t, &models.App{Name: s.AppName})
|
|
s.GivenRouteExists(t, s.AppName, s.BasicRoute())
|
|
|
|
changed := s.BasicRoute()
|
|
changed.Type = newRouteType
|
|
|
|
updatedRoute, err := s.PutRoute(s.AppName, s.RoutePath, changed)
|
|
|
|
if err != nil {
|
|
t.Fatalf("Failed to update route, got %v", err)
|
|
}
|
|
got := updatedRoute.Payload.Route.Type
|
|
if got != newRouteType {
|
|
t.Errorf("expected type to be %v after update, got %v", newRouteType, got)
|
|
}
|
|
}
|
|
|
|
func TestPutIsIdempotentForHeaders(t *testing.T) {
|
|
s := SetupHarness()
|
|
defer s.Cleanup()
|
|
|
|
s.GivenAppExists(t, &models.App{Name: s.AppName})
|
|
|
|
routeHeaders := map[string][]string{}
|
|
routeHeaders["A"] = []string{"a"}
|
|
routeHeaders["B"] = []string{"b"}
|
|
|
|
r1 := s.BasicRoute()
|
|
r1.Headers = routeHeaders
|
|
|
|
updatedRoute1, err := s.PutRoute(s.AppName, s.RoutePath, r1)
|
|
|
|
if err != nil {
|
|
t.Fatalf("Failed to update route, got %v", err)
|
|
}
|
|
if firstMatches := reflect.DeepEqual(routeHeaders, updatedRoute1.Payload.Route.Headers); !firstMatches {
|
|
t.Errorf("Route headers should remain the same after multiple deploys with exact the same parameters '%v' != '%v'", routeHeaders, updatedRoute1.Payload.Route.Headers)
|
|
}
|
|
|
|
updatedRoute2, err := s.PutRoute(s.AppName, s.RoutePath, r1)
|
|
|
|
if bothmatch := reflect.DeepEqual(updatedRoute1.Payload.Route.Headers, updatedRoute2.Payload.Route.Headers); !bothmatch {
|
|
t.Error("Route headers should remain the same after multiple deploys with exact the same parameters")
|
|
}
|
|
}
|