not->toBeFalse('lib/snmp.php must be readable'); $declaration = strpos($source, 'function cacti_snmp_walk('); // without this the strpos below would start from offset 0 and read some // unrelated parenthesis group, so the test would pass on the wrong text expect($declaration)->not->toBeFalse('cacti_snmp_walk() must exist in lib/snmp.php'); $opening = strpos($source, '(', $declaration); expect($opening)->not->toBeFalse('cacti_snmp_walk() must have an opening parenthesis'); return walk_size_split(walk_size_balanced($source, $opening)); } /** * Reads the arguments query_snmp_host() passes to cacti_snmp_walk(). * * @return string[] One entry per argument, in order. */ function walk_size_walk_arguments() : array { $source = file_get_contents(dirname(__DIR__, 4) . '/lib/data_query.php'); expect($source)->not->toBeFalse('lib/data_query.php must be readable'); $host = strpos($source, 'function query_snmp_host('); expect($host)->not->toBeFalse('query_snmp_host() must exist in lib/data_query.php'); $after = strpos($source, "\nfunction ", $host + 1); $body = substr($source, $host, ($after === false ? strlen($source) : $after) - $host); $call = strpos($body, 'cacti_snmp_walk('); expect($call)->not->toBeFalse('query_snmp_host() must still walk for output_format fields'); $opening = strpos($body, '(', $call); expect($opening)->not->toBeFalse('cacti_snmp_walk() call must have an opening parenthesis'); return walk_size_split(walk_size_balanced($body, $opening)); } test('cacti_snmp_walk still declares a bulk walk size and no max_oids', function () { $names = array_map( fn ($parameter) => preg_match('/\$(\w+)/', $parameter, $m) ? $m[1] : '', walk_size_snmp_parameters() ); // the whole defect was reading this slot as if it were max OIDs per get expect($names)->toContain('bulk_walk_size') ->and($names)->not->toContain('max_oids'); }); test('the output_format walk passes the normalized walk size in the bulk walk size slot', function () { $names = array_map( fn ($parameter) => preg_match('/\$(\w+)/', $parameter, $m) ? $m[1] : '', walk_size_snmp_parameters() ); $slot = array_search('bulk_walk_size', $names, true); $args = walk_size_walk_arguments(); expect($slot)->not->toBeFalse() ->and($args)->toHaveCount(count($names)); // pre-fix this slot held $host['max_oids'], which is max OIDs per get expect($args[$slot])->toBe('$walk_size'); }); test('the walk size is normalized before the output_format walk reads it', function () { $source = file_get_contents(dirname(__DIR__, 4) . '/lib/data_query.php'); $host = strpos($source, 'function query_snmp_host('); $after = strpos($source, "\nfunction ", $host + 1); $body = substr($source, $host, ($after === false ? strlen($source) : $after) - $host); $normalization = strpos($body, '$walk_size = $host[\'bulk_walk_size\']'); // anchor on the normalization itself: strpos($body, '$walk_size') would // find the auto-tuning branch's "$walk_size = 5" and pass even if the // normalization moved below the walk expect($normalization)->not->toBeFalse() ->and($normalization)->toBeLessThan(strpos($body, 'cacti_snmp_walk(')); }); test('max_oids is still passed to the session calls that take it', function () { $source = file_get_contents(dirname(__DIR__, 4) . '/lib/data_query.php'); // the #7493 fix must not have swapped every max_oids for the walk size. // max_oids reaches the session either directly or through // cacti_snmp_session_from_host(), which forwards $host['max_oids']. $direct = substr_count($source, "\$host['max_oids']"); $wrapped = substr_count($source, 'cacti_snmp_session_from_host('); expect($direct + $wrapped)->toBeGreaterThan(0); });