You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
scrutiny/collector/pkg/detect/detect_test.go

363 lines
12 KiB

package detect_test
import (
"os"
"strings"
"testing"
mock_shell "github.com/analogj/scrutiny/collector/pkg/common/shell/mock"
mock_config "github.com/analogj/scrutiny/collector/pkg/config/mock"
"github.com/analogj/scrutiny/collector/pkg/detect"
"github.com/analogj/scrutiny/collector/pkg/models"
"github.com/golang/mock/gomock"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestDetect_SmartctlScan(t *testing.T) {
// setup
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
fakeConfig := mock_config.NewMockInterface(mockCtrl)
fakeConfig.EXPECT().GetString("host.id").AnyTimes().Return("")
fakeConfig.EXPECT().GetDeviceOverrides().AnyTimes().Return([]models.ScanOverride{})
fakeConfig.EXPECT().GetString("commands.metrics_smartctl_bin").AnyTimes().Return("smartctl")
fakeConfig.EXPECT().GetString("commands.metrics_scan_args").AnyTimes().Return("--scan --json")
fakeShell := mock_shell.NewMockInterface(mockCtrl)
testScanResults, err := os.ReadFile("testdata/smartctl_scan_simple.json")
fakeShell.EXPECT().Command(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(string(testScanResults), err)
d := detect.Detect{
Logger: logrus.WithFields(logrus.Fields{}),
Shell: fakeShell,
Config: fakeConfig,
}
// test
scannedDevices, err := d.SmartctlScan()
// assert
require.NoError(t, err)
require.Equal(t, 7, len(scannedDevices))
require.Equal(t, "scsi", scannedDevices[0].DeviceType)
}
func TestDetect_SmartctlScan_Megaraid(t *testing.T) {
// setup
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
fakeConfig := mock_config.NewMockInterface(mockCtrl)
fakeConfig.EXPECT().GetString("host.id").AnyTimes().Return("")
fakeConfig.EXPECT().GetDeviceOverrides().AnyTimes().Return([]models.ScanOverride{})
fakeConfig.EXPECT().GetString("commands.metrics_smartctl_bin").AnyTimes().Return("smartctl")
fakeConfig.EXPECT().GetString("commands.metrics_scan_args").AnyTimes().Return("--scan --json")
fakeShell := mock_shell.NewMockInterface(mockCtrl)
testScanResults, err := os.ReadFile("testdata/smartctl_scan_megaraid.json")
fakeShell.EXPECT().Command(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(string(testScanResults), err)
d := detect.Detect{
Logger: logrus.WithFields(logrus.Fields{}),
Shell: fakeShell,
Config: fakeConfig,
}
// test
scannedDevices, err := d.SmartctlScan()
// assert
require.NoError(t, err)
require.Equal(t, 2, len(scannedDevices))
require.Equal(t, []models.Device{
{DeviceName: "bus/0", DeviceType: "megaraid,0"},
{DeviceName: "bus/0", DeviceType: "megaraid,1"},
}, scannedDevices)
}
func TestDetect_SmartctlScan_Nvme(t *testing.T) {
// setup
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
fakeConfig := mock_config.NewMockInterface(mockCtrl)
fakeConfig.EXPECT().GetString("host.id").AnyTimes().Return("")
fakeConfig.EXPECT().GetDeviceOverrides().AnyTimes().Return([]models.ScanOverride{})
fakeConfig.EXPECT().GetString("commands.metrics_smartctl_bin").AnyTimes().Return("smartctl")
fakeConfig.EXPECT().GetString("commands.metrics_scan_args").AnyTimes().Return("--scan --json")
fakeShell := mock_shell.NewMockInterface(mockCtrl)
testScanResults, err := os.ReadFile("testdata/smartctl_scan_nvme.json")
fakeShell.EXPECT().Command(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(string(testScanResults), err)
d := detect.Detect{
Logger: logrus.WithFields(logrus.Fields{}),
Shell: fakeShell,
Config: fakeConfig,
}
// test
scannedDevices, err := d.SmartctlScan()
// assert
require.NoError(t, err)
require.Equal(t, 1, len(scannedDevices))
require.Equal(t, []models.Device{
{DeviceName: "nvme0", DeviceType: "nvme"},
}, scannedDevices)
}
func TestDetect_TransformDetectedDevices_Empty(t *testing.T) {
// setup
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
fakeConfig := mock_config.NewMockInterface(mockCtrl)
fakeConfig.EXPECT().GetString("host.id").AnyTimes().Return("")
fakeConfig.EXPECT().GetDeviceOverrides().AnyTimes().Return([]models.ScanOverride{})
fakeConfig.EXPECT().GetString("commands.metrics_smartctl_bin").AnyTimes().Return("smartctl")
fakeConfig.EXPECT().GetString("commands.metrics_scan_args").AnyTimes().Return("--scan --json")
detectedDevices := models.Scan{
Devices: []models.ScanDevice{
{
Name: "/dev/sda",
InfoName: "/dev/sda",
Protocol: "scsi",
Type: "scsi",
},
},
}
d := detect.Detect{
Config: fakeConfig,
}
// test
transformedDevices := d.TransformDetectedDevices(detectedDevices)
// assert
require.Equal(t, "sda", transformedDevices[0].DeviceName)
require.Equal(t, "scsi", transformedDevices[0].DeviceType)
}
func TestDetect_TransformDetectedDevices_Ignore(t *testing.T) {
// setup
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
fakeConfig := mock_config.NewMockInterface(mockCtrl)
fakeConfig.EXPECT().GetString("host.id").AnyTimes().Return("")
fakeConfig.EXPECT().GetDeviceOverrides().AnyTimes().Return([]models.ScanOverride{{Device: "/dev/sda", DeviceType: nil, Ignore: true}})
fakeConfig.EXPECT().GetString("commands.metrics_smartctl_bin").AnyTimes().Return("smartctl")
fakeConfig.EXPECT().GetString("commands.metrics_scan_args").AnyTimes().Return("--scan --json")
detectedDevices := models.Scan{
Devices: []models.ScanDevice{
{
Name: "/dev/sda",
InfoName: "/dev/sda",
Protocol: "scsi",
Type: "scsi",
},
},
}
d := detect.Detect{
Config: fakeConfig,
}
// test
transformedDevices := d.TransformDetectedDevices(detectedDevices)
// assert
require.Equal(t, []models.Device{}, transformedDevices)
}
func TestDetect_TransformDetectedDevices_Raid(t *testing.T) {
// setup
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
fakeConfig := mock_config.NewMockInterface(mockCtrl)
fakeConfig.EXPECT().GetString("host.id").AnyTimes().Return("")
fakeConfig.EXPECT().GetString("commands.metrics_smartctl_bin").AnyTimes().Return("smartctl")
fakeConfig.EXPECT().GetString("commands.metrics_scan_args").AnyTimes().Return("--scan --json")
fakeConfig.EXPECT().GetDeviceOverrides().AnyTimes().Return([]models.ScanOverride{
{
Device: "/dev/bus/0",
DeviceType: []string{"megaraid,14", "megaraid,15", "megaraid,18", "megaraid,19", "megaraid,20", "megaraid,21"},
Ignore: false,
},
{
Device: "/dev/twa0",
DeviceType: []string{"3ware,0", "3ware,1", "3ware,2", "3ware,3", "3ware,4", "3ware,5"},
Ignore: false,
},
})
detectedDevices := models.Scan{
Devices: []models.ScanDevice{
{
Name: "/dev/bus/0",
InfoName: "/dev/bus/0",
Protocol: "scsi",
Type: "scsi",
},
},
}
d := detect.Detect{
Config: fakeConfig,
}
// test
transformedDevices := d.TransformDetectedDevices(detectedDevices)
// assert
require.Equal(t, 12, len(transformedDevices))
}
func TestDetect_TransformDetectedDevices_Simple(t *testing.T) {
// setup
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
fakeConfig := mock_config.NewMockInterface(mockCtrl)
fakeConfig.EXPECT().GetString("host.id").AnyTimes().Return("")
fakeConfig.EXPECT().GetString("commands.metrics_smartctl_bin").AnyTimes().Return("smartctl")
fakeConfig.EXPECT().GetString("commands.metrics_scan_args").AnyTimes().Return("--scan --json")
fakeConfig.EXPECT().GetDeviceOverrides().AnyTimes().Return([]models.ScanOverride{{Device: "/dev/sda", DeviceType: []string{"sat+megaraid"}}})
detectedDevices := models.Scan{
Devices: []models.ScanDevice{
{
Name: "/dev/sda",
InfoName: "/dev/sda",
Protocol: "ata",
Type: "ata",
},
},
}
d := detect.Detect{
Config: fakeConfig,
}
// test
transformedDevices := d.TransformDetectedDevices(detectedDevices)
// assert
require.Equal(t, 1, len(transformedDevices))
require.Equal(t, "sat+megaraid", transformedDevices[0].DeviceType)
}
// test https://github.com/AnalogJ/scrutiny/issues/255#issuecomment-1164024126
func TestDetect_TransformDetectedDevices_WithoutDeviceTypeOverride(t *testing.T) {
// setup
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
fakeConfig := mock_config.NewMockInterface(mockCtrl)
fakeConfig.EXPECT().GetString("host.id").AnyTimes().Return("")
fakeConfig.EXPECT().GetString("commands.metrics_smartctl_bin").AnyTimes().Return("smartctl")
fakeConfig.EXPECT().GetString("commands.metrics_scan_args").AnyTimes().Return("--scan --json")
fakeConfig.EXPECT().GetDeviceOverrides().AnyTimes().Return([]models.ScanOverride{{Device: "/dev/sda"}})
detectedDevices := models.Scan{
Devices: []models.ScanDevice{
{
Name: "/dev/sda",
InfoName: "/dev/sda",
Protocol: "ata",
Type: "scsi",
},
},
}
d := detect.Detect{
Config: fakeConfig,
}
// test
transformedDevices := d.TransformDetectedDevices(detectedDevices)
// assert
require.Equal(t, 1, len(transformedDevices))
require.Equal(t, "scsi", transformedDevices[0].DeviceType)
}
func TestDetect_TransformDetectedDevices_WhenDeviceNotDetected(t *testing.T) {
// setup
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
fakeConfig := mock_config.NewMockInterface(mockCtrl)
fakeConfig.EXPECT().GetString("host.id").AnyTimes().Return("")
fakeConfig.EXPECT().GetString("commands.metrics_smartctl_bin").AnyTimes().Return("smartctl")
fakeConfig.EXPECT().GetString("commands.metrics_scan_args").AnyTimes().Return("--scan --json")
fakeConfig.EXPECT().GetDeviceOverrides().AnyTimes().Return([]models.ScanOverride{{Device: "/dev/sda"}})
detectedDevices := models.Scan{}
d := detect.Detect{
Config: fakeConfig,
}
// test
transformedDevices := d.TransformDetectedDevices(detectedDevices)
// assert
require.Equal(t, 1, len(transformedDevices))
require.Equal(t, "ata", transformedDevices[0].DeviceType)
}
func TestDetect_SmartCtlInfo(t *testing.T) {
t.Run("should report nvme info", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
const (
someArgs = "--info --json"
// device info
someDeviceName = "some-device-name"
someModelName = "KCD61LUL3T84"
someSerialNumber = "61Q0A05UT7B8"
someFirmware = "8002"
someDeviceProtocol = "NVMe"
someDeviceType = "nvme"
someCapacity int64 = 3840755982336
)
fakeConfig := mock_config.NewMockInterface(ctrl)
fakeConfig.EXPECT().
GetCommandMetricsInfoArgs("/dev/" + someDeviceName).
Return(someArgs)
fakeConfig.EXPECT().
GetString("commands.metrics_smartctl_bin").
Return("smartctl")
someLogger := logrus.WithFields(logrus.Fields{})
smartctlInfoResults, err := os.ReadFile("testdata/smartctl_info_nvme.json")
require.NoError(t, err)
fakeShell := mock_shell.NewMockInterface(ctrl)
fakeShell.EXPECT().
Command(someLogger, "smartctl", append(strings.Split(someArgs, " "), "/dev/"+someDeviceName), "", gomock.Any()).
Return(string(smartctlInfoResults), err)
d := detect.Detect{
Logger: someLogger,
Shell: fakeShell,
Config: fakeConfig,
}
someDevice := &models.Device{
WWN: "some wwn",
DeviceName: someDeviceName,
}
require.NoError(t, d.SmartCtlInfo(someDevice))
assert.Equal(t, someDeviceName, someDevice.DeviceName)
assert.Equal(t, someModelName, someDevice.ModelName)
assert.Equal(t, someSerialNumber, someDevice.SerialNumber)
assert.Equal(t, someFirmware, someDevice.Firmware)
assert.Equal(t, someDeviceProtocol, someDevice.DeviceProtocol)
assert.Equal(t, someDeviceType, someDevice.DeviceType)
assert.Equal(t, someCapacity, someDevice.Capacity)
})
}