github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/drivers/docker/stats_test.go (about)

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