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