File Coverage

blib/lib/Apache/TestConfigC.pm
Criterion Covered Total %
statement 25 197 12.7
branch 2 58 3.4
condition 0 8 0.0
subroutine 9 25 36.0
pod 0 17 0.0
total 36 305 11.8


line stmt bran cond sub pod time code
1             # Licensed to the Apache Software Foundation (ASF) under one or more
2             # contributor license agreements. See the NOTICE file distributed with
3             # this work for additional information regarding copyright ownership.
4             # The ASF licenses this file to You under the Apache License, Version 2.0
5             # (the "License"); you may not use this file except in compliance with
6             # the License. You may obtain a copy of the License at
7             #
8             # http://www.apache.org/licenses/LICENSE-2.0
9             #
10             # Unless required by applicable law or agreed to in writing, software
11             # distributed under the License is distributed on an "AS IS" BASIS,
12             # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13             # See the License for the specific language governing permissions and
14             # limitations under the License.
15             #
16             package Apache::TestConfig; #not TestConfigC on purpose
17              
18 6     6   104 use strict;
  6         56  
  6         110  
19 6     6   90 use warnings FATAL => 'all';
  6         100  
  6         118  
20              
21 6     6   195 use Config;
  6         58  
  6         94  
22 6     6   178 use Apache::TestConfig ();
  6         91  
  6         59  
23 6     6   134 use Apache::TestConfigPerl ();
  6         52  
  6         75  
24 6     6   104 use Apache::TestTrace;
  6         75  
  6         166  
25 6     6   111 use File::Find qw(finddepth);
  6         62  
  6         1397  
26              
27             sub cmodule_find {
28 0     0 0 0     my($self, $mod) = @_;
29              
30 0 0       0     return unless $mod =~ /^mod_(\w+)\.c$/;
31 0         0     my $sym = $1;
32              
33 0         0     my $dir = $File::Find::dir;
34 0         0     my $file = catfile $dir, $mod;
35              
36 0 0       0     unless ($self->{APXS}) {
37 0         0         $self->{cmodules_disabled}->{$mod} = "no apxs configured";
38 0         0         return;
39                 }
40              
41 0         0     my $fh = Symbol::gensym();
42 0 0       0     open $fh, $file or die "open $file: $!";
43 0         0     my $v = <$fh>;
44 0 0       0     if ($v =~ /^\#define\s+HTTPD_TEST_REQUIRE_APACHE\s+(\d+)\s*$/) {
    0          
45             #define HTTPD_TEST_REQUIRE_APACHE 1
46 0 0       0         unless ($self->{server}->{rev} == $1) {
47 0         0             my $reason = "requires Apache version $1";
48 0         0             $self->{cmodules_disabled}->{$mod} = $reason;
49 0         0             notice "$mod $reason, skipping.";
50 0         0             return;
51                     }
52                 }
53                 elsif ($v =~ /^\#define\s+HTTPD_TEST_REQUIRE_APACHE\s+(\d\.\d+(\.\d+)?)/) {
54             #define HTTPD_TEST_REQUIRE_APACHE 2.1
55 0         0         my $wanted = $1;
56 0         0         (my $current) = $self->{server}->{version} =~ m:^Apache/(\d\.\d+\.\d+):;
57              
58 0 0       0         if (Apache::Test::normalize_vstring($current) <
59                         Apache::Test::normalize_vstring($wanted)) {
60 0         0             my $reason = "requires Apache version $wanted";
61 0         0             $self->{cmodules_disabled}->{$mod} = $reason;
62 0         0             notice "$mod $reason, skipping.";
63 0         0             return;
64                     }
65                 }
66 0         0     close $fh;
67              
68 0         0     push @{ $self->{cmodules} }, {
  0         0  
69                     name => "mod_$sym",
70                     sym => "${sym}_module",
71                     dir => $dir,
72                     subdir => basename $dir,
73                 };
74             }
75              
76             sub cmodules_configure {
77 0     0 0 0     my($self, $dir) = @_;
78              
79 0         0     $self->{cmodules_disabled} = {}; #for have_module to check
80              
81 0   0     0     $dir ||= catfile $self->{vars}->{top_dir}, 'c-modules';
82              
83 0 0       0     unless (-d $dir) {
84 0         0         return;
85                 }
86              
87 0         0     $self->{cmodules_dir} = $dir;
88              
89 0     0   0     finddepth(sub { cmodule_find($self, $_) }, $dir);
  0         0  
90              
91 0 0       0     unless ($self->{APXS}) {
92 0         0         warning "cannot build c-modules without apxs";
93 0         0         return;
94                 }
95              
96 0         0     $self->cmodules_generate_include;
97 0         0     $self->cmodules_write_makefiles;
98 0         0     $self->cmodules_compile;
99 0         0     $self->cmodules_httpd_conf;
100             }
101              
102             sub cmodules_makefile_vars {
103 0     0 0 0     return <<EOF;
104             MAKE = $Config{make}
105             EOF
106             }
107              
108             my %lib_dir = Apache::TestConfig::WIN32
109                 ? (1 => "", 2 => "")
110                 : (1 => "", 2 => ".libs/");
111              
112             sub cmodules_build_so {
113 0     0 0 0     my($self, $name) = @_;
114 0 0       0     $name = "mod_$name" unless $name =~ /^mod_/;
115 0         0     my $libdir = $self->server->version_of(\%lib_dir);
116 0         0     my $lib = "$libdir$name.so";
117             }
118              
119             sub cmodules_write_makefiles {
120 0     0 0 0     my $self = shift;
121              
122 0         0     my $modules = $self->{cmodules};
123              
124 0         0     for (@$modules) {
125 0         0         $self->cmodules_write_makefile($_);
126                 }
127              
128 0         0     my $file = catfile $self->{cmodules_dir}, 'Makefile';
129 0         0     my $fh = Symbol::gensym();
130 0 0       0     open $fh, ">$file" or die "open $file: $!";
131              
132 0         0     print $fh $self->cmodules_makefile_vars;
133              
134 0         0     my @dirs = map { $_->{subdir} } @$modules;
  0         0  
135              
136 0         0     my @targets = qw(clean);
137 0         0     my @libs;
138              
139 0         0     for my $dir (@dirs) {
140 0         0         for my $targ (@targets) {
141 0         0             print $fh "$dir-$targ:\n\tcd $dir && \$(MAKE) $targ\n\n";
142                     }
143              
144 0         0         my $lib = $self->cmodules_build_so($dir);
145 0         0         my $cfile = "$dir/mod_$dir.c";
146 0         0         push @libs, "$dir/$lib";
147 0         0         print $fh "$libs[-1]: $cfile\n\tcd $dir && \$(MAKE) $lib\n\n";
148                 }
149              
150 0         0     for my $targ (@targets) {
151 0         0         print $fh "$targ: ", (map { "$_-$targ " } @dirs), "\n\n";
  0         0  
152                 }
153              
154 0         0     print $fh "all: @libs\n\n";
155              
156 0 0       0     close $fh or die "close $file: $!";
157             }
158              
159             sub cmodules_write_makefile {
160 0     0 0 0     my ($self, $mod) = @_;
161 0         0     my $write = \&{"cmodules_write_makefile_$^O"};
  0         0  
162 0 0       0     $write = \&cmodules_write_makefile_default unless defined &$write;
163 0         0     $write->($self, $mod);
164             }
165              
166             sub cmodules_write_makefile_default {
167 0     0 0 0     my($self, $mod) = @_;
168              
169 0         0     my $dversion = $self->server->dversion;
170 0         0     my $name = $mod->{name};
171 0         0     my $makefile = catfile $mod->{dir}, 'Makefile';
172 0         0     debug "writing $makefile";
173              
174 0         0     my $lib = $self->cmodules_build_so($name);
175              
176 0         0     my $fh = Symbol::gensym();
177 0 0       0     open $fh, ">$makefile" or die "open $makefile: $!";
178              
179 0         0     print $fh <<EOF;
180             APXS=$self->{APXS}
181             all: $lib
182            
183             $lib: $name.c
184             \$(APXS) $dversion -I$self->{cmodules_dir} -c $name.c
185            
186             clean:
187             -rm -rf $name.o $name.lo $name.slo $name.la .libs
188             EOF
189              
190 0 0       0     close $fh or die "close $makefile: $!";
191             }
192              
193             sub cmodules_write_makefile_aix {
194 0     0 0 0     my($self, $mod) = @_;
195              
196 0         0     my $dversion = $self->server->dversion;
197 0         0     my $name = $mod->{name};
198 0         0     my $makefile = catfile $mod->{dir}, 'Makefile';
199 0         0     my $apxsflags = '';
200              
201             #
202             # Only do this for Apache 1.*
203             #
204 0 0       0     if ($self->server->{rev} == 1) {
205 0         0         $apxsflags = "-Wl,-bE:$name.exp";
206 0         0         my $expfile = catfile $mod->{dir}, "$name.exp";
207 0 0       0         if (! -f $expfile) {
208 0         0             my $fh = Symbol::gensym();
209 0         0             $name =~ /^mod_(\w+)(?:\.c)?$/;
210 0         0             my $sym = $1 . '_module';
211 0 0       0             open $fh, ">$expfile" or die "open $expfile: $!";
212 0         0             print $fh "$sym\n";
213 0         0             close $fh;
214                     }
215                 }
216 0         0     debug "writing $makefile";
217              
218 0         0     my $lib = $self->cmodules_build_so($name);
219              
220 0         0     my $fh = Symbol::gensym();
221 0 0       0     open $fh, ">$makefile" or die "open $makefile: $!";
222              
223 0         0     print $fh <<EOF;
224             APXS=$self->{APXS}
225             APXSFLAGS=$apxsflags
226             all: $lib
227            
228             $lib: $name.c
229             \$(APXS) $dversion -I$self->{cmodules_dir} \$(APXSFLAGS) -c $name.c
230            
231             clean:
232             -rm -rf $name.o $name.lo $name.slo $name.la .libs
233             EOF
234              
235 0 0       0     close $fh or die "close $makefile: $!";
236             }
237              
238             sub cmodules_write_makefile_MSWin32 {
239 0     0 0 0     my($self, $mod) = @_;
240              
241 0         0     my $dversion = $self->server->dversion;
242 0         0     my $name = $mod->{name};
243 0         0     my $makefile = "$mod->{dir}/Makefile";
244 0         0     debug "writing $makefile";
245 0         0     my $extras = '';
246              
247 0         0     my $lib = $self->cmodules_build_so($name);
248 0 0       0     $extras = ' -llibhttpd -p ' if ($self->server->{rev} != 1);
249 0         0     my $goners = join ' ', (map {$name . '.' . $_} qw(exp lib so lo));
  0         0  
250              
251 0         0     my $fh = Symbol::gensym();
252 0 0       0     open $fh, ">$makefile" or die "open $makefile: $!";
253              
254 0         0     print $fh <<EOF;
255             APXS=$self->{APXS}
256             all: $lib
257            
258             $lib: $name.c
259             \$(APXS) $dversion -I$self->{cmodules_dir} $extras -c $name.c
260            
261             clean:
262             -erase $goners
263             EOF
264              
265 0 0       0     close $fh or die "close $makefile: $!";
266             }
267              
268             sub cmodules_make {
269 0     0 0 0     my $self = shift;
270 0   0     0     my $targ = shift || 'all';
271              
272 0         0     my $cmd = "cd $self->{cmodules_dir} && $Config{make} $targ";
273 0         0     debug $cmd;
274 0         0     system $cmd;
275 0 0       0     if ($?) {
276 0         0         die "Failed to build c-modules";
277                 }
278             }
279              
280             sub cmodules_compile {
281 0     0 0 0     shift->cmodules_make('all');
282             }
283              
284             sub cmodules_httpd_conf {
285 0     0 0 0     my $self = shift;
286              
287 0         0     my @args;
288              
289 0         0     for my $mod (@{ $self->{cmodules} }) {
  0         0  
290 0         0         my $dir = $mod->{dir};
291 0         0         my $lib = $self->cmodules_build_so($mod->{name});
292 0         0         my $so = "$dir/$lib";
293              
294 0 0       0         next unless -e $so;
295              
296 0         0         $self->preamble(LoadModule => "$mod->{sym} $so");
297              
298 0         0         my $cname = "$mod->{name}.c";
299 0         0         my $cfile = "$dir/$cname";
300 0         0         $self->{modules}->{$cname} = 1;
301              
302 0         0         $self->add_module_config($cfile, \@args);
303                 }
304              
305 0 0       0     $self->postamble(\@args) if @args;
306             }
307              
308             sub cmodules_clean {
309 0     0 0 0     my $self = shift;
310              
311 0         0     my $dir = $self->{cmodules_dir};
312 0 0 0     0     return unless $dir and -e "$dir/Makefile";
313              
314 0 0       0     unless ($self->{clean_level} > 1) {
315             #skip t/TEST -conf
316 0         0         warning "skipping rebuild of c-modules; run t/TEST -clean to force";
317 0         0         return;
318                 }
319              
320 0         0     $self->cmodules_make('clean');
321              
322 0         0     for my $mod (@{ $self->{cmodules} }) {
  0         0  
323 0         0         my $makefile = "$mod->{dir}/Makefile";
324 0         0         debug "unlink $makefile";
325 0         0         unlink $makefile;
326                 }
327              
328 0         0     unlink "$dir/Makefile";
329             }
330              
331             #try making it easier for test modules to compile with both 1.x and 2.x
332             sub cmodule_define_name {
333 258     258 0 2590     my $name = shift;
334 258 100       4384     $name eq 'NULL' ? $name : "APACHE_HTTPD_TEST_\U$name";
335             }
336              
337             sub cmodule_define {
338 96     96 0 1004     my $hook = cmodule_define_name(@_);
339 96         1207     "#ifndef $hook\n#define $hook NULL\n#endif\n";
340             }
341              
342             my @cmodule_config_names = qw(per_dir_create per_dir_merge
343             per_srv_create per_srv_merge
344             commands);
345              
346             my @cmodule_config_defines = map {
347                 cmodule_define($_);
348             } @cmodule_config_names;
349              
350             my $cmodule_config_extra =
351                 "#ifndef APACHE_HTTPD_TEST_EXTRA_HOOKS\n".
352                 "#define APACHE_HTTPD_TEST_EXTRA_HOOKS(p) do { } while (0)\n".
353                 "#endif\n";
354              
355             my $cmodule_config_hooks = join ",\n ", map {
356                 cmodule_define_name($_);
357             } @cmodule_config_names;
358              
359             my @cmodule_phases = qw(post_read_request translate_name header_parser
360             access_checker check_user_id auth_checker
361             type_checker fixups handler log_transaction
362             child_init);
363              
364             my $cmodule_hooks_1 = join ",\n ", map {
365                 cmodule_define_name($_);
366             } qw(translate_name check_user_id auth_checker access_checker
367             type_checker fixups log_transaction header_parser
368             child_init NULL post_read_request);
369              
370             my $cmodule_template_1 = <<"EOF",
371             static const handler_rec name ## _handlers[] =
372             {
373             {#name, APACHE_HTTPD_TEST_HANDLER}, /* ok if handler is NULL */
374             {NULL}
375             };
376            
377             module MODULE_VAR_EXPORT name ## _module =
378             {
379             STANDARD_MODULE_STUFF,
380             NULL, /* initializer */
381             $cmodule_config_hooks,
382             name ## _handlers, /* handlers */
383             $cmodule_hooks_1
384             }
385             EOF
386              
387             my @cmodule_hooks = map {
388                 my $hook = cmodule_define_name($_);
389                 <<EOF;
390             if ($hook != NULL)
391             ap_hook_$_($hook,
392             NULL, NULL,
393             APACHE_HTTPD_TEST_HOOK_ORDER);
394             EOF
395             } @cmodule_phases;
396              
397             my @cmodule_hook_defines = map {
398                 cmodule_define($_);
399             } @cmodule_phases;
400              
401             my $cmodule_template_2 = <<"EOF";
402             static void name ## _register_hooks(apr_pool_t *p)
403             {
404             @cmodule_hooks
405             APACHE_HTTPD_TEST_EXTRA_HOOKS(p);
406             }
407            
408             module AP_MODULE_DECLARE_DATA name ## _module = {
409             STANDARD20_MODULE_STUFF,
410             $cmodule_config_hooks,
411             name ## _register_hooks, /* register hooks */
412             }
413             EOF
414              
415             my %cmodule_templates = (1 => $cmodule_template_1, 2 => $cmodule_template_2);
416              
417             sub cmodules_module_template {
418 0     0 0       my $self = shift;
419 0               my $template = $self->server->version_of(\%cmodule_templates);
420 0               chomp $template;
421              
422 0               $template =~ s,$, \\,mg;
423 0               $template =~ s, \\$,,s;
424              
425 0               local $" = ', ';
426              
427 0               return <<EOF;
428             #define APACHE_HTTPD_TEST_MODULE(name) \\
429             $template
430             EOF
431             }
432              
433             sub cmodules_generate_include {
434 0     0 0       my $self = shift;
435              
436 0               my $file = "$self->{cmodules_dir}/apache_httpd_test.h";
437 0               my $fh = $self->genfile($file);
438              
439 0               while (read Apache::TestConfigC::DATA, my $buf, 1024) {
440 0                   print $fh $buf;
441                 }
442              
443 0               print $fh @cmodule_hook_defines, @cmodule_config_defines;
444              
445 0               print $fh $cmodule_config_extra;
446              
447 0               print $fh $self->cmodules_module_template;
448              
449 0               close $fh;
450             }
451              
452             package Apache::TestConfigC; #Apache/TestConfig.pm also has __DATA__
453             1;
454             __DATA__
455             #ifndef APACHE_HTTPD_TEST_H
456             #define APACHE_HTTPD_TEST_H
457            
458             /* headers present in both 1.x and 2.x */
459             #include "httpd.h"
460             #include "http_config.h"
461             #include "http_protocol.h"
462             #include "http_request.h"
463             #include "http_log.h"
464             #include "http_main.h"
465             #include "http_core.h"
466             #include "ap_config.h"
467            
468             #ifdef APACHE1
469             #define AP_METHOD_BIT 1
470             typedef size_t apr_size_t;
471             typedef array_header apr_array_header_t;
472             #define APR_OFF_T_FMT "ld"
473             #define APR_SIZE_T_FMT "lu"
474             #endif /* APACHE1 */
475            
476             #ifdef APACHE2
477             #ifndef APACHE_HTTPD_TEST_HOOK_ORDER
478             #define APACHE_HTTPD_TEST_HOOK_ORDER APR_HOOK_MIDDLE
479             #endif
480             #include "ap_compat.h"
481             #endif /* APACHE2 */
482            
483             #endif /* APACHE_HTTPD_TEST_H */
484            
485