File Coverage

File:t/10-coverage.t
Coverage:98.3%

linestmtbrancondsubpodtimecode
1
1
1
1
4608
3
39
use strict;
2
1
1
1
5
1
55
use warnings;
3
4
1
1
1
806
1566
153
use FindBin qw/$Bin/;
5
1
1
1
414
894
10
use lib qq{$Bin/../lib};
6
1
1
1
843
124504
5
use Test::More;
7
8
1
1
1
516
2
2
use OpenMP::Environment;
9
1
57
use OpenMP::Environment::Validation qw/
10    validate_value validate_assignment assert_variable assert_environment
11    analyze_environment
12
1
1
4
1
/;
13
14# Exercise each explicit-import arm independently.  This complements the
15# public DSL tests without changing the regression files from master.
16{
17
0
0
    package OpenMPEnvironmentExplicitAssert;
18
1
1
1
18
1
2
    use OpenMP::Environment qw/assert/;
19}
20
1
64187
package main;
21
1
8
ok( OpenMPEnvironmentExplicitAssert->can(q{assert}), q{explicit assert import is covered} );
22
1
294
ok( !OpenMPEnvironmentExplicitAssert->can(q{unset}), q{explicit assert import does not imply unset} );
23
24{
25
0
0
    package OpenMPEnvironmentExplicitConstant;
26
1
1
1
4
1
2
    use OpenMP::Environment qw/omp_num_threads/;
27}
28
1
198
package main;
29
1
2
is OpenMPEnvironmentExplicitConstant::omp_num_threads(), q{OMP_NUM_THREADS}, q{explicit constant-only import is covered};
30
1
214
ok( !OpenMPEnvironmentExplicitConstant->can(q{assert}), q{constant-only import does not imply assert} );
31
1
197
ok( !OpenMPEnvironmentExplicitConstant->can(q{unset}), q{constant-only import does not imply unset} );
32
33# Retained private compatibility helper: cover both sides of each legacy
34# predicate independently.
35
1
187
is OpenMP::Environment::_is_ge_if_set( 1, q{x} ),
36  q{Value must be an integer great than or equal to 1},
37  q{legacy integer helper rejects non-integers};
38
1
204
is OpenMP::Environment::_is_ge_if_set( 1, 0 ),
39  q{Value must be an integer great than or equal to 1},
40  q{legacy integer helper rejects values below the minimum};
41
1
201
is OpenMP::Environment::_is_ge_if_set( 1, 1 ), undef,
42  q{legacy integer helper accepts the minimum};
43
44# OpenMP 5.2 generally permits leading/trailing whitespace in environment
45# values.  The public boolean compatibility behavior should still unset false
46# values after that standard whitespace is ignored.
47
1
250
my $whitespace_env = OpenMP::Environment->new;
48
1
2
$whitespace_env->omp_dynamic(q{true});
49
1
2
$whitespace_env->omp_dynamic(q{  false  });
50ok !exists $ENV{OMP_DYNAMIC},
51
1
2
  q{OMP_DYNAMIC whitespace-wrapped FALSE retains historical unset behavior};
52
1
197
$whitespace_env->omp_nested(q{true});
53
1
2
$whitespace_env->omp_nested(q{  FALSE  });
54ok !exists $ENV{OMP_NESTED},
55
1
2
  q{OMP_NESTED whitespace-wrapped FALSE retains historical unset behavior};
