1
0
Fork 0
mirror of https://github.com/arangodb/kube-arangodb.git synced 2024-12-15 17:51:03 +00:00
kube-arangodb/tests/load_balancer_test.go
2018-10-31 11:40:45 +01:00

226 lines
6.6 KiB
Go

//
// DISCLAIMER
//
// Copyright 2018 ArangoDB GmbH, Cologne, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
// Author Ewout Prangsma
//
package tests
import (
"context"
"reflect"
"testing"
"time"
"github.com/dchest/uniuri"
driver "github.com/arangodb/go-driver"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
"github.com/arangodb/kube-arangodb/pkg/client"
"github.com/arangodb/kube-arangodb/pkg/util"
)
func TestLoadBalancingCursorVST(t *testing.T) {
longOrSkip(t)
// run with VST
loadBalancingCursorSubtest(t, true)
}
func TestLoadBalancingCursorHTTP(t *testing.T) {
longOrSkip(t)
// run with HTTP
loadBalancingCursorSubtest(t, false)
}
func wasForwarded(r driver.Response) bool {
h := r.Header("x-arango-request-forwarded-to")
return h != ""
}
// tests cursor forwarding with load-balanced conn.
func loadBalancingCursorSubtest(t *testing.T, useVst bool) {
c := client.MustNewInCluster()
kubecli := mustNewKubeClient(t)
ns := getNamespace(t)
// Prepare deployment config
namePrefix := "test-lb-"
if useVst {
namePrefix += "vst-"
} else {
namePrefix += "http-"
}
depl := newDeployment(namePrefix + uniuri.NewLen(4))
depl.Spec.Mode = api.NewMode(api.DeploymentModeCluster)
depl.Spec.Image = util.NewString("arangodb/arangodb:3.3.13") // Note: 3.3.13 is the first version supporting the cursor forwarding feature.
// Create deployment
_, err := c.DatabaseV1alpha().ArangoDeployments(ns).Create(depl)
if err != nil {
t.Fatalf("Create deployment failed: %v", err)
}
// Prepare cleanup
defer removeDeployment(c, depl.GetName(), ns)
// Wait for deployment to be ready
apiObject, err := waitUntilDeployment(c, depl.GetName(), ns, deploymentIsReady())
if err != nil {
t.Fatalf("Deployment not running in time: %v", err)
}
// Create a database client
ctx := context.Background()
clOpts := &DatabaseClientOptions{
UseVST: useVst,
ShortTimeout: true,
}
client := mustNewArangodDatabaseClient(ctx, kubecli, apiObject, t, clOpts)
// Wait for cluster to be available
if err := waitUntilVersionUp(client, nil); err != nil {
t.Fatalf("Cluster not running returning version in time: %v", err)
}
// Create data set
collectionData := map[string][]interface{}{
"books": []interface{}{
Book{Title: "Book 01"},
Book{Title: "Book 02"},
Book{Title: "Book 03"},
Book{Title: "Book 04"},
Book{Title: "Book 05"},
Book{Title: "Book 06"},
Book{Title: "Book 07"},
Book{Title: "Book 08"},
Book{Title: "Book 09"},
Book{Title: "Book 10"},
Book{Title: "Book 11"},
Book{Title: "Book 12"},
Book{Title: "Book 13"},
Book{Title: "Book 14"},
Book{Title: "Book 15"},
Book{Title: "Book 16"},
Book{Title: "Book 17"},
Book{Title: "Book 18"},
Book{Title: "Book 19"},
Book{Title: "Book 20"},
},
"users": []interface{}{
UserDoc{Name: "John", Age: 13},
UserDoc{Name: "Jake", Age: 25},
UserDoc{Name: "Clair", Age: 12},
UserDoc{Name: "Johnny", Age: 42},
UserDoc{Name: "Blair", Age: 67},
UserDoc{Name: "Zz", Age: 12},
},
}
db := ensureDatabase(ctx, client, "lb_cursor_test", nil, t)
for colName, colDocs := range collectionData {
col := ensureCollection(ctx, db, colName, nil, t)
if _, _, err := col.CreateDocuments(ctx, colDocs); err != nil {
t.Fatalf("Expected success, got %s", err)
}
}
// Setup tests
tests := []queryTest{
queryTest{
Query: "FOR d IN books SORT d.Title RETURN d",
ExpectSuccess: true,
ExpectedDocuments: collectionData["books"],
DocumentType: reflect.TypeOf(Book{}),
},
}
var r driver.Response
// Setup context
ctx = driver.WithResponse(driver.WithQueryBatchSize(nil, 1), &r)
// keep track of whether at least one request was forwarded internally to the
// correct coordinator behind the load balancer
someRequestsForwarded := false
someRequestsNotForwarded := false
// Run tests for every context alternative
for i, test := range tests {
cursor, err := db.Query(ctx, test.Query, test.BindVars)
if err == nil {
// Close upon exit of the function
defer cursor.Close()
}
if test.ExpectSuccess {
if err != nil {
t.Errorf("Expected success in query %d (%s), got '%s'", i, test.Query, err)
continue
}
if count := cursor.Count(); count != 0 {
t.Errorf("Expected count of 0, got %d in query %d (%s)", count, i, test.Query)
}
var result []interface{}
for {
hasMore := cursor.HasMore()
doc := reflect.New(test.DocumentType)
if _, err := cursor.ReadDocument(ctx, doc.Interface()); driver.IsNoMoreDocuments(err) {
if hasMore {
t.Error("HasMore returned true, but ReadDocument returns a IsNoMoreDocuments error")
}
break
} else if err != nil {
t.Errorf("Failed to result document %d: %s", len(result), err)
}
if !hasMore {
t.Error("HasMore returned false, but ReadDocument returns a document")
}
result = append(result, doc.Elem().Interface())
if wasForwarded(r) {
someRequestsForwarded = true
} else {
someRequestsNotForwarded = true
}
time.Sleep(200 * time.Millisecond)
}
if len(result) != len(test.ExpectedDocuments) {
t.Errorf("Expected %d documents, got %d in query %d (%s)", len(test.ExpectedDocuments), len(result), i, test.Query)
} else {
for resultIdx, resultDoc := range result {
if !reflect.DeepEqual(resultDoc, test.ExpectedDocuments[resultIdx]) {
t.Errorf("Unexpected document in query %d (%s) at index %d: got %+v, expected %+v", i, test.Query, resultIdx, resultDoc, test.ExpectedDocuments[resultIdx])
}
}
}
// Close anyway (this tests calling Close more than once)
if err := cursor.Close(); err != nil {
t.Errorf("Expected success in Close of cursor from query %d (%s), got '%s'", i, test.Query, err)
}
} else {
if err == nil {
t.Errorf("Expected error in query %d (%s), got '%s'", i, test.Query, err)
continue
}
}
}
if !someRequestsForwarded {
t.Error("Did not detect any request being forwarded behind load balancer!")
}
if !someRequestsNotForwarded {
t.Error("Did not detect any request NOT being forwarded behind load balancer!")
}
}