File Coverage

File:t/08-validation.t
Coverage:99.5%

linestmtbrancondsubpodtimecode
1
1
1
1
2957
2
24
use strict;
2
1
1
1
3
0
36
use warnings;
3
4
1
1
1
249
1338
116
use FindBin qw/$Bin/;
5
1
1
1
287
605
6
use lib qq{$Bin/../lib};
6
1
1
1
545
83285
7
use Test::More;
7
8
1
3111
use OpenMP::Environment::Validation qw/
9    validate_value validate_assignment assert_variable assert_environment
10    analyze_environment validation_rules
11
1
1
726
3
/;
12
13sub rejects {
14
58
120
    my ( $name, $value, $label, $pattern ) = @_;
15
58
65
    local $@;
16
58
58
79
119
    eval { validate_value( $name, $value ) };
17
58
169
    ok length($@), $label;
18
58
16346
    like $@, $pattern || qr/\Q$name\E/, qq{$label reports a useful diagnostic};
19}
20
21
1
73850
my $rules = validation_rules();
22
1
1
3
6
is scalar( @{ $rules->{fields} } ), 25, q{validation metadata contains every supported field};
23
1
1
341
5
is scalar( keys %{ $rules->{validators} } ), 25, q{validation metadata contains every validator};
24
1
6
1
273
10
2
ok grep( { $_ eq q{OMP_CANCELLATION} } @{ $rules->{normalized} } ), q{validation metadata records legacy-normalized variables};
25
1
15
1
251
18
3
ok grep( { $_ eq q{OMP_NUM_THREADS} } @{ $rules->{assignment_validated} } ), q{validation metadata records variables validated during compatible assignment};
26
1
248
is_deeply $rules->{whitespace_significant}, [ q{OMP_AFFINITY_FORMAT} ], q{validation metadata identifies the OpenMP whitespace-significant exception};
27
1
507
is $rules->{profile}, q{OpenMP 5.2 + GCC 16.2/libgomp}, q{validation metadata names the selected standards/runtime profile};
28
29
1
269
local $@;
30
1
1
1
3
eval { validate_value( undef, 1 ) };
31
1
13
like $@, qr/name is required/, q{validate_value requires a variable name};
32
1
1
459
4
eval { validate_value( q{OMP_NOT_REAL}, 1 ) };
33
1
10
like $@, qr/Unsupported/, q{validate_value rejects unsupported names};
34
1
455
is validate_value( q{OMP_NUM_THREADS}, undef ), undef, q{validate_value passes undef through};
35
36
1
634
is validate_assignment( q{GOMP_SPINCOUNT}, q{historical pass through} ), q{historical pass through}, q{assignment compatibility keeps formerly unvalidated values pass-through};
37
1
514
is validate_assignment( q{OMP_CANCELLATION}, q{true} ), q{TRUE}, q{assignment validation retains legacy normalization};
38
1
1
485
5
eval { validate_assignment( undef, 1 ) };
39
1
10
like $@, qr/name is required/, q{validate_assignment requires a variable name};
40
1
1
454
4
eval { validate_assignment( q{OMP_NOT_REAL}, 1 ) };
41
1
9
like $@, qr/Unsupported/, q{validate_assignment rejects unsupported names};
42
1
490
is validate_assignment( q{GOMP_SPINCOUNT}, undef ), undef, q{validate_assignment passes undef through};
43
44
1
598
is validate_value( q{OMP_CANCELLATION}, q{true} ), q{TRUE}, q{OMP_CANCELLATION accepts true};
45
1
484
is validate_value( q{OMP_CANCELLATION}, q{  true  } ), q{TRUE}, q{OMP_CANCELLATION accepts OpenMP-permitted surrounding whitespace};
46
1
485
rejects( q{OMP_CANCELLATION}, q{sometimes}, q{OMP_CANCELLATION rejects unknown boolean}, qr/TRUE/ );
47
1
451
is validate_value( q{OMP_DISPLAY_ENV}, q{verbose} ), q{VERBOSE}, q{OMP_DISPLAY_ENV accepts VERBOSE};
48
1
495
rejects( q{OMP_DISPLAY_ENV}, q{ALL}, q{OMP_DISPLAY_ENV rejects unknown display level} );
49
1
446
is validate_value( q{OMP_DEFAULT_DEVICE}, 0 ), 0, q{OMP_DEFAULT_DEVICE accepts zero};
50
1
504
is validate_value( q{OMP_DEFAULT_DEVICE}, q{  0  } ), q{0}, q{OMP_DEFAULT_DEVICE ignores surrounding OpenMP whitespace in strict validation};
51
1
486
rejects( q{OMP_DEFAULT_DEVICE}, -1, q{OMP_DEFAULT_DEVICE rejects negative values}, qr/integer/ );
52
1
448
rejects( q{OMP_DEFAULT_DEVICE}, q{gpu0}, q{OMP_DEFAULT_DEVICE rejects non-integers}, qr/integer/ );
53
1
441
is validate_value( q{OMP_NUM_TEAMS}, 1 ), 1, q{OMP_NUM_TEAMS accepts a positive integer};
54
1
478
rejects( q{OMP_NUM_TEAMS}, 0, q{OMP_NUM_TEAMS rejects zero} );
55
1
482
is validate_value( q{OMP_DYNAMIC}, q{true} ), q{true}, q{OMP_DYNAMIC accepts true without changing historical case};
56
1
476
is validate_value( q{OMP_DYNAMIC}, 1 ), 1, q{OMP_DYNAMIC retains historical numeric true support};
57
1
478
rejects( q{OMP_DYNAMIC}, q{maybe}, q{OMP_DYNAMIC rejects non-boolean value} );
58
1
454
is validate_value( q{OMP_MAX_ACTIVE_LEVELS}, 1 ), 1, q{OMP_MAX_ACTIVE_LEVELS follows libgomp positive-integer rule};
59
1
481
rejects( q{OMP_MAX_ACTIVE_LEVELS}, 0, q{OMP_MAX_ACTIVE_LEVELS applies the documented libgomp/legacy positive-integer profile even though OpenMP 5.2 permits zero} );
60
1
451
is validate_value( q{OMP_MAX_TASK_PRIORITY}, 0 ), 0, q{OMP_MAX_TASK_PRIORITY accepts zero};
61
1
479
rejects( q{OMP_MAX_TASK_PRIORITY}, -1, q{OMP_MAX_TASK_PRIORITY rejects negative values} );
62
1
445
is validate_value( q{OMP_NESTED}, q{true} ), q{TRUE}, q{OMP_NESTED retains uppercase filter};
63
1
478
is validate_value( q{OMP_NESTED}, 0 ), 0, q{OMP_NESTED retains numeric false compatibility};
64
1
480
rejects( q{OMP_NESTED}, q{maybe}, q{OMP_NESTED rejects non-boolean value} );
65
1
448
is validate_value( q{OMP_NUM_THREADS}, q{8, 4, 2} ), q{8, 4, 2}, q{OMP_NUM_THREADS accepts nested positive-integer lists};
66
1
480
rejects( q{OMP_NUM_THREADS}, q{8,0,2}, q{OMP_NUM_THREADS rejects zero in a list}, qr/comma-separated/ );
67
68
1
445
for my $value ( q{TRUE}, q{FALSE}, q{PRIMARY}, q{CLOSE}, q{SPREAD}, q{MASTER,CLOSE,SPREAD}, q{spread,close,primary} ) {
69
7
2905
    is validate_value( q{OMP_PROC_BIND}, $value ), $value, qq{OMP_PROC_BIND accepts $value};
70}
71
1
481
rejects( q{OMP_PROC_BIND}, q{TRUE,CLOSE}, q{OMP_PROC_BIND does not mix boolean and policy-list syntax} );
72
1
449
rejects( q{OMP_PROC_BIND}, q{NEAR}, q{OMP_PROC_BIND rejects an unknown policy} );
73
74
1
447
for my $value (
75    q{cores}, q{cores(4)}, q{vendor_places(2)}, q{{0,1,2},{3,4,5}},
76    q{{0:4},{4:4}}, q{!{0},1:3}, q{{0}:4:2}, q{0:4:2}
77) {
78
8
3475
    is validate_value( q{OMP_PLACES}, $value ), $value, qq{OMP_PLACES accepts $value};
79}
80
1
486
rejects( q{OMP_PLACES}, q{}, q{OMP_PLACES rejects an empty value} );
81
1
450
rejects( q{OMP_PLACES}, q{{0,,2}}, q{OMP_PLACES rejects an empty resource} );
82
1
452
rejects( q{OMP_PLACES}, q{{0,2},}, q{OMP_PLACES rejects an empty place} );
83
1
450
rejects( q{OMP_PLACES}, '{0,2}, {3', q{OMP_PLACES rejects unbalanced braces} );
84
1
450
rejects( q{OMP_PLACES}, q{{x}}, q{OMP_PLACES rejects a nonnumeric explicit resource} );
85
1
448
is validate_value( q{OMP_PLACES}, q{{!0,1}} ), q{{!0,1}}, q{OMP_PLACES accepts resource exclusion syntax};
86
1
212
rejects( q{OMP_PLACES}, q{@}, q{OMP_PLACES rejects a malformed explicit place} );
87
1
193
rejects( q{OMP_PLACES}, '0}', q{OMP_PLACES rejects an unmatched closing brace} );
88
1
190
rejects( q{OMP_PLACES}, q{{}}, q{OMP_PLACES rejects an empty explicit resource list} );
89
1
197
rejects( q{OMP_PLACES}, q{0:0}, q{OMP_PLACES rejects a zero-length place interval} );
90
91
1
192
for my $value ( q{1}, q{1024}, q{64M}, q{2G}, q{4096K} ) {
92
5
831
    is validate_value( q{OMP_STACKSIZE}, $value ), $value, qq{OMP_STACKSIZE accepts $value};
93}
94
1
205
rejects( q{OMP_STACKSIZE}, q{0}, q{OMP_STACKSIZE rejects zero} );
95
1
194
rejects( q{OMP_STACKSIZE}, q{4T}, q{OMP_STACKSIZE rejects an unsupported unit} );
96
97
1
191
for my $value ( q{static}, q{dynamic,4}, q{guided,8}, q{auto}, q{monotonic:static}, q{nonmonotonic:dynamic,4} ) {
98
6
1032
    is validate_value( q{OMP_SCHEDULE}, $value ), $value, qq{OMP_SCHEDULE accepts $value};
99}
100
1
207
rejects( q{OMP_SCHEDULE}, q{banana}, q{OMP_SCHEDULE rejects an unknown kind} );
101
1
196
rejects( q{OMP_SCHEDULE}, q{dynamic,0}, q{OMP_SCHEDULE rejects zero chunk size} );
102
1
200
rejects( q{OMP_SCHEDULE}, q{random:dynamic,4}, q{OMP_SCHEDULE rejects an unknown modifier} );
103
1
190
is validate_value( q{OMP_SCHEDULE}, q{  dynamic,4  } ), q{dynamic,4}, q{OMP_SCHEDULE ignores surrounding OpenMP whitespace};
104
105
1
208
is validate_value( q{OMP_TARGET_OFFLOAD}, q{mandatory} ), q{MANDATORY}, q{OMP_TARGET_OFFLOAD normalizes a standard value};
106
1
205
rejects( q{OMP_TARGET_OFFLOAD}, q{FORCE}, q{OMP_TARGET_OFFLOAD rejects an unknown mode} );
107
1
204
is validate_value( q{OMP_THREAD_LIMIT}, 1 ), 1, q{OMP_THREAD_LIMIT accepts positive integer};
108
1
206
rejects( q{OMP_THREAD_LIMIT}, 0, q{OMP_THREAD_LIMIT rejects zero} );
109
1
204
is validate_value( q{OMP_WAIT_POLICY}, q{active} ), q{ACTIVE}, q{OMP_WAIT_POLICY accepts ACTIVE};
110
1
205
rejects( q{OMP_WAIT_POLICY}, q{SLEEP}, q{OMP_WAIT_POLICY rejects unknown policy} );
111
112
1
189
for my $value ( q{0}, q{0 3 1-2 4-15:2}, q{0,2,4-8:2} ) {
113
3
417
    is validate_value( q{GOMP_CPU_AFFINITY}, $value ), $value, qq{GOMP_CPU_AFFINITY accepts $value};
114}
115
1
207
rejects( q{GOMP_CPU_AFFINITY}, q{cpu0}, q{GOMP_CPU_AFFINITY rejects symbolic CPUs} );
116
1
191
rejects( q{GOMP_CPU_AFFINITY}, q{4-8:0}, q{GOMP_CPU_AFFINITY rejects zero stride} );
117
1
192
is validate_value( q{GOMP_DEBUG}, 0 ), 0, q{GOMP_DEBUG accepts zero};
118
1
207
is validate_value( q{GOMP_DEBUG}, 1 ), 1, q{GOMP_DEBUG accepts one};
119
1
204
rejects( q{GOMP_DEBUG}, 2, q{GOMP_DEBUG rejects values outside 0/1} );
120
1
192
is validate_value( q{GOMP_STACKSIZE}, q{1024} ), q{1024}, q{GOMP_STACKSIZE accepts the GNU-native numeric-kilobyte form};
121
1
206
is validate_value( q{GOMP_STACKSIZE}, q{1024G} ), q{1024G}, q{GOMP_STACKSIZE retains the documented OpenMP::Environment unit-suffix compatibility extension};
122
1
205
is validate_assignment( q{GOMP_STACKSIZE}, q{1024G} ), q{1024G}, q{GOMP_STACKSIZE assignment remains pass-through for pre-1.5 compatibility};
123
1
204
rejects( q{GOMP_STACKSIZE}, 0, q{GOMP_STACKSIZE rejects zero} );
124
1
205
for my $value ( q{0}, q{300000}, q{4k}, q{30M}, q{2G}, q{1T}, q{INFINITE}, q{INFINITY} ) {
125
8
1440
    is validate_value( q{GOMP_SPINCOUNT}, $value ), $value, qq{GOMP_SPINCOUNT accepts $value};
126}
127
1
221
rejects( q{GOMP_SPINCOUNT}, q{4m}, q{GOMP_SPINCOUNT preserves documented suffix case} );
128
1
192
rejects( q{GOMP_SPINCOUNT}, q{forever}, q{GOMP_SPINCOUNT rejects unknown words} );
129
1
194
is validate_value( q{GOMP_RTEMS_THREAD_POOLS}, q{1@WRK0:3$4@WRK1} ), q{1@WRK0:3$4@WRK1}, q{GOMP_RTEMS_THREAD_POOLS accepts libgomp example grammar};
130
1
208
rejects( q{GOMP_RTEMS_THREAD_POOLS}, q{0@WRK0}, q{GOMP_RTEMS_THREAD_POOLS rejects zero pool count} );
131
1
190
rejects( q{GOMP_RTEMS_THREAD_POOLS}, q{1WRK0}, q{GOMP_RTEMS_THREAD_POOLS requires scheduler separator} );
132
1
190
is validate_value( q{OMP_TEAMS_THREAD_LIMIT}, 1 ), 1, q{OMP_TEAMS_THREAD_LIMIT accepts positive integer};
133
1
232
rejects( q{OMP_TEAMS_THREAD_LIMIT}, 0, q{OMP_TEAMS_THREAD_LIMIT rejects zero} );
134
135
1
192
for my $value (
136    q{omp_default_mem_alloc}, q{omp_high_bw_mem_alloc}, q{omp_default_mem_space},
137    q{omp_large_cap_mem_space:alignment=16,pinned=true},
138    q{omp_low_lat_mem_space:sync_hint=private,access=thread,pool_size=1024,partition=nearest},
139    q{ompx_gnu_pinned_mem_alloc}, q{ompx_gnu_managed_mem_alloc},
140    q{ompx_gnu_managed_mem_space}
141) {
142
8
1446
    is validate_value( q{OMP_ALLOCATOR}, $value ), $value, qq{OMP_ALLOCATOR accepts $value};
143}
144
1
206
rejects( q{OMP_ALLOCATOR}, q{not_an_allocator}, q{OMP_ALLOCATOR rejects an unknown allocator} );
145
1
192
rejects( q{OMP_ALLOCATOR}, q{omp_low_lat_mem_space:}, q{OMP_ALLOCATOR rejects an empty trait list} );
146
1
192
rejects( q{OMP_ALLOCATOR}, q{omp_low_lat_mem_space:alignment=3}, q{OMP_ALLOCATOR requires power-of-two alignment} );
147
1
195
rejects( q{OMP_ALLOCATOR}, q{omp_low_lat_mem_space:alignment=foo}, q{OMP_ALLOCATOR requires numeric alignment} );
148
1
193
rejects( q{OMP_ALLOCATOR}, q{omp_low_lat_mem_space:pool_size=0}, q{OMP_ALLOCATOR requires positive pool size} );
149
1
193
rejects( q{OMP_ALLOCATOR}, q{omp_low_lat_mem_space:pinned=maybe}, q{OMP_ALLOCATOR validates boolean traits} );
150
1
190
rejects( q{OMP_ALLOCATOR}, q{omp_low_lat_mem_space:partition=random}, q{OMP_ALLOCATOR validates partition values} );
151
1
191
rejects( q{OMP_ALLOCATOR}, q{omp_low_lat_mem_space:access=process}, q{OMP_ALLOCATOR validates access values} );
152
1
191
rejects( q{OMP_ALLOCATOR}, q{omp_low_lat_mem_space:sync_hint=often}, q{OMP_ALLOCATOR validates sync_hint values} );
153
1
206
is validate_value( q{OMP_ALLOCATOR}, q{omp_low_lat_mem_space:fallback=allocator_fb} ), q{omp_low_lat_mem_space:fallback=allocator_fb}, q{OMP_ALLOCATOR accepts allocator_fb because libgomp explicitly lists it as an allowed fallback token};
154
1
205
is validate_value( q{OMP_ALLOCATOR}, q{OMP_HIGH_BW_MEM_ALLOC} ), q{OMP_HIGH_BW_MEM_ALLOC}, q{OMP_ALLOCATOR values are case-insensitive under the general OpenMP environment rule};
155
1
207
rejects( q{OMP_ALLOCATOR}, q{omp_low_lat_mem_space:fb_data=not_an_allocator}, q{OMP_ALLOCATOR validates fb_data allocator names before applying the libgomp restriction} );
156
1
192
rejects( q{OMP_ALLOCATOR}, q{omp_low_lat_mem_space:fb_data=omp_default_mem_alloc}, q{OMP_ALLOCATOR rejects OpenMP fb_data because libgomp documents it as unsupported} );
157
1
191
is validate_value( q{OMP_ALLOCATOR}, q{omp_low_lat_mem_space:fallback=default_mem_fb} ), q{omp_low_lat_mem_space:fallback=default_mem_fb}, q{OMP_ALLOCATOR accepts non-handle fallback choices};
158
1
206
rejects( q{OMP_ALLOCATOR}, q{omp_low_lat_mem_space:alignment=16,alignment=32}, q{OMP_ALLOCATOR rejects duplicate traits} );
159
1
212
rejects( q{OMP_ALLOCATOR}, q{omp_low_lat_mem_space:mystery=yes}, q{OMP_ALLOCATOR rejects unknown traits} );
160
1
190
rejects( q{OMP_ALLOCATOR}, q{omp_low_lat_mem_space:pinned}, q{OMP_ALLOCATOR rejects malformed traits} );
161
162
1
190
for my $value ( q{literal text}, q{thread %n affinity %A}, q{level %4L thread %0.2n}, q{host %.12{host}}, q{%% %n}, q{%{thread_num}}, q{vendor %x} ) {
163
7
1255
    is validate_value( q{OMP_AFFINITY_FORMAT}, $value ), $value, qq{OMP_AFFINITY_FORMAT accepts $value};
164}
165
1
208
is validate_value( q{OMP_AFFINITY_FORMAT}, q{  %n  } ), q{  %n  }, q{OMP_AFFINITY_FORMAT preserves significant leading and trailing whitespace};
166
1
206
rejects( q{OMP_AFFINITY_FORMAT}, q{thread %}, q{OMP_AFFINITY_FORMAT rejects a trailing percent} );
167
1
192
rejects( q{OMP_AFFINITY_FORMAT}, q{thread %0n}, q{OMP_AFFINITY_FORMAT rejects malformed width syntax} );
168
1
192
rejects( q{OMP_AFFINITY_FORMAT}, q{thread %.0L}, q{OMP_AFFINITY_FORMAT rejects a zero minimum width} );
169
1
214
rejects( q{OMP_AFFINITY_FORMAT}, q{thread %0.0L}, q{OMP_AFFINITY_FORMAT rejects a zero-padded zero minimum width} );
170
1
191
rejects( q{OMP_AFFINITY_FORMAT}, q{thread %{bad-name}}, q{OMP_AFFINITY_FORMAT rejects malformed long field name} );
171
1
189
is validate_value( q{OMP_DISPLAY_AFFINITY}, q{false} ), q{FALSE}, q{OMP_DISPLAY_AFFINITY accepts and normalizes false};
172
1
206
rejects( q{OMP_DISPLAY_AFFINITY}, q{sometimes}, q{OMP_DISPLAY_AFFINITY rejects non-boolean value} );
173
174
1
190
local $@;
175
1
1
1
2
eval { assert_variable( [], q{OMP_NUM_THREADS} ) };
176
1
4
like $@, qr/hash reference/, q{assert_variable requires a hash reference};
177
1
1
192
2
eval { assert_variable( {}, q{OMP_NOT_REAL} ) };
178
1
4
like $@, qr/Unsupported/, q{assert_variable rejects unknown names};
179
1
196
my %one = ( OMP_NUM_THREADS => q{4,2} );
180
1
2
ok assert_variable( \%one, q{OMP_NUM_THREADS} ), q{assert_variable validates a set variable};
181
1
219
my %unset;
182
1
3
ok assert_variable( \%unset, q{OMP_NUM_THREADS} ), q{assert_variable accepts an unset variable};
183
1
209
my %unrelated_conflict = ( OMP_NESTED => q{FALSE}, OMP_MAX_ACTIVE_LEVELS => 4, OMP_SCHEDULE => q{static} );
184
1
3
ok assert_variable( \%unrelated_conflict, q{OMP_SCHEDULE} ), q{assert_variable ignores a cross-variable conflict unrelated to the requested variable};
185
186
1
197
local $@;
187
1
1
1
2
eval { assert_environment([]) };
188
1
4
like $@, qr/hash reference/, q{assert_environment requires a hash reference};
189
1
195
my %strict = ( OMP_CANCELLATION => q{true}, OMP_SCHEDULE => q{guided,4} );
190
1
3
ok assert_environment( \%strict ), q{assert_environment validates a portable environment};
191
1
198
is $strict{OMP_CANCELLATION}, q{TRUE}, q{assert_environment writes normalized values back};
192
1
210
my %conflict = ( OMP_NESTED => q{FALSE}, OMP_MAX_ACTIVE_LEVELS => 4 );
193
1
1
1
2
eval { assert_environment( \%conflict ) };
194
1
3
like $@, qr/conflict/, q{assert_environment rejects an explicit OpenMP implementation-defined conflict};
195
196
1
194
local $@;
197
1
1
1
2
eval { analyze_environment([]) };
198
1
6
like $@, qr/hash reference/, q{analyze_environment requires a hash reference};
199
1
199
my %analysis_env = (
200    OMP_NESTED            => q{TRUE},
201    OMP_MAX_ACTIVE_LEVELS => 4,
202    OMP_NUM_THREADS       => q{8,4},
203    OMP_PROC_BIND         => q{SPREAD,CLOSE},
204    GOMP_CPU_AFFINITY     => q{0-7},
205    OMP_PLACES            => q{cores},
206    OMP_DEFAULT_DEVICE    => 7,
207    OMP_STACKSIZE         => q{64G},
208    OMP_ALLOCATOR         => q{omp_high_bw_mem_alloc},
209    OMP_THREAD_LIMIT      => 1024,
210    GOMP_RTEMS_THREAD_POOLS => q{1@WRK0},
211);
212
1
3
my $analysis = analyze_environment( \%analysis_env );
213
1
5
ok $analysis->{valid}, q{runtime-dependent but syntactically valid environment remains valid};
214
1
1
204
4
ok @{ $analysis->{runtime_dependent} } >= 8, q{analysis identifies runtime-dependent settings without probing the system};
215
1
1
194
11
ok grep( /OMP_PROC_BIND takes precedence/, @{ $analysis->{notes} } ), q{analysis documents GNU precedence relationship};
216
1
1
193
5
ok grep( /OMP_NESTED has no effect/, @{ $analysis->{notes} } ), q{analysis documents nonconflicting OMP_NESTED relationship};
217
1
1
189
5
ok grep( /max-active-levels-var/, @{ $analysis->{notes} } ), q{analysis documents nested list effect on max-active-levels-var};
218
219
1
191
my $bad_analysis = analyze_environment( { OMP_SCHEDULE => q{banana} } );
220
1
4
ok !$bad_analysis->{valid}, q{analysis marks malformed environment invalid};
221
1
1
204
2
is scalar( @{ $bad_analysis->{errors} } ), 1, q{analysis reports malformed value as an error};
222
1
209
my $conflict_analysis = analyze_environment( { OMP_NESTED => q{false}, OMP_MAX_ACTIVE_LEVELS => 2 } );
223
1
4
ok !$conflict_analysis->{valid}, q{analysis marks cross-variable conflict invalid};
224
1
196
is $conflict_analysis->{conflicts}->[0]->{class}, q{implementation-defined}, q{analysis classifies the OpenMP conflict};
225
226
1
209
done_testing;
227