]>
Commit | Line | Data |
---|---|---|
5774fe62 DC |
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')); | |
19dcd1ad DC |
55 | } elsif ($cmd->[0] =~ m/lvs/i) { |
56 | @$outputlines = split(/\n/, read_test_file('lvs')); | |
8cd6d7e8 DC |
57 | } elsif ($cmd->[0] =~ m/lsblk/i) { |
58 | my $content = read_test_file('lsblk'); | |
59 | if ($content eq '') { | |
60 | $content = '{}'; | |
61 | } | |
62 | @$outputlines = split(/\n/, $content); | |
5774fe62 | 63 | } else { |
8cd6d7e8 | 64 | die "unexpected run_command call: '@$cmd', aborting\n"; |
5774fe62 DC |
65 | } |
66 | } else { | |
67 | print "unexpected run_command call: '@$cmd', aborting\n"; | |
68 | die; | |
69 | } | |
70 | ||
71 | my $outfunc; | |
72 | if ($param{outfunc}) { | |
73 | $outfunc = $param{outfunc}; | |
74 | map { &$outfunc(($_)) } @$outputlines; | |
75 | ||
76 | return 0; | |
77 | } | |
78 | } | |
79 | ||
80 | sub mocked_get_sysdir_info { | |
81 | my ($param) = @_; | |
82 | ||
83 | my $originalsub = $diskmanage_module->original('get_sysdir_info'); | |
84 | ||
85 | $param =~ s|/sys/block|disk_tests/$testcasedir|; | |
86 | ||
87 | return &$originalsub($param); | |
88 | } | |
89 | ||
40be5c5c FE |
90 | sub mocked_get_sysdir_size { |
91 | my ($param) = @_; | |
92 | ||
93 | my $originalsub = $diskmanage_module->original('get_sysdir_size'); | |
94 | ||
95 | $param =~ s|/sys/block|disk_tests/$testcasedir|; | |
96 | ||
97 | return &$originalsub($param); | |
98 | } | |
99 | ||
eebcdb11 DC |
100 | sub mocked_is_iscsi { |
101 | return 0; | |
102 | } | |
103 | ||
5774fe62 DC |
104 | sub mocked_dir_glob_foreach { |
105 | my ($dir, $regex, $sub) = @_; | |
106 | ||
107 | my $lines = []; | |
108 | ||
109 | # read lines in from file | |
110 | if ($dir =~ m{^/sys/block$} ) { | |
111 | @$lines = split(/\n/, read_test_file('disklist')); | |
112 | } elsif ($dir =~ m{^/sys/block/([^/]+)}) { | |
113 | @$lines = split(/\n/, read_test_file('partlist')); | |
114 | } | |
115 | ||
116 | foreach my $line (@$lines) { | |
117 | if ($line =~ m/$regex/) { | |
118 | &$sub($line); | |
119 | } | |
120 | } | |
121 | } | |
122 | ||
123 | sub mocked_parse_proc_mounts { | |
124 | my $text = read_test_file('mounts'); | |
125 | ||
126 | my $mounts = []; | |
127 | ||
128 | foreach my $line(split(/\n/, $text)) { | |
129 | push @$mounts, [split(/\s+/, $line)]; | |
130 | } | |
131 | ||
132 | return $mounts; | |
133 | } | |
134 | ||
135 | sub read_test_file { | |
136 | my ($filename) = @_; | |
137 | ||
138 | if (!-f "disk_tests/$testcasedir/$filename") { | |
139 | print "file '$testcasedir/$filename' not found\n"; | |
140 | return ''; | |
141 | } | |
142 | open (my $fh, '<', "disk_tests/$testcasedir/$filename") | |
143 | or die "Cannot open disk_tests/$testcasedir/$filename: $!"; | |
144 | ||
145 | my $output = <$fh> // ''; | |
146 | chomp $output if $output; | |
147 | while (my $line = <$fh>) { | |
148 | chomp $line; | |
149 | $output .= "\n$line"; | |
150 | } | |
151 | ||
152 | return $output; | |
153 | } | |
154 | ||
155 | ||
156 | sub test_disk_list { | |
157 | my ($testdir) = @_; | |
158 | subtest "Test '$testdir'" => sub { | |
159 | my $testcount = 0; | |
160 | $testcasedir = $testdir; | |
161 | ||
162 | my $disks; | |
163 | my $expected_disk_list; | |
164 | eval { | |
165 | $disks = PVE::Diskmanage::get_disks(); | |
166 | }; | |
167 | warn $@ if $@; | |
168 | $expected_disk_list = decode_json(read_test_file('disklist_expected.json')); | |
169 | ||
170 | print Dumper($disks) if $print; | |
171 | $testcount++; | |
172 | is_deeply($disks, $expected_disk_list, 'disk list should be the same'); | |
173 | ||
174 | foreach my $disk (sort keys %$disks) { | |
175 | my $smart; | |
176 | my $expected_smart; | |
177 | eval { | |
178 | $smart = PVE::Diskmanage::get_smart_data("/dev/$disk"); | |
179 | print Dumper($smart) if $print; | |
180 | $expected_smart = decode_json(read_test_file("${disk}_smart_expected.json")); | |
181 | }; | |
182 | ||
183 | if ($smart && $expected_smart) { | |
184 | $testcount++; | |
185 | is_deeply($smart, $expected_smart, "smart data for '$disk' should be the same"); | |
186 | } elsif ($smart && -f "disk_tests/$testcasedir/${disk}_smart_expected.json") { | |
187 | $testcount++; | |
188 | ok(0, "could not parse expected smart for '$disk'\n"); | |
189 | } | |
d0a217f6 DC |
190 | my $disk_tmp = {}; |
191 | ||
192 | # test single disk parameter | |
193 | $disk_tmp = PVE::Diskmanage::get_disks($disk); | |
194 | warn $@ if $@; | |
195 | $testcount++; | |
196 | print Dumper $disk_tmp if $print; | |
197 | is_deeply($disk_tmp->{$disk}, $expected_disk_list->{$disk}, "disk $disk should be the same"); | |
198 | ||
199 | ||
200 | # test wrong parameter | |
201 | eval { | |
202 | PVE::Diskmanage::get_disks( { test => 1 } ); | |
203 | }; | |
204 | my $err = $@; | |
205 | $testcount++; | |
206 | is_deeply($err, "disks is not a string or array reference\n", "error message should be the same"); | |
207 | ||
5774fe62 | 208 | } |
d0a217f6 DC |
209 | # test multi disk parameter |
210 | $disks = PVE::Diskmanage::get_disks( [ keys %$disks ] ); | |
211 | $testcount++; | |
212 | is_deeply($disks, $expected_disk_list, 'disk list should be the same'); | |
5774fe62 DC |
213 | |
214 | done_testing($testcount); | |
215 | }; | |
216 | } | |
217 | ||
218 | # start reading tests: | |
219 | ||
220 | if (@ARGV && $ARGV[0] eq 'print') { | |
221 | $print = 1; | |
222 | } | |
223 | ||
224 | print("Setting up Mocking\n"); | |
225 | $diskmanage_module = new Test::MockModule('PVE::Diskmanage', no_auto => 1); | |
226 | $diskmanage_module->mock('run_command' => \&mocked_run_command); | |
227 | print("\tMocked run_command\n"); | |
228 | $diskmanage_module->mock('dir_glob_foreach' => \&mocked_dir_glob_foreach); | |
229 | print("\tMocked dir_glob_foreach\n"); | |
230 | $diskmanage_module->mock('get_sysdir_info' => \&mocked_get_sysdir_info); | |
231 | print("\tMocked get_sysdir_info\n"); | |
40be5c5c FE |
232 | $diskmanage_module->mock('get_sysdir_size' => \&mocked_get_sysdir_size); |
233 | print("\tMocked get_sysdir_size\n"); | |
eebcdb11 DC |
234 | $diskmanage_module->mock('is_iscsi' => \&mocked_is_iscsi); |
235 | print("\tMocked is_iscsi\n"); | |
5774fe62 DC |
236 | $diskmanage_module->mock('assert_blockdev' => sub { return 1; }); |
237 | print("\tMocked assert_blockdev\n"); | |
238 | $diskmanage_module->mock('dir_is_empty' => sub { | |
239 | # all partitions have a holder dir | |
240 | my $val = shift; | |
241 | if ($val =~ m|^/sys/block/.+/.+/|) { | |
242 | return 0; | |
243 | } | |
244 | return 1; | |
245 | }); | |
246 | print("\tMocked dir_is_empty\n"); | |
525b4a6e FE |
247 | $diskmanage_module->mock('check_bin' => sub { return 1; }); |
248 | print("\tMocked check_bin\n"); | |
5774fe62 DC |
249 | my $tools_module= new Test::MockModule('PVE::ProcFSTools', no_auto => 1); |
250 | $tools_module->mock('parse_proc_mounts' => \&mocked_parse_proc_mounts); | |
251 | print("\tMocked parse_proc_mounts\n"); | |
252 | print("Done Setting up Mocking\n\n"); | |
253 | ||
254 | print("Beginning Tests:\n\n"); | |
255 | opendir (my $dh, 'disk_tests') | |
256 | or die "Cannot open disk_tests: $!"; | |
257 | ||
258 | while (readdir $dh) { | |
259 | my $dir = $_; | |
260 | next if $dir eq '.' or $dir eq '..'; | |
261 | $testcount++; | |
262 | test_disk_list($dir); | |
263 | } | |
264 | ||
265 | done_testing($testcount); |