summaryrefslogtreecommitdiffstats
path: root/test/php/library/Icingadb/Util
diff options
context:
space:
mode:
Diffstat (limited to 'test/php/library/Icingadb/Util')
-rw-r--r--test/php/library/Icingadb/Util/PerfdataSetTest.php120
-rw-r--r--test/php/library/Icingadb/Util/PerfdataTest.php591
-rw-r--r--test/php/library/Icingadb/Util/ThresholdRangeTest.php343
3 files changed, 1054 insertions, 0 deletions
diff --git a/test/php/library/Icingadb/Util/PerfdataSetTest.php b/test/php/library/Icingadb/Util/PerfdataSetTest.php
new file mode 100644
index 0000000..618c29a
--- /dev/null
+++ b/test/php/library/Icingadb/Util/PerfdataSetTest.php
@@ -0,0 +1,120 @@
+<?php
+
+/* Icinga DB Web | (c) 2023 Icinga GmbH | GPLv2 */
+
+namespace Tests\Icinga\Module\Icingadb\Util;
+
+use Icinga\Module\Icingadb\Util\PerfDataSet;
+use PHPUnit\Framework\TestCase;
+use Tests\Icinga\Module\Icingadb\Lib\PerfdataSetWithPublicData;
+
+class PerfdataSetTest extends TestCase
+{
+ public function testWhetherValidSimplePerfdataLabelsAreProperlyParsed()
+ {
+ $pset = PerfdataSetWithPublicData::fromString('key1=val1 key2=val2 key3 =val3');
+ $this->assertSame(
+ 'key1',
+ $pset->perfdata[0]->getLabel(),
+ 'PerfdataSet does not correctly parse valid simple labels'
+ );
+ $this->assertSame(
+ 'key2',
+ $pset->perfdata[1]->getLabel(),
+ 'PerfdataSet does not correctly parse valid simple labels'
+ );
+ $this->assertSame(
+ 'key3',
+ $pset->perfdata[2]->getLabel(),
+ 'PerfdataSet does not correctly parse valid simple labels'
+ );
+ }
+
+ public function testWhetherNonQuotedPerfdataLablesWithSpacesAreProperlyParsed()
+ {
+ $pset = PerfdataSetWithPublicData::fromString('key 1=val1 key 1 + 1=val2');
+ $this->assertSame(
+ 'key 1',
+ $pset->perfdata[0]->getLabel(),
+ 'PerfdataSet does not correctly parse non quoted labels with spaces'
+ );
+ $this->assertSame(
+ 'key 1 + 1',
+ $pset->perfdata[1]->getLabel(),
+ 'PerfdataSet does not correctly parse non quoted labels with spaces'
+ );
+ }
+
+ public function testWhetherValidQuotedPerfdataLabelsAreProperlyParsed()
+ {
+ $pset = PerfdataSetWithPublicData::fromString('\'key 1\'=val1 "key 2"=val2 \'a=b\'=0%;;2');
+ $this->assertSame(
+ 'key 1',
+ $pset->perfdata[0]->getLabel(),
+ 'PerfdataSet does not correctly parse valid quoted labels'
+ );
+ $this->assertSame(
+ 'key 2',
+ $pset->perfdata[1]->getLabel(),
+ 'PerfdataSet does not correctly parse valid quoted labels'
+ );
+ $this->assertSame(
+ 'a=b',
+ $pset->perfdata[2]->getLabel(),
+ 'PerfdataSet does not correctly parse labels with equal signs'
+ );
+ }
+
+ public function testWhetherInvalidQuotedPerfdataLabelsAreProperlyParsed()
+ {
+ $pset = PerfdataSetWithPublicData::fromString('\'key 1=1 key 2"=2');
+ $this->assertSame(
+ 'key 1',
+ $pset->perfdata[0]->getLabel(),
+ 'PerfdataSet does not correctly parse invalid quoted labels'
+ );
+ $this->assertSame(
+ 'key 2"',
+ $pset->perfdata[1]->getLabel(),
+ 'PerfdataSet does not correctly parse invalid quoted labels'
+ );
+ $pset = PerfdataSetWithPublicData::fromString('"key 1=1 "key 2"=2');
+ $this->assertSame(
+ 'key 1=1',
+ $pset->perfdata[0]->getLabel(),
+ 'PerfdataSet does not correctly parse invalid quoted labels'
+ );
+ $this->assertNull(
+ $pset->perfdata[0]->getValue()
+ );
+ $this->assertSame(
+ '2"',
+ $pset->perfdata[1]->getLabel(),
+ 'PerfdataSet does not correctly parse invalid quoted labels'
+ );
+ $this->assertSame(
+ 2.0,
+ $pset->perfdata[1]->getValue()
+ );
+ }
+
+ /**
+ * @depends testWhetherValidSimplePerfdataLabelsAreProperlyParsed
+ */
+ public function testWhetherAPerfdataSetIsIterable()
+ {
+ $pset = PerfdataSet::fromString('key=value');
+ foreach ($pset as $p) {
+ $this->assertSame('key', $p->getLabel());
+ return;
+ }
+
+ $this->fail('PerfdataSet objects cannot be iterated');
+ }
+
+ public function testWhetherPerfdataSetsCanBeInitializedWithEmptyStrings()
+ {
+ $pset = PerfdataSetWithPublicData::fromString('');
+ $this->assertEmpty($pset->perfdata, 'PerfdataSet::fromString does not accept emtpy strings');
+ }
+}
diff --git a/test/php/library/Icingadb/Util/PerfdataTest.php b/test/php/library/Icingadb/Util/PerfdataTest.php
new file mode 100644
index 0000000..5a63825
--- /dev/null
+++ b/test/php/library/Icingadb/Util/PerfdataTest.php
@@ -0,0 +1,591 @@
+<?php
+
+/* Icinga DB Web | (c) 2023 Icinga GmbH | GPLv2 */
+
+namespace Tests\Icinga\Module\Icingadb\Util;
+
+use Icinga\Module\Icingadb\Util\PerfData;
+use PHPUnit\Framework\TestCase;
+
+class PerfdataTest extends TestCase
+{
+ public function testWhetherFromStringThrowsExceptionWhenGivenAnEmptyString()
+ {
+ $this->expectException(\InvalidArgumentException::class);
+
+ Perfdata::fromString('');
+ }
+
+ public function testWhetherFromStringThrowsExceptionWhenGivenAnInvalidString()
+ {
+ $this->expectException(\InvalidArgumentException::class);
+
+ Perfdata::fromString('test');
+ }
+
+ public function testWhetherFromStringParsesAGivenStringCorrectly()
+ {
+ $p = Perfdata::fromString('key=1234');
+ $this->assertSame(
+ 'key',
+ $p->getLabel(),
+ 'Perfdata::fromString does not properly parse performance data labels'
+ );
+ $this->assertSame(
+ 1234.0,
+ $p->getValue(),
+ 'Perfdata::fromString does not properly parse performance data values'
+ );
+ }
+
+ /**
+ * @depends testWhetherFromStringParsesAGivenStringCorrectly
+ */
+ public function testWhetherGetValueReturnsValidValues()
+ {
+ $this->assertSame(
+ 1337.0,
+ Perfdata::fromString('test=1337')->getValue(),
+ 'Perfdata::getValue does not return correct values'
+ );
+ $this->assertSame(
+ 1337.0,
+ Perfdata::fromString('test=1337;;;;')->getValue(),
+ 'Perfdata::getValue does not return correct values'
+ );
+ }
+
+ /**
+ * @depends testWhetherFromStringParsesAGivenStringCorrectly
+ */
+ public function testWhetherDecimalValuesAreCorrectlyParsed()
+ {
+ $this->assertSame(
+ 1337.5,
+ Perfdata::fromString('test=1337.5')->getValue(),
+ 'Perfdata objects do not parse decimal values correctly'
+ );
+ $this->assertSame(
+ 1337.5,
+ Perfdata::fromString('test=1337.5B')->getValue(),
+ 'Perfdata objects do not parse decimal values correctly'
+ );
+ }
+
+ /**
+ * @depends testWhetherFromStringParsesAGivenStringCorrectly
+ */
+ public function testWhetherGetValueReturnsNullForInvalidOrUnknownValues()
+ {
+ $this->assertNull(
+ Perfdata::fromString('test=U')->getValue(),
+ 'Perfdata::getValue does not return null for unknown values'
+ );
+ $this->assertNull(
+ Perfdata::fromString('test=i am not a value')->getValue(),
+ 'Perfdata::getValue does not return null for invalid values'
+ );
+ $this->assertNull(
+ PerfData::fromString('test=')->getValue(),
+ 'Perfdata::getValue does not return null for invalid values'
+ );
+ $this->assertNull(
+ PerfData::fromString('test=-kW')->getValue(),
+ 'Perfdata::getValue does not return null for invalid values'
+ );
+ $this->assertNull(
+ PerfData::fromString('test=kW')->getValue(),
+ 'Perfdata::getValue does not return null for invalid values'
+ );
+ $this->assertNull(
+ PerfData::fromString('test=-')->getValue(),
+ 'Perfdata::getValue does not return null for invalid values'
+ );
+ }
+
+ /**
+ * @depends testWhetherFromStringParsesAGivenStringCorrectly
+ */
+ public function testWhetherUnitOfUnkownValuesIsCorrectlyIdentified()
+ {
+ $this->assertNull(
+ Perfdata::fromString('test=U')->getUnit(),
+ 'Perfdata::getUnit does not return null for unknown values'
+ );
+ $this->assertNull(
+ Perfdata::fromString('test=i am not a value')->getUnit(),
+ 'Perfdata::getUnit does not return null for unknown values'
+ );
+ $this->assertNull(
+ PerfData::fromString('test=')->getUnit(),
+ 'Perfdata::getUnit does not return null for unknown values'
+ );
+ $this->assertSame(
+ 'kW',
+ PerfData::fromString('test=-kW')->getUnit(),
+ 'Perfdata::getUnit does not return correct unit for invalid values'
+ );
+ $this->assertSame(
+ 'kW',
+ PerfData::fromString('test=kW')->getUnit(),
+ 'Perfdata::getUnit does not return correct unit for invalid values'
+ );
+ $this->assertNull(
+ PerfData::fromString('test=-')->getUnit(),
+ 'Perfdata::getUnit does not return null for unknown values'
+ );
+ }
+
+ /**
+ * @depends testWhetherFromStringParsesAGivenStringCorrectly
+ */
+ public function testWhethergetWarningThresholdReturnsCorrectValues()
+ {
+ $zeroToTen = Perfdata::fromString('test=1;10')->getWarningThreshold();
+ $this->assertSame(
+ 0.0,
+ $zeroToTen->getMin(),
+ 'Perfdata::getWarningThreshold does not return correct values'
+ );
+ $this->assertSame(
+ 10.0,
+ $zeroToTen->getMax(),
+ 'Perfdata::getWarningThreshold does not return correct values'
+ );
+ $tenToInfinity = Perfdata::fromString('test=1;10:')->getWarningThreshold();
+ $this->assertSame(
+ 10.0,
+ $tenToInfinity->getMin(),
+ 'Perfdata::getWarningThreshold does not return correct values'
+ );
+ $this->assertNull(
+ $tenToInfinity->getMax(),
+ 'Perfdata::getWarningThreshold does not return correct values'
+ );
+ $infinityToTen = Perfdata::fromString('test=1;~:10')->getWarningThreshold();
+ $this->assertNull(
+ $infinityToTen->getMin(),
+ 'Perfdata::getWarningThreshold does not return correct values'
+ );
+ $this->assertSame(
+ 10.0,
+ $infinityToTen->getMax(),
+ 'Perfdata::getWarningThreshold does not return correct values'
+ );
+ $tenToTwenty = Perfdata::fromString('test=1;10:20')->getWarningThreshold();
+ $this->assertSame(
+ 10.0,
+ $tenToTwenty->getMin(),
+ 'Perfdata::getWarningThreshold does not return correct values'
+ );
+ $this->assertSame(
+ 20.0,
+ $tenToTwenty->getMax(),
+ 'Perfdata::getWarningThreshold does not return correct values'
+ );
+ $tenToTwentyInverted = Perfdata::fromString('test=1;@10:20')->getWarningThreshold();
+ $this->assertTrue(
+ $tenToTwentyInverted->isInverted(),
+ 'Perfdata::getWarningThreshold does not return correct values'
+ );
+ }
+
+ /**
+ * @depends testWhetherFromStringParsesAGivenStringCorrectly
+ */
+ public function testWhetherGetCriticalThresholdReturnsCorrectValues()
+ {
+ $zeroToTen = Perfdata::fromString('test=1;;10')->getCriticalThreshold();
+ $this->assertSame(
+ 0.0,
+ $zeroToTen->getMin(),
+ 'Perfdata::getCriticalThreshold does not return correct values'
+ );
+ $this->assertSame(
+ 10.0,
+ $zeroToTen->getMax(),
+ 'Perfdata::getCriticalThreshold does not return correct values'
+ );
+ $tenToInfinity = Perfdata::fromString('test=1;;10:')->getCriticalThreshold();
+ $this->assertSame(
+ 10.0,
+ $tenToInfinity->getMin(),
+ 'Perfdata::getCriticalThreshold does not return correct values'
+ );
+ $this->assertNull(
+ $tenToInfinity->getMax(),
+ 'Perfdata::getCriticalThreshold does not return correct values'
+ );
+ $infinityToTen = Perfdata::fromString('test=1;;~:10')->getCriticalThreshold();
+ $this->assertNull(
+ $infinityToTen->getMin(),
+ 'Perfdata::getCriticalThreshold does not return correct values'
+ );
+ $this->assertSame(
+ 10.0,
+ $infinityToTen->getMax(),
+ 'Perfdata::getCriticalThreshold does not return correct values'
+ );
+ $tenToTwenty = Perfdata::fromString('test=1;;10:20')->getCriticalThreshold();
+ $this->assertSame(
+ 10.0,
+ $tenToTwenty->getMin(),
+ 'Perfdata::getCriticalThreshold does not return correct values'
+ );
+ $this->assertSame(
+ 20.0,
+ $tenToTwenty->getMax(),
+ 'Perfdata::getCriticalThreshold does not return correct values'
+ );
+ $tenToTwentyInverted = Perfdata::fromString('test=1;;@10:20')->getCriticalThreshold();
+ $this->assertTrue(
+ $tenToTwentyInverted->isInverted(),
+ 'Perfdata::getCriticalThreshold does not return correct values'
+ );
+ }
+
+ /**
+ * @depends testWhetherFromStringParsesAGivenStringCorrectly
+ */
+ public function testWhetherGetMinimumValueReturnsCorrectValues()
+ {
+ $this->assertSame(
+ 1337.0,
+ Perfdata::fromString('test=1;;;1337')->getMinimumValue(),
+ 'Perfdata::getMinimumValue does not return correct values'
+ );
+ $this->assertSame(
+ 1337.5,
+ Perfdata::fromString('test=1;;;1337.5')->getMinimumValue(),
+ 'Perfdata::getMinimumValue does not return correct values'
+ );
+ }
+
+ /**
+ * @depends testWhetherFromStringParsesAGivenStringCorrectly
+ */
+ public function testWhetherGetMaximumValueReturnsCorrectValues()
+ {
+ $this->assertSame(
+ 1337.0,
+ Perfdata::fromString('test=1;;;;1337')->getMaximumValue(),
+ 'Perfdata::getMaximumValue does not return correct values'
+ );
+ $this->assertSame(
+ 1337.5,
+ Perfdata::fromString('test=1;;;;1337.5')->getMaximumValue(),
+ 'Perfdata::getMaximumValue does not return correct values'
+ );
+ }
+
+ /**
+ * @depends testWhetherFromStringParsesAGivenStringCorrectly
+ */
+ public function testWhetherMissingValuesAreProperlyHandled()
+ {
+ $perfdata = Perfdata::fromString('test=1;;3;5');
+ $this->assertEmpty(
+ (string) $perfdata->getWarningThreshold(),
+ 'Perfdata objects do not correctly identify omitted warning tresholds'
+ );
+ $this->assertNull(
+ $perfdata->getMaximumValue(),
+ 'Perfdata objects do not return null for missing maximum values'
+ );
+ }
+
+ /**
+ * @depends testWhetherGetValueReturnsValidValues
+ */
+ public function testWhetherValuesAreIdentifiedAsNumber()
+ {
+ $this->assertTrue(
+ Perfdata::fromString('test=666')->isNumber(),
+ 'Perfdata objects do not identify ordinary digits as number'
+ );
+ }
+
+ /**
+ * @depends testWhetherGetValueReturnsValidValues
+ */
+ public function testWhetherValuesAreIdentifiedAsSeconds()
+ {
+ $this->assertTrue(
+ Perfdata::fromString('test=666s')->isSeconds(),
+ 'Perfdata objects do not identify seconds as seconds'
+ );
+ }
+
+ /**
+ * @depends testWhetherGetValueReturnsValidValues
+ */
+ public function testWhetherValuesAreIdentifiedAsPercentage()
+ {
+ $this->assertTrue(
+ Perfdata::fromString('test=66%')->isPercentage(),
+ 'Perfdata objects do not identify percentages as percentages'
+ );
+ }
+
+ /**
+ * @depends testWhetherValuesAreIdentifiedAsPercentage
+ */
+ public function testWhetherMinAndMaxAreNotRequiredIfUnitIsInPercent()
+ {
+ $perfdata = Perfdata::fromString('test=1%');
+ $this->assertSame(
+ 0.0,
+ $perfdata->getMinimumValue(),
+ 'Perfdata objects do not set minimum value to 0 if UOM is %'
+ );
+ $this->assertSame(
+ 100.0,
+ $perfdata->getMaximumValue(),
+ 'Perfdata objects do not set maximum value to 100 if UOM is %'
+ );
+ }
+
+ /**
+ * @depends testWhetherGetValueReturnsValidValues
+ */
+ public function testWhetherValuesAreIdentifiedAsBytes()
+ {
+ $this->assertTrue(
+ Perfdata::fromString('test=66666B')->isBytes(),
+ 'Perfdata objects do not identify bytes as bytes'
+ );
+ }
+
+ /**
+ * @depends testWhetherGetValueReturnsValidValues
+ */
+ public function testWhetherValuesAreIdentifiedAsCounter()
+ {
+ $this->assertTrue(
+ Perfdata::fromString('test=123c')->isCounter(),
+ 'Perfdata objects do not identify counters as counters'
+ );
+ }
+
+ /**
+ * @depends testWhetherValuesAreIdentifiedAsPercentage
+ */
+ public function testWhetherPercentagesAreHandledCorrectly()
+ {
+ $this->assertSame(
+ 66.0,
+ Perfdata::fromString('test=66%')->getPercentage(),
+ 'Perfdata objects do not correctly handle native percentages'
+ );
+ $this->assertSame(
+ 50.0,
+ Perfdata::fromString('test=0;;;-250;250')->getPercentage(),
+ 'Perfdata objects do not correctly convert suitable values to percentages'
+ );
+ $this->assertNull(
+ Perfdata::fromString('test=50')->getPercentage(),
+ 'Perfdata objects do return a percentage though their unit is not % and no maximum is given'
+ );
+ $this->assertNull(
+ Perfdata::fromString('test=25;;;50;100')->getPercentage(),
+ 'Perfdata objects do return a percentage though their value is lower than it\'s allowed minimum'
+ );
+ $this->assertNull(
+ Perfdata::fromString('test=25;;;0;')->getPercentage(),
+ 'Perfdata objects do not ignore empty max values when returning percentages'
+ );
+ $this->assertNull(
+ Perfdata::fromString('test=25;;;0;0')->getPercentage(),
+ 'Perfdata objects do not ignore impossible min/max combinations when returning percentages'
+ );
+ }
+
+ public function testWhetherInvalidValueInPerfDataHandledCorrectly()
+ {
+ $p1 = Perfdata::fromString('test=2,0');
+ $this->assertFalse($p1->isValid());
+ $this->assertNull(
+ $p1->getValue(),
+ 'Perfdata::getValue does not return null for invalid values'
+ );
+ $this->assertSame(
+ '2,0',
+ $p1->toArray()['value']
+ );
+
+ $p2 = Perfdata::fromString('test=i am not a value');
+ $this->assertFalse($p2->isValid());
+ $this->assertNull(
+ $p2->getValue(),
+ 'Perfdata::getValue does not return null for invalid values'
+ );
+ $this->assertSame(
+ 'i am not a value',
+ $p2->toArray()['value']
+ );
+
+ $p3 = Perfdata::fromString('test=');
+ $this->assertFalse($p3->isValid());
+ $this->assertNull(
+ $p3->getValue(),
+ 'Perfdata::getValue does not return null for invalid values'
+ );
+ $this->assertSame(
+ '',
+ $p3->toArray()['value']
+ );
+
+ $p4 = Perfdata::fromString('test=-kW');
+ $this->assertFalse($p4->isValid());
+ $this->assertNull(
+ $p4->getValue(),
+ 'Perfdata::getValue does not return null for invalid values'
+ );
+ $this->assertSame(
+ '-kW',
+ $p4->toArray()['value']
+ );
+
+ $p5 = Perfdata::fromString('test=kW');
+ $this->assertFalse($p5->isValid());
+ $this->assertNull(
+ $p5->getValue(),
+ 'Perfdata::getValue does not return null for invalid values'
+ );
+ $this->assertSame(
+ 'kW',
+ $p5->toArray()['value']
+ );
+
+ $p6 = Perfdata::fromString('test=-');
+ $this->assertFalse($p6->isValid());
+ $this->assertNull(
+ $p6->getValue(),
+ 'Perfdata::getValue does not return null for invalid values'
+ );
+ $this->assertSame(
+ '-',
+ $p6->toArray()['value']
+ );
+ }
+
+ public function testWhetherInvalidMinInPerfDataHandledCorrectly()
+ {
+ $p1 = Perfdata::fromString('test=1;;;2,0');
+ $this->assertFalse($p1->isValid());
+ $this->assertNull(
+ $p1->getMinimumValue(),
+ 'Perfdata::getMinimumValue does not return null for invalid min values'
+ );
+ $this->assertSame(
+ '2,0',
+ $p1->toArray()['min']
+ );
+
+ $p2 = Perfdata::fromString('test=1;;;foo');
+ $this->assertFalse($p2->isValid());
+ $this->assertNull(
+ $p2->getMinimumValue(),
+ 'Perfdata::getMinimumValue does not return null for invalid min values'
+ );
+ $this->assertSame(
+ 'foo',
+ $p2->toArray()['min']
+ );
+ }
+
+ public function testWhetherInvalidMaxInPerfDataHandledCorrectly()
+ {
+ $p1 = Perfdata::fromString('test=1;;;;2,0');
+ $this->assertFalse($p1->isValid());
+ $this->assertNull(
+ $p1->getMaximumValue(),
+ 'Perfdata::getMaximumValue does not return null for invalid max values'
+ );
+ $this->assertSame(
+ '2,0',
+ $p1->toArray()['max']
+ );
+
+ $p2 = Perfdata::fromString('test=1;;;;foo');
+ $this->assertFalse($p2->isValid());
+ $this->assertNull(
+ $p2->getMaximumValue(),
+ 'Perfdata::getMaximumValue does not return null for invalid max values'
+ );
+ $this->assertSame(
+ 'foo',
+ $p2->toArray()['max']
+ );
+ }
+
+ public function testWhetherInvalidWarningThresholdInPerfDataHandledCorrectly()
+ {
+ $p1 = Perfdata::fromString('test=1;2,0:');
+ $this->assertFalse($p1->getWarningThreshold()->isValid());
+ $this->assertFalse($p1->isValid());
+ $this->assertSame(
+ '2,0:',
+ (string) $p1->getWarningThreshold()
+ );
+
+ $p2 = Perfdata::fromString('test=1;0:4,0');
+ $this->assertFalse($p2->getWarningThreshold()->isValid());
+ $this->assertFalse($p2->isValid());
+ $this->assertSame(
+ '0:4,0',
+ (string) $p2->getWarningThreshold()
+ );
+
+ $p3 = Perfdata::fromString('test=1;foo');
+ $this->assertFalse($p2->getWarningThreshold()->isValid());
+ $this->assertFalse($p3->isValid());
+ $this->assertSame(
+ 'foo',
+ (string) $p3->getWarningThreshold()
+ );
+
+ $p4 = Perfdata::fromString('test=1;10@');
+ $this->assertFalse($p2->getWarningThreshold()->isValid());
+ $this->assertFalse($p4->isValid());
+ $this->assertSame(
+ '10@',
+ (string) $p4->getWarningThreshold()
+ );
+ }
+
+ public function testWhetherInvalidCriticalThresholdInPerfDataHandledCorrectly()
+ {
+ $p1 = Perfdata::fromString('test=1;;2,0:');
+ $this->assertFalse($p1->getCriticalThreshold()->isValid());
+ $this->assertFalse($p1->isValid());
+ $this->assertSame(
+ '2,0:',
+ (string) $p1->getCriticalThreshold()
+ );
+
+ $p2 = Perfdata::fromString('test=1;;0:4,0');
+ $this->assertFalse($p2->getCriticalThreshold()->isValid());
+ $this->assertFalse($p2->isValid());
+ $this->assertSame(
+ '0:4,0',
+ (string) $p2->getCriticalThreshold()
+ );
+
+ $p3 = Perfdata::fromString('test=1;;foo');
+ $this->assertFalse($p2->getCriticalThreshold()->isValid());
+ $this->assertFalse($p3->isValid());
+ $this->assertSame(
+ 'foo',
+ (string) $p3->getCriticalThreshold()
+ );
+
+ $p4 = Perfdata::fromString('test=1;;10@');
+ $this->assertFalse($p2->getCriticalThreshold()->isValid());
+ $this->assertFalse($p4->isValid());
+ $this->assertSame(
+ '10@',
+ (string) $p4->getCriticalThreshold()
+ );
+ }
+}
diff --git a/test/php/library/Icingadb/Util/ThresholdRangeTest.php b/test/php/library/Icingadb/Util/ThresholdRangeTest.php
new file mode 100644
index 0000000..b191e88
--- /dev/null
+++ b/test/php/library/Icingadb/Util/ThresholdRangeTest.php
@@ -0,0 +1,343 @@
+<?php
+
+/* Icinga DB Web | (c) 2023 Icinga GmbH | GPLv2 */
+
+namespace Tests\Icinga\Module\Icingadb\Util;
+
+use Icinga\Module\Icingadb\Util\ThresholdRange;
+use PHPUnit\Framework\TestCase;
+
+class ThresholdRangeTest extends TestCase
+{
+ public function testFromStringProperlyParsesDoubleExclusiveRanges()
+ {
+ $outside0And10 = ThresholdRange::fromString('10');
+ $this->assertSame(
+ 0.0,
+ $outside0And10->getMin(),
+ 'ThresholdRange::fromString() does not identify zero as default minimum for double exclusive ranges'
+ );
+ $this->assertSame(
+ 10.0,
+ $outside0And10->getMax(),
+ 'ThresholdRange::fromString() does not identify ten as explicit maximum for double exclusive ranges'
+ );
+ $this->assertFalse(
+ $outside0And10->isInverted(),
+ 'ThresholdRange::fromString() identifies double exclusive ranges as inclusive'
+ );
+
+ $outside10And20 = ThresholdRange::fromString('10:20');
+ $this->assertSame(
+ 10.0,
+ $outside10And20->getMin(),
+ 'ThresholdRange::fromString() does not identify ten as explicit minimum for double exclusive ranges'
+ );
+ $this->assertSame(
+ 20.0,
+ $outside10And20->getMax(),
+ 'ThresholdRange::fromString() does not identify twenty as explicit maximum for double exclusive ranges'
+ );
+ $this->assertFalse(
+ $outside10And20->isInverted(),
+ 'ThresholdRange::fromString() identifies double exclusive ranges as inclusive'
+ );
+ }
+
+ /**
+ * @depends testFromStringProperlyParsesDoubleExclusiveRanges
+ */
+ public function testContainsCorrectlyEvaluatesDoubleExclusiveRanges()
+ {
+ $outside0And10 = ThresholdRange::fromString('10');
+ $this->assertFalse(
+ $outside0And10->contains(-1),
+ 'ThresholdRange::contains() identifies negative values as greater than or equal to zero'
+ );
+ $this->assertFalse(
+ $outside0And10->contains(11),
+ 'ThresholdRange::contains() identifies eleven as smaller than or equal to ten'
+ );
+ $this->assertTrue(
+ $outside0And10->contains(10),
+ 'ThresholdRange::contains() identifies 10 as outside the range 0..10'
+ );
+
+ $outside10And20 = ThresholdRange::fromString('10:20');
+ $this->assertFalse(
+ $outside10And20->contains(9),
+ 'ThresholdRange::contains() identifies nine as greater than or equal to 10'
+ );
+ $this->assertFalse(
+ $outside10And20->contains(21),
+ 'ThresholdRange::contains() identifies twenty-one as smaller than or equal to twenty'
+ );
+ $this->assertTrue(
+ $outside10And20->contains(20),
+ 'ThresholdRange::contains() identifies 20 as outside the range 10..20'
+ );
+ }
+
+ public function testFromStringProperlyParsesSingleExclusiveRanges()
+ {
+ $smallerThan10 = ThresholdRange::fromString('10:');
+ $this->assertSame(
+ 10.0,
+ $smallerThan10->getMin(),
+ 'ThresholdRange::fromString() does not identify ten as explicit minimum for single exclusive ranges'
+ );
+ $this->assertNull(
+ $smallerThan10->getMax(),
+ 'ThresholdRange::fromString() does not identify infinity as default maximum for single exclusive ranges'
+ );
+ $this->assertFalse(
+ $smallerThan10->isInverted(),
+ 'ThresholdRange::fromString() identifies single exclusive ranges as inclusive'
+ );
+
+ $greaterThan10 = ThresholdRange::fromString('~:10');
+ $this->assertNull(
+ $greaterThan10->getMin(),
+ 'ThresholdRange::fromString() does not identify infinity as explicit minimum for single exclusive ranges'
+ );
+ $this->assertSame(
+ 10.0,
+ $greaterThan10->getMax(),
+ 'ThresholdRange::fromString() does not identify ten as explicit maximum for single exclusive ranges'
+ );
+ $this->assertFalse(
+ $greaterThan10->isInverted(),
+ 'ThresholdRange::fromString() identifies single exclusive ranges as inclusive'
+ );
+ }
+
+ /**
+ * @depends testFromStringProperlyParsesSingleExclusiveRanges
+ */
+ public function testContainsCorrectlyEvaluatesSingleExclusiveRanges()
+ {
+ $smallerThan10 = ThresholdRange::fromString('10:');
+ $this->assertFalse(
+ $smallerThan10->contains(9),
+ 'ThresholdRange::contains() identifies nine as greater than or equal to ten'
+ );
+ $this->assertTrue(
+ $smallerThan10->contains(PHP_INT_MAX),
+ 'ThresholdRange::contains() identifies infinity as outside the range 10..~'
+ );
+
+ $greaterThan10 = ThresholdRange::fromString('~:10');
+ $this->assertFalse(
+ $greaterThan10->contains(11),
+ 'ThresholdRange::contains() identifies eleven as smaller than or equal to ten'
+ );
+ $this->assertTrue(
+ $greaterThan10->contains(~PHP_INT_MAX),
+ 'ThresholdRange::contains() identifies negative infinity as outside the range ~..10'
+ );
+ }
+
+ public function testFromStringProperlyParsesInclusiveRanges()
+ {
+ $inside0And10 = ThresholdRange::fromString('@10');
+ $this->assertSame(
+ 0.0,
+ $inside0And10->getMin(),
+ 'ThresholdRange::fromString() does not identify zero as default minimum for inclusive ranges'
+ );
+ $this->assertSame(
+ 10.0,
+ $inside0And10->getMax(),
+ 'ThresholdRange::fromString() does not identify ten as explicit maximum for inclusive ranges'
+ );
+ $this->assertTrue(
+ $inside0And10->isInverted(),
+ 'ThresholdRange::fromString() identifies inclusive ranges as double exclusive'
+ );
+
+ $inside10And20 = ThresholdRange::fromString('@10:20');
+ $this->assertSame(
+ 10.0,
+ $inside10And20->getMin(),
+ 'ThresholdRange::fromString() does not identify ten as explicit minimum for inclusive ranges'
+ );
+ $this->assertSame(
+ 20.0,
+ $inside10And20->getMax(),
+ 'ThresholdRange::fromString() does not identify twenty as explicit maximum for inclusive ranges'
+ );
+ $this->assertTrue(
+ $inside10And20->isInverted(),
+ 'ThresholdRange::fromString() identifies inclusive ranges as double exclusive'
+ );
+
+ $greaterThan10 = ThresholdRange::fromString('@10:');
+ $this->assertSame(
+ 10.0,
+ $greaterThan10->getMin(),
+ 'ThresholdRange::fromString() does not identify ten as explicit minimum for inclusive ranges'
+ );
+ $this->assertNull(
+ $greaterThan10->getMax(),
+ 'ThresholdRange::fromString() does not identify infinity as default maximum for inclusive ranges'
+ );
+ $this->assertTrue(
+ $greaterThan10->isInverted(),
+ 'ThresholdRange::fromString() identifies inclusive ranges as single exclusive'
+ );
+
+ $smallerThan10 = ThresholdRange::fromString('@~:10');
+ $this->assertNull(
+ $smallerThan10->getMin(),
+ 'ThresholdRange::fromString() does not identify infinity as explicit minimum for inclusive ranges'
+ );
+ $this->assertSame(
+ 10.0,
+ $smallerThan10->getMax(),
+ 'ThresholdRange::fromString() does not identify ten as explicit maximum for inclusive ranges'
+ );
+ $this->assertTrue(
+ $smallerThan10->isInverted(),
+ 'ThresholdRange::fromString() identifies inclusive ranges as single exclusive'
+ );
+ }
+
+ /**
+ * @depends testFromStringProperlyParsesInclusiveRanges
+ */
+ public function testContainsCorrectlyEvaluatesInclusiveRanges()
+ {
+ $inside0And10 = ThresholdRange::fromString('@10');
+ $this->assertFalse(
+ $inside0And10->contains(10),
+ 'ThresholdRange::contains() identifies ten as greater than ten'
+ );
+ $this->assertTrue(
+ $inside0And10->contains(11),
+ 'ThresholdRange::contains() identifies eleven as smaller than or equal to ten'
+ );
+ $this->assertTrue(
+ $inside0And10->contains(-1),
+ 'ThresholdRange::contains() identifies negative values as greater than or equal to zero'
+ );
+
+ $inside10And20 = ThresholdRange::fromString('@10:20');
+ $this->assertFalse(
+ $inside10And20->contains(20),
+ 'ThresholdRange::contains() identifies twenty as greater than twenty'
+ );
+ $this->assertTrue(
+ $inside10And20->contains(21),
+ 'ThresholdRange::contains() identifies twenty-one as smaller than or equal to twenty'
+ );
+ $this->assertTrue(
+ $inside10And20->contains(9),
+ 'ThresholdRange::contains() identifies nine as greater than or equal to ten'
+ );
+
+ $greaterThan10 = ThresholdRange::fromString('@10:');
+ $this->assertFalse(
+ $greaterThan10->contains(PHP_INT_MAX),
+ 'ThresholdRange::contains() identifies infinity as smaller than ten'
+ );
+ $this->assertTrue(
+ $greaterThan10->contains(9),
+ 'ThresholdRange::contains() identifies nine as greater than or equal to ten'
+ );
+
+ $smallerThan10 = ThresholdRange::fromString('@~:10');
+ $this->assertFalse(
+ $smallerThan10->contains(~PHP_INT_MAX),
+ 'ThresholdRange::contains() identifies negative infinity as greater than ten'
+ );
+ $this->assertTrue(
+ $smallerThan10->contains(11),
+ 'ThresholdRange::contains() identifies eleven as smaller than or equal to ten'
+ );
+ }
+
+ public function testFromStringProperlyParsesEmptyThresholds()
+ {
+ $emptyThreshold = ThresholdRange::fromString('');
+ $this->assertNull(
+ $emptyThreshold->getMin(),
+ 'ThresholdRange::fromString() does not identify negative infinity as implicit minimum for empty strings'
+ );
+ $this->assertNull(
+ $emptyThreshold->getMax(),
+ 'ThresholdRange::fromString() does not identify infinity as implicit maximum for empty strings'
+ );
+ $this->assertFalse(
+ $emptyThreshold->isInverted(),
+ 'ThresholdRange::fromString() identifies empty strings as inclusive ranges rather than exclusive'
+ );
+ }
+
+ /**
+ * @depends testFromStringProperlyParsesEmptyThresholds
+ */
+ public function testContainsEvaluatesEverythingToTrueForEmptyThresholds()
+ {
+ $emptyThreshold = ThresholdRange::fromString('');
+ $this->assertTrue(
+ $emptyThreshold->contains(0),
+ 'ThresholdRange::contains() does not identify zero as valid without any threshold'
+ );
+ $this->assertTrue(
+ $emptyThreshold->contains(10),
+ 'ThresholdRange::contains() does not identify ten as valid without any threshold'
+ );
+ $this->assertTrue(
+ $emptyThreshold->contains(PHP_INT_MAX),
+ 'ThresholdRange::contains() does not identify infinity as valid without any threshold'
+ );
+ $this->assertTrue(
+ $emptyThreshold->contains(~PHP_INT_MAX),
+ 'ThresholdRange::contains() does not identify negative infinity as valid without any threshold'
+ );
+ }
+
+ public function testInvalidThresholdNotationsAreRenderedAsIs()
+ {
+ $this->assertSame(
+ ':',
+ (string) ThresholdRange::fromString(':')
+ );
+ $this->assertSame(
+ '~:',
+ (string) ThresholdRange::fromString('~:')
+ );
+ $this->assertSame(
+ '20:10',
+ (string) ThresholdRange::fromString('20:10')
+ );
+ $this->assertSame(
+ '10@',
+ (string) ThresholdRange::fromString('10@')
+ );
+ $this->assertSame(
+ 'foo',
+ (string) ThresholdRange::fromString('foo')
+ );
+ $this->assertSame(
+ '4,4:2,2',
+ (string) ThresholdRange::fromString('4,4:2,2')
+ );
+ }
+
+ public function testInvalidThresholdNotationsConsideredInValid()
+ {
+ $this->assertFalse(
+ ThresholdRange::fromString('10@')->isValid(),
+ 'Invalid threshold notation 10@ considered as valid'
+ );
+ $this->assertFalse(
+ ThresholdRange::fromString('foo')->isValid(),
+ 'Invalid threshold notation foo considered as valid'
+ );
+ $this->assertFalse(
+ ThresholdRange::fromString('4,4:2,2')->isValid(),
+ 'Invalid threshold notation 4,4:2,2 considered as valid'
+ );
+ }
+}