/* Copyright 2015 The Kubernetes Authors All rights reserved. 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. */ package mesos import ( "bytes" "net" "reflect" "testing" "time" log "github.com/golang/glog" "speter.net/go/exp/math/dec/inf" ) func TestIPAddress(t *testing.T) { expected4 := net.IPv4(127, 0, 0, 1) ip, err := ipAddress("127.0.0.1") if err != nil { t.Fatalf("unexpected error: %v", err) } if !reflect.DeepEqual(ip, expected4) { t.Fatalf("expected %#v instead of %#v", expected4, ip) } expected6 := net.ParseIP("::1") if expected6 == nil { t.Fatalf("failed to parse ipv6 ::1") } ip, err = ipAddress("::1") if err != nil { t.Fatalf("unexpected error: %v", err) } if !reflect.DeepEqual(ip, expected6) { t.Fatalf("expected %#v instead of %#v", expected6, ip) } ip, err = ipAddress("localhost") if err != nil { t.Fatalf("unexpected error: %v", err) } if !reflect.DeepEqual(ip, expected4) && !reflect.DeepEqual(ip, expected6) { t.Fatalf("expected %#v or %#v instead of %#v", expected4, expected6, ip) } _, err = ipAddress("") if err != noHostNameSpecified { t.Fatalf("expected error noHostNameSpecified but got none") } } // test mesos.newMesosCloud with no config func Test_newMesosCloud_NoConfig(t *testing.T) { defer log.Flush() mesosCloud, err := newMesosCloud(nil) if err != nil { t.Fatalf("Creating a new Mesos cloud provider without config does not yield an error: %#v", err) } if mesosCloud.client.httpClient.Timeout != DefaultHttpClientTimeout { t.Fatalf("Creating a new Mesos cloud provider without config does not yield an error: %#v", err) } if mesosCloud.client.state.ttl != DefaultStateCacheTTL { t.Fatalf("Mesos client with default config has the expected state cache TTL value") } } // test mesos.newMesosCloud with custom config func Test_newMesosCloud_WithConfig(t *testing.T) { defer log.Flush() configString := ` [mesos-cloud] http-client-timeout = 500ms state-cache-ttl = 1h` reader := bytes.NewBufferString(configString) mesosCloud, err := newMesosCloud(reader) if err != nil { t.Fatalf("Creating a new Mesos cloud provider with a custom config does not yield an error: %#v", err) } if mesosCloud.client.httpClient.Timeout != time.Duration(500)*time.Millisecond { t.Fatalf("Mesos client with a custom config has the expected HTTP client timeout value") } if mesosCloud.client.state.ttl != time.Duration(1)*time.Hour { t.Fatalf("Mesos client with a custom config has the expected state cache TTL value") } } // tests for capability reporting functions // test mesos.Instances func Test_Instances(t *testing.T) { defer log.Flush() mesosCloud, _ := newMesosCloud(nil) instances, supports_instances := mesosCloud.Instances() if !supports_instances || instances == nil { t.Fatalf("MesosCloud provides an implementation of Instances") } } // test mesos.TCPLoadBalancer func Test_TcpLoadBalancer(t *testing.T) { defer log.Flush() mesosCloud, _ := newMesosCloud(nil) lb, supports_lb := mesosCloud.TCPLoadBalancer() if supports_lb || lb != nil { t.Fatalf("MesosCloud does not provide an implementation of TCPLoadBalancer") } } // test mesos.Zones func Test_Zones(t *testing.T) { defer log.Flush() mesosCloud, _ := newMesosCloud(nil) zones, supports_zones := mesosCloud.Zones() if supports_zones || zones != nil { t.Fatalf("MesosCloud does not provide an implementation of Zones") } } // test mesos.Clusters func Test_Clusters(t *testing.T) { defer log.Flush() mesosCloud, _ := newMesosCloud(nil) clusters, supports_clusters := mesosCloud.Clusters() if !supports_clusters || clusters == nil { t.Fatalf("MesosCloud does not provide an implementation of Clusters") } } // test mesos.MasterURI func Test_MasterURI(t *testing.T) { defer log.Flush() mesosCloud, _ := newMesosCloud(nil) uri := mesosCloud.MasterURI() if uri != DefaultMesosMaster { t.Fatalf("MasterURI returns the expected master URI (expected \"localhost\", actual \"%s\"", uri) } } // test mesos.ListClusters func Test_ListClusters(t *testing.T) { defer log.Flush() md := FakeMasterDetector{} httpServer, httpClient, httpTransport := makeHttpMocks() defer httpServer.Close() cacheTTL := 500 * time.Millisecond mesosClient, err := createMesosClient(md, httpClient, httpTransport, cacheTTL) mesosCloud := &MesosCloud{client: mesosClient, config: createDefaultConfig()} clusters, err := mesosCloud.ListClusters() if err != nil { t.Fatalf("ListClusters does not yield an error: %#v", err) } if len(clusters) != 1 { t.Fatalf("ListClusters should return a list of size 1: (actual: %#v)", clusters) } expectedClusterNames := []string{"mesos"} if !reflect.DeepEqual(clusters, expectedClusterNames) { t.Fatalf("ListClusters should return the expected list of names: (expected: %#v, actual: %#v)", expectedClusterNames, clusters) } } // test mesos.Master func Test_Master(t *testing.T) { defer log.Flush() md := FakeMasterDetector{} httpServer, httpClient, httpTransport := makeHttpMocks() defer httpServer.Close() cacheTTL := 500 * time.Millisecond mesosClient, err := createMesosClient(md, httpClient, httpTransport, cacheTTL) mesosCloud := &MesosCloud{client: mesosClient, config: createDefaultConfig()} clusters, err := mesosCloud.ListClusters() clusterName := clusters[0] master, err := mesosCloud.Master(clusterName) if err != nil { t.Fatalf("Master does not yield an error: %#v", err) } expectedMaster := unpackIPv4(TEST_MASTER_IP) if master != expectedMaster { t.Fatalf("Master returns the expected value: (expected: %#v, actual: %#v", expectedMaster, master) } } // test mesos.List func Test_List(t *testing.T) { defer log.Flush() md := FakeMasterDetector{} httpServer, httpClient, httpTransport := makeHttpMocks() defer httpServer.Close() cacheTTL := 500 * time.Millisecond mesosClient, err := createMesosClient(md, httpClient, httpTransport, cacheTTL) mesosCloud := &MesosCloud{client: mesosClient, config: createDefaultConfig()} clusters, err := mesosCloud.List(".*") // recognizes the language of all strings if err != nil { t.Fatalf("List does not yield an error: %#v", err) } if len(clusters) != 3 { t.Fatalf("List with a catch-all filter should return a list of size 3: (actual: %#v)", clusters) } clusters, err = mesosCloud.List("$^") // end-of-string followed by start-of-string: recognizes the empty language if err != nil { t.Fatalf("List does not yield an error: %#v", err) } if len(clusters) != 0 { t.Fatalf("List with a reject-all filter should return a list of size 0: (actual: %#v)", clusters) } } // test mesos.GetNodeResources func Test_GetNodeResources(t *testing.T) { defer log.Flush() md := FakeMasterDetector{} httpServer, httpClient, httpTransport := makeHttpMocks() defer httpServer.Close() cacheTTL := 500 * time.Millisecond mesosClient, err := createMesosClient(md, httpClient, httpTransport, cacheTTL) mesosCloud := &MesosCloud{client: mesosClient, config: createDefaultConfig()} resources, err := mesosCloud.GetNodeResources("mesos1.internal.company.com") if err != nil { t.Fatalf("GetNodeResources does not yield an error: %#v", err) } expectedCpu := inf.NewDec(8, 0) expectedMem := inf.NewDec(15360, 0) actualCpu := resources.Capacity["cpu"].Amount actualMem := resources.Capacity["memory"].Amount if actualCpu.Cmp(expectedCpu) != 0 { t.Fatalf("GetNodeResources should return the expected amount of cpu: (expected: %#v, vactual: %#v)", expectedCpu, actualCpu) } if actualMem.Cmp(expectedMem) != 0 { t.Fatalf("GetNodeResources should return the expected amount of memory: (expected: %#v, vactual: %#v)", expectedMem, actualMem) } }