56
57# Assignment validation: exercise the strict legacy-validated failure path.
58
1
221
local $@;
59
1
1
2
2
eval { validate_assignment( q{OMP_CANCELLATION}, q{maybe} ) };
60
1
4
like $@, qr/OMP_CANCELLATION/, q{strict assignment path can fail for historically validated variables};
61
62# assert_variable/assert_environment both distinguish absent values from keys
63# that exist but are undef.
64
1
201
my %undefined_one = ( OMP_NUM_THREADS => undef );
65
1
2
ok assert_variable( \%undefined_one, q{OMP_NUM_THREADS} ),
66  q{assert_variable accepts an explicitly undefined supported value};
67
68
1
191
my %undefined_environment = (
69    OMP_NUM_THREADS => undef,
70    OMP_SCHEDULE    => q{static},
71);
72
1
2
ok assert_environment( \%undefined_environment ),
73  q{assert_environment skips explicitly undefined supported values};
74
75# Cover each stage of the portable OMP_NESTED / OMP_MAX_ACTIVE_LEVELS
76# relationship without any system probing.
77
1
205
my $a = analyze_environment( { OMP_NESTED => q{FALSE} } );
78
1
3
ok $a->{valid}, q{FALSE OMP_NESTED alone is valid};
79
80
1
190
$a = analyze_environment({
81    OMP_NESTED            => q{FALSE},
82    OMP_MAX_ACTIVE_LEVELS => q{bogus},
83});
84
1
3
ok !$a->{valid}, q{nonnumeric max-active-levels is a value error rather than a cross-variable conflict};
85
1
1
211
3
is scalar( @{ $a->{conflicts} } ), 0,
86  q{nonnumeric max-active-levels does not enter numeric conflict logic};
87
88
1
206
$a = analyze_environment({
89    OMP_NESTED            => q{FALSE},
90    OMP_MAX_ACTIVE_LEVELS => 1,
91});
92
1
3
ok $a->{valid}, q{FALSE OMP_NESTED with one active level is not the implementation-defined conflict};
93
1
1
188
3
is scalar( @{ $a->{conflicts} } ), 0,
94  q{one active level leaves the conflict list empty};
95
96
1
203
$a = analyze_environment({
97    OMP_NESTED            => q{FALSE},
98    OMP_MAX_ACTIVE_LEVELS => 2,
99});
100
1
3
ok !$a->{valid}, q{FALSE OMP_NESTED with more than one active level is flagged};
101
1
1
213
3
is scalar( @{ $a->{conflicts} } ), 1,
102  q{the implementation-defined combination produces one conflict};
103
104# Precedence/nesting notes: cover the partial and alternate paths separately.
105
1
202
$a = analyze_environment({ GOMP_CPU_AFFINITY => q{0-3} });
106
1
3
ok $a->{valid}, q{GOMP_CPU_AFFINITY alone is valid};
107
1
1
192
3
is scalar( @{ $a->{notes} } ), 0,
108  q{GNU affinity precedence note requires OMP_PROC_BIND too};
109
110
1
204
$a = analyze_environment({ OMP_NESTED => q{TRUE} });
111
1
3
ok $a->{valid}, q{OMP_NESTED alone is valid};
112
1
1
188
3
is scalar( @{ $a->{notes} } ), 0,
113  q{OMP_NESTED relationship note requires OMP_MAX_ACTIVE_LEVELS too};
114
115
1
202
$a = analyze_environment({
116    OMP_NUM_THREADS => 8,
117    OMP_PROC_BIND   => q{SPREAD,CLOSE},
118});
119
1
3
ok $a->{valid}, q{PROC_BIND list with scalar NUM_THREADS is valid};
120
1
1
188
5
ok grep( /max-active-levels-var/, @{ $a->{notes} } ),
121  q{PROC_BIND list independently triggers the nested-level initialization note};
122
123
1
184
$a = analyze_environment({
124    OMP_NUM_THREADS => 8,
125    OMP_PROC_BIND   => q{CLOSE},
126});
127
1
3
ok $a->{valid}, q{single-item thread and binding settings are valid};
128
1
1
185
2
is scalar( @{ $a->{notes} } ), 0,
129  q{single-item values do not trigger the nested-list note};
130
131# OMP_PLACES parser edges exercise parenthesis state, top-level separator
132# behavior, explicit place suffixes, and resource strides.
133
1
216
for my $bad (
134    q{vendor(1,2)},
135    q{vendor(1,2},
136    q{vendor(1,2))},
137) {
138
3
376
    local $@;
139
3
3
3
5
    eval { validate_value( q{OMP_PLACES}, $bad ) };
140
3
10
    like $@, qr/OMP_PLACES|Expected an explicit/, qq{OMP_PLACES rejects malformed parenthesized form $bad};
141}
142
143
1
186
is validate_value( q{OMP_PLACES}, q{0:4:-1} ), q{0:4:-1},
144  q{OMP_PLACES accepts a signed explicit-place stride};
145
1
203
is validate_value( q{OMP_PLACES}, q{{0:4:-1}} ), q{{0:4:-1}},
146  q{OMP_PLACES accepts a signed resource stride};
147
148
149# Public OMP_PLACES parsing rejects unbalanced input before the lower-level
150# place helper is reached; call the helper directly to cover its defensive
151# unbalanced-brace return and the matching-brace end-of-input path.
152
1
203
is OpenMP::Environment::Validation::_validate_place_interval(q[{0]),
153  q{Unbalanced braces in OMP_PLACES},
154  q{place-interval helper reports an unbalanced opening brace};
155
1
202
is OpenMP::Environment::Validation::_matching_brace(q[{0]), -1,
156  q{matching-brace helper reports end-of-input without a close};
157
158# A colon-bearing unknown memory-space name reaches the second half of the
159# allocator name/space decision rather than the no-colon form.
160
1
200
local $@;
161
1
1
2
2
eval { validate_value( q{OMP_ALLOCATOR}, q{not_a_space:alignment=16} ) };
162
1
4
like $@, qr/predefined OpenMP allocator or memory space/,
163  q{OMP_ALLOCATOR rejects an unknown colon-qualified memory space};
164
165# Cover width syntax on the long affinity field form.
166
1
195
is validate_value( q{OMP_AFFINITY_FORMAT}, q{thread %.3{thread_num}} ),
167  q{thread %.3{thread_num}},
168  q{OMP_AFFINITY_FORMAT accepts width syntax on a long field};
169
170# Direct helper coverage for the defined/no-comma/comma cases used by
171# analyze_environment.  These are internal policy helpers, not system probes.
172
1
203
is OpenMP::Environment::Validation::_has_multiple_items(undef), 0,
173  q{multiple-item helper handles undef};
174
1
199
is OpenMP::Environment::Validation::_has_multiple_items(q{8}), 0,
175  q{multiple-item helper handles a scalar value};
176
1
201
is OpenMP::Environment::Validation::_has_multiple_items(q{8,4}), 1,
177  q{multiple-item helper recognizes a list};
178
1
198
is OpenMP::Environment::Validation::_has_proc_bind_list(undef), 0,
179  q{proc-bind list helper handles undef};
180
1
198
is OpenMP::Environment::Validation::_has_proc_bind_list(q{CLOSE}), 0,
181  q{proc-bind list helper handles one policy};
182
1
199
is OpenMP::Environment::Validation::_has_proc_bind_list(q{CLOSE,SPREAD}), 1,
183  q{proc-bind list helper recognizes multiple policies};
184
185# The enum helper has both successful and rejected paths and is used by many
186# public validators.
187
1
196
is OpenMP::Environment::Validation::_enum( q{TRUE}, qw/TRUE FALSE/ ), undef,
188  q{enum helper recognizes an allowed value};
189
1
243
like OpenMP::Environment::Validation::_enum( q{MAYBE}, qw/TRUE FALSE/ ),
190  qr/Expected one of/,
191  q{enum helper reports a rejected value};
192
193
1
189
done_testing;
194