github.com/hernad/nomad@v1.6.112/drivers/docker/stats_test.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package docker
     5  
     6  import (
     7  	"runtime"
     8  	"sync"
     9  	"testing"
    10  	"time"
    11  
    12  	docker "github.com/fsouza/go-dockerclient"
    13  	"github.com/hernad/nomad/ci"
    14  	cstructs "github.com/hernad/nomad/client/structs"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  func TestDriver_DockerStatsCollector(t *testing.T) {
    19  	ci.Parallel(t)
    20  	require := require.New(t)
    21  
    22  	src := make(chan *docker.Stats)
    23  	defer close(src)
    24  	dst, recvCh := newStatsChanPipe()
    25  	defer dst.close()
    26  	stats := &docker.Stats{}
    27  	stats.CPUStats.ThrottlingData.Periods = 10
    28  	stats.CPUStats.ThrottlingData.ThrottledPeriods = 10
    29  	stats.CPUStats.ThrottlingData.ThrottledTime = 10
    30  
    31  	stats.MemoryStats.Stats.Rss = 6537216
    32  	stats.MemoryStats.Stats.Cache = 1234
    33  	stats.MemoryStats.Stats.Swap = 0
    34  	stats.MemoryStats.Stats.MappedFile = 1024
    35  	stats.MemoryStats.Usage = 5651904
    36  	stats.MemoryStats.MaxUsage = 6651904
    37  	stats.MemoryStats.Commit = 123231
    38  	stats.MemoryStats.CommitPeak = 321323
    39  	stats.MemoryStats.PrivateWorkingSet = 62222
    40  
    41  	go dockerStatsCollector(dst, src, time.Second)
    42  
    43  	select {
    44  	case src <- stats:
    45  	case <-time.After(time.Second):
    46  		require.Fail("sending stats should not block here")
    47  	}
    48  
    49  	select {
    50  	case ru := <-recvCh:
    51  		if runtime.GOOS != "windows" {
    52  			require.Equal(stats.MemoryStats.Stats.Rss, ru.ResourceUsage.MemoryStats.RSS)
    53  			require.Equal(stats.MemoryStats.Stats.Cache, ru.ResourceUsage.MemoryStats.Cache)
    54  			require.Equal(stats.MemoryStats.Stats.Swap, ru.ResourceUsage.MemoryStats.Swap)
    55  			require.Equal(stats.MemoryStats.Stats.MappedFile, ru.ResourceUsage.MemoryStats.MappedFile)
    56  			require.Equal(stats.MemoryStats.Usage, ru.ResourceUsage.MemoryStats.Usage)
    57  			require.Equal(stats.MemoryStats.MaxUsage, ru.ResourceUsage.MemoryStats.MaxUsage)
    58  			require.Equal(stats.CPUStats.ThrottlingData.ThrottledPeriods, ru.ResourceUsage.CpuStats.ThrottledPeriods)
    59  			require.Equal(stats.CPUStats.ThrottlingData.ThrottledTime, ru.ResourceUsage.CpuStats.ThrottledTime)
    60  		} else {
    61  			require.Equal(stats.MemoryStats.PrivateWorkingSet, ru.ResourceUsage.MemoryStats.RSS)
    62  			require.Equal(stats.MemoryStats.Commit, ru.ResourceUsage.MemoryStats.Usage)
    63  			require.Equal(stats.MemoryStats.CommitPeak, ru.ResourceUsage.MemoryStats.MaxUsage)
    64  			require.Equal(stats.CPUStats.ThrottlingData.ThrottledPeriods, ru.ResourceUsage.CpuStats.ThrottledPeriods)
    65  			require.Equal(stats.CPUStats.ThrottlingData.ThrottledTime, ru.ResourceUsage.CpuStats.ThrottledTime)
    66  
    67  		}
    68  	case <-time.After(time.Second):
    69  		require.Fail("receiving stats should not block here")
    70  	}
    71  }
    72  
    73  // TestDriver_DockerUsageSender asserts that the TaskResourceUsage chan wrapper
    74  // supports closing and sending on a chan from concurrent goroutines.
    75  func TestDriver_DockerUsageSender(t *testing.T) {
    76  	ci.Parallel(t)
    77  
    78  	// sample payload
    79  	res := &cstructs.TaskResourceUsage{}
    80  
    81  	destCh, recvCh := newStatsChanPipe()
    82  
    83  	// Sending should never fail
    84  	destCh.send(res)
    85  	destCh.send(res)
    86  	destCh.send(res)
    87  
    88  	// Clear chan
    89  	<-recvCh
    90  
    91  	// Send and close concurrently to let the race detector help us out
    92  	wg := sync.WaitGroup{}
    93  	wg.Add(3)
    94  
    95  	// Sender
    96  	go func() {
    97  		destCh.send(res)
    98  		wg.Done()
    99  	}()
   100  
   101  	// Closer
   102  	go func() {
   103  		destCh.close()
   104  		wg.Done()
   105  	}()
   106  
   107  	// Clear recv chan
   108  	go func() {
   109  		for range recvCh {
   110  		}
   111  		wg.Done()
   112  	}()
   113  
   114  	wg.Wait()
   115  
   116  	// Assert closed
   117  	destCh.mu.Lock()
   118  	closed := destCh.closed
   119  	destCh.mu.Unlock()
   120  	require.True(t, closed)
   121  
   122  	select {
   123  	case _, ok := <-recvCh:
   124  		require.False(t, ok)
   125  	default:
   126  		require.Fail(t, "expect recvCh to be closed")
   127  	}
   128  
   129  	// Assert sending and closing never fails
   130  	destCh.send(res)
   131  	destCh.close()
   132  	destCh.close()
   133  	destCh.send(res)
   134  }