Merge branch 'refactor-getpartitions' into kpmcore-manager

This commit is contained in:
Adriaan de Groot 2019-06-24 13:11:20 +02:00
commit a991577779
6 changed files with 227 additions and 77 deletions

View File

@ -60,26 +60,47 @@ ClearMountsJob::prettyStatusMessage() const
} }
QStringList
getPartitionsForDevice( const QString& deviceName )
{
QStringList partitions;
QFile dev_partitions( "/proc/partitions" );
if ( dev_partitions.open( QFile::ReadOnly ) )
{
cDebug() << "Reading from" << dev_partitions.fileName();
QTextStream in( &dev_partitions );
(void) in.readLine(); // That's the header line, skip it
while ( !in.atEnd() )
{
// The fourth column (index from 0, so index 3) is the name of the device;
// keep it if it is followed by something.
QStringList columns = in.readLine().split( ' ', QString::SkipEmptyParts );
if ( ( columns.count() >= 4 ) && ( columns[3].startsWith( deviceName ) ) && ( columns[3] != deviceName ) )
{
partitions.append( columns[3] );
}
}
}
else
{
cDebug() << "Could not open" << dev_partitions.fileName();
}
return partitions;
}
Calamares::JobResult Calamares::JobResult
ClearMountsJob::exec() ClearMountsJob::exec()
{ {
CalamaresUtils::Partition::Syncer s; CalamaresUtils::Partition::Syncer s;
QStringList goodNews;
QString deviceName = m_device->deviceNode().split( '/' ).last(); QString deviceName = m_device->deviceNode().split( '/' ).last();
QStringList goodNews;
QProcess process; QProcess process;
process.setProgram( "sh" );
process.setArguments( {
"-c",
QString( "echo $(awk '{print $4}' /proc/partitions | sed -e '/name/d' -e '/^$/d' -e '/[1-9]/!d' | grep %1)" )
.arg( deviceName )
} );
process.start();
process.waitForFinished();
const QString partitions = process.readAllStandardOutput(); QStringList partitionsList = getPartitionsForDevice( deviceName );
const QStringList partitionsList = partitions.simplified().split( ' ' );
// Build a list of partitions of type 82 (Linux swap / Solaris). // Build a list of partitions of type 82 (Linux swap / Solaris).
// We then need to clear them just in case they contain something resumable from a // We then need to clear them just in case they contain something resumable from a

View File

@ -1,17 +1,9 @@
find_package( Qt5 COMPONENTS Gui REQUIRED ) find_package( Qt5 COMPONENTS Gui REQUIRED )
# Roundabout way of saying ..
set( PartitionModule_SOURCE_DIR .. ) set( PartitionModule_SOURCE_DIR .. )
# This is set by parent CMakeLists.txt
set( partitionjobtests_SRCS # set( _partition_defs )
${PartitionModule_SOURCE_DIR}/core/KPMHelpers.cpp
${PartitionModule_SOURCE_DIR}/core/PartitionInfo.cpp
${PartitionModule_SOURCE_DIR}/jobs/CreatePartitionJob.cpp
${PartitionModule_SOURCE_DIR}/jobs/CreatePartitionTableJob.cpp
${PartitionModule_SOURCE_DIR}/jobs/DeletePartitionJob.cpp
${PartitionModule_SOURCE_DIR}/jobs/PartitionJob.cpp
${PartitionModule_SOURCE_DIR}/jobs/ResizePartitionJob.cpp
PartitionJobTests.cpp
)
include_directories( include_directories(
${Qt5Gui_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS}
@ -21,7 +13,16 @@ include_directories(
) )
if( ECM_FOUND AND BUILD_TESTING ) if( ECM_FOUND AND BUILD_TESTING )
ecm_add_test( ${partitionjobtests_SRCS} ecm_add_test(
${PartitionModule_SOURCE_DIR}/core/KPMHelpers.cpp
${PartitionModule_SOURCE_DIR}/core/PartitionInfo.cpp
${PartitionModule_SOURCE_DIR}/jobs/CreatePartitionJob.cpp
${PartitionModule_SOURCE_DIR}/jobs/CreatePartitionTableJob.cpp
${PartitionModule_SOURCE_DIR}/jobs/DeletePartitionJob.cpp
${PartitionModule_SOURCE_DIR}/jobs/PartitionJob.cpp
${PartitionModule_SOURCE_DIR}/jobs/ResizePartitionJob.cpp
PartitionJobTests.cpp
TEST_NAME partitionjobtests TEST_NAME partitionjobtests
LINK_LIBRARIES LINK_LIBRARIES
${CALAMARES_LIBRARIES} ${CALAMARES_LIBRARIES}
@ -32,4 +33,20 @@ if( ECM_FOUND AND BUILD_TESTING )
set_target_properties( partitionjobtests PROPERTIES AUTOMOC TRUE ) set_target_properties( partitionjobtests PROPERTIES AUTOMOC TRUE )
target_compile_definitions( partitionjobtests PRIVATE ${_partition_defs} ) target_compile_definitions( partitionjobtests PRIVATE ${_partition_defs} )
ecm_add_test(
${PartitionModule_SOURCE_DIR}/jobs/ClearMountsJob.cpp
ClearMountsJobTests.cpp
TEST_NAME clearmountsjobtests
LINK_LIBRARIES
${CALAMARES_LIBRARIES}
kpmcore
Qt5::Core
Qt5::Test
)
set_target_properties( clearmountsjobtests PROPERTIES AUTOMOC TRUE )
target_compile_definitions( clearmountsjobtests PRIVATE ${_partition_defs} )
endif() endif()

View File

@ -0,0 +1,66 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2019, Adriaan de Groot <groot@kde.org>
*
* Calamares is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Calamares is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ClearMountsJobTests.h"
#include "utils/Logger.h"
#include <QtTest/QtTest>
QTEST_GUILESS_MAIN( ClearMountsJobTests )
/* Not exactly public API */
QStringList
getPartitionsForDevice( const QString& deviceName );
QStringList
getPartitionsForDevice_other(const QString& deviceName)
{
QProcess process;
process.setProgram( "sh" );
process.setArguments( {
"-c",
QString( "echo $(awk '{print $4}' /proc/partitions | sed -e '/name/d' -e '/^$/d' -e '/[1-9]/!d' | grep %1)" )
.arg( deviceName )
} );
process.start();
process.waitForFinished();
const QString partitions = process.readAllStandardOutput();
const QStringList partitionsList = partitions.simplified().split( ' ' );
return partitionsList;
}
ClearMountsJobTests::ClearMountsJobTests()
{
Logger::setupLogLevel(6);
}
void ClearMountsJobTests::testFindPartitions()
{
QStringList partitions = getPartitionsForDevice( "sda" );
QStringList other_part = getPartitionsForDevice_other( "sda" );
cDebug() << "Initial implementation:" << Logger::DebugList( partitions );
cDebug() << "Other implementation:" << Logger::DebugList( other_part );
QCOMPARE( partitions, other_part );
}

View File

@ -0,0 +1,34 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2019, Adriaan de Groot <groot@kde.org>
*
* Calamares is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Calamares is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CLEARMOUNTSJOBTESTS_H
#define CLEARMOUNTSJOBTESTS_H
#include <QObject>
class ClearMountsJobTests : public QObject
{
Q_OBJECT
public:
ClearMountsJobTests();
private Q_SLOTS:
void testFindPartitions();
};
#endif

View File

@ -24,10 +24,10 @@
#include "utils/Logger.h" #include "utils/Logger.h"
#include "utils/Units.h" #include "utils/Units.h"
#include <core/KPMHelpers.h>
#include <jobs/CreatePartitionJob.h> #include <jobs/CreatePartitionJob.h>
#include <jobs/CreatePartitionTableJob.h> #include <jobs/CreatePartitionTableJob.h>
#include <jobs/ResizePartitionJob.h> #include <jobs/ResizePartitionJob.h>
#include <core/KPMHelpers.h>
// CalaPM // CalaPM
#include <backend/corebackend.h> #include <backend/corebackend.h>
@ -59,15 +59,14 @@ public:
~PartitionMounter() ~PartitionMounter()
{ {
if ( !m_mounted ) if ( !m_mounted )
{
return; return;
}
int ret = QProcess::execute( "umount", QStringList() << m_mountPointDir.path() ); int ret = QProcess::execute( "umount", QStringList() << m_mountPointDir.path() );
QCOMPARE( ret, 0 ); QCOMPARE( ret, 0 );
} }
QString mountPoint() const QString mountPoint() const { return m_mounted ? m_mountPointDir.path() : QString(); }
{
return m_mounted ? m_mountPointDir.path() : QString();
}
private: private:
QString m_devicePath; QString m_devicePath;
@ -80,9 +79,9 @@ static QByteArray
generateTestData( qint64 size ) generateTestData( qint64 size )
{ {
QByteArray ba; QByteArray ba;
ba.resize( static_cast<int>( size ) ); ba.resize( static_cast< int >( size ) );
// Fill the array explicitly to keep Valgrind happy // Fill the array explicitly to keep Valgrind happy
for ( auto it = ba.data() ; it < ba.data() + size ; ++it ) for ( auto it = ba.data(); it < ba.data() + size; ++it )
{ {
*it = char( rand() & 0xff ); *it = char( rand() & 0xff );
} }
@ -105,9 +104,9 @@ writeFile( const QString& path, const QByteArray data )
if ( count < 0 ) if ( count < 0 )
{ {
QString msg = QString( "Writing file failed. Only %1 bytes written out of %2. Error: '%3'." ) QString msg = QString( "Writing file failed. Only %1 bytes written out of %2. Error: '%3'." )
.arg( ptr - data.constData() ) .arg( ptr - data.constData() )
.arg( data.size() ) .arg( data.size() )
.arg( file.errorString() ); .arg( file.errorString() );
QFAIL( qPrintable( msg ) ); QFAIL( qPrintable( msg ) );
} }
ptr += count; ptr += count;
@ -117,9 +116,11 @@ writeFile( const QString& path, const QByteArray data )
static Partition* static Partition*
firstFreePartition( PartitionNode* parent ) firstFreePartition( PartitionNode* parent )
{ {
for( auto child : parent->children() ) for ( auto child : parent->children() )
if ( isPartitionFreeSpace( child ) ) if ( isPartitionFreeSpace( child ) )
{
return child; return child;
}
return nullptr; return nullptr;
} }
@ -146,7 +147,9 @@ QueueRunner::run()
m_queue->start(); m_queue->start();
QEventLoop loop; QEventLoop loop;
while ( !m_finished ) while ( !m_finished )
{
loop.processEvents(); loop.processEvents();
}
return m_success; return m_success;
} }
@ -169,7 +172,8 @@ CalamaresUtils::Partition::KPMManager* kpmcore = nullptr;
//- PartitionJobTests ------------------------------------------------------------------ //- PartitionJobTests ------------------------------------------------------------------
PartitionJobTests::PartitionJobTests() PartitionJobTests::PartitionJobTests()
: m_runner( &m_queue ) : m_runner( &m_queue )
{} {
}
void void
PartitionJobTests::initTestCase() PartitionJobTests::initTestCase()
@ -178,7 +182,8 @@ PartitionJobTests::initTestCase()
if ( devicePath.isEmpty() ) if ( devicePath.isEmpty() )
{ {
// The 0 is to keep the macro parameters happy // The 0 is to keep the macro parameters happy
QSKIP( "Skipping test, CALAMARES_TEST_DISK is not set. It should point to a disk which can be safely formatted", 0 ); QSKIP( "Skipping test, CALAMARES_TEST_DISK is not set. It should point to a disk which can be safely formatted",
0 );
} }
kpmcore = new CalamaresUtils::Partition::KPMManager(); kpmcore = new CalamaresUtils::Partition::KPMManager();
@ -216,7 +221,7 @@ PartitionJobTests::testPartitionTable()
} }
void void
PartitionJobTests::queuePartitionTableCreation( PartitionTable::TableType type) PartitionJobTests::queuePartitionTableCreation( PartitionTable::TableType type )
{ {
auto job = new CreatePartitionTableJob( m_device.data(), type ); auto job = new CreatePartitionTableJob( m_device.data(), type );
job->updatePreview(); job->updatePreview();
@ -224,7 +229,10 @@ PartitionJobTests::queuePartitionTableCreation( PartitionTable::TableType type)
} }
CreatePartitionJob* CreatePartitionJob*
PartitionJobTests::newCreatePartitionJob( Partition* freeSpacePartition, PartitionRole role, FileSystem::Type type, qint64 size ) PartitionJobTests::newCreatePartitionJob( Partition* freeSpacePartition,
PartitionRole role,
FileSystem::Type type,
qint64 size )
{ {
Q_ASSERT( freeSpacePartition ); Q_ASSERT( freeSpacePartition );
@ -232,25 +240,27 @@ PartitionJobTests::newCreatePartitionJob( Partition* freeSpacePartition, Partiti
qint64 lastSector; qint64 lastSector;
if ( size > 0 ) if ( size > 0 )
{
lastSector = firstSector + size / m_device->logicalSize(); lastSector = firstSector + size / m_device->logicalSize();
}
else else
{
lastSector = freeSpacePartition->lastSector(); lastSector = freeSpacePartition->lastSector();
FileSystem* fs = FileSystemFactory::create( type, firstSector, lastSector }
,m_device->logicalSize() FileSystem* fs = FileSystemFactory::create( type, firstSector, lastSector, m_device->logicalSize() );
);
Partition* partition = new Partition( Partition* partition = new Partition( freeSpacePartition->parent(),
freeSpacePartition->parent(), *m_device,
*m_device, role,
role, fs,
fs, firstSector, lastSector, firstSector,
QString() /* path */, lastSector,
KPM_PARTITION_FLAG(None) /* availableFlags */, QString() /* path */,
QString() /* mountPoint */, KPM_PARTITION_FLAG( None ) /* availableFlags */,
false /* mounted */, QString() /* mountPoint */,
KPM_PARTITION_FLAG(None) /* activeFlags */, false /* mounted */,
KPM_PARTITION_STATE(New) KPM_PARTITION_FLAG( None ) /* activeFlags */,
); KPM_PARTITION_STATE( New ) );
return new CreatePartitionJob( m_device.data(), partition ); return new CreatePartitionJob( m_device.data(), partition );
} }
@ -263,7 +273,7 @@ PartitionJobTests::testCreatePartition()
freePartition = firstFreePartition( m_device->partitionTable() ); freePartition = firstFreePartition( m_device->partitionTable() );
QVERIFY( freePartition ); QVERIFY( freePartition );
job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::Ext4, 1_MiB); job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::Ext4, 1_MiB );
Partition* partition1 = job->partition(); Partition* partition1 = job->partition();
QVERIFY( partition1 ); QVERIFY( partition1 );
job->updatePreview(); job->updatePreview();
@ -271,7 +281,7 @@ PartitionJobTests::testCreatePartition()
freePartition = firstFreePartition( m_device->partitionTable() ); freePartition = firstFreePartition( m_device->partitionTable() );
QVERIFY( freePartition ); QVERIFY( freePartition );
job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::LinuxSwap, 1_MiB); job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::LinuxSwap, 1_MiB );
Partition* partition2 = job->partition(); Partition* partition2 = job->partition();
QVERIFY( partition2 ); QVERIFY( partition2 );
job->updatePreview(); job->updatePreview();
@ -279,7 +289,7 @@ PartitionJobTests::testCreatePartition()
freePartition = firstFreePartition( m_device->partitionTable() ); freePartition = firstFreePartition( m_device->partitionTable() );
QVERIFY( freePartition ); QVERIFY( freePartition );
job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::Fat32, 1_MiB); job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::Fat32, 1_MiB );
Partition* partition3 = job->partition(); Partition* partition3 = job->partition();
QVERIFY( partition3 ); QVERIFY( partition3 );
job->updatePreview(); job->updatePreview();
@ -304,7 +314,7 @@ PartitionJobTests::testCreatePartitionExtended()
freePartition = firstFreePartition( m_device->partitionTable() ); freePartition = firstFreePartition( m_device->partitionTable() );
QVERIFY( freePartition ); QVERIFY( freePartition );
job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::Ext4, 10_MiB); job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::Ext4, 10_MiB );
Partition* partition1 = job->partition(); Partition* partition1 = job->partition();
QVERIFY( partition1 ); QVERIFY( partition1 );
job->updatePreview(); job->updatePreview();
@ -312,14 +322,15 @@ PartitionJobTests::testCreatePartitionExtended()
freePartition = firstFreePartition( m_device->partitionTable() ); freePartition = firstFreePartition( m_device->partitionTable() );
QVERIFY( freePartition ); QVERIFY( freePartition );
job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Extended ), FileSystem::Extended, 10_MiB); job = newCreatePartitionJob(
freePartition, PartitionRole( PartitionRole::Extended ), FileSystem::Extended, 10_MiB );
job->updatePreview(); job->updatePreview();
m_queue.enqueue( job_ptr( job ) ); m_queue.enqueue( job_ptr( job ) );
Partition* extendedPartition = job->partition(); Partition* extendedPartition = job->partition();
freePartition = firstFreePartition( extendedPartition ); freePartition = firstFreePartition( extendedPartition );
QVERIFY( freePartition ); QVERIFY( freePartition );
job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Logical ), FileSystem::Ext4, 0); job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Logical ), FileSystem::Ext4, 0 );
Partition* partition2 = job->partition(); Partition* partition2 = job->partition();
QVERIFY( partition2 ); QVERIFY( partition2 );
job->updatePreview(); job->updatePreview();
@ -343,10 +354,10 @@ PartitionJobTests::testResizePartition_data()
QTest::addColumn< unsigned int >( "newStartMiB" ); QTest::addColumn< unsigned int >( "newStartMiB" );
QTest::addColumn< unsigned int >( "newSizeMiB" ); QTest::addColumn< unsigned int >( "newSizeMiB" );
QTest::newRow("grow") << 10 << 50 << 10 << 70; QTest::newRow( "grow" ) << 10 << 50 << 10 << 70;
QTest::newRow("shrink") << 10 << 70 << 10 << 50; QTest::newRow( "shrink" ) << 10 << 70 << 10 << 50;
QTest::newRow("moveLeft") << 10 << 50 << 8 << 50; QTest::newRow( "moveLeft" ) << 10 << 50 << 8 << 50;
QTest::newRow("moveRight") << 10 << 50 << 12 << 50; QTest::newRow( "moveRight" ) << 10 << 50 << 12 << 50;
} }
void void
@ -360,9 +371,9 @@ PartitionJobTests::testResizePartition()
const qint64 sectorsPerMiB = 1_MiB / m_device->logicalSize(); const qint64 sectorsPerMiB = 1_MiB / m_device->logicalSize();
qint64 oldFirst = sectorsPerMiB * oldStartMiB; qint64 oldFirst = sectorsPerMiB * oldStartMiB;
qint64 oldLast = oldFirst + sectorsPerMiB * oldSizeMiB - 1; qint64 oldLast = oldFirst + sectorsPerMiB * oldSizeMiB - 1;
qint64 newFirst = sectorsPerMiB * newStartMiB; qint64 newFirst = sectorsPerMiB * newStartMiB;
qint64 newLast = newFirst + sectorsPerMiB * newSizeMiB - 1; qint64 newLast = newFirst + sectorsPerMiB * newSizeMiB - 1;
// Make the test data file smaller than the full size of the partition to // Make the test data file smaller than the full size of the partition to
// accomodate for the file system overhead // accomodate for the file system overhead
@ -376,15 +387,13 @@ PartitionJobTests::testResizePartition()
Partition* freePartition = firstFreePartition( m_device->partitionTable() ); Partition* freePartition = firstFreePartition( m_device->partitionTable() );
QVERIFY( freePartition ); QVERIFY( freePartition );
Partition* partition = KPMHelpers::createNewPartition( Partition* partition = KPMHelpers::createNewPartition( freePartition->parent(),
freePartition->parent(), *m_device,
*m_device, PartitionRole( PartitionRole::Primary ),
PartitionRole( PartitionRole::Primary ), FileSystem::Ext4,
FileSystem::Ext4, oldFirst,
oldFirst, oldLast,
oldLast, KPM_PARTITION_FLAG( None ) );
KPM_PARTITION_FLAG(None)
);
CreatePartitionJob* job = new CreatePartitionJob( m_device.data(), partition ); CreatePartitionJob* job = new CreatePartitionJob( m_device.data(), partition );
job->updatePreview(); job->updatePreview();
m_queue.enqueue( job_ptr( job ) ); m_queue.enqueue( job_ptr( job ) );
@ -396,7 +405,8 @@ PartitionJobTests::testResizePartition()
// Write a test file in the partition // Write a test file in the partition
refreshDevice(); refreshDevice();
QVERIFY( m_device->partitionTable() ); QVERIFY( m_device->partitionTable() );
Partition* partition = m_device->partitionTable()->findPartitionBySector( oldFirst, PartitionRole( PartitionRole::Primary ) ); Partition* partition
= m_device->partitionTable()->findPartitionBySector( oldFirst, PartitionRole( PartitionRole::Primary ) );
QVERIFY( partition ); QVERIFY( partition );
QCOMPARE( partition->firstSector(), oldFirst ); QCOMPARE( partition->firstSector(), oldFirst );
QCOMPARE( partition->lastSector(), oldLast ); QCOMPARE( partition->lastSector(), oldLast );
@ -421,7 +431,8 @@ PartitionJobTests::testResizePartition()
{ {
refreshDevice(); refreshDevice();
QVERIFY( m_device->partitionTable() ); QVERIFY( m_device->partitionTable() );
Partition* partition = m_device->partitionTable()->findPartitionBySector( newFirst, PartitionRole( PartitionRole::Primary ) ); Partition* partition
= m_device->partitionTable()->findPartitionBySector( newFirst, PartitionRole( PartitionRole::Primary ) );
QVERIFY( partition ); QVERIFY( partition );
QCOMPARE( partition->firstSector(), newFirst ); QCOMPARE( partition->firstSector(), newFirst );
QCOMPARE( partition->lastSector(), newLast ); QCOMPARE( partition->lastSector(), newLast );

View File

@ -72,7 +72,8 @@ private:
QueueRunner m_runner; QueueRunner m_runner;
void queuePartitionTableCreation( PartitionTable::TableType type ); void queuePartitionTableCreation( PartitionTable::TableType type );
CreatePartitionJob* newCreatePartitionJob( Partition* freeSpacePartition, PartitionRole, FileSystem::Type type, qint64 size ); CreatePartitionJob*
newCreatePartitionJob( Partition* freeSpacePartition, PartitionRole, FileSystem::Type type, qint64 size );
void refreshDevice(); void refreshDevice();
}; };