github.com/grailbio/base@v0.0.11/pprof/pprof-test/main_test.go (about)

     1  // Copyright 2018 GRAIL, Inc. All rights reserved.
     2  // Use of this source code is governed by the Apache-2.0
     3  // license that can be found in the LICENSE file.
     4  
     5  package main_test
     6  
     7  import (
     8  	"bufio"
     9  	"errors"
    10  	"net/http"
    11  	"os"
    12  	"path/filepath"
    13  	"reflect"
    14  	"sync"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/grailbio/testutil"
    19  	"github.com/stretchr/testify/require"
    20  	"v.io/x/lib/gosh"
    21  )
    22  
    23  func retry(url string, duration time.Duration, iterations int) error {
    24  	i := 0
    25  	for {
    26  		if iterations == i {
    27  			return errors.New("max attempts exceeded for URL")
    28  		}
    29  
    30  		i++
    31  		response, err := http.Get(url)
    32  		if err == nil {
    33  			if response.StatusCode == 200 {
    34  				return nil
    35  			}
    36  
    37  			return errors.New("page not found")
    38  		}
    39  
    40  		time.Sleep(duration)
    41  	}
    42  }
    43  
    44  func find(t *testing.T, dir string, files []string) []string {
    45  	if len(files) == 0 {
    46  		return nil
    47  	}
    48  	d, err := os.Open(dir)
    49  	require.NoError(t, err)
    50  	entries, err := d.Readdirnames(0)
    51  	require.NoError(t, err)
    52  	found := []string{}
    53  	for _, want := range files {
    54  		for _, f := range entries {
    55  			if f == want {
    56  				found = append(found, want)
    57  				break
    58  			}
    59  		}
    60  	}
    61  	return found
    62  }
    63  
    64  func TestEverything(t *testing.T) {
    65  	sh := gosh.NewShell(nil)
    66  	bin := testutil.GoExecutable(t, "//go/src/github.com/grailbio/base/pprof/pprof-test/pprof-test")
    67  	tempDir := sh.MakeTempDir()
    68  	cpu := filepath.Join(tempDir, "c")
    69  	heap := filepath.Join(tempDir, "h")
    70  
    71  	for _, tst := range []struct {
    72  		name    string
    73  		args    []string
    74  		files   []string
    75  		success bool
    76  	}{
    77  		{"without", []string{}, nil, false},
    78  		{"with", []string{"-pprof=127.0.0.1:0"}, nil, true},
    79  		{"with-cl", []string{"-pprof=127.0.0.1:0", "-cpu-profile=" + cpu, "-heap-profile=" + heap}, []string{"c-00000.pprof", "h-00000.pprof"}, true},
    80  	} {
    81  		addrs := make(chan string)
    82  
    83  		var wg sync.WaitGroup
    84  		wg.Add(1)
    85  		go func() {
    86  			cmd := sh.Cmd(bin, tst.args...)
    87  			rc := cmd.StdoutPipe()
    88  			cmd.Start()
    89  			require.NoError(t, cmd.Err)
    90  			scanner := bufio.NewScanner(rc)
    91  			for cmd.Err == nil && scanner.Scan() {
    92  				a := scanner.Text()
    93  				addrs <- a
    94  			}
    95  			rc.Close()
    96  			cmd.Wait()
    97  			close(addrs)
    98  			wg.Done()
    99  		}()
   100  
   101  		mainAddr := <-addrs
   102  		debugAddr := <-addrs
   103  
   104  		// Make sure the main webserver is alive/test app is running.
   105  		if err := retry("http://"+mainAddr+"/alive/", 100*time.Millisecond, 50); err != nil {
   106  			t.Fatal(err)
   107  		}
   108  
   109  		// Make sure that /debug/ is not on the main webserver.
   110  		if err := retry("http://"+mainAddr+"/debug/pprof/", 50*time.Millisecond, 1); err == nil {
   111  			t.Fatal("found /debug/ on main server")
   112  		}
   113  
   114  		// Make sure that /debug/ is on the debug server, if configured.
   115  		if err := retry("http://"+debugAddr+"/debug/pprof/", 100*time.Millisecond, 50); tst.success != (err == nil) {
   116  			t.Fatalf("error detecting /debug/ %v %v %v %v %v", tst.success, err == nil, err, mainAddr, debugAddr)
   117  		}
   118  
   119  		// Quit the test app.
   120  		http.Get("http://" + mainAddr + "/quitquitquit/")
   121  
   122  		// Wait for the command to finish before testing for the files it
   123  		// should have written.
   124  		wg.Wait()
   125  
   126  		if got, want := find(t, tempDir, tst.files), tst.files; !reflect.DeepEqual(got, want) {
   127  			t.Errorf("%s: got %v, want %v", tst.name, got, want)
   128  		}
   129  	}
   130  }