formula = new FormulaService(); } public function testPayrollFormulaHonorsPrecedenceAndVariables(): void { $value = $this->formula->calculate('basic_salary + overtime_hours * overtime_rate', array( 'basic_salary' => 5000000, 'overtime_hours' => 4, 'overtime_rate' => 50000, )); self::assertSame(5200000.0, $value); } public function testProrataFormulaAndRounding(): void { self::assertSame(333333.33, $this->formula->calculate('salary / work_days', array( 'salary' => 7000000, 'work_days' => 21, ))); } public function testUnknownVariableIsZeroForBackwardCompatibleFormula(): void { self::assertSame(1000.0, $this->formula->calculate('base + optional_bonus', array('base' => 1000))); } public function testRejectsDivisionByZero(): void { $this->expectException(BusinessException::class); $this->formula->calculate('salary / days', array('salary' => 1000, 'days' => 0)); } public function testRejectsUnsafeTokens(): void { $this->expectException(BusinessException::class); $this->formula->calculate('system("whoami")', array()); } }