Skip to content

Commit e4d876b

Browse files
test: add Pest v1 security test scaffold from Cacti#328
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
1 parent 992c588 commit e4d876b

5 files changed

Lines changed: 424 additions & 0 deletions

File tree

tests/Pest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
/*
3+
+-------------------------------------------------------------------------+
4+
| Copyright (C) 2004-2026 The Cacti Group |
5+
+-------------------------------------------------------------------------+
6+
| Cacti: The Complete RRDtool-based Graphing Solution |
7+
+-------------------------------------------------------------------------+
8+
*/
9+
10+
/*
11+
* Pest configuration file.
12+
*/
13+
14+
require_once __DIR__ . '/bootstrap.php';
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
/*
3+
+-------------------------------------------------------------------------+
4+
| Copyright (C) 2004-2026 The Cacti Group |
5+
+-------------------------------------------------------------------------+
6+
| Cacti: The Complete RRDtool-based Graphing Solution |
7+
+-------------------------------------------------------------------------+
8+
*/
9+
10+
/*
11+
* Verify plugin source files do not use PHP 8.0+ syntax.
12+
* Cacti 1.2.x plugins must remain compatible with PHP 7.4.
13+
*/
14+
15+
describe('PHP 7.4 compatibility in mactrack', function () {
16+
$files = array(
17+
'mactrack_devices.php',
18+
'mactrack_device_types.php',
19+
'mactrack_interfaces.php',
20+
'mactrack_sites.php',
21+
'mactrack_snmp.php',
22+
'mactrack_utilities.php',
23+
'mactrack_view_arp.php',
24+
'mactrack_view_macs.php',
25+
'mactrack_view_sites.php',
26+
'setup.php',
27+
);
28+
29+
it('does not use str_contains (PHP 8.0)', function () use ($files) {
30+
foreach ($files as $relativeFile) {
31+
$path = realpath(__DIR__ . '/../../' . $relativeFile);
32+
33+
if ($path === false) {
34+
continue;
35+
}
36+
37+
$contents = file_get_contents($path);
38+
39+
if ($contents === false) {
40+
continue;
41+
}
42+
43+
expect(preg_match('/\bstr_contains\s*\(/', $contents))->toBe(0,
44+
"{$relativeFile} uses str_contains() which requires PHP 8.0"
45+
);
46+
}
47+
});
48+
49+
it('does not use str_starts_with (PHP 8.0)', function () use ($files) {
50+
foreach ($files as $relativeFile) {
51+
$path = realpath(__DIR__ . '/../../' . $relativeFile);
52+
53+
if ($path === false) {
54+
continue;
55+
}
56+
57+
$contents = file_get_contents($path);
58+
59+
if ($contents === false) {
60+
continue;
61+
}
62+
63+
expect(preg_match('/\bstr_starts_with\s*\(/', $contents))->toBe(0,
64+
"{$relativeFile} uses str_starts_with() which requires PHP 8.0"
65+
);
66+
}
67+
});
68+
69+
it('does not use str_ends_with (PHP 8.0)', function () use ($files) {
70+
foreach ($files as $relativeFile) {
71+
$path = realpath(__DIR__ . '/../../' . $relativeFile);
72+
73+
if ($path === false) {
74+
continue;
75+
}
76+
77+
$contents = file_get_contents($path);
78+
79+
if ($contents === false) {
80+
continue;
81+
}
82+
83+
expect(preg_match('/\bstr_ends_with\s*\(/', $contents))->toBe(0,
84+
"{$relativeFile} uses str_ends_with() which requires PHP 8.0"
85+
);
86+
}
87+
});
88+
89+
it('does not use nullsafe operator (PHP 8.0)', function () use ($files) {
90+
foreach ($files as $relativeFile) {
91+
$path = realpath(__DIR__ . '/../../' . $relativeFile);
92+
93+
if ($path === false) {
94+
continue;
95+
}
96+
97+
$contents = file_get_contents($path);
98+
99+
if ($contents === false) {
100+
continue;
101+
}
102+
103+
expect(preg_match('/\?->/', $contents))->toBe(0,
104+
"{$relativeFile} uses nullsafe operator which requires PHP 8.0"
105+
);
106+
}
107+
});
108+
});
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
/*
3+
+-------------------------------------------------------------------------+
4+
| Copyright (C) 2004-2026 The Cacti Group |
5+
+-------------------------------------------------------------------------+
6+
| Cacti: The Complete RRDtool-based Graphing Solution |
7+
+-------------------------------------------------------------------------+
8+
*/
9+
10+
/*
11+
* Verify migrated files use prepared DB helpers exclusively.
12+
* Catches regressions where raw db_execute/db_fetch_* calls creep back in.
13+
*/
14+
15+
describe('prepared statement consistency in mactrack', function () {
16+
it('uses prepared DB helpers in all plugin files', function () {
17+
$targetFiles = array(
18+
'mactrack_devices.php',
19+
'mactrack_device_types.php',
20+
'mactrack_interfaces.php',
21+
'mactrack_sites.php',
22+
'mactrack_snmp.php',
23+
'mactrack_utilities.php',
24+
'mactrack_view_arp.php',
25+
'mactrack_view_macs.php',
26+
'mactrack_view_sites.php',
27+
'setup.php',
28+
);
29+
30+
$rawPattern = '/\bdb_(?:execute|fetch_row|fetch_assoc|fetch_cell)\s*\(/';
31+
$preparedPattern = '/\bdb_(?:execute|fetch_row|fetch_assoc|fetch_cell)_prepared\s*\(/';
32+
33+
foreach ($targetFiles as $relativeFile) {
34+
$path = realpath(__DIR__ . '/../../' . $relativeFile);
35+
36+
if ($path === false) {
37+
continue;
38+
}
39+
40+
$contents = file_get_contents($path);
41+
42+
if ($contents === false) {
43+
continue;
44+
}
45+
46+
$lines = explode("\n", $contents);
47+
$rawCallsOutsideComments = 0;
48+
49+
foreach ($lines as $line) {
50+
$trimmed = ltrim($line);
51+
52+
if (strpos($trimmed, '//') === 0 || strpos($trimmed, '*') === 0 || strpos($trimmed, '#') === 0) {
53+
continue;
54+
}
55+
56+
if (preg_match($rawPattern, $line) && !preg_match($preparedPattern, $line)) {
57+
$rawCallsOutsideComments++;
58+
}
59+
}
60+
61+
expect($rawCallsOutsideComments)->toBe(0,
62+
"File {$relativeFile} contains raw (unprepared) DB calls"
63+
);
64+
}
65+
});
66+
});
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
/*
3+
+-------------------------------------------------------------------------+
4+
| Copyright (C) 2004-2026 The Cacti Group |
5+
+-------------------------------------------------------------------------+
6+
| Cacti: The Complete RRDtool-based Graphing Solution |
7+
+-------------------------------------------------------------------------+
8+
*/
9+
10+
/*
11+
* Verify setup.php defines required plugin hooks and info function.
12+
*/
13+
14+
describe('mactrack setup.php structure', function () {
15+
$source = file_get_contents(realpath(__DIR__ . '/../../setup.php'));
16+
17+
it('defines plugin_mactrack_install function', function () use ($source) {
18+
expect($source)->toContain('function plugin_mactrack_install');
19+
});
20+
21+
it('defines plugin_mactrack_version function', function () use ($source) {
22+
expect($source)->toContain('function plugin_mactrack_version');
23+
});
24+
25+
it('defines plugin_mactrack_uninstall function', function () use ($source) {
26+
expect($source)->toContain('function plugin_mactrack_uninstall');
27+
});
28+
29+
it('returns version array with name key', function () use ($source) {
30+
expect($source)->toMatch('/[\'\""]name[\'\""]\s*=>/');
31+
});
32+
33+
it('returns version array with version key', function () use ($source) {
34+
expect($source)->toMatch('/[\'\""]version[\'\""]\s*=>/');
35+
});
36+
});

0 commit comments

Comments
 (0)