]> git.proxmox.com Git - pve-storage.git/blame - test/disklist_test.pm
Diskmanage: replace check for zpool binary with a function and mock it
[pve-storage.git] / test / disklist_test.pm
CommitLineData
5774fe62
DC
1package PVE::Diskmanage::Test;
2
3use strict;
4use warnings;
5
6use lib qw(..);
7
8use PVE::Diskmanage;
9use PVE::Tools;
10
11use Test::MockModule;
12use Test::More;
13use JSON;
14use Data::Dumper;
15
16my $testcasedir; # current case directory
17my $testcount = 0; # testcount for TAP::Harness
18my $diskmanage_module; # mockmodule for PVE::Diskmanage
19my $print = 0;
20
21sub 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
80sub 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
90sub 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
100sub mocked_is_iscsi {
101 return 0;
102}
103
5774fe62
DC
104sub 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
123sub 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
135sub 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
156sub 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
220if (@ARGV && $ARGV[0] eq 'print') {
221 $print = 1;
222}
223
224print("Setting up Mocking\n");
225$diskmanage_module = new Test::MockModule('PVE::Diskmanage', no_auto => 1);
226$diskmanage_module->mock('run_command' => \&mocked_run_command);
227print("\tMocked run_command\n");
228$diskmanage_module->mock('dir_glob_foreach' => \&mocked_dir_glob_foreach);
229print("\tMocked dir_glob_foreach\n");
230$diskmanage_module->mock('get_sysdir_info' => \&mocked_get_sysdir_info);
231print("\tMocked get_sysdir_info\n");
40be5c5c
FE
232$diskmanage_module->mock('get_sysdir_size' => \&mocked_get_sysdir_size);
233print("\tMocked get_sysdir_size\n");
eebcdb11
DC
234$diskmanage_module->mock('is_iscsi' => \&mocked_is_iscsi);
235print("\tMocked is_iscsi\n");
5774fe62
DC
236$diskmanage_module->mock('assert_blockdev' => sub { return 1; });
237print("\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 });
246print("\tMocked dir_is_empty\n");
525b4a6e
FE
247$diskmanage_module->mock('check_bin' => sub { return 1; });
248print("\tMocked check_bin\n");
5774fe62
DC
249my $tools_module= new Test::MockModule('PVE::ProcFSTools', no_auto => 1);
250$tools_module->mock('parse_proc_mounts' => \&mocked_parse_proc_mounts);
251print("\tMocked parse_proc_mounts\n");
252print("Done Setting up Mocking\n\n");
253
254print("Beginning Tests:\n\n");
255opendir (my $dh, 'disk_tests')
256 or die "Cannot open disk_tests: $!";
257
258while (readdir $dh) {
259 my $dir = $_;
260 next if $dir eq '.' or $dir eq '..';
261 $testcount++;
262 test_disk_list($dir);
263}
264
265done_testing($testcount);