1 //go:build windows 2 3 package main 4 5 import ( 6 "context" 7 "fmt" 8 "reflect" 9 "testing" 10 "time" 11 12 "github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/stats" 13 v1 "github.com/containerd/cgroups/stats/v1" 14 "github.com/containerd/containerd/runtime/v2/task" 15 "github.com/pkg/errors" 16 ) 17 18 func verifyExpectedError(t *testing.T, resp interface{}, actual, expected error) { 19 t.Helper() 20 if actual == nil || errors.Cause(actual) != expected || !errors.Is(actual, expected) { 21 t.Fatalf("expected error: %v, got: %v", expected, actual) 22 } 23 24 isnil := false 25 ty := reflect.TypeOf(resp) 26 if ty == nil { 27 isnil = true 28 } else { 29 isnil = reflect.ValueOf(resp).IsNil() 30 } 31 if !isnil { 32 t.Fatalf("expect nil response for error return, got: %v", resp) 33 } 34 } 35 36 func verifyExpectedStats(t *testing.T, isWCOW, ownsHost bool, s *stats.Statistics) { 37 t.Helper() 38 if isWCOW { 39 verifyExpectedWindowsContainerStatistics(t, s.GetWindows()) 40 } else { 41 verifyExpectedCgroupMetrics(t, s.GetLinux()) 42 } 43 if ownsHost { 44 verifyExpectedVirtualMachineStatistics(t, s.VM) 45 } 46 } 47 48 func verifyExpectedWindowsContainerStatistics(t *testing.T, w *stats.WindowsContainerStatistics) { 49 t.Helper() 50 if w == nil { 51 t.Fatal("expected non-nil WindowsContainerStatistics") 52 } 53 if w.UptimeNS != 100 { 54 t.Fatalf("expected WindowsContainerStatistics.UptimeNS == 100, got: %d", w.UptimeNS) 55 } 56 if w.Processor == nil { 57 t.Fatal("expected non-nil WindowsContainerStatistics.Processor") 58 } 59 if w.Processor.TotalRuntimeNS != 100 { 60 t.Fatalf("expected WindowsContainerStatistics.Processor.TotalRuntimeNS == 100, got: %d", w.Processor.TotalRuntimeNS) 61 } 62 if w.Processor.RuntimeUserNS != 100 { 63 t.Fatalf("expected WindowsContainerStatistics.Processor.RuntimeUserNS == 100, got: %d", w.Processor.RuntimeUserNS) 64 } 65 if w.Processor.RuntimeKernelNS != 100 { 66 t.Fatalf("expected WindowsContainerStatistics.Processor.RuntimeKernelNS == 100, got: %d", w.Processor.RuntimeKernelNS) 67 } 68 if w.Memory == nil { 69 t.Fatal("expected non-nil WindowsContainerStatistics.Memory") 70 } 71 if w.Memory.MemoryUsageCommitBytes != 100 { 72 t.Fatalf("expected WindowsContainerStatistics.Memory.MemoryUsageCommitBytes == 100, got: %d", w.Memory.MemoryUsageCommitBytes) 73 } 74 if w.Memory.MemoryUsageCommitPeakBytes != 100 { 75 t.Fatalf("expected WindowsContainerStatistics.Memory.MemoryUsageCommitPeakBytes == 100, got: %d", w.Memory.MemoryUsageCommitPeakBytes) 76 } 77 if w.Memory.MemoryUsagePrivateWorkingSetBytes != 100 { 78 t.Fatalf("expected WindowsContainerStatistics.Memory.MemoryUsagePrivateWorkingSetBytes == 100, got: %d", w.Memory.MemoryUsagePrivateWorkingSetBytes) 79 } 80 if w.Storage == nil { 81 t.Fatal("expected non-nil WindowsContainerStatistics.Memory") 82 } 83 if w.Storage.ReadCountNormalized != 100 { 84 t.Fatalf("expected WindowsContainerStatistics.Storage.ReadCountNormalized == 100, got: %d", w.Storage.ReadCountNormalized) 85 } 86 if w.Storage.ReadSizeBytes != 100 { 87 t.Fatalf("expected WindowsContainerStatistics.Storage.ReadSizeBytes == 100, got: %d", w.Storage.ReadSizeBytes) 88 } 89 if w.Storage.WriteCountNormalized != 100 { 90 t.Fatalf("expected WindowsContainerStatistics.Storage.WriteCountNormalized == 100, got: %d", w.Storage.WriteCountNormalized) 91 } 92 if w.Storage.WriteSizeBytes != 100 { 93 t.Fatalf("expected WindowsContainerStatistics.Storage.WriteSizeBytes == 100, got: %d", w.Storage.WriteSizeBytes) 94 } 95 } 96 97 func verifyExpectedCgroupMetrics(t *testing.T, v *v1.Metrics) { 98 t.Helper() 99 if v == nil { 100 t.Fatal("expected non-nil cgroups Metrics") 101 } 102 if v.CPU == nil { 103 t.Fatal("expected non-nil Metrics.CPU") 104 } 105 if v.CPU.Usage.Total != 100 { 106 t.Fatalf("Expected Metrics.CPU.Usage == 100, got: %d", v.CPU.Usage) 107 } 108 if v.Memory == nil { 109 t.Fatal("expected non-nil Metrics.Memory") 110 } 111 if v.Memory.TotalInactiveFile != 100 { 112 t.Fatalf("Expected Metrics.Memory.TotalInactiveFile == 100, got: %d", v.Memory.TotalInactiveFile) 113 } 114 if v.Memory.Usage == nil { 115 t.Fatal("expected non-nil Metrics.Memory.Usage") 116 } 117 if v.Memory.Usage.Usage != 200 { 118 t.Fatalf("Expected Metrics.Memory.Usage.Usage == 200, got: %d", v.Memory.Usage.Usage) 119 } 120 } 121 122 func verifyExpectedVirtualMachineStatistics(t *testing.T, v *stats.VirtualMachineStatistics) { 123 t.Helper() 124 if v == nil { 125 t.Fatal("expected non-nil VirtualMachineStatistics") 126 } 127 if v.Processor == nil { 128 t.Fatal("expected non-nil VirtualMachineStatistics.Processor") 129 } 130 if v.Processor.TotalRuntimeNS != 100 { 131 t.Fatalf("expected VirtualMachineStatistics.Processor.TotalRuntimeNS == 100, got: %d", v.Processor.TotalRuntimeNS) 132 } 133 if v.Memory == nil { 134 t.Fatal("expected non-nil VirtualMachineStatistics.Memory") 135 } 136 if v.Memory.WorkingSetBytes != 100 { 137 t.Fatalf("expected VirtualMachineStatistics.Memory.WorkingSetBytes == 100, got: %d", v.Memory.WorkingSetBytes) 138 } 139 } 140 141 func Test_Service_shutdownInternal(t *testing.T) { 142 for _, now := range []bool{true, false} { 143 t.Run(fmt.Sprintf("%s_Now_%t", t.Name(), now), func(t *testing.T) { 144 s, err := NewService(WithTID(t.Name())) 145 if err != nil { 146 t.Fatal(err) 147 } 148 149 if s.IsShutdown() { 150 t.Fatal("service prematurely shutdown") 151 } 152 153 _, err = s.shutdownInternal(context.Background(), &task.ShutdownRequest{ 154 ID: s.tid, 155 Now: now, 156 }) 157 if err != nil { 158 t.Fatalf("could not shut down service: %v", err) 159 } 160 161 tm := time.NewTimer(5 * time.Millisecond) 162 select { 163 case <-tm.C: 164 t.Fatalf("shutdown channel did not close") 165 case <-s.Done(): 166 tm.Stop() 167 } 168 169 if !s.IsShutdown() { 170 t.Fatal("service did not shutdown") 171 } 172 }) 173 } 174 } 175