github.com/clintkitson/docker@v1.9.1/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, "bridge") 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 }