1package net 2 3import ( 4 "fmt" 5 "io/ioutil" 6 "net" 7 "os" 8 "strings" 9 "syscall" 10 "testing" 11 12 "github.com/shirou/gopsutil/internal/common" 13 "github.com/stretchr/testify/assert" 14) 15 16func TestIOCountersByFileParsing(t *testing.T) { 17 // Prpare a temporary file, which will be read during the test 18 tmpfile, err := ioutil.TempFile("", "proc_dev_net") 19 defer os.Remove(tmpfile.Name()) // clean up 20 21 assert.Nil(t, err, "Temporary file creation failed: ", err) 22 23 cases := [4][2]string{ 24 [2]string{"eth0: ", "eth1: "}, 25 [2]string{"eth0:0: ", "eth1:0: "}, 26 [2]string{"eth0:", "eth1:"}, 27 [2]string{"eth0:0:", "eth1:0:"}, 28 } 29 for _, testCase := range cases { 30 err = tmpfile.Truncate(0) 31 assert.Nil(t, err, "Temporary file truncating problem: ", err) 32 33 // Parse interface name for assertion 34 interface0 := strings.TrimSpace(testCase[0]) 35 interface0 = interface0[:len(interface0)-1] 36 37 interface1 := strings.TrimSpace(testCase[1]) 38 interface1 = interface1[:len(interface1)-1] 39 40 // Replace the interfaces from the test case 41 proc := []byte(fmt.Sprintf("Inter-| Receive | Transmit\n face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed\n %s1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16\n %s100 200 300 400 500 600 700 800 900 1000 1100 1200 1300 1400 1500 1600\n", testCase[0], testCase[1])) 42 43 // Write /proc/net/dev sample output 44 _, err = tmpfile.Write(proc) 45 assert.Nil(t, err, "Temporary file writing failed: ", err) 46 47 counters, err := IOCountersByFile(true, tmpfile.Name()) 48 49 assert.Nil(t, err) 50 assert.NotEmpty(t, counters) 51 assert.Equal(t, 2, len(counters)) 52 assert.Equal(t, interface0, counters[0].Name) 53 assert.Equal(t, 1, int(counters[0].BytesRecv)) 54 assert.Equal(t, 2, int(counters[0].PacketsRecv)) 55 assert.Equal(t, 3, int(counters[0].Errin)) 56 assert.Equal(t, 4, int(counters[0].Dropin)) 57 assert.Equal(t, 5, int(counters[0].Fifoin)) 58 assert.Equal(t, 9, int(counters[0].BytesSent)) 59 assert.Equal(t, 10, int(counters[0].PacketsSent)) 60 assert.Equal(t, 11, int(counters[0].Errout)) 61 assert.Equal(t, 12, int(counters[0].Dropout)) 62 assert.Equal(t, 13, int(counters[0].Fifoout)) 63 assert.Equal(t, interface1, counters[1].Name) 64 assert.Equal(t, 100, int(counters[1].BytesRecv)) 65 assert.Equal(t, 200, int(counters[1].PacketsRecv)) 66 assert.Equal(t, 300, int(counters[1].Errin)) 67 assert.Equal(t, 400, int(counters[1].Dropin)) 68 assert.Equal(t, 500, int(counters[1].Fifoin)) 69 assert.Equal(t, 900, int(counters[1].BytesSent)) 70 assert.Equal(t, 1000, int(counters[1].PacketsSent)) 71 assert.Equal(t, 1100, int(counters[1].Errout)) 72 assert.Equal(t, 1200, int(counters[1].Dropout)) 73 assert.Equal(t, 1300, int(counters[1].Fifoout)) 74 } 75 76 err = tmpfile.Close() 77 assert.Nil(t, err, "Temporary file closing failed: ", err) 78} 79 80func TestGetProcInodesAll(t *testing.T) { 81 waitForServer := make(chan bool) 82 go func() { // TCP listening goroutine to have some opened inodes even in CI 83 addr, err := net.ResolveTCPAddr("tcp", "localhost:0") // dynamically get a random open port from OS 84 if err != nil { 85 t.Skip("unable to resolve localhost:", err) 86 } 87 l, err := net.ListenTCP(addr.Network(), addr) 88 if err != nil { 89 t.Skip(fmt.Sprintf("unable to listen on %v: %v", addr, err)) 90 } 91 defer l.Close() 92 waitForServer <- true 93 for { 94 conn, err := l.Accept() 95 if err != nil { 96 t.Skip("unable to accept connection:", err) 97 } 98 defer conn.Close() 99 } 100 }() 101 <-waitForServer 102 103 root := common.HostProc("") 104 v, err := getProcInodesAll(root, 0) 105 assert.Nil(t, err) 106 assert.NotEmpty(t, v) 107} 108 109func TestConnectionsMax(t *testing.T) { 110 if os.Getenv("CI") != "" { 111 t.Skip("Skip CI") 112 } 113 114 max := 10 115 v, err := ConnectionsMax("tcp", max) 116 assert.Nil(t, err) 117 assert.NotEmpty(t, v) 118 119 cxByPid := map[int32]int{} 120 for _, cx := range v { 121 if cx.Pid > 0 { 122 cxByPid[cx.Pid]++ 123 } 124 } 125 for _, c := range cxByPid { 126 assert.True(t, c <= max) 127 } 128} 129 130type AddrTest struct { 131 IP string 132 Port int 133 Error bool 134} 135 136func TestDecodeAddress(t *testing.T) { 137 assert := assert.New(t) 138 139 addr := map[string]AddrTest{ 140 "0500000A:0016": { 141 IP: "10.0.0.5", 142 Port: 22, 143 }, 144 "0100007F:D1C2": { 145 IP: "127.0.0.1", 146 Port: 53698, 147 }, 148 "11111:0035": { 149 Error: true, 150 }, 151 "0100007F:BLAH": { 152 Error: true, 153 }, 154 "0085002452100113070057A13F025401:0035": { 155 IP: "2400:8500:1301:1052:a157:7:154:23f", 156 Port: 53, 157 }, 158 "00855210011307F025401:0035": { 159 Error: true, 160 }, 161 } 162 163 for src, dst := range addr { 164 family := syscall.AF_INET 165 if len(src) > 13 { 166 family = syscall.AF_INET6 167 } 168 addr, err := decodeAddress(uint32(family), src) 169 if dst.Error { 170 assert.NotNil(err, src) 171 } else { 172 assert.Nil(err, src) 173 assert.Equal(dst.IP, addr.IP, src) 174 assert.Equal(dst.Port, int(addr.Port), src) 175 } 176 } 177} 178 179func TestReverse(t *testing.T) { 180 src := []byte{0x01, 0x02, 0x03} 181 assert.Equal(t, []byte{0x03, 0x02, 0x01}, Reverse(src)) 182} 183 184func TestConntrackStatFileParsing(t *testing.T) { 185 tmpfile, err := ioutil.TempFile("", "proc_net_stat_conntrack") 186 defer os.Remove(tmpfile.Name()) 187 assert.Nil(t, err, "Temporary file creation failed: ", err) 188 189 data := []byte(` 190entries searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete search_restart 1910000007b 00000000 00000000 00000000 000b115a 00000084 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000004a 1920000007b 00000000 00000000 00000000 0007eee5 00000068 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000035 1930000007b 00000000 00000000 00000000 0090346b 00000057 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000025 1940000007b 00000000 00000000 00000000 0005920f 00000069 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000064 1950000007b 00000000 00000000 00000000 000331ff 00000059 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000003b 1960000007b 00000000 00000000 00000000 000314ea 00000066 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000054 1970000007b 00000000 00000000 00000000 0002b270 00000055 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000003d 1980000007b 00000000 00000000 00000000 0002f67d 00000057 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000042 199`) 200 201 // Expected results 202 slist := NewConntrackStatList() 203 204 slist.Append(&ConntrackStat{ 205 Entries: 123, 206 Searched: 0, 207 Found: 0, 208 New: 0, 209 Invalid: 725338, 210 Ignore: 132, 211 Delete: 0, 212 DeleteList: 0, 213 Insert: 0, 214 InsertFailed: 0, 215 Drop: 0, 216 EarlyDrop: 0, 217 IcmpError: 0, 218 ExpectNew: 0, 219 ExpectCreate: 0, 220 ExpectDelete: 0, 221 SearchRestart: 74, 222 }) 223 slist.Append(&ConntrackStat{123, 0, 0, 0, 519909, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53}) 224 225 slist.Append(&ConntrackStat{123, 0, 0, 0, 9450603, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37}) 226 slist.Append(&ConntrackStat{123, 0, 0, 0, 365071, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100}) 227 228 slist.Append(&ConntrackStat{123, 0, 0, 0, 209407, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59}) 229 slist.Append(&ConntrackStat{123, 0, 0, 0, 201962, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84}) 230 231 slist.Append(&ConntrackStat{123, 0, 0, 0, 176752, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61}) 232 slist.Append(&ConntrackStat{123, 0, 0, 0, 194173, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66}) 233 234 // Write data to tempfile 235 _, err = tmpfile.Write(data) 236 assert.Nil(t, err, "Temporary file writing failed: ", err) 237 238 // Function under test 239 stats, err := conntrackStatsFromFile(tmpfile.Name(), true) 240 assert.Equal(t, 8, len(stats), "Expected 8 results") 241 242 summary := &ConntrackStat{} 243 for i, exp := range slist.Items() { 244 st := stats[i] 245 246 assert.Equal(t, exp.Entries, st.Entries) 247 summary.Entries += st.Entries 248 249 assert.Equal(t, exp.Searched, st.Searched) 250 summary.Searched += st.Searched 251 252 assert.Equal(t, exp.Found, st.Found) 253 summary.Found += st.Found 254 255 assert.Equal(t, exp.New, st.New) 256 summary.New += st.New 257 258 assert.Equal(t, exp.Invalid, st.Invalid) 259 summary.Invalid += st.Invalid 260 261 assert.Equal(t, exp.Ignore, st.Ignore) 262 summary.Ignore += st.Ignore 263 264 assert.Equal(t, exp.Delete, st.Delete) 265 summary.Delete += st.Delete 266 267 assert.Equal(t, exp.DeleteList, st.DeleteList) 268 summary.DeleteList += st.DeleteList 269 270 assert.Equal(t, exp.Insert, st.Insert) 271 summary.Insert += st.Insert 272 273 assert.Equal(t, exp.InsertFailed, st.InsertFailed) 274 summary.InsertFailed += st.InsertFailed 275 276 assert.Equal(t, exp.Drop, st.Drop) 277 summary.Drop += st.Drop 278 279 assert.Equal(t, exp.EarlyDrop, st.EarlyDrop) 280 summary.EarlyDrop += st.EarlyDrop 281 282 assert.Equal(t, exp.IcmpError, st.IcmpError) 283 summary.IcmpError += st.IcmpError 284 285 assert.Equal(t, exp.ExpectNew, st.ExpectNew) 286 summary.ExpectNew += st.ExpectNew 287 288 assert.Equal(t, exp.ExpectCreate, st.ExpectCreate) 289 summary.ExpectCreate += st.ExpectCreate 290 291 assert.Equal(t, exp.ExpectDelete, st.ExpectDelete) 292 summary.ExpectDelete += st.ExpectDelete 293 294 assert.Equal(t, exp.SearchRestart, st.SearchRestart) 295 summary.SearchRestart += st.SearchRestart 296 } 297 298 // Test summary grouping 299 totals, err := conntrackStatsFromFile(tmpfile.Name(), false) 300 for i, st := range totals { 301 assert.Equal(t, summary.Entries, st.Entries) 302 assert.Equal(t, summary.Searched, st.Searched) 303 assert.Equal(t, summary.Found, st.Found) 304 assert.Equal(t, summary.New, st.New) 305 assert.Equal(t, summary.Invalid, st.Invalid) 306 assert.Equal(t, summary.Ignore, st.Ignore) 307 assert.Equal(t, summary.Delete, st.Delete) 308 assert.Equal(t, summary.DeleteList, st.DeleteList) 309 assert.Equal(t, summary.Insert, st.Insert) 310 assert.Equal(t, summary.InsertFailed, st.InsertFailed) 311 assert.Equal(t, summary.Drop, st.Drop) 312 assert.Equal(t, summary.EarlyDrop, st.EarlyDrop) 313 assert.Equal(t, summary.IcmpError, st.IcmpError) 314 assert.Equal(t, summary.ExpectNew, st.ExpectNew) 315 assert.Equal(t, summary.ExpectCreate, st.ExpectCreate) 316 assert.Equal(t, summary.ExpectDelete, st.ExpectDelete) 317 assert.Equal(t, summary.SearchRestart, st.SearchRestart) 318 319 assert.Equal(t, 0, i) // Should only have one element 320 } 321} 322