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