Update vendored dependencies

This includes github.com/kurin/blazer 0.2.0, which resolves #1291
This commit is contained in:
Alexander Neumann
2017-10-01 10:13:39 +02:00
parent ba23d24dd1
commit 61cb1cc6f8
1044 changed files with 203022 additions and 97709 deletions

View File

@@ -15,21 +15,27 @@
package profiler
import (
"bytes"
"compress/gzip"
"errors"
"fmt"
"io"
"runtime/pprof"
"log"
"math/rand"
"os"
"strings"
"testing"
"time"
gcemd "cloud.google.com/go/compute/metadata"
"cloud.google.com/go/internal/testutil"
"cloud.google.com/go/profiler/mocks"
"github.com/golang/mock/gomock"
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes"
"github.com/google/pprof/profile"
gax "github.com/googleapis/gax-go"
"golang.org/x/net/context"
gtransport "google.golang.org/api/transport/grpc"
pb "google.golang.org/genproto/googleapis/devtools/cloudprofiler/v2"
edpb "google.golang.org/genproto/googleapis/rpc/errdetails"
"google.golang.org/grpc/codes"
@@ -38,18 +44,21 @@ import (
)
const (
testProjectID = "test-project-ID"
testInstanceName = "test-instance-name"
testZoneName = "test-zone-name"
testTarget = "test-target"
testService = "test-service"
testServiceVersion = "test-service-version"
testProjectID = "test-project-ID"
testInstance = "test-instance"
testZone = "test-zone"
testTarget = "test-target"
testService = "test-service"
testSvcVersion = "test-service-version"
testProfileDuration = time.Second * 10
testServerTimeout = time.Second * 15
wantFunctionName = "profilee"
)
func createTestDeployment() *pb.Deployment {
labels := map[string]string{
zoneNameLabel: testZoneName,
versionLabel: testServiceVersion,
zoneNameLabel: testZone,
versionLabel: testSvcVersion,
}
return &pb.Deployment{
ProjectId: testProjectID,
@@ -59,11 +68,10 @@ func createTestDeployment() *pb.Deployment {
}
func createTestAgent(psc pb.ProfilerServiceClient) *agent {
c := &client{client: psc}
return &agent{
client: c,
client: psc,
deployment: createTestDeployment(),
profileLabels: map[string]string{instanceLabel: testInstanceName},
profileLabels: map[string]string{instanceLabel: testInstance},
}
}
@@ -98,11 +106,9 @@ func TestCreateProfile(t *testing.T) {
}
func TestProfileAndUpload(t *testing.T) {
oldStartCPUProfile, oldStopCPUProfile, oldWriteHeapProfile, oldSleep := startCPUProfile, stopCPUProfile, writeHeapProfile, sleep
defer func() {
startCPUProfile = pprof.StartCPUProfile
stopCPUProfile = pprof.StopCPUProfile
writeHeapProfile = pprof.WriteHeapProfile
sleep = gax.Sleep
startCPUProfile, stopCPUProfile, writeHeapProfile, sleep = oldStartCPUProfile, oldStopCPUProfile, oldWriteHeapProfile, oldSleep
}()
ctx := context.Background()
@@ -306,118 +312,396 @@ func TestRetry(t *testing.T) {
}
}
func TestInitializeResources(t *testing.T) {
d := createTestDeployment()
l := map[string]string{instanceLabel: testInstanceName}
ctx := context.Background()
a, ctx := initializeResources(ctx, nil, d, l)
if xg := a.client.xGoogHeader; len(xg) == 0 {
t.Errorf("initializeResources() sets empty xGoogHeader")
} else {
if !strings.Contains(xg[0], "gl-go/") {
t.Errorf("initializeResources() sets wrong xGoogHeader, got: %v, want gl-go key", xg[0])
}
if !strings.Contains(xg[0], "gccl/") {
t.Errorf("initializeResources() sets wrong xGoogHeader, got: %v, want gccl key", xg[0])
}
if !strings.Contains(xg[0], "gax/") {
t.Errorf("initializeResources() sets wrong xGoogHeader, got: %v, want gax key", xg[0])
}
if !strings.Contains(xg[0], "grpc/") {
t.Errorf("initializeResources() sets wrong xGoogHeader, got: %v, want grpc key", xg[0])
}
}
func TestWithXGoogHeader(t *testing.T) {
ctx := withXGoogHeader(context.Background())
md, _ := grpcmd.FromOutgoingContext(ctx)
if !testutil.Equal(md[xGoogAPIMetadata], a.client.xGoogHeader) {
t.Errorf("md[%v] = %v, want equal xGoogHeader = %v", xGoogAPIMetadata, md[xGoogAPIMetadata], a.client.xGoogHeader)
if xg := md[xGoogAPIMetadata]; len(xg) == 0 {
t.Errorf("withXGoogHeader() sets empty xGoogHeader")
} else {
if !strings.Contains(xg[0], "gl-go/") {
t.Errorf("withXGoogHeader() got: %v, want gl-go key", xg[0])
}
if !strings.Contains(xg[0], "gccl/") {
t.Errorf("withXGoogHeader() got: %v, want gccl key", xg[0])
}
if !strings.Contains(xg[0], "gax/") {
t.Errorf("withXGoogHeader() got: %v, want gax key", xg[0])
}
if !strings.Contains(xg[0], "grpc/") {
t.Errorf("withXGoogHeader() got: %v, want grpc key", xg[0])
}
}
}
func TestInitializeDeployment(t *testing.T) {
defer func() {
getProjectID = gcemd.ProjectID
getZone = gcemd.Zone
config = Config{}
}()
getProjectID = func() (string, error) {
return testProjectID, nil
}
getZone = func() (string, error) {
return testZoneName, nil
}
cfg := Config{Service: testService, ServiceVersion: testServiceVersion}
initializeConfig(cfg)
d, err := initializeDeployment()
if err != nil {
t.Errorf("initializeDeployment() got error: %v, want no error", err)
}
if want := createTestDeployment(); !testutil.Equal(d, want) {
t.Errorf("initializeDeployment() got: %v, want %v", d, want)
}
}
func TestInitializeConfig(t *testing.T) {
func TestInitializeAgent(t *testing.T) {
oldConfig := config
defer func() {
config = oldConfig
}()
for _, tt := range []struct {
config Config
wantDeploymentLabels map[string]string
wantProfileLabels map[string]string
}{
{
config: Config{ServiceVersion: testSvcVersion, zone: testZone},
wantDeploymentLabels: map[string]string{zoneNameLabel: testZone, versionLabel: testSvcVersion},
wantProfileLabels: map[string]string{},
},
{
config: Config{zone: testZone},
wantDeploymentLabels: map[string]string{zoneNameLabel: testZone},
wantProfileLabels: map[string]string{},
},
{
config: Config{ServiceVersion: testSvcVersion},
wantDeploymentLabels: map[string]string{versionLabel: testSvcVersion},
wantProfileLabels: map[string]string{},
},
{
config: Config{instance: testInstance},
wantDeploymentLabels: map[string]string{},
wantProfileLabels: map[string]string{instanceLabel: testInstance},
},
} {
config = tt.config
config.ProjectID = testProjectID
config.Target = testTarget
a := initializeAgent(nil)
wantDeployment := &pb.Deployment{
ProjectId: testProjectID,
Target: testTarget,
Labels: tt.wantDeploymentLabels,
}
if !testutil.Equal(a.deployment, wantDeployment) {
t.Errorf("initializeResources() got deployment: %v, want %v", a.deployment, wantDeployment)
}
if !testutil.Equal(a.profileLabels, tt.wantProfileLabels) {
t.Errorf("initializeResources() got profile labels: %v, want %v", a.profileLabels, tt.wantProfileLabels)
}
}
}
func TestInitializeConfig(t *testing.T) {
oldConfig, oldService, oldVersion, oldGetProjectID, oldGetInstanceName, oldGetZone, oldOnGCE := config, os.Getenv("GAE_SERVICE"), os.Getenv("GAE_VERSION"), getProjectID, getInstanceName, getZone, onGCE
defer func() {
config, getProjectID, getInstanceName, getZone, onGCE = oldConfig, oldGetProjectID, oldGetInstanceName, oldGetZone, oldOnGCE
if err := os.Setenv("GAE_SERVICE", oldService); err != nil {
t.Fatal(err)
}
if err := os.Setenv("GAE_VERSION", oldVersion); err != nil {
t.Fatal(err)
}
}()
testGAEService := "test-gae-service"
testGAEVersion := "test-gae-version"
testGCEProjectID := "test-gce-project-id"
for _, tt := range []struct {
config Config
wantTarget string
wantConfig Config
wantErrorString string
onGAE bool
onGCE bool
}{
{
Config{Service: testService},
testService,
Config{Target: testService, ProjectID: testGCEProjectID, zone: testZone, instance: testInstance},
"",
false,
true,
},
{
Config{Target: testTarget},
testTarget,
Config{Target: testTarget, ProjectID: testGCEProjectID, zone: testZone, instance: testInstance},
"",
false,
true,
},
{
Config{},
"",
Config{},
"service name must be specified in the configuration",
false,
true,
},
{
Config{Service: testService},
Config{Target: testService, ServiceVersion: testGAEVersion, ProjectID: testGCEProjectID, zone: testZone, instance: testInstance},
"",
true,
true,
},
{
Config{Target: testTarget},
Config{Target: testTarget, ServiceVersion: testGAEVersion, ProjectID: testGCEProjectID, zone: testZone, instance: testInstance},
"",
true,
true,
},
{
Config{},
Config{Target: testGAEService, ServiceVersion: testGAEVersion, ProjectID: testGCEProjectID, zone: testZone, instance: testInstance},
"",
true,
true,
},
{
Config{Service: testService, ServiceVersion: testSvcVersion},
Config{Target: testService, ServiceVersion: testSvcVersion, ProjectID: testGCEProjectID, zone: testZone, instance: testInstance},
"",
false,
true,
},
{
Config{Service: testService, ServiceVersion: testSvcVersion},
Config{Target: testService, ServiceVersion: testSvcVersion, ProjectID: testGCEProjectID, zone: testZone, instance: testInstance},
"",
true,
true,
},
{
Config{Service: testService, ProjectID: testProjectID},
Config{Target: testService, ProjectID: testProjectID, zone: testZone, instance: testInstance},
"",
false,
true,
},
{
Config{Service: testService},
Config{Target: testService},
"project ID must be specified in the configuration if running outside of GCP",
false,
false,
},
} {
envService, envVersion := "", ""
if tt.onGAE {
envService, envVersion = testGAEService, testGAEVersion
}
if err := os.Setenv("GAE_SERVICE", envService); err != nil {
t.Fatal(err)
}
if err := os.Setenv("GAE_VERSION", envVersion); err != nil {
t.Fatal(err)
}
if tt.onGCE {
onGCE = func() bool { return true }
getProjectID = func() (string, error) { return testGCEProjectID, nil }
getZone = func() (string, error) { return testZone, nil }
getInstanceName = func() (string, error) { return testInstance, nil }
} else {
onGCE = func() bool { return false }
getProjectID = func() (string, error) { return "", fmt.Errorf("test get project id error") }
getZone = func() (string, error) { return "", fmt.Errorf("test get zone error") }
getInstanceName = func() (string, error) { return "", fmt.Errorf("test get instance error") }
}
errorString := ""
if err := initializeConfig(tt.config); err != nil {
errorString = err.Error()
}
if errorString != tt.wantErrorString {
t.Errorf("initializeConfig(%v) got error: %v, want %v", tt.config, errorString, tt.wantErrorString)
if !strings.Contains(errorString, tt.wantErrorString) {
t.Errorf("initializeConfig(%v) got error: %v, want contain %v", tt.config, errorString, tt.wantErrorString)
}
if config.Target != tt.wantTarget {
t.Errorf("initializeConfig(%v) got target: %v, want %v", tt.config, config.Target, tt.wantTarget)
if tt.wantErrorString == "" {
tt.wantConfig.APIAddr = apiAddress
}
tt.wantConfig.Service = tt.config.Service
if config != tt.wantConfig {
t.Errorf("initializeConfig(%v) got: %v, want %v", tt.config, config, tt.wantConfig)
}
}
for _, tt := range []struct {
wantErrorString string
getProjectIDError bool
getZoneError bool
getInstanceError bool
}{
{
wantErrorString: "failed to get the project ID from Compute Engine:",
getProjectIDError: true,
},
{
wantErrorString: "failed to get zone from Compute Engine:",
getZoneError: true,
},
{
wantErrorString: "failed to get instance from Compute Engine:",
getInstanceError: true,
},
} {
onGCE = func() bool { return true }
if tt.getProjectIDError {
getProjectID = func() (string, error) { return "", fmt.Errorf("test get project ID error") }
} else {
getProjectID = func() (string, error) { return testGCEProjectID, nil }
}
if tt.getZoneError {
getZone = func() (string, error) { return "", fmt.Errorf("test get zone error") }
} else {
getZone = func() (string, error) { return testZone, nil }
}
if tt.getInstanceError {
getInstanceName = func() (string, error) { return "", fmt.Errorf("test get instance error") }
} else {
getInstanceName = func() (string, error) { return testInstance, nil }
}
errorString := ""
if err := initializeConfig(Config{Service: testService}); err != nil {
errorString = err.Error()
}
if !strings.Contains(errorString, tt.wantErrorString) {
t.Errorf("initializeConfig() got error: %v, want contain %v", errorString, tt.wantErrorString)
}
}
}
func TestInitializeProfileLabels(t *testing.T) {
type fakeProfilerServer struct {
pb.ProfilerServiceServer
count int
gotCPUProfile []byte
gotHeapProfile []byte
done chan bool
}
func (fs *fakeProfilerServer) CreateProfile(ctx context.Context, in *pb.CreateProfileRequest) (*pb.Profile, error) {
fs.count++
switch fs.count {
case 1:
return &pb.Profile{Name: "testCPU", ProfileType: pb.ProfileType_CPU, Duration: ptypes.DurationProto(testProfileDuration)}, nil
case 2:
return &pb.Profile{Name: "testHeap", ProfileType: pb.ProfileType_HEAP}, nil
default:
select {}
}
}
func (fs *fakeProfilerServer) UpdateProfile(ctx context.Context, in *pb.UpdateProfileRequest) (*pb.Profile, error) {
switch in.Profile.ProfileType {
case pb.ProfileType_CPU:
fs.gotCPUProfile = in.Profile.ProfileBytes
case pb.ProfileType_HEAP:
fs.gotHeapProfile = in.Profile.ProfileBytes
fs.done <- true
}
return in.Profile, nil
}
func profileeLoop(quit chan bool) {
for {
select {
case <-quit:
return
default:
profileeWork()
}
}
}
func profileeWork() {
data := make([]byte, 1024*1024)
rand.Read(data)
var b bytes.Buffer
gz := gzip.NewWriter(&b)
if _, err := gz.Write(data); err != nil {
log.Printf("failed to write to gzip stream", err)
return
}
if err := gz.Flush(); err != nil {
log.Printf("failed to flush to gzip stream", err)
return
}
if err := gz.Close(); err != nil {
log.Printf("failed to close gzip stream", err)
}
}
func checkSymbolization(p *profile.Profile) error {
for _, l := range p.Location {
if len(l.Line) > 0 && l.Line[0].Function != nil && strings.Contains(l.Line[0].Function.Name, wantFunctionName) {
return nil
}
}
return fmt.Errorf("want function name %v not found in profile", wantFunctionName)
}
func validateProfile(rawData []byte) error {
p, err := profile.ParseData(rawData)
if err != nil {
return fmt.Errorf("ParseData failed: %v", err)
}
if len(p.Sample) == 0 {
return fmt.Errorf("profile contains zero samples: %v", p)
}
if len(p.Location) == 0 {
return fmt.Errorf("profile contains zero locations: %v", p)
}
if len(p.Function) == 0 {
return fmt.Errorf("profile contains zero functions: %v", p)
}
if err := checkSymbolization(p); err != nil {
return fmt.Errorf("checkSymbolization failed: %v for %v", err, p)
}
return nil
}
func TestAgentWithServer(t *testing.T) {
oldDialGRPC, oldConfig := dialGRPC, config
defer func() {
getInstanceName = gcemd.InstanceName
dialGRPC, config = oldDialGRPC, oldConfig
}()
getInstanceName = func() (string, error) {
return testInstanceName, nil
srv, err := testutil.NewServer()
if err != nil {
t.Fatalf("testutil.NewServer(): %v", err)
}
fakeServer := &fakeProfilerServer{done: make(chan bool)}
pb.RegisterProfilerServiceServer(srv.Gsrv, fakeServer)
srv.Start()
dialGRPC = gtransport.DialInsecure
if err := Start(Config{
Target: testTarget,
ProjectID: testProjectID,
APIAddr: srv.Addr,
instance: testInstance,
zone: testZone,
}); err != nil {
t.Fatalf("Start(): %v", err)
}
l := initializeProfileLabels()
want := map[string]string{instanceLabel: testInstanceName}
if !testutil.Equal(l, want) {
t.Errorf("initializeProfileLabels() got: %v, want %v", l, want)
quitProfilee := make(chan bool)
go profileeLoop(quitProfilee)
select {
case <-fakeServer.done:
case <-time.After(testServerTimeout):
t.Errorf("got timeout after %v, want fake server done", testServerTimeout)
}
quitProfilee <- true
if err := validateProfile(fakeServer.gotCPUProfile); err != nil {
t.Errorf("validateProfile(gotCPUProfile): %v", err)
}
if err := validateProfile(fakeServer.gotHeapProfile); err != nil {
t.Errorf("validateProfile(gotHeapProfile): %v", err)
}
}