assertIsInt($s); $this->assertIsInt($e); $this->assertLessThan($s + 100, $e); // Invalid addresses -> verbose returns null and records warnings Message::reset(); $this->assertNull(LocationUtil::rangeToLongVerbose('bad-ip', '10.0.0.1')); $this->assertContains('main.value-invalid', Message::$warnings); Message::reset(); $this->assertNull(LocationUtil::rangeToLongVerbose('10.0.0.9', '10.0.0.1')); $this->assertContains('main.value-invalid', Message::$warnings); } public function testGetOverlappingSubnetsSelfAndOther(): void { // Sanity: 2 and 3 are siblings under 1 in the canonical seed $assoc = Location::getLocationsAssoc(); $this->assertSame(1, $assoc[2]['parentlocationid']); $this->assertSame(1, $assoc[3]['parentlocationid']); $this->assertNotContains(2, $assoc[3]['parents']); $this->assertNotContains(3, $assoc[2]['parents']); // Self-overlap in location 5: add overlapping ranges $startA = sprintf('%u', ip2long('192.168.1.0')); $endA = sprintf('%u', ip2long('192.168.1.127')); $startB = sprintf('%u', ip2long('192.168.1.64')); $endB = sprintf('%u', ip2long('192.168.1.200')); Database::exec('INSERT INTO subnet (startaddr, endaddr, locationid) VALUES (:s, :e, 5)', ['s' => $startA, 'e' => $endA]); Database::exec('INSERT INTO subnet (startaddr, endaddr, locationid) VALUES (:s, :e, 5)', ['s' => $startB, 'e' => $endB]); // Other-overlap between unrelated siblings 2 and 3: make 3 overlap 2's 10.0.0.128/26 by adding a // wider 10.0.0.0/24 in location 3. $startC = sprintf('%u', ip2long('10.0.0.0')); $endC = sprintf('%u', ip2long('10.0.0.255')); Database::exec('INSERT INTO subnet (startaddr, endaddr, locationid) VALUES (:s, :e, 3)', ['s' => $startC, 'e' => $endC]); $overSelf = []; $overOther = []; LocationUtil::getOverlappingSubnets($overSelf, $overOther); // Self: expect one entry with location name 'Offsite' (id 5 in seed) $this->assertNotEmpty($overSelf); $names = array_column($overSelf, 'locationname'); $this->assertContains('Offsite', $names); // Other: expect a pair 2|3 (order not guaranteed, check that both names present) $this->assertNotEmpty($overOther); $pairFound = false; foreach ($overOther as $p) { if ((isset($p['name1']) && isset($p['name2']))) { $pair = [$p['name1'], $p['name2']]; sort($pair); if ($pair === ['Building A', 'Building B']) { $pairFound = true; break; } } } $this->assertTrue($pairFound, 'Expected overlap between Building A and Building B'); } public function testGetMachinesWithLocationMismatchSummaryAndDetail(): void { // Summary across all locations $summary = LocationUtil::getMachinesWithLocationMismatch(0, false); // Expect entries for fixedlocationid 5 (m1 mismatch) and 2 (wrong2) $byId = []; foreach ($summary as $row) { $byId[$row['locationid']] = $row; } $this->assertArrayHasKey(5, $byId); $this->assertArrayHasKey(2, $byId); $this->assertSame('Offsite', $byId[5]['locationname']); $this->assertSame('Building A', $byId[2]['locationname']); $this->assertGreaterThanOrEqual(1, $byId[5]['count']); $this->assertGreaterThanOrEqual(1, $byId[2]['count']); // Detail for location 5 $detail = LocationUtil::getMachinesWithLocationMismatch(5, false); $this->assertSame(5, $detail['locationid']); $this->assertSame('Offsite', $detail['locationname']); $this->assertNotEmpty($detail['clients']); $client = $detail['clients'][0]; $this->assertArrayHasKey('machineuuid', $client); $this->assertArrayHasKey('iplocationid', $client); $this->assertSame('Campus', $client['iplocationname']); // iplocationid 1 from seed $this->assertFalse($client['ipisleaf']); // root has children $this->assertFalse($client['canmove']); // not leaf -> cannot move } }