This file is indexed.

/usr/share/polymake/scripts/run_testcases is in polymake-common 3.2r2-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
#  Copyright (c) 1997-2018
#  Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
#  http://www.polymake.org
#
#  This program is free software; you can redistribute it and/or modify it
#  under the terms of the GNU General Public License as published by the
#  Free Software Foundation; either version 2, or (at your option) any
#  later version: http://www.gnu.org/licenses/gpl.txt.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#-------------------------------------------------------------------------------
#
#  Driver for unit tests
#

use Polymake::Test;

##################################################################
#
#  Option parsing and preparations
#

my (@apps, @extensions, @testgroups, @examples, $jenkins_report, $annotate_mode, $emacs_style,
    $validate, $ignore_random_failures, $shuffle_seed, $no_new_glue_code, $single_script,
    %extensions, %found_testgroups, $exit, $auto_adjust);

if ( !GetOptions( 'applications=s' => sub { collect_arglist(\@apps, $_[1]) },
                  'extensions=s' => sub { collect_arglist(\@extensions, $_[1]) },
                  'testgroups=s' => sub { collect_arglist(\@testgroups, $_[1]) },
                  'examples=s' => sub { collect_arglist(\@examples, $_[1]) },
                  'jenkins-report=s' => \$jenkins_report,
                  'annotate-mode=s' => \$annotate_mode,
                  'emacs-style' => \$emacs_style,
                  'validate-XML' => \$validate,
                  'shuffle:i' => \$shuffle_seed,
                  'random-failures=s' => \$ignore_random_failures,
                  'no-new-glue-code' => \$no_new_glue_code,
                  'allow-exec-time=f' => \$Test::Case::allowed_exec_time,
                  'auto-adjust' =>\$auto_adjust,
                )
     or @ARGV>1
     or @ARGV==1 && !-f ($single_script=shift @ARGV) &&
        die ("script file $single_script ", -e $single_script ? "is not a regular file " : "does not exist", "\n")
     or $jenkins_report ? ($emacs_style || @extensions || @testgroups || @examples || $ignore_random_failures) : ($annotate_mode)
     or $single_script && ($jenkins_report || @apps || @extensions || @testgroups || @examples)
     or $ignore_random_failures && $ignore_random_failures !~ /^(?:ignore|hide|show)$/ ) {
   die <<'.'
usage: polymake --script run_testcases [ options ] [ test_script.pl ]
   or: polymake --script run_testcases [ options ] --jenkins-report REPORT

If a test script file is specified, it is executed and the success indicator
returned to the caller.  Otherwise all existing test groups are executed,
which satisfy the filtering options described below, if any.

Options are:
   --applications APPNAME ...
       only run tests from the specified applications (default: all known applications)
   --extensions EXTDIR ... | 'ALL' | 'all'
       run tests from the specified extensions; ALL means from all registered extension
       (default: from bundled extensions only)
   --testgroups TESTNAME ...
       only execute testgroups with matching names; shell-like wildcards allowed
   --examples TOPIC ...
       only execute examples embedded in the interactive help for matching topics, e.g. functions
       or properties; shell-like wildcards allowed;
       "NONE" or "none" will suppress execution of any examples
   --shuffle [SEED]
       permute apps and testgroups randomly
       specify an integer SEED to reproduce a (failed) run;
       if omitted, a random seed is generated and reported on stdout
   --random-failures =ignore|hide|show
       do not treat mismatching results as failues in tests known to be randomly volatile
       the option value controls their reporting in the final summary:
       ignore - report them briefly without showing the differing test results
       hide   - do not report then at all
       show   - report them fully like the normal failures
   --validate-XML
       perform additional sanity checks on data files: generate elaborated schemata,
       validate all input files, and check the idempotence of a save & load sequence
   --no-new-glue-code
       forbid automatic generation and compilation of C++/perl interface code snippets (aka wrappers)
   --allow-exec-time SEC
       increase the allowed execution time for a single test case;
       test scripts may still override this for especially slow cases
   --jenkins-report REPORT
       produce a JUnit-compatible test report REPORT_APPNAME.xml for each application,
       do not print any test results or warnings to STDOUT.
       This option is incompatible with --extensions, --testgroups, and --random-failures.
   --annotate-mode MODE
       annotate every testcase in JUnit test reports with '@MODE',
       allowing to distinguish tests repeatedly run in different build modes
   --emacs-style
       produce simple report without colors, cursor control, and with error messages
       comprehensible to emacs compilation mode
   --auto-adjust
       try to adjust test objects to changed rules or version upgrade by adding/removing properties;
       to be used in interactive mode only and with uttermost care
.
}

# run as a standalone script from the command line?
my $standalone=(caller(1))[3] eq "Polymake::Main::run_script";

