github.com/gondor/docker@v1.9.0-rc1/integration-cli/docker_api_stats_test.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  	"os/exec"
     8  	"runtime"
     9  	"strconv"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/docker/docker/api/types"
    14  	"github.com/go-check/check"
    15  )
    16  
    17  func (s *DockerSuite) TestApiStatsNoStreamGetCpu(c *check.C) {
    18  	testRequires(c, DaemonIsLinux)
    19  	out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "while true;do echo 'Hello'; usleep 100000; done")
    20  
    21  	id := strings.TrimSpace(out)
    22  	c.Assert(waitRun(id), check.IsNil)
    23  
    24  	resp, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/stats?stream=false", id), nil, "")
    25  	c.Assert(err, check.IsNil)
    26  	c.Assert(resp.ContentLength > 0, check.Equals, true, check.Commentf("should not use chunked encoding"))
    27  	c.Assert(resp.Header.Get("Content-Type"), check.Equals, "application/json")
    28  
    29  	var v *types.Stats
    30  	err = json.NewDecoder(body).Decode(&v)
    31  	c.Assert(err, check.IsNil)
    32  	body.Close()
    33  
    34  	var cpuPercent = 0.0
    35  	cpuDelta := float64(v.CPUStats.CPUUsage.TotalUsage - v.PreCPUStats.CPUUsage.TotalUsage)
    36  	systemDelta := float64(v.CPUStats.SystemUsage - v.PreCPUStats.SystemUsage)
    37  	cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CPUStats.CPUUsage.PercpuUsage)) * 100.0
    38  	if cpuPercent == 0 {
    39  		c.Fatalf("docker stats with no-stream get cpu usage failed: was %v", cpuPercent)
    40  	}
    41  }
    42  
    43  func (s *DockerSuite) TestApiStatsStoppedContainerInGoroutines(c *check.C) {
    44  	testRequires(c, DaemonIsLinux)
    45  	out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "echo 1")
    46  	id := strings.TrimSpace(out)
    47  
    48  	getGoRoutines := func() int {
    49  		_, body, err := sockRequestRaw("GET", fmt.Sprintf("/info"), nil, "")
    50  		c.Assert(err, check.IsNil)
    51  		info := types.Info{}
    52  		err = json.NewDecoder(body).Decode(&info)
    53  		c.Assert(err, check.IsNil)
    54  		body.Close()
    55  		return info.NGoroutines
    56  	}
    57  
    58  	// When the HTTP connection is closed, the number of goroutines should not increase.
    59  	routines := getGoRoutines()
    60  	_, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/stats", id), nil, "")
    61  	c.Assert(err, check.IsNil)
    62  	body.Close()
    63  
    64  	t := time.After(30 * time.Second)
    65  	for {
    66  		select {
    67  		case <-t:
    68  			c.Assert(getGoRoutines() <= routines, check.Equals, true)
    69  			return
    70  		default:
    71  			if n := getGoRoutines(); n <= routines {
    72  				return
    73  			}
    74  			time.Sleep(200 * time.Millisecond)
    75  		}
    76  	}
    77  }
    78  
    79  func (s *DockerSuite) TestApiStatsNetworkStats(c *check.C) {
    80  	testRequires(c, SameHostDaemon)
    81  	testRequires(c, DaemonIsLinux)
    82  	// Run container for 30 secs
    83  	out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
    84  	id := strings.TrimSpace(out)
    85  	c.Assert(waitRun(id), check.IsNil)
    86  
    87  	// Retrieve the container address
    88  	contIP := findContainerIP(c, id)
    89  	numPings := 10
    90  
    91  	var preRxPackets uint64
    92  	var preTxPackets uint64
    93  	var postRxPackets uint64
    94  	var postTxPackets uint64
    95  
    96  	// Get the container networking stats before and after pinging the container
    97  	nwStatsPre := getNetworkStats(c, id)
    98  	for _, v := range nwStatsPre {
    99  		preRxPackets += v.RxPackets
   100  		preTxPackets += v.TxPackets
   101  	}
   102  
   103  	countParam := "-c"
   104  	if runtime.GOOS == "windows" {
   105  		countParam = "-n" // Ping count parameter is -n on Windows
   106  	}
   107  	pingout, err := exec.Command("ping", contIP, countParam, strconv.Itoa(numPings)).Output()
   108  	pingouts := string(pingout[:])
   109  	c.Assert(err, check.IsNil)
   110  	nwStatsPost := getNetworkStats(c, id)
   111  	for _, v := range nwStatsPost {
   112  		postRxPackets += v.RxPackets
   113  		postTxPackets += v.TxPackets
   114  	}
   115  
   116  	// Verify the stats contain at least the expected number of packets (account for ARP)
   117  	expRxPkts := 1 + preRxPackets + uint64(numPings)
   118  	expTxPkts := 1 + preTxPackets + uint64(numPings)
   119  	c.Assert(postTxPackets >= expTxPkts, check.Equals, true,
   120  		check.Commentf("Reported less TxPackets than expected. Expected >= %d. Found %d. %s", expTxPkts, postTxPackets, pingouts))
   121  	c.Assert(postRxPackets >= expRxPkts, check.Equals, true,
   122  		check.Commentf("Reported less Txbytes than expected. Expected >= %d. Found %d. %s", expRxPkts, postRxPackets, pingouts))
   123  }
   124  
   125  func getNetworkStats(c *check.C, id string) map[string]types.NetworkStats {
   126  	var st *types.StatsJSON
   127  
   128  	_, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/stats?stream=false", id), nil, "")
   129  	c.Assert(err, check.IsNil)
   130  
   131  	err = json.NewDecoder(body).Decode(&st)
   132  	c.Assert(err, check.IsNil)
   133  	body.Close()
   134  
   135  	return st.Networks
   136  }
   137  
   138  func (s *DockerSuite) TestApiStatsContainerNotFound(c *check.C) {
   139  	testRequires(c, DaemonIsLinux)
   140  
   141  	status, _, err := sockRequest("GET", "/containers/nonexistent/stats", nil)
   142  	c.Assert(err, check.IsNil)
   143  	c.Assert(status, check.Equals, http.StatusNotFound)
   144  
   145  	status, _, err = sockRequest("GET", "/containers/nonexistent/stats?stream=0", nil)
   146  	c.Assert(err, check.IsNil)
   147  	c.Assert(status, check.Equals, http.StatusNotFound)
   148  }