createMock(Table::class); // Expect the table will have 6 rows $table->method('getRealRowCountTable')->willReturn(6); $table->method('countRecords')->willReturn(6); $dbi = $this->createMock(DatabaseInterface::class); $dbi->method('getTable')->willReturn($table); $GLOBALS['dbi'] = $dbi; $this->template = new Template(); $this->response = new ResponseStub(); $this->relation = new Relation($dbi); $this->replication = new Replication(); $this->relationCleanup = new RelationCleanup($dbi, $this->relation); $this->operations = new Operations($dbi, $this->relation); $this->flash = new FlashMessages(); } /** * Tests for getValuesForInnodbTable() */ public function testGetValuesForInnodbTable(): void { $class = new ReflectionClass(StructureController::class); $method = $class->getMethod('getValuesForInnodbTable'); if (PHP_VERSION_ID < 80100) { $method->setAccessible(true); } $controller = new StructureController( $this->response, $this->template, $GLOBALS['db'], $this->relation, $this->replication, $this->relationCleanup, $this->operations, $GLOBALS['dbi'], $this->flash ); // Showing statistics $property = $class->getProperty('isShowStats'); if (PHP_VERSION_ID < 80100) { $property->setAccessible(true); } $property->setValue($controller, true); $GLOBALS['cfg']['MaxExactCount'] = 10; $currentTable = [ 'ENGINE' => 'InnoDB', 'TABLE_ROWS' => 5, 'Data_length' => 16384, 'Index_length' => 0, 'TABLE_NAME' => 'table', ]; [$currentTable, , , $sumSize] = $method->invokeArgs( $controller, [ $currentTable, 10, ] ); self::assertTrue($currentTable['COUNTED']); self::assertSame(6, $currentTable['TABLE_ROWS']); self::assertSame(16394, $sumSize); $currentTable['ENGINE'] = 'MYISAM'; [$currentTable, , , $sumSize] = $method->invokeArgs( $controller, [ $currentTable, 10, ] ); self::assertFalse($currentTable['COUNTED']); self::assertSame(16394, $sumSize); $controller = new StructureController( $this->response, $this->template, $GLOBALS['db'], $this->relation, $this->replication, $this->relationCleanup, $this->operations, $GLOBALS['dbi'], $this->flash ); $currentTable['ENGINE'] = 'InnoDB'; [$currentTable, , , $sumSize] = $method->invokeArgs($controller, [$currentTable, 10]); self::assertTrue($currentTable['COUNTED']); self::assertSame(10, $sumSize); $currentTable['ENGINE'] = 'MYISAM'; [$currentTable, , , $sumSize] = $method->invokeArgs($controller, [$currentTable, 10]); self::assertFalse($currentTable['COUNTED']); self::assertSame(10, $sumSize); } /** * Tests for the getValuesForAriaTable() */ public function testGetValuesForAriaTable(): void { $class = new ReflectionClass(StructureController::class); $method = $class->getMethod('getValuesForAriaTable'); if (PHP_VERSION_ID < 80100) { $method->setAccessible(true); } $controller = new StructureController( $this->response, $this->template, $GLOBALS['db'], $this->relation, $this->replication, $this->relationCleanup, $this->operations, $GLOBALS['dbi'], $this->flash ); // Showing statistics $property = $class->getProperty('isShowStats'); if (PHP_VERSION_ID < 80100) { $property->setAccessible(true); } $property->setValue($controller, true); $property = $class->getProperty('dbIsSystemSchema'); if (PHP_VERSION_ID < 80100) { $property->setAccessible(true); } $property->setValue($controller, true); $currentTable = [ 'Data_length' => 16384, 'Index_length' => 0, 'Name' => 'table', 'Data_free' => 300, ]; [$currentTable, , , , , $overheadSize, $sumSize] = $method->invokeArgs( $controller, [ $currentTable, 0, 0, 0, 0, 0, 0, ] ); self::assertSame(6, $currentTable['Rows']); self::assertSame(16384, $sumSize); self::assertSame(300, $overheadSize); unset($currentTable['Data_free']); [$currentTable, , , , , $overheadSize] = $method->invokeArgs( $controller, [ $currentTable, 0, 0, 0, 0, 0, 0, ] ); self::assertSame(0, $overheadSize); $controller = new StructureController( $this->response, $this->template, $GLOBALS['db'], $this->relation, $this->replication, $this->relationCleanup, $this->operations, $GLOBALS['dbi'], $this->flash ); [$currentTable, , , , , , $sumSize] = $method->invokeArgs( $controller, [ $currentTable, 0, 0, 0, 0, 0, 0, ] ); self::assertSame(0, $sumSize); $controller = new StructureController( $this->response, $this->template, $GLOBALS['db'], $this->relation, $this->replication, $this->relationCleanup, $this->operations, $GLOBALS['dbi'], $this->flash ); [$currentTable] = $method->invokeArgs( $controller, [ $currentTable, 0, 0, 0, 0, 0, 0, ] ); self::assertArrayNotHasKey('Row', $currentTable); } /** * Tests for hasTable() */ public function testHasTable(): void { $class = new ReflectionClass(StructureController::class); $method = $class->getMethod('hasTable'); if (PHP_VERSION_ID < 80100) { $method->setAccessible(true); } $controller = new StructureController( $this->response, $this->template, $GLOBALS['db'], $this->relation, $this->replication, $this->relationCleanup, $this->operations, $GLOBALS['dbi'], $this->flash ); // When parameter $db is empty self::assertFalse($method->invokeArgs($controller, [[], 'table'])); // Correct parameter $tables = ['db.table']; self::assertTrue($method->invokeArgs($controller, [$tables, 'table'])); // Table not in database $tables = ['db.tab1e']; self::assertFalse($method->invokeArgs($controller, [$tables, 'table'])); } /** * Tests for checkFavoriteTable() */ public function testCheckFavoriteTable(): void { $class = new ReflectionClass(StructureController::class); $method = $class->getMethod('checkFavoriteTable'); if (PHP_VERSION_ID < 80100) { $method->setAccessible(true); } $GLOBALS['db'] = 'sakila'; $GLOBALS['dbi'] = $this->dbi; $this->dummyDbi->removeDefaultResults(); $this->dummyDbi->addResult( 'SHOW COLUMNS FROM `sakila`.`country`', [ ['country_id', 'smallint(5) unsigned', 'NO', 'PRI', null, 'auto_increment'], ], ['Field', 'Type', 'Null', 'Key', 'Default', 'Extra'] ); $this->dummyDbi->addResult( 'SHOW INDEXES FROM `sakila`.`country`', [], ['Table', 'Non_unique', 'Key_name', 'Column_name'] ); $controller = new StructureController( $this->response, $this->template, $GLOBALS['db'], $this->relation, $this->replication, $this->relationCleanup, $this->operations, $GLOBALS['dbi'], $this->flash ); $recentFavoriteTables = RecentFavoriteTable::getInstance('favorite'); self::assertSame([], $recentFavoriteTables->getTables()); $recentFavoriteTables->remove('sakila', 'country'); $recentFavoriteTables->add('sakila', 'country'); self::assertSame([ [ 'db' => 'sakila', 'table' => 'country', ], ], $recentFavoriteTables->getTables()); self::assertFalse($method->invokeArgs($controller, [''])); self::assertTrue($method->invokeArgs($controller, ['country'])); } /** * @throws ReflectionException */ public function testDisplayTableList(): void { $GLOBALS['cfg']['ShowDbStructureCreation'] = true; $GLOBALS['cfg']['ShowDbStructureLastUpdate'] = true; $GLOBALS['cfg']['ShowDbStructureLastCheck'] = true; $class = new ReflectionClass(StructureController::class); $method = $class->getMethod('displayTableList'); if (PHP_VERSION_ID < 80100) { $method->setAccessible(true); } $controller = new StructureController( $this->response, $this->template, $GLOBALS['db'], $this->relation, $this->replication, $this->relationCleanup, $this->operations, $GLOBALS['dbi'], $this->flash ); // Showing statistics $class = new ReflectionClass(StructureController::class); $showStatsProperty = $class->getProperty('isShowStats'); if (PHP_VERSION_ID < 80100) { $showStatsProperty->setAccessible(true); } $showStatsProperty->setValue($controller, true); $tablesProperty = $class->getProperty('tables'); if (PHP_VERSION_ID < 80100) { $tablesProperty->setAccessible(true); } $numTables = $class->getProperty('numTables'); if (PHP_VERSION_ID < 80100) { $numTables->setAccessible(true); } $_REQUEST['db'] = 'my_unique_test_db'; //no tables $numTables->setValue($controller, 0); $tablesProperty->setValue($controller, []); /** @var string $result */ $result = $method->invoke($controller, ['status' => false]); self::assertStringContainsString($_REQUEST['db'], $result); self::assertStringNotContainsString('id="overhead"', $result); //with table $tableInfo = [ 'ENGINE' => 'Maria', 'TABLE_TYPE' => 'BASE TABLE', 'TABLE_ROWS' => '0', 'TABLE_COMMENT' => 'test', 'Data_length' => '5000', 'Index_length' => '100', 'Data_free' => '10000', ]; $tablesProperty->setValue($controller, [ 'my_unique_test_table_1' => [ 'TABLE_NAME' => 'my_unique_test_table_1', 'Create_time' => '2026-09-04 09:11:00', 'Update_time' => '2026-09-04 10:11:00', 'Check_time' => '2026-09-04 11:11:00', ] + $tableInfo, 'my_unique_test_table_2' => [ 'TABLE_NAME' => 'my_unique_test_table_2', 'Create_time' => '2026-09-04 09:22:00', 'Update_time' => '2026-09-04 10:22:00', 'Check_time' => '2026-09-04 11:22:00', ] + $tableInfo, ]); $numTables->setValue($controller, 2); /** @var string $result */ $result = $method->invoke($controller, ['status' => false]); self::assertStringContainsString($_REQUEST['db'], $result); self::assertStringContainsString('id="overhead"', $result); self::assertStringContainsString('9.8', $result); self::assertStringContainsString( '