if (@extensions) {
   if ($#extensions==0 && lc($extensions[0]) eq "all") {
      @extensions=();
   } elsif ($standalone) {
      # detect wrong extension directories
      $_=Cwd::abs_path($_) for @extensions;
      @extensions{@extensions}=();
      my @known=grep { exists $extensions{$_->dir} } @Core::Extension::active;
      if (@known != @extensions) {
         my @unknown=grep { !contains_string(\@known, $_) } @extensions;
         die "Unknown extension", @unknown>1 && "s", " ", join(", ", @unknown), "\n";
      }

      # filter out unwanted extensions; preserve all bundled extensions
      my %keep=%extensions;
      for (my $i=$#Core::Extension::active; $i>=$Core::Extension::num_bundled; --$i) {
         my $ext=$Core::Extension::active[$i];
         if (exists $keep{$ext->dir}) {
            @keep{ map { $_->dir } @{$ext->requires} }=();
         } else {
            splice @Core::Extension::active, $i, 1;
         }
      }
   } else {
      die "Sorry, filtering by extensions is not supported when this script is called from polymake shell\n";
   }
} elsif ($standalone) {
   # crop the extension list after the last bundled extension
   $#Core::Extension::active=$Core::Extension::num_bundled-1;
}

if (@apps) {
   if (@extensions) {
      foreach my $appname (@apps) {
         if ((map { glob "$_/apps/$appname" } @extensions)==0) {
            if (@extensions>1) {
               die "None of specified extensions contributes to the application $appname\n";
            } else {
               die "Extension @extensions does not contribute to the application $appname\n";
            }
         }
      }
   }

} elsif ($single_script) {
   $single_script=Cwd::abs_path($single_script) if $single_script !~ m{^/};
   if ($single_script =~ m{/apps/(\w+)/testsuite/[^/]+/test(?:_.*)?\.pl$}) {
      push @apps, $1;
   } else {
      die "A test script must reside in an application-specific testsuite subdirectory and be named 'test[_SUBGROUP].pl'\n";
   }

} else {
   if (@extensions) {
      @apps= sorted_uniq(sort( map { /$filename_re/o } map { glob("$_/apps/*") } @extensions ));
   } else {
      @apps= map { /$filename_re/o } glob "$InstallTop/apps/*";
   }
}

my $env=new Test::Environment($Scope, shuffle_seed => $shuffle_seed,
                              validate => $validate, annotate_mode => $annotate_mode,
                              no_new_glue_code => $no_new_glue_code,
                              ignore_random_failures => $ignore_random_failures);

if ($jenkins_report) {
   $jenkins_report =~ s{^(?=[^/.])}{$InstallTop/};
} else {
   $env->prepare_pretty_output($emacs_style);
}

if (defined $shuffle_seed) {
   # on Jenkins, applications are often tested in parallel, the output must be disambiguated
   print "\n*** RANDOM SEED=", $env->shuffle_seed, @apps==1 && " (application @apps)", " ***\n";
}

if (!@testgroups && !@examples && !@extensions && !-d "$InstallTop/testscenarios") {
   # testing outside the source tree: just run the examples
   push @examples, "*";
}

my $disable_examples= @examples==1 && uc($examples[0]) eq "NONE"
  and pop @examples;
$Polymake::Core::InteractiveHelp::store_provenience=!$disable_examples;

########################################
#
#  The outer loop over all applications
#

foreach my $app ($env->shuffle->(@apps)) {

   local $_=12345;
   readonly($_);        # detect the abuse of $_ in the rules

   application($app);
   Test::Rule::fill_rule_cache($_) for $application, values %{$application->used};

   local_unshift(\@INC, $application);
   local_unshift($application->myINC, $Test::Subgroup::preamble);

   if ($single_script) {
      if (index($single_script, $application->top) != 0) {
         foreach my $ext (@{$application->extensions}) {
            if (index($single_script, $ext->app_dir($application)) == 0) {
               push @extensions, $ext;  last;
            }
         }
         @extensions
           or die "Test script $single_script does not reside in the application core tree neither in one of registered extensions\n";
      }
      my $group=new Test::Group($env, $single_script, $application, $extensions[0]);
      my $OK=$group->run;
      err_print($@), $@="" if $OK<0;
      $exit= $OK<=0;
      last;
   }

   $env->start_testsuite($jenkins_report, $app);

   ##################################################
   #
   #  The middle loop over all (selected) extensions,
   #    unless we only want to run some examples
   #
   if (!@examples or @testgroups) {

      foreach my $ext ($env->shuffle->(undef, @{$application->extensions})) {
         my $top_dir;
         if (defined $ext) {
            next if @extensions && !exists $extensions{$ext->dir};
            $top_dir=$ext->app_dir($application);
         } else {
            $top_dir=$application->top;
         }

         #################################################
         #
         #  The inner loop over all (selected) testgroups
         #
         if (@testgroups) {
            foreach my $pattern (@testgroups) {
               foreach my $dir (list_matching_testgroups($top_dir, $pattern)) {
                  $found_testgroups{$pattern}=1;
                  my $group=new Test::Group($env, $dir, $application, $ext);
                  if (@{$group->subgroups}) {
                     my $OK=$group->run;
                     $exit ||= $OK<=0;
                  } else {
                     warn("No test scripts found in testgroup $dir\n");
                     $exit=1;
                  }
               }
            }
         } else {
            my $tests_found;
            foreach my $dir ($env->shuffle->(glob("$top_dir/testsuite/*/."))) {
               substr($dir,-2)="";
               my $group=new Test::Group($env, $dir, $application, $ext);
               if (@{$group->subgroups}) {
                  $tests_found=1;
                  my $OK=$group->run;
                  $exit ||= $OK<=0;
               }
            }
            # tolerate for a while bundled extensions without testsuites
            if (!$tests_found && -d "$top_dir/testsuite") {
               if (glob("$top_dir/rules/*.rule*") ||
                   glob("$top_dir/include/*.h") ||
                   glob("$top_dir/src/*.cc") ||
                   glob("$top_dir/perllib/*")) {
                  warn_print( "No testcases found for application $app", $ext && " in extension ".$ext->URI );
                  $exit=1 if !$ext || @extensions || $ext->is_bundled;
               }
            }
         }
      }
   }

   ###########################################################################
   #
   #  Run all or selected examples,
   #    unless they have been disabled or we only want to run some testgroups
   #
   if (@examples) {
      foreach my $topic_name (@examples) {
         my $group=new Test::Examples($env, $topic_name, $application);
         if (@{$group->subgroups}) {
            my $OK=$group->run;
            $exit ||= $OK<=0;
         } elsif (@examples > 1 || $examples[0] ne "*") {
            warn("No examples found in any topics matching $topic_name\n");
            $exit=1;
         } else {
            print "No examples found\n";
         }
      }

   } elsif (!$disable_examples && !@testgroups) {
      my $group=new Test::Examples($env, undef, $application);
      if (@{$group->subgroups}) {
         my $OK=$group->run;
         $exit ||= $OK<=0;
      }
   }

   $env->close_testsuite;
}


if ($validate) {
   if (keys %{$env->validation_groups}) {
      my $schemata=$env->create_validation_schemata;
   
      while (my ($app, $groups)=each %{$env->validation_groups}) {
         $env->start_testsuite($jenkins_report, $app, "validation");
         foreach my $group (@$groups) {
            my $OK=$group->run($schemata);
            $exit ||= $OK<=0;
         }
         $env->close_testsuite;
      }
   }
}


if (!$jenkins_report) {
   if (@testgroups==keys %found_testgroups) {
      $env->print_summary;
   } else {
      foreach (grep { !$found_testgroups{$_} } @testgroups) {
         warn( /[*?\[\]{}]/ ? "No matching testgroups for the pattern '$_'\n" : "Testgroup $_ does not exist\n" );
      }
      $exit=1;
   }
}

if ($standalone) {
   exit($exit) if $exit;
} else {
   if ($auto_adjust && @{$env->failed}) {
      foreach (@{$env->failed}) {
         my ($where, @errors)=split /\n/;
         my $obj;
         if ($where =~ m{^"(.*)/[^/]+", line \d+: testcase (\S+)}) {
            my ($dir, $testcase)=($1, $2);
            my @files=glob("$dir/$testcase.[a-z]*");
            if (@files > 1) {
               print STDERR "ambiguous testcase $dir/$testcase\n";
               next;
            } elsif (@files) {
               $obj=$files[0];
            } else {
               print STDERR "no testcase found for $dir/$testcase\n";
               next;
            }
            my (@remove, @provide);
            foreach (@errors) {
               if (m{^lacking property (\w+)$}) {
                  push @remove, $1;
               } elsif (m{^unexpected property (\w+)$}) {
                  push @provide, $1;
               } else {
                  print STDERR "$obj: unknown action for $_\n";
                  undef $obj;
                  last;
               }
            }
            if (defined $obj) {
               eval {
                  $obj=Test::Environment::load_trusted_object_file($obj);
                  if (@remove) {
                     $obj->remove(@remove);
                  }
                  if (@provide) {
                     $obj->provide(@provide);
                  }
               };
               if ($@) {
                  print STDERR "auto-adjustment for ", $obj->name, " failed: $@";
               }
            }
         }
      }
   }
   return !$exit;   # 0 (=SUCCESS) => TRUE
}

##################################################################
#
#  Internal functions
#

sub list_matching_testgroups {
   my ($top_dir, $pattern)=@_;
   if ($pattern =~ /[*?]/) {
      map { substr($_, 0, length($_)-2) } glob("$top_dir/testsuite/$pattern/.")
   } elsif (-d (my $dir="$top_dir/testsuite/$pattern")) {
      $dir
   } else {
      ()
   }
}

# Local Variables:
# mode: perl
# cperl-indent-level:3
# indent-tabs-mode:nil
# End: