]> git.proxmox.com Git - pve-storage.git/blob - test/disklist_test.pm
fixup error messages when getting file size info
[pve-storage.git] / test / disklist_test.pm
1 package PVE::Diskmanage::Test;
2
3 use strict;
4 use warnings;
5
6 use lib qw(..);
7
8 use PVE::Diskmanage;
9 use PVE::Tools;
10
11 use Test::MockModule;
12 use Test::More;
13 use JSON;
14 use Data::Dumper;
15
16 my $testcasedir; # current case directory
17 my $testcount = 0; # testcount for TAP::Harness
18 my $diskmanage_module; # mockmodule for PVE::Diskmanage
19 my $print = 0;
20
21 sub mocked_run_command {
22 my ($cmd, %param) = @_;
23
24 my $outputlines = [];
25 if (my $ref = ref($cmd)) {
26 if ($cmd->[0] =~ m/udevadm/i) {
27 # simulate udevadm output
28 my $dev = $cmd->[3];
29 $dev =~ s|/sys/block/||;
30 @$outputlines = split(/\n/, read_test_file("${dev}_udevadm"));
31
32 } elsif ($cmd->[0] =~ m/smartctl/i) {
33 # simulate smartctl output
34 my $dev;
35 my $type;
36 if (@$cmd > 3) {
37 $dev = $cmd->[5];
38 $type = 'smart';
39 } else {
40 $dev = $cmd->[2];
41 $type = 'health';
42 }
43 $dev =~ s|/dev/||;
44 @$outputlines = split(/\n/, read_test_file("${dev}_${type}"));
45 } elsif ($cmd->[0] =~ m/sgdisk/i) {
46 # simulate sgdisk
47 die "implement me: @$cmd\n";
48 } elsif ($cmd->[0] =~ m/zpool/i) {
49 # simulate zpool output
50 @$outputlines = split(/\n/, read_test_file('zpool'));
51
52 } elsif ($cmd->[0] =~ m/pvs/i) {
53 # simulate lvs output
54 @$outputlines = split(/\n/, read_test_file('pvs'));
55 } else {
56 print "unexpected run_command call: '@$cmd', aborting\n";
57 die;
58 }
59 } else {
60 print "unexpected run_command call: '@$cmd', aborting\n";
61 die;
62 }
63
64 my $outfunc;
65 if ($param{outfunc}) {
66 $outfunc = $param{outfunc};
67 map { &$outfunc(($_)) } @$outputlines;
68
69 return 0;
70 }
71 }
72
73 sub mocked_get_sysdir_info {
74 my ($param) = @_;
75
76 my $originalsub = $diskmanage_module->original('get_sysdir_info');
77
78 $param =~ s|/sys/block|disk_tests/$testcasedir|;
79
80 return &$originalsub($param);
81 }
82
83 sub mocked_is_iscsi {
84 return 0;
85 }
86
87 sub mocked_dir_glob_foreach {
88 my ($dir, $regex, $sub) = @_;
89
90 my $lines = [];
91
92 # read lines in from file
93 if ($dir =~ m{^/sys/block$} ) {
94 @$lines = split(/\n/, read_test_file('disklist'));
95 } elsif ($dir =~ m{^/sys/block/([^/]+)}) {
96 @$lines = split(/\n/, read_test_file('partlist'));
97 }
98
99 foreach my $line (@$lines) {
100 if ($line =~ m/$regex/) {
101 &$sub($line);
102 }
103 }
104 }
105
106 sub mocked_parse_proc_mounts {
107 my $text = read_test_file('mounts');
108
109 my $mounts = [];
110
111 foreach my $line(split(/\n/, $text)) {
112 push @$mounts, [split(/\s+/, $line)];
113 }
114
115 return $mounts;
116 }
117
118 sub read_test_file {
119 my ($filename) = @_;
120
121 if (!-f "disk_tests/$testcasedir/$filename") {
122 print "file '$testcasedir/$filename' not found\n";
123 return '';
124 }
125 open (my $fh, '<', "disk_tests/$testcasedir/$filename")
126 or die "Cannot open disk_tests/$testcasedir/$filename: $!";
127
128 my $output = <$fh> // '';
129 chomp $output if $output;
130 while (my $line = <$fh>) {
131 chomp $line;
132 $output .= "\n$line";
133 }
134
135 return $output;
136 }
137
138
139 sub test_disk_list {
140 my ($testdir) = @_;
141 subtest "Test '$testdir'" => sub {
142 my $testcount = 0;
143 $testcasedir = $testdir;
144
145 my $disks;
146 my $expected_disk_list;
147 eval {
148 $disks = PVE::Diskmanage::get_disks();
149 };
150 warn $@ if $@;
151 $expected_disk_list = decode_json(read_test_file('disklist_expected.json'));
152
153 print Dumper($disks) if $print;
154 $testcount++;
155 is_deeply($disks, $expected_disk_list, 'disk list should be the same');
156
157 foreach my $disk (sort keys %$disks) {
158 my $smart;
159 my $expected_smart;
160 eval {
161 $smart = PVE::Diskmanage::get_smart_data("/dev/$disk");
162 print Dumper($smart) if $print;
163 $expected_smart = decode_json(read_test_file("${disk}_smart_expected.json"));
164 };
165
166 if ($smart && $expected_smart) {
167 $testcount++;
168 is_deeply($smart, $expected_smart, "smart data for '$disk' should be the same");
169 } elsif ($smart && -f "disk_tests/$testcasedir/${disk}_smart_expected.json") {
170 $testcount++;
171 ok(0, "could not parse expected smart for '$disk'\n");
172 }
173 }
174
175 done_testing($testcount);
176 };
177 }
178
179 # start reading tests:
180
181 if (@ARGV && $ARGV[0] eq 'print') {
182 $print = 1;
183 }
184
185 print("Setting up Mocking\n");
186 $diskmanage_module = new Test::MockModule('PVE::Diskmanage', no_auto => 1);
187 $diskmanage_module->mock('run_command' => \&mocked_run_command);
188 print("\tMocked run_command\n");
189 $diskmanage_module->mock('dir_glob_foreach' => \&mocked_dir_glob_foreach);
190 print("\tMocked dir_glob_foreach\n");
191 $diskmanage_module->mock('get_sysdir_info' => \&mocked_get_sysdir_info);
192 print("\tMocked get_sysdir_info\n");
193 $diskmanage_module->mock('is_iscsi' => \&mocked_is_iscsi);
194 print("\tMocked is_iscsi\n");
195 $diskmanage_module->mock('assert_blockdev' => sub { return 1; });
196 print("\tMocked assert_blockdev\n");
197 $diskmanage_module->mock('dir_is_empty' => sub {
198 # all partitions have a holder dir
199 my $val = shift;
200 if ($val =~ m|^/sys/block/.+/.+/|) {
201 return 0;
202 }
203 return 1;
204 });
205 print("\tMocked dir_is_empty\n");
206 my $tools_module= new Test::MockModule('PVE::ProcFSTools', no_auto => 1);
207 $tools_module->mock('parse_proc_mounts' => \&mocked_parse_proc_mounts);
208 print("\tMocked parse_proc_mounts\n");
209 print("Done Setting up Mocking\n\n");
210
211 print("Beginning Tests:\n\n");
212 opendir (my $dh, 'disk_tests')
213 or die "Cannot open disk_tests: $!";
214
215 while (readdir $dh) {
216 my $dir = $_;
217 next if $dir eq '.' or $dir eq '..';
218 $testcount++;
219 test_disk_list($dir);
220 }
221
222 done_testing($testcount);