github.com/ubuntu/ubuntu-report@v1.7.4-0.20240410144652-96f37d845fac/internal/metrics/metrics_test.go (about) 1 package metrics_test 2 3 import ( 4 "context" 5 "encoding/json" 6 "os/exec" 7 "path/filepath" 8 "testing" 9 10 "github.com/ubuntu/ubuntu-report/internal/helper" 11 "github.com/ubuntu/ubuntu-report/internal/metrics" 12 ) 13 14 func TestGetIDS(t *testing.T) { 15 t.Parallel() 16 17 testCases := []struct { 18 name string 19 root string 20 21 wantDistro string 22 wantVersion string 23 wantErr bool 24 }{ 25 {"regular", "testdata/good", "ubuntu", "18.04", false}, 26 {"doesn't exist", "testdata/none", "", "", true}, 27 {"empty file", "testdata/empty", "", "", true}, 28 {"missing distro", "testdata/missing-fields/ids/distro", "", "", true}, 29 {"missing version", "testdata/missing-fields/ids/version", "", "", true}, 30 {"missing both", "testdata/missing-fields/ids/both", "", "", true}, 31 {"empty distro", "testdata/empty-fields/ids/distro", "", "", true}, 32 {"empty version", "testdata/empty-fields/ids/version", "", "", true}, 33 {"empty both", "testdata/empty-fields/ids/both", "", "", true}, 34 {"garbage content", "testdata/garbage", "", "", true}, 35 } 36 for _, tc := range testCases { 37 tc := tc // capture range variable for parallel execution 38 t.Run(tc.name, func(t *testing.T) { 39 t.Parallel() 40 a := helper.Asserter{T: t} 41 42 m := newTestMetrics(t, metrics.WithRootAt(tc.root)) 43 d, v, err := m.GetIDS() 44 45 a.CheckWantedErr(err, tc.wantErr) 46 a.Equal(d, tc.wantDistro) 47 a.Equal(v, tc.wantVersion) 48 }) 49 } 50 } 51 52 func TestCollect(t *testing.T) { 53 t.Parallel() 54 55 testCases := []struct { 56 name string 57 root string 58 caseGPU string 59 caseCPU string 60 caseScreen string 61 casePartition string 62 caseArchitecture string 63 caseLibc6 string 64 caseHwCap string 65 env map[string]string 66 67 // note that only an internal json package error can make it returning an error 68 wantErr bool 69 }{ 70 {"regular", 71 "testdata/good", "one gpu", "regular", "one screen", 72 "one partition", "regular", "regular", "regular", 73 map[string]string{"XDG_CURRENT_DESKTOP": "some:thing", "XDG_SESSION_DESKTOP": "ubuntusession", "XDG_SESSION_TYPE": "x12", "LANG": "fr_FR.UTF-8", "LANGUAGE": "fr_FR.UTF-8"}, 74 false}, 75 {"empty", 76 "testdata/none", "empty", "empty", "empty", "empty", "empty", "empty", "empty", 77 nil, 78 false}, 79 } 80 for _, tc := range testCases { 81 tc := tc // capture range variable for parallel execution 82 t.Run(tc.name, func(t *testing.T) { 83 t.Parallel() 84 a := helper.Asserter{T: t} 85 86 cmdGPU, cancel := newMockShortCmd(t, "lspci", "-n", tc.caseGPU) 87 defer cancel() 88 cmdCPU, cancel := newMockShortCmd(t, "lscpu", "-J", tc.caseCPU) 89 defer cancel() 90 cmdScreen, cancel := newMockShortCmd(t, "xrandr", tc.caseScreen) 91 defer cancel() 92 cmdPartition, cancel := newMockShortCmd(t, "df", tc.casePartition) 93 defer cancel() 94 cmdArchitecture, cancel := newMockShortCmd(t, "dpkg", "--print-architecture", tc.caseArchitecture) 95 defer cancel() 96 cmdLibc6, cancel := newMockShortCmd(t, "dpkg", "--status", "libc6", tc.caseHwCap) 97 defer cancel() 98 cmdHwCap, cancel := newMockShortCmd(t, "/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2", "--help", tc.caseHwCap) 99 defer cancel() 100 101 m := newTestMetrics(t, metrics.WithRootAt(tc.root), 102 metrics.WithGPUInfoCommand(cmdGPU), 103 metrics.WithCPUInfoCommand(cmdCPU), 104 metrics.WithScreenInfoCommand(cmdScreen), 105 metrics.WithSpaceInfoCommand(cmdPartition), 106 metrics.WithArchitectureCommand(cmdArchitecture), 107 metrics.WithHwCapCommand(cmdHwCap), 108 metrics.WithLibc6Command(cmdLibc6), 109 metrics.WithMapForEnv(tc.env)) 110 got, err := m.Collect() 111 112 want := helper.LoadOrUpdateGolden(t, filepath.Join(tc.root, "gold", "collect"), got, *metrics.Update) 113 a.CheckWantedErr(err, tc.wantErr) 114 a.Equal(got, want) 115 }) 116 } 117 } 118 119 func TestRunCollectTwice(t *testing.T) { 120 t.Parallel() 121 122 testCases := []struct { 123 name string 124 root string 125 caseGPU string 126 caseCPU string 127 caseScreen string 128 casePartition string 129 caseArchitecture string 130 caseLibc6 string 131 caseHwCap string 132 env map[string]string 133 134 // note that only an internal json package error can make it returning an error 135 wantErr bool 136 }{ 137 {"regular", 138 "testdata/good", "one gpu", "regular", "one screen", 139 "one partition", "regular", "regular", "regular", 140 map[string]string{"XDG_CURRENT_DESKTOP": "some:thing", "XDG_SESSION_DESKTOP": "ubuntusession", "XDG_SESSION_TYPE": "x12", "LANG": "fr_FR.UTF-8", "LANGUAGE": "fr_FR.UTF-8"}, 141 false}, 142 {"empty", 143 "testdata/none", "empty", "empty", "empty", "empty", "empty", "empty", "empty", 144 nil, 145 false}, 146 } 147 for _, tc := range testCases { 148 tc := tc // capture range variable for parallel execution 149 t.Run(tc.name, func(t *testing.T) { 150 t.Parallel() 151 a := helper.Asserter{T: t} 152 153 cmdGPU, cancel := newMockShortCmd(t, "lspci", "-n", tc.caseGPU) 154 defer cancel() 155 cmdCPU, cancel := newMockShortCmd(t, "lscpu", "-J", tc.caseCPU) 156 defer cancel() 157 cmdScreen, cancel := newMockShortCmd(t, "xrandr", tc.caseScreen) 158 defer cancel() 159 cmdPartition, cancel := newMockShortCmd(t, "df", tc.casePartition) 160 defer cancel() 161 cmdArchitecture, cancel := newMockShortCmd(t, "dpkg", "--print-architecture", tc.caseArchitecture) 162 defer cancel() 163 cmdLibc6, cancel := newMockShortCmd(t, "dpkg", "--status", "libc6", tc.caseHwCap) 164 defer cancel() 165 cmdHwCap, cancel := newMockShortCmd(t, "/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2", "--help", tc.caseHwCap) 166 defer cancel() 167 168 m := newTestMetrics(t, metrics.WithRootAt(tc.root), 169 metrics.WithGPUInfoCommand(cmdGPU), 170 metrics.WithCPUInfoCommand(cmdCPU), 171 metrics.WithScreenInfoCommand(cmdScreen), 172 metrics.WithSpaceInfoCommand(cmdPartition), 173 metrics.WithArchitectureCommand(cmdArchitecture), 174 metrics.WithHwCapCommand(cmdHwCap), 175 metrics.WithLibc6Command(cmdLibc6), 176 metrics.WithMapForEnv(tc.env)) 177 b1, err1 := m.Collect() 178 179 cmdGPU, cancel = newMockShortCmd(t, "lspci", "-n", tc.caseGPU) 180 defer cancel() 181 cmdCPU, cancel = newMockShortCmd(t, "lscpu", "-J", tc.caseCPU) 182 defer cancel() 183 cmdScreen, cancel = newMockShortCmd(t, "xrandr", tc.caseScreen) 184 defer cancel() 185 cmdPartition, cancel = newMockShortCmd(t, "df", tc.casePartition) 186 defer cancel() 187 cmdArchitecture, cancel = newMockShortCmd(t, "dpkg", "--print-architecture", tc.caseArchitecture) 188 defer cancel() 189 cmdLibc6, cancel = newMockShortCmd(t, "dpkg", "--status", "libc6", tc.caseHwCap) 190 defer cancel() 191 cmdHwCap, cancel = newMockShortCmd(t, "/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2", "--help", tc.caseHwCap) 192 defer cancel() 193 m = newTestMetrics(t, metrics.WithRootAt(tc.root), 194 metrics.WithGPUInfoCommand(cmdGPU), 195 metrics.WithCPUInfoCommand(cmdCPU), 196 metrics.WithScreenInfoCommand(cmdScreen), 197 metrics.WithSpaceInfoCommand(cmdPartition), 198 metrics.WithArchitectureCommand(cmdArchitecture), 199 metrics.WithHwCapCommand(cmdHwCap), 200 metrics.WithLibc6Command(cmdLibc6), 201 metrics.WithMapForEnv(tc.env)) 202 b2, err2 := m.Collect() 203 204 a.CheckWantedErr(err1, tc.wantErr) 205 a.CheckWantedErr(err2, tc.wantErr) 206 var got1, got2 json.RawMessage 207 json.Unmarshal(b1, &got1) 208 json.Unmarshal(b2, &got2) 209 210 a.Equal(got1, got2) 211 }) 212 } 213 } 214 215 func newTestMetrics(t *testing.T, fixtures ...func(m *metrics.Metrics) error) metrics.Metrics { 216 t.Helper() 217 m, err := metrics.New(fixtures...) 218 if err != nil { 219 t.Fatal("can't create metrics object", err) 220 } 221 return m 222 } 223 224 func newMockShortCmd(t *testing.T, s ...string) (*exec.Cmd, context.CancelFunc) { 225 t.Helper() 226 return helper.ShortProcess(t, "TestMetricsHelperProcess", s...) 227 }