github.com/google/fleetspeak@v0.1.15-0.20240426164851-4f31f62c1aea/fleetspeak/src/client/internal/monitoring/resource_usage_fetcher_test.go (about) 1 // Copyright 2017 Google Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package monitoring 16 17 import ( 18 "fmt" 19 "os/exec" 20 "runtime" 21 "testing" 22 "time" 23 24 log "github.com/golang/glog" 25 ) 26 27 func checkFloat64(name string, value, min, max float64) error { 28 if value < min || value > max { 29 return fmt.Errorf("Expected %s to be between %v and %v, got %v", name, min, max, value) 30 } 31 return nil 32 } 33 34 func checkInt64(name string, value, min, max int64) error { 35 if value < min || value > max { 36 return fmt.Errorf("Expected %s to be between %d and %d, got %d", name, min, max, value) 37 } 38 return nil 39 } 40 41 func TestResourceUsageFromFinishedCmd(t *testing.T) { 42 ruf := ResourceUsageFetcher{} 43 // Generate some system (os.listdir) and user (everything else) execution 44 // time, consume some memory... 45 cmd := exec.Command("python", "-c", ` 46 import os 47 import time 48 49 s = "" 50 for i in range(5000): 51 s += str(i) 52 53 t0 = time.time() 54 while time.time() - t0 < 1.: 55 os.listdir(".") 56 `) 57 start := time.Now() 58 if err := cmd.Run(); err != nil { 59 t.Fatalf("Unexpected error from Run(): %v", err) 60 } 61 runTime := time.Since(start) 62 ru := ruf.ResourceUsageFromFinishedCmd(cmd) 63 64 log.Infof("got resource usage: %#v", ru) 65 66 // Can CPU time be > observed wall-time if multiple cores are involved? 67 if err := checkFloat64("UserCPUMillis", ru.UserCPUMillis, 0.0, runTime.Seconds()*1000.0); err != nil { 68 t.Error(err) 69 } 70 if err := checkFloat64("SystemCPUMillis", ru.SystemCPUMillis, 0.0, runTime.Seconds()*1000.0); err != nil { 71 t.Error(err) 72 } 73 74 if ru.Timestamp.Before(start) { 75 t.Errorf("Expected timestamp to be at least %v, but it was %v", start, ru.Timestamp) 76 } 77 } 78 79 func TestResourceUsageForPID(t *testing.T) { 80 ruf := ResourceUsageFetcher{} 81 log.Infof("Testing resource usage on [%s, %s]", runtime.GOARCH, runtime.GOOS) 82 // Generate some system (os.listdir) and user (everything else) execution 83 // time, consume some memory... 84 cmd := exec.Command("python", "-c", ` 85 import os 86 import time 87 88 s = "" 89 for i in range(5000): 90 s += str(i) 91 92 t0 = time.time() 93 while time.time() - t0 < 60.: 94 os.listdir(".") 95 `) 96 start := time.Now() 97 if err := cmd.Start(); err != nil { 98 t.Fatalf("Unexpected error from Run(): %v", err) 99 } 100 defer func() { 101 if err := cmd.Process.Kill(); err != nil { 102 t.Errorf("Error killing cmd: %v", err) 103 } 104 if err := cmd.Wait(); err != nil { 105 log.Errorf("Error waiting for cmd: %v", err) 106 } 107 }() 108 time.Sleep(3 * time.Second) 109 runTime := time.Since(start) 110 ru, err := ruf.ResourceUsageForPID(cmd.Process.Pid) 111 if err != nil { 112 t.Fatalf("Error getting ResourceUsageForPid: %v", err) 113 } 114 log.Infof("got resource usage: %#v", ru) 115 116 // Can CPU time be > observed wall-time if multiple cores are involved? 117 if err := checkFloat64("UserCPUMillis", ru.UserCPUMillis, 0.0, runTime.Seconds()*1000.0); err != nil { 118 t.Error(err) 119 } 120 if err := checkFloat64("SystemCPUMillis", ru.SystemCPUMillis, 0.0, runTime.Seconds()*1000.0); err != nil { 121 t.Error(err) 122 } 123 124 if ru.Timestamp.Before(start) { 125 t.Errorf("Expected timestamp to be at least %v, but it was %v", start, ru.Timestamp) 126 } 127 if err := checkInt64("resident memory", ru.ResidentMemory, 128*1024, 100*1024*1024); err != nil { 128 t.Error(err) 129 } 130 131 if runtime.GOOS == "linux" { 132 if ru.NumFDs == 0 { 133 t.Errorf("Expected NumFDs to be non-0.") 134 } 135 } else { 136 if ru.NumFDs != 0 { 137 t.Errorf("Expected NumFDs to always be 0 on non-Linux systems.") 138 } 139 } 140 141 debugStatus, err := ruf.DebugStatusForPID(cmd.Process.Pid) 142 if err != nil { 143 t.Fatal(err) 144 } 145 if debugStatus == "" { 146 t.Error("Expected debug status to be non-empty.") 147 } 148 }