github.com/openebs/node-disk-manager@v1.9.1-0.20230225014141-4531f06ffa1e/pkg/udev/common_test.go (about)

     1  /*
     2  Copyright 2018 OpenEBS Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package udev
    18  
    19  import (
    20  	"path/filepath"
    21  	"testing"
    22  
    23  	"github.com/openebs/node-disk-manager/pkg/util"
    24  	"github.com/stretchr/testify/assert"
    25  )
    26  
    27  /*
    28  	In this test case we create os disk's UdevDevice object.
    29  	get the syspath of that disk and compare with mock details
    30  */
    31  func TestGetSyspath(t *testing.T) {
    32  	diskDetails, err := MockDiskDetails()
    33  	if err != nil {
    34  		t.Fatal(err)
    35  	}
    36  	newUdev, err := NewUdev()
    37  	if err != nil {
    38  		t.Fatal(err)
    39  	}
    40  	defer newUdev.UnrefUdev()
    41  	device, err := newUdev.NewDeviceFromSysPath(diskDetails.SysPath)
    42  	if err != nil {
    43  		t.Fatal(err)
    44  	}
    45  	defer device.UdevDeviceUnref()
    46  	tests := map[string]struct {
    47  		actualSyspath   string
    48  		expectedSysPath string
    49  	}{
    50  		"compare syspath of os disk": {actualSyspath: device.GetSyspath(), expectedSysPath: diskDetails.SysPath},
    51  	}
    52  	for name, test := range tests {
    53  		t.Run(name, func(t *testing.T) {
    54  			assert.Equal(t, test.actualSyspath, test.expectedSysPath)
    55  		})
    56  	}
    57  }
    58  
    59  /*
    60  	In this test case we create os disk's UdevDevice object.
    61  	and get the data what udevProbe can fill and compare it
    62  	with mock UdevDiskDetails struct
    63  */
    64  func TestDiskInfoFromLibudev(t *testing.T) {
    65  	diskDetails, err := MockDiskDetails()
    66  	if err != nil {
    67  		t.Fatal(err)
    68  	}
    69  	newUdev, err := NewUdev()
    70  	if err != nil {
    71  		t.Fatal(err)
    72  	}
    73  	defer newUdev.UnrefUdev()
    74  	device, err := newUdev.NewDeviceFromSysPath(diskDetails.SysPath)
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  	defer device.UdevDeviceUnref()
    79  	expectedDiskDetails := UdevDiskDetails{
    80  		Model:              diskDetails.Model,
    81  		Serial:             diskDetails.Serial,
    82  		Vendor:             diskDetails.Vendor,
    83  		WWN:                diskDetails.Wwn,
    84  		DiskType:           diskDetails.DevType,
    85  		Path:               diskDetails.DevNode,
    86  		ByIdDevLinks:       diskDetails.ByIdDevLinks,
    87  		ByPathDevLinks:     diskDetails.ByPathDevLinks,
    88  		SymLinks:           diskDetails.SymLinks,
    89  		PartitionTableType: diskDetails.PartTableType,
    90  		IDType:             diskDetails.IdType,
    91  	}
    92  	tests := map[string]struct {
    93  		actualDetails   UdevDiskDetails
    94  		expectedDetails UdevDiskDetails
    95  	}{
    96  		"check for details which udev probe can fill": {actualDetails: device.DiskInfoFromLibudev(), expectedDetails: expectedDiskDetails},
    97  	}
    98  	for name, test := range tests {
    99  		t.Run(name, func(t *testing.T) {
   100  			assert.True(t, unorderedEqual(test.expectedDetails.ByIdDevLinks, test.actualDetails.ByIdDevLinks))
   101  			assert.True(t, unorderedEqual(test.expectedDetails.ByPathDevLinks, test.actualDetails.ByPathDevLinks))
   102  			// need to make this nil as devlinks already compared.
   103  			test.expectedDetails.ByIdDevLinks = nil
   104  			test.expectedDetails.ByPathDevLinks = nil
   105  			test.expectedDetails.SymLinks = nil
   106  			test.actualDetails.ByIdDevLinks = nil
   107  			test.actualDetails.ByPathDevLinks = nil
   108  			test.actualDetails.SymLinks = nil
   109  			assert.Equal(t, test.expectedDetails, test.actualDetails)
   110  		})
   111  	}
   112  }
   113  
   114  /*
   115  	In this test case we create os disk's UdevDevice object.
   116  	as it is a disk it should return true
   117  */
   118  func TestIsDisk(t *testing.T) {
   119  	diskDetails, err := MockDiskDetails()
   120  	if err != nil {
   121  		t.Fatal(err)
   122  	}
   123  	newUdev, err := NewUdev()
   124  	if err != nil {
   125  		t.Fatal(err)
   126  	}
   127  	defer newUdev.UnrefUdev()
   128  	device, err := newUdev.NewDeviceFromSysPath(diskDetails.SysPath)
   129  	if err != nil {
   130  		t.Fatal(err)
   131  	}
   132  	defer device.UdevDeviceUnref()
   133  	tests := map[string]struct {
   134  		actual   bool
   135  		expected bool
   136  	}{
   137  		"check if os disk is disk or not": {actual: device.IsDisk(), expected: true},
   138  	}
   139  	for name, test := range tests {
   140  		t.Run(name, func(t *testing.T) {
   141  			assert.Equal(t, test.actual, test.expected)
   142  		})
   143  	}
   144  }
   145  
   146  /*
   147  	In this test case we create os disk's UdevDevice object from that we
   148  	get uuid of os disk. Then we compare it with uuid generation logic.
   149  */
   150  func TestGetUid(t *testing.T) {
   151  	diskDetails, err := MockDiskDetails()
   152  	if err != nil {
   153  		t.Fatal(err)
   154  	}
   155  	newUdev, err := NewUdev()
   156  	if err != nil {
   157  		t.Fatal(err)
   158  	}
   159  	defer newUdev.UnrefUdev()
   160  	device, err := newUdev.NewDeviceFromSysPath(diskDetails.SysPath)
   161  	if err != nil {
   162  		t.Fatal(err)
   163  	}
   164  	defer device.UdevDeviceUnref()
   165  	expectedUid := NDMBlockDevicePrefix + util.Hash(diskDetails.Wwn+diskDetails.Model+diskDetails.Serial+diskDetails.Vendor)
   166  	tests := map[string]struct {
   167  		actualUuid   string
   168  		expectedUuid string
   169  	}{
   170  		"check for os disk uuid": {actualUuid: device.GetUid(), expectedUuid: expectedUid},
   171  	}
   172  	for name, test := range tests {
   173  		t.Run(name, func(t *testing.T) {
   174  			assert.Equal(t, test.actualUuid, test.expectedUuid)
   175  		})
   176  	}
   177  }
   178  
   179  /*
   180  	Get devlinks and devnode (/dev/sda or /dev/sdb ... ) of os
   181  	disk, read file path of those devlinks and match with devnode.
   182  	Each devlink should be valid and file path of those links
   183  	equal with devnode of os disk.
   184  */
   185  func TestGetDevLinks(t *testing.T) {
   186  	diskDetails, err := MockDiskDetails()
   187  	if err != nil {
   188  		t.Fatal(err)
   189  	}
   190  	newUdev, err := NewUdev()
   191  	if err != nil {
   192  		t.Fatal(err)
   193  	}
   194  	defer newUdev.UnrefUdev()
   195  	device, err := newUdev.NewDeviceFromSysPath(diskDetails.SysPath)
   196  	if err != nil {
   197  		t.Fatal(err)
   198  	}
   199  	defer device.UdevDeviceUnref()
   200  	osDiskPath := diskDetails.DevNode
   201  	var expectedError error
   202  	for name, links := range device.GetDevLinks() {
   203  		for _, link := range links {
   204  			t.Run(name, func(t *testing.T) {
   205  				path, err := filepath.EvalSymlinks(link)
   206  				assert.Equal(t, expectedError, err)
   207  				assert.Equal(t, osDiskPath, path)
   208  			})
   209  		}
   210  	}
   211  }
   212  
   213  // unorderedEqual compares 2 arrays, if all elements in one array are present
   214  // in the second array.
   215  // eg: [1,2,3] and [3,1,2] are equal in unorderedEqual.
   216  func unorderedEqual(first, second []string) bool {
   217  	if len(first) != len(second) {
   218  		return false
   219  	}
   220  	exists := make(map[string]bool)
   221  	for _, value := range first {
   222  		exists[value] = true
   223  	}
   224  	for _, value := range second {
   225  		if !exists[value] {
   226  			return false
   227  		}
   228  	}
   229  	return true
   230  }