github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/utils/cgnetcls/cgnetcls_test.go (about) 1 // +build linux 2 3 package cgnetcls 4 5 import ( 6 "fmt" 7 "io/ioutil" 8 "math/rand" 9 "os" 10 "path/filepath" 11 "strconv" 12 "strings" 13 "syscall" 14 "testing" 15 16 markconstants "go.aporeto.io/enforcerd/trireme-lib/utils/constants" 17 ) 18 19 // This package does not use interfaces/objects from other trireme component so we don't need to mock anything here 20 // We will create actual system objects 21 // This can be tested only on linux since the directory structure will not exist anywhere else 22 // Tests here will be skipped if you don't run as root 23 24 const ( 25 testcgroupname = "/test" 26 testcgroupnameformat = "test" 27 testmark = 100 28 testRootUser = "root" 29 ) 30 31 func cleanupnetclsgroup() { 32 data, _ := ioutil.ReadFile(filepath.Join(cgroupNetClsPath, testcgroupname, procs)) 33 fmt.Println(string(data)) 34 _ = ioutil.WriteFile(filepath.Join(cgroupNetClsPath, procs), data, 0644) 35 _ = os.RemoveAll(filepath.Join(cgroupNetClsPath, testcgroupname)) 36 } 37 38 func TestCreategroup(t *testing.T) { 39 40 if os.Getenv("USER") != testRootUser { 41 t.SkipNow() 42 } 43 44 cg := NewCgroupNetController("/tmp", "") 45 if err := cg.Creategroup(testcgroupnameformat); err != nil { 46 //Check if all the files required are created 47 t.Errorf("Failed to create group error returned %s", err.Error()) 48 } 49 50 defer cleanupnetclsgroup() 51 52 if _, err := ioutil.ReadFile(filepath.Join(cgroupNetClsPath, releaseAgentConfFile)); err != nil { 53 if os.IsNotExist(err) { 54 t.Errorf("ReleaseAgentConf File does not exist.Cgroup mount failed") 55 t.SkipNow() 56 } 57 } 58 59 if val, err := ioutil.ReadFile(filepath.Join(cgroupNetClsPath, notifyOnReleaseFile)); err != nil { 60 if os.IsNotExist(err) { 61 t.Errorf("Notify on release file does not exist.Cgroup mount failed") 62 t.SkipNow() 63 } 64 } else { 65 if strings.TrimSpace(string(val)) != "1" { 66 t.Errorf("Notify release file in base net_cls not programmed") 67 t.SkipNow() 68 } 69 } 70 71 if val, err := ioutil.ReadFile(filepath.Join(cgroupNetClsPath, notifyOnReleaseFile)); err != nil { 72 if os.IsNotExist(err) { 73 t.Errorf("Notify on release file does not exist.Cgroup mount failed") 74 t.SkipNow() 75 } 76 } else { 77 if strings.TrimSpace(string(val)) != "1" { 78 t.Errorf("Notify release file in aporeto base dir /sys/fs/cgroup/aporeto not programmed") 79 t.SkipNow() 80 } 81 } 82 83 if val, err := ioutil.ReadFile(filepath.Join(cgroupNetClsPath, testcgroupname, notifyOnReleaseFile)); err != nil { 84 if os.IsNotExist(err) { 85 t.Errorf("Notify on release file does not exist.Cgroup mount failed") 86 t.SkipNow() 87 } 88 } else { 89 if strings.TrimSpace(string(val)) != "1" { 90 t.Errorf("Notify release file in cgroup not programmed") 91 t.SkipNow() 92 } 93 } 94 } 95 96 func TestAssignMark(t *testing.T) { 97 cg := NewCgroupNetController("/tmp", "") 98 if os.Getenv("USER") != testRootUser { 99 t.SkipNow() 100 } 101 //Assigning mark before creating group 102 if err := cg.AssignMark(testcgroupname, testmark); err == nil { 103 t.Errorf("Assign mark succeeded without a valid group being present ") 104 t.SkipNow() 105 } 106 if err := cg.Creategroup(testcgroupnameformat); err != nil { 107 t.Errorf("Error creating cgroup %s", err) 108 t.SkipNow() 109 } 110 111 defer cleanupnetclsgroup() 112 113 if err := cg.AssignMark(testcgroupnameformat, testmark); err != nil { 114 t.Errorf("Failed to assign mark error = %s", err.Error()) 115 t.SkipNow() 116 } else { 117 data, _ := ioutil.ReadFile(filepath.Join(cgroupNetClsPath, testcgroupname, markFile)) 118 u, err := strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64) 119 if err != nil { 120 t.Errorf("Non Integer mark value in classid file") 121 t.SkipNow() 122 } 123 if u != testmark { 124 t.Errorf("Unexpected mark val expected %d, read %d", testmark, u) 125 t.SkipNow() 126 } 127 } 128 } 129 130 func TestAddProcess(t *testing.T) { 131 //hopefully this pid does not exist 132 pid := 1<<31 - 1 133 r := rand.New(rand.NewSource(23)) 134 if os.Getenv("USER") != testRootUser { 135 t.SkipNow() 136 } 137 cg := NewCgroupNetController("/tmp", "") 138 //AddProcess to a non-existent group 139 if err := cg.AddProcess(testcgroupname, os.Getpid()); err == nil { 140 t.Errorf("Process successfully added to a non existent group") 141 t.SkipNow() 142 } 143 if err := cg.Creategroup(testcgroupnameformat); err != nil { 144 t.Errorf("Error creating cgroup") 145 t.SkipNow() 146 } 147 148 defer cleanupnetclsgroup() 149 150 //Add a non-existent process 151 //loop to find non-existent pid 152 for { 153 if err := syscall.Kill(pid, 0); err != nil { 154 break 155 } 156 pid = r.Int() 157 158 } 159 if err := cg.AddProcess(testcgroupnameformat, pid); err != nil { 160 t.Errorf("Unexpected error not returned for non-existent process") 161 t.SkipNow() 162 } 163 pid = 1 //Guaranteed to be present 164 if err := cg.AddProcess(testcgroupname, pid); err != nil { 165 t.Errorf("Failed to add process %s", err.Error()) 166 t.SkipNow() 167 } else { 168 //This directory structure should not be delete 169 if err := os.RemoveAll(filepath.Join(cgroupNetClsPath, testcgroupname)); err == nil { 170 t.Errorf("Process not added to cgroup") 171 t.SkipNow() 172 } 173 } 174 } 175 176 func TestRemoveProcess(t *testing.T) { 177 if os.Getenv("USER") != testRootUser { 178 t.SkipNow() 179 } 180 cg := NewCgroupNetController("/tmp", "") 181 //Removing process from non-existent group 182 if err := cg.RemoveProcess(testcgroupname, 1); err == nil { 183 t.Errorf("RemoveProcess succeeded without valid group being present ") 184 t.SkipNow() 185 } 186 if err := cg.Creategroup(testcgroupnameformat); err != nil { 187 t.Errorf("Error creating cgroup") 188 t.SkipNow() 189 } 190 191 defer cleanupnetclsgroup() 192 193 if err := cg.AddProcess(testcgroupname, 1); err != nil { 194 t.Errorf("Error adding process") 195 t.SkipNow() 196 } 197 if err := cg.RemoveProcess(testcgroupnameformat, 10); err == nil { 198 t.Errorf("Removed process which was not a part of this cgroup") 199 t.SkipNow() 200 } 201 if err := cg.RemoveProcess(testcgroupname, 1); err != nil { 202 t.Errorf("Failed to remove process %s", err.Error()) 203 t.SkipNow() 204 } 205 } 206 207 func TestDeleteCgroup(t *testing.T) { 208 if os.Getenv("USER") != testRootUser { 209 t.SkipNow() 210 } 211 cg := NewCgroupNetController("/tmp", "") 212 //Removing process from non-existent group 213 if err := cg.DeleteCgroup(testcgroupnameformat); err != nil { 214 t.Errorf("Non-existent cgroup delelte returned an error") 215 t.SkipNow() 216 } 217 if err := cg.Creategroup(testcgroupname); err != nil { 218 t.Errorf("Failed to create cgroup %s", err.Error()) 219 t.SkipNow() 220 } 221 222 defer cleanupnetclsgroup() 223 224 if err := cg.DeleteCgroup(testcgroupname); err != nil { 225 t.Errorf("Failed to delete cgroup %s", err.Error()) 226 t.SkipNow() 227 } 228 229 } 230 231 func TestDeleteBasePath(t *testing.T) { 232 if os.Getenv("USER") != testRootUser { 233 t.SkipNow() 234 } 235 cg := NewCgroupNetController("/tmp", "") 236 //Removing process from non-existent group 237 if err := cg.DeleteCgroup(testcgroupname); err != nil { 238 t.Errorf("Delete of group failed %s", err.Error()) 239 } 240 241 defer cleanupnetclsgroup() 242 243 cg.Deletebasepath(testcgroupnameformat) 244 _, err := os.Stat(filepath.Join(cgroupNetClsPath, testcgroupname)) 245 if err == nil { 246 t.Errorf("Delete of cgroup from system failed") 247 t.SkipNow() 248 } 249 } 250 251 func TestListCgroupProcesses(t *testing.T) { 252 pid := 1<<31 - 1 253 r := rand.New(rand.NewSource(23)) 254 if os.Getenv("USER") != testRootUser { 255 t.SkipNow() 256 } 257 cg := NewCgroupNetController("/tmp", "") 258 259 _, err := cg.ListCgroupProcesses(testcgroupname) 260 if err == nil { 261 t.Errorf("No process found but succeeded") 262 } 263 //AddProcess to a non-existent group 264 if err = cg.AddProcess(testcgroupname, os.Getpid()); err == nil { 265 t.Errorf("Process successfully added to a non existent group") 266 t.SkipNow() 267 } 268 if err = cg.Creategroup(testcgroupname); err != nil { 269 t.Errorf("Error creating cgroup") 270 t.SkipNow() 271 } 272 273 defer cleanupnetclsgroup() 274 275 //Add a non-existent process 276 //loop to find non-existent pid 277 for { 278 if err = syscall.Kill(pid, 0); err != nil { 279 break 280 } 281 pid = r.Int() 282 283 } 284 285 pid = 1 //Guaranteed to be present 286 if err = cg.AddProcess(testcgroupname, pid); err != nil { 287 t.Errorf("Failed to add process %s", err.Error()) 288 t.SkipNow() 289 } else { 290 //This directory structure should not be delete 291 if err = os.RemoveAll(filepath.Join(cgroupNetClsPath, testcgroupname)); err == nil { 292 t.Errorf("Process not added to cgroup") 293 t.SkipNow() 294 } 295 } 296 297 procs, err := cg.ListCgroupProcesses(testcgroupname) 298 if procs[0] != "1" && err != nil { 299 t.Errorf("No process found %d", err) 300 } 301 } 302 303 func TestMarkVal(t *testing.T) { 304 type test struct { 305 name string 306 want uint64 307 } 308 // this is kind of silly, but as this is an atomic counter, 309 // there is no other way than to really count up and compare 310 generateTests := func() []test { 311 ret := []test{} 312 i := 1 313 for { 314 want := i + markconstants.Initialmarkval 315 // this is the exception, in this case we should get plus one 316 if want >= markconstants.EnforcerCgroupMark { 317 want++ 318 } 319 ret = append(ret, test{ 320 name: strconv.Itoa(i + markconstants.Initialmarkval), 321 want: uint64(want), 322 }) 323 // abort a couple tests after that 324 if want == markconstants.EnforcerCgroupMark+2 { 325 break 326 } 327 i++ 328 } 329 return ret 330 } 331 for _, tt := range generateTests() { 332 t.Run(tt.name, func(t *testing.T) { 333 got := MarkVal() 334 t.Logf("test %s, markVal %d", tt.name, got) 335 if got != tt.want { 336 t.Errorf("MarkVal() = %v, want %v", got, tt.want) 337 } 338 }) 339 } 340 }