github.com/jaypipes/ghw@v0.21.1/pkg/topology/topology_linux_test.go (about) 1 // 2 // Use and distribution licensed under the Apache license version 2. 3 // 4 // See the COPYING file in the root project directory for full text. 5 // 6 7 package topology_test 8 9 import ( 10 "encoding/json" 11 "path/filepath" 12 "testing" 13 14 "github.com/jaypipes/ghw/pkg/memory" 15 "github.com/jaypipes/ghw/pkg/option" 16 "github.com/jaypipes/ghw/pkg/topology" 17 18 "github.com/jaypipes/ghw/testdata" 19 ) 20 21 // nolint: gocyclo 22 func TestTopologyNUMADistances(t *testing.T) { 23 testdataPath, err := testdata.SnapshotsDirectory() 24 if err != nil { 25 t.Fatalf("Expected nil err, but got %v", err) 26 } 27 28 multiNumaSnapshot := filepath.Join(testdataPath, "linux-amd64-intel-xeon-L5640.tar.gz") 29 // from now on we use constants reflecting the content of the snapshot we requested, 30 // which we reviewed beforehand. IOW, you need to know the content of the 31 // snapshot to fully understand this test. Inspect it using 32 // GHW_SNAPSHOT_PATH="/path/to/linux-amd64-intel-xeon-L5640.tar.gz" ghwc topology 33 34 info, err := topology.New(option.WithSnapshot(option.SnapshotOptions{ 35 Path: multiNumaSnapshot, 36 })) 37 38 if err != nil { 39 t.Fatalf("Expected nil err, but got %v", err) 40 } 41 if info == nil { 42 t.Fatalf("Expected non-nil TopologyInfo, but got nil") 43 } 44 45 if len(info.Nodes) != 2 { 46 t.Fatalf("Expected 2 nodes but got 0.") 47 } 48 49 for _, n := range info.Nodes { 50 if len(n.Distances) != len(info.Nodes) { 51 t.Fatalf("Expected distances to all known nodes") 52 } 53 } 54 55 if info.Nodes[0].Distances[0] != info.Nodes[1].Distances[1] { 56 t.Fatalf("Expected symmetric distance to self, got %v and %v", info.Nodes[0].Distances, info.Nodes[1].Distances) 57 } 58 59 if info.Nodes[0].Distances[1] != info.Nodes[1].Distances[0] { 60 t.Fatalf("Expected symmetric distance to the other node, got %v and %v", info.Nodes[0].Distances, info.Nodes[1].Distances) 61 } 62 } 63 64 // we have this test in topology_linux_test.go (and not in topology_test.go) because `topologyFillInfo` 65 // is not implemented on darwin; so having it in the platform-independent tests would lead to false negatives. 66 func TestTopologyMarshalUnmarshal(t *testing.T) { 67 data, err := topology.New(option.WithNullAlerter()) 68 if err != nil { 69 t.Fatalf("Expected no error creating topology.Info, but got %v", err) 70 } 71 72 jdata, err := json.Marshal(data) 73 if err != nil { 74 t.Fatalf("Expected no error marshaling topology.Info, but got %v", err) 75 } 76 77 var topo *topology.Info 78 79 err = json.Unmarshal(jdata, &topo) 80 if err != nil { 81 t.Fatalf("Expected no error unmarshaling topology.Info, but got %v", err) 82 } 83 } 84 85 // nolint: gocyclo 86 func TestTopologyPerNUMAMemory(t *testing.T) { 87 testdataPath, err := testdata.SnapshotsDirectory() 88 if err != nil { 89 t.Fatalf("Expected nil err, but got %v", err) 90 } 91 92 multiNumaSnapshot := filepath.Join(testdataPath, "linux-amd64-intel-xeon-L5640.tar.gz") 93 // from now on we use constants reflecting the content of the snapshot we requested, 94 // which we reviewed beforehand. IOW, you need to know the content of the 95 // snapshot to fully understand this test. Inspect it using 96 // GHW_SNAPSHOT_PATH="/path/to/linux-amd64-intel-xeon-L5640.tar.gz" ghwc topology 97 98 memInfo, err := memory.New(option.WithSnapshot(option.SnapshotOptions{ 99 Path: multiNumaSnapshot, 100 })) 101 102 if err != nil { 103 t.Fatalf("Expected nil err, but got %v", err) 104 } 105 if memInfo == nil { 106 t.Fatalf("Expected non-nil MemoryInfo, but got nil") 107 } 108 109 info, err := topology.New(option.WithSnapshot(option.SnapshotOptions{ 110 Path: multiNumaSnapshot, 111 })) 112 113 if err != nil { 114 t.Fatalf("Expected nil err, but got %v", err) 115 } 116 if info == nil { 117 t.Fatalf("Expected non-nil TopologyInfo, but got nil") 118 } 119 120 if len(info.Nodes) != 2 { 121 t.Fatalf("Expected 2 nodes but got 0.") 122 } 123 124 for _, node := range info.Nodes { 125 if node.Memory == nil { 126 t.Fatalf("missing memory information for node %d", node.ID) 127 } 128 129 if node.Memory.TotalPhysicalBytes <= 0 { 130 t.Fatalf("negative physical size for node %d", node.ID) 131 } 132 if node.Memory.TotalPhysicalBytes > memInfo.TotalPhysicalBytes { 133 t.Fatalf("physical size for node %d exceeds system's", node.ID) 134 } 135 if node.Memory.TotalUsableBytes <= 0 { 136 t.Fatalf("negative usable size for node %d", node.ID) 137 } 138 if node.Memory.TotalUsableBytes > memInfo.TotalUsableBytes { 139 t.Fatalf("usable size for node %d exceeds system's", node.ID) 140 } 141 if node.Memory.TotalUsableBytes > node.Memory.TotalPhysicalBytes { 142 t.Fatalf("excessive usable size for node %d", node.ID) 143 } 144 if node.Memory.DefaultHugePageSize == 0 { 145 t.Fatalf("unexpected default HP size for node %d", node.ID) 146 } 147 if len(node.Memory.HugePageAmountsBySize) != 2 { 148 t.Fatalf("expected 2 huge page info records, but got '%d' for node %d", len(node.Memory.HugePageAmountsBySize), node.ID) 149 } 150 } 151 }