@@ -15,9 +15,12 @@ use RESTAPI\Responses\ServerError;
1515
1616class APIModelsFirewallRuleTestCase extends TestCase {
1717 /**
18- * Reads the active ruleset directly from pfctl.
18+ * Reads the active ruleset directly from pfctl. If pfctl is not ready, it will retry up to 5 times before
19+ * throwing an error.
20+ * @param string|null $needle Optional string to search for in the output before returning
21+ * @return Command The Command object containing the pfctl output
1922 */
20- public function read_pfctl_rules (): Command {
23+ public function read_pfctl_rules (? string $ needle = null ): Command {
2124 # Keywords that indicate pf is not ready yet
2225 $ not_ready_keywords = ['pfctl: DIOCGETRULE: Device busy ' , 'pfctl: DIOCGETRULENV: Device busy ' ];
2326
@@ -32,15 +35,18 @@ class APIModelsFirewallRuleTestCase extends TestCase {
3235 # pf is not ready if any of the keywords are found in the output
3336 if (str_contains ($ cmd ->output , $ keyword )) {
3437 $ ready = false ;
35- $ attempt ++;
36- sleep (1 );
3738 break ;
3839 }
3940 }
4041
41- if ($ ready ) {
42+ # If pfctl is ready and either no needle was specified or the needle was found, return the output
43+ if ($ ready and (!$ needle or str_contains ($ cmd ->output , $ needle ))) {
4244 return $ cmd ;
4345 }
46+
47+ # Otherwise, wait a second and try again
48+ sleep (1 );
49+ $ attempt ++;
4450 }
4551
4652 throw new ServerError (
@@ -833,7 +839,7 @@ class APIModelsFirewallRuleTestCase extends TestCase {
833839 $ rule ->create (apply: true );
834840
835841 # Ensure the dnpipe is correctly represented
836- $ pfctl = $ this ->read_pfctl_rules ();
842+ $ pfctl = $ this ->read_pfctl_rules (needle: $ rule -> tracker -> value );
837843 $ this ->assert_str_contains (
838844 $ pfctl ->output ,
839845 "ridentifier {$ rule ->tracker ->value } dnpipe {$ limiter ->number ->value }" ,
0 commit comments