01-function_tests.t 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. use Test::Fatal;
  2. use Test::More tests => 17;
  3. use Test::MockModule;
  4. use Disk::SMART;
  5. my $smart_output = "smartctl 6.2 2013-07-26 r3841 [x86_64-linux-3.10.0-229.4.2.el7.x86_64] (local build)
  6. Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org
  7. === START OF INFORMATION SECTION ===
  8. Model Family: Seagate Barracuda 7200.10
  9. Device Model: ST3250410AS
  10. Serial Number: 6RYBDDDQ
  11. Firmware Version: 3.AAF
  12. User Capacity: 250,059,350,016 bytes [250 GB]
  13. Sector Size: 512 bytes logical/physical
  14. Device is: In smartctl database [for details use: -P show]
  15. ATA Version is: ATA/ATAPI-7 (minor revision not indicated)
  16. Local Time is: Thu May 28 10:38:55 2015 CDT
  17. SMART support is: Available - device has SMART capability.
  18. SMART support is: Enabled
  19. === START OF READ SMART DATA SECTION ===
  20. SMART overall-health self-assessment test result: PASSED
  21. General SMART Values:
  22. Offline data collection status: (0x82) Offline data collection activity
  23. was completed without error.
  24. Auto Offline Data Collection: Enabled.
  25. Self-test execution status: ( 0) The previous self-test routine completed
  26. without error or no self-test has ever
  27. been run.
  28. Total time to complete Offline
  29. data collection: ( 430) seconds.
  30. Offline data collection
  31. capabilities: (0x5b) SMART execute Offline immediate.
  32. Auto Offline data collection on/off support.
  33. Suspend Offline collection upon new
  34. command.
  35. Offline surface scan supported.
  36. Self-test supported.
  37. No Conveyance Self-test supported.
  38. Selective Self-test supported.
  39. SMART capabilities: (0x0003) Saves SMART data before entering
  40. power-saving mode.
  41. Supports SMART auto save timer.
  42. Error logging capability: (0x01) Error logging supported.
  43. General Purpose Logging supported.
  44. Short self-test routine
  45. recommended polling time: ( 1) minutes.
  46. Extended self-test routine
  47. recommended polling time: ( 64) minutes.
  48. SCT capabilities: (0x0001) SCT Status supported.
  49. SMART Attributes Data Structure revision number: 10
  50. Vendor Specific SMART Attributes with Thresholds:
  51. ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
  52. 1 Raw_Read_Error_Rate 0x000f 100 253 006 Pre-fail Always - 0
  53. 3 Spin_Up_Time 0x0003 097 097 000 Pre-fail Always - 0
  54. 4 Start_Stop_Count 0x0032 100 100 020 Old_age Always - 33
  55. 5 Reallocated_Sector_Ct 0x0033 100 100 036 Pre-fail Always - 0
  56. 7 Seek_Error_Rate 0x000f 075 060 030 Pre-fail Always - 40666623
  57. 9 Power_On_Hours 0x0032 093 093 000 Old_age Always - 6356
  58. 10 Spin_Retry_Count 0x0013 100 100 097 Pre-fail Always - 0
  59. 12 Power_Cycle_Count 0x0032 100 100 020 Old_age Always - 33
  60. 187 Reported_Uncorrect 0x0032 100 100 000 Old_age Always - 0
  61. 189 High_Fly_Writes 0x003a 100 100 000 Old_age Always - 0
  62. 190 Airflow_Temperature_Cel 0x0022 064 050 045 Old_age Always - 36 (Min/Max 13/50)
  63. 194 Temperature_Celsius 0x0022 036 050 000 Old_age Always - 36 (0 13 0 0 0)
  64. 195 Hardware_ECC_Recovered 0x001a 069 060 000 Old_age Always - 121831984
  65. 197 Current_Pending_Sector 0x0012 100 100 000 Old_age Always - 0
  66. 198 Offline_Uncorrectable 0x0010 100 100 000 Old_age Offline - 0
  67. 199 UDMA_CRC_Error_Count 0x003e 200 200 000 Old_age Always - 0
  68. 200 Multi_Zone_Error_Rate 0x0000 100 253 000 Old_age Offline - 0
  69. 202 Data_Address_Mark_Errs 0x0032 100 253 000 Old_age Always - 0
  70. SMART Error Log Version: 1
  71. No Errors Logged
  72. SMART Self-test log structure revision number 1
  73. Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error
  74. # 1 Short offline Completed without error 00% 1100 -
  75. # 2 Short offline Completed without error 00% 1100 -
  76. # 3 Extended offline Aborted by host 90% 1100 -
  77. # 4 Short offline Completed without error 00% 1100 -
  78. # 5 Short offline Completed without error 00% 1100 -
  79. # 6 Short offline Completed without error 00% 1099 -
  80. SMART Selective self-test log data structure revision number 1
  81. SPAN MIN_LBA MAX_LBA CURRENT_TEST_STATUS
  82. 1 0 0 Not_testing
  83. 2 0 0 Not_testing
  84. 3 0 0 Not_testing
  85. 4 0 0 Not_testing
  86. 5 0 0 Not_testing
  87. Selective self-test flags (0x0):
  88. After scanning selected spans, do NOT read-scan remainder of disk.
  89. If Selective self-test is pending on power-up, resume after 0 minute delay.";
  90. my $mock = Test::MockModule->new('Disk::SMART');
  91. $mock->mock(
  92. 'new' => sub {
  93. my ( $class, @devices ) = @_;
  94. my $self = bless {}, $class;
  95. $self->update_data(@devices);
  96. return $self;
  97. },
  98. '_get_smart_output' => sub { return $smart_output; },
  99. 'run_short_test' => 'Completed without error'
  100. );
  101. my $disk = '/dev/sda'; # this is being mocked
  102. my $smart = Disk::SMART->new($disk);
  103. # Verify functions return correctly with SMART data present
  104. my %disk_attribs = $smart->get_disk_attributes($disk);
  105. is( keys %disk_attribs, 18, 'get_disk_attributes() returns hash of device attributes' );
  106. is( $smart->get_disk_errors($disk), 'No Errors Logged', 'get_disk_errors() returns no errors logged' );
  107. is( $smart->get_disk_health($disk), 'PASSED', 'get_disk_health() returns health status' );
  108. is( $smart->get_disk_model($disk), 'ST3250410AS', 'get_disk_model() returns device model' );
  109. is( scalar($smart->get_disk_temp($disk)), 2, 'get_disk_temp() returns device temperature' );
  110. is( $smart->run_short_test($disk), 'Completed without error', 'run_short_test() returns test status' );
  111. # Change some SMART data around and see if the functions return correctly
  112. $smart_output =~ s/ST3250410AS//;
  113. $smart_output =~ s/187 Reported_Uncorrect 0x0032 100 100 000 Old_age Always - 0/187 Reported_Uncorrect 0x0032 100 100 000 Old_age Always - 1/;
  114. $smart_output =~ s/190 Airflow_Temperature_Cel.*\n//;
  115. $smart_output =~ s/194 Temperature_Celsius.*\n//;
  116. is( $smart->update_data($disk), undef, 'update_data() updated object with changed device data' );
  117. is( $smart->get_disk_health($disk), 'PASSED: 187 - Reported_Uncorrect = 1', 'get_disk_health() returns failed attribute status when SMART attribute 187 > 0' );
  118. is( $smart->get_disk_model($disk), 'N/A', 'get_disk_model() returns N/A when no model was found' );
  119. my @disk_temps = $smart->get_disk_temp($disk);
  120. is( $disk_temps[0], 'N/A', "get_disk_temp() returns 'N/A' when smartctl doesn't report temperaure" );
  121. #Exception testing
  122. $disk = '/dev/test_bad';
  123. $mock->mock(
  124. 'update_data' => "Smartctl couldn't poll device",
  125. );
  126. $mock->unmock('run_short_test');
  127. like( exception { $smart->get_disk_attributes($disk); }, qr/$disk not found in object/, 'get_disk_attributes() returns failure when passed invalid device' );
  128. like( exception { $smart->get_disk_errors($disk); }, qr/$disk not found in object/, 'get_disk_model() returns failure when passed invalid device' );
  129. like( exception { $smart->get_disk_health($disk); }, qr/$disk not found in object/, 'get_disk_health() returns failure when passed invalid device' );
  130. like( exception { $smart->get_disk_model($disk); }, qr/$disk not found in object/, 'get_disk_model() returns failure when passed invalid device' );
  131. like( exception { $smart->get_disk_temp($disk); }, qr/$disk not found in object/, 'get_disk_temp() returns failure when passed invalid device' );
  132. like( exception { $smart->run_short_test($disk); }, qr/$disk not found in object/, 'run_short_test() returns failure when passed invalid device' );
  133. like( $smart->update_data($disk), qr/couldn't poll/, 'update_data() returns falure when passed invalid device' );