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