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