mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-07 10:33:24 -08:00
Merge branch 'master' into tooomm-qt5
This commit is contained in:
commit
94b85b8940
266 changed files with 11392 additions and 930 deletions
|
|
@ -306,6 +306,12 @@ TEST_F(SettingsDefaultsTest, Chat_IgnoreAllPrivateMessages_Default)
|
|||
ASSERT_EQ(s.getIgnoreAllPrivateMessages(), false);
|
||||
}
|
||||
|
||||
TEST_F(SettingsDefaultsTest, Chat_UseGameTime_Default)
|
||||
{
|
||||
ChatSettings s(settingsPath, nullptr);
|
||||
ASSERT_EQ(s.getUseGameTime(), false);
|
||||
}
|
||||
|
||||
// --- PersonalSettings ---
|
||||
|
||||
TEST_F(SettingsDefaultsTest, Personal_Lang_Default)
|
||||
|
|
@ -334,6 +340,38 @@ TEST_F(SettingsDefaultsTest, Download_DownloadSpoilersStatus_Default)
|
|||
ASSERT_EQ(s.getDownloadSpoilersStatus(), false);
|
||||
}
|
||||
|
||||
TEST_F(SettingsDefaultsTest, Download_HostRequestLimits_Default)
|
||||
{
|
||||
DownloadSettings s(settingsPath, nullptr);
|
||||
ASSERT_TRUE(s.getHostRequestLimits().isEmpty());
|
||||
}
|
||||
|
||||
TEST_F(SettingsDefaultsTest, Download_HostRequestLimits_SetAndGet)
|
||||
{
|
||||
DownloadSettings s(settingsPath, nullptr);
|
||||
s.setHostRequestLimits({{"api.scryfall.com", 5}});
|
||||
const QHash<QString, int> limits = s.getHostRequestLimits();
|
||||
ASSERT_EQ(limits.size(), 1);
|
||||
ASSERT_EQ(limits.value("api.scryfall.com"), 5);
|
||||
}
|
||||
|
||||
TEST_F(SettingsDefaultsTest, Download_HostRequestLimits_StackedHostCaps)
|
||||
{
|
||||
DownloadSettings s(settingsPath, nullptr);
|
||||
// The developer cap for the Scryfall API lowers the ceiling to 9; a user can
|
||||
// reduce it further but can never raise it above the cap.
|
||||
ASSERT_EQ(s.clampHostRequestLimit("api.scryfall.com", 9), 9);
|
||||
ASSERT_EQ(s.clampHostRequestLimit("api.scryfall.com", 20), 9);
|
||||
ASSERT_EQ(s.clampHostRequestLimit("api.scryfall.com", 5), 5);
|
||||
ASSERT_EQ(s.clampHostRequestLimit("api.scryfall.com", 0), 1);
|
||||
// Hosts without a developer cap fall back to the global default ceiling.
|
||||
ASSERT_EQ(s.clampHostRequestLimit("gatherer.wizards.com", 10), 10);
|
||||
ASSERT_EQ(s.clampHostRequestLimit("gatherer.wizards.com", 20), 10);
|
||||
// The Scryfall CDN is unlocked: no upper bound (values are only floored).
|
||||
ASSERT_EQ(s.clampHostRequestLimit("cards.scryfall.io", 20), 20);
|
||||
ASSERT_EQ(s.clampHostRequestLimit("cards.scryfall.io", 0), 1);
|
||||
}
|
||||
|
||||
// --- AppearanceSettings ---
|
||||
|
||||
TEST_F(SettingsDefaultsTest, Appearance_ThemeName_Default)
|
||||
|
|
@ -538,6 +576,21 @@ TEST_F(SettingsDefaultsTest, CardsDisplay_VisualDeckEditorCardSize_Default)
|
|||
ASSERT_EQ(s.getVisualDeckEditorCardSize(), 100);
|
||||
}
|
||||
|
||||
TEST_F(SettingsDefaultsTest, CardsDisplay_VisualDeckEditorShowCardCounts_Default)
|
||||
{
|
||||
CardsDisplaySettings s(settingsPath, nullptr);
|
||||
ASSERT_EQ(s.getVisualDeckEditorShowCardCounts(), true);
|
||||
}
|
||||
|
||||
TEST_F(SettingsDefaultsTest, CardsDisplay_VisualDeckEditorShowCardCounts_SetAndGet)
|
||||
{
|
||||
CardsDisplaySettings s(settingsPath, nullptr);
|
||||
s.setVisualDeckEditorShowCardCounts(false);
|
||||
ASSERT_EQ(s.getVisualDeckEditorShowCardCounts(), false);
|
||||
s.setVisualDeckEditorShowCardCounts(true);
|
||||
ASSERT_EQ(s.getVisualDeckEditorShowCardCounts(), true);
|
||||
}
|
||||
|
||||
TEST_F(SettingsDefaultsTest, CardsDisplay_EDHRecCardSize_Default)
|
||||
{
|
||||
CardsDisplaySettings s(settingsPath, nullptr);
|
||||
|
|
@ -575,6 +628,19 @@ TEST_F(SettingsDefaultsTest, CardsDisplay_CardLang_SetAndGet)
|
|||
ASSERT_EQ(s.getCardLang(), QString("de"));
|
||||
}
|
||||
|
||||
TEST_F(SettingsDefaultsTest, CardsDisplay_CardSearchLanguage_Default)
|
||||
{
|
||||
CardsDisplaySettings s(settingsPath, nullptr);
|
||||
ASSERT_EQ(s.getCardSearchLanguage(), static_cast<int>(SearchLanguageMode::English));
|
||||
}
|
||||
|
||||
TEST_F(SettingsDefaultsTest, CardsDisplay_CardSearchLanguage_SetAndGet)
|
||||
{
|
||||
CardsDisplaySettings s(settingsPath, nullptr);
|
||||
s.setCardSearchLanguage(static_cast<int>(SearchLanguageMode::Selected));
|
||||
ASSERT_EQ(s.getCardSearchLanguage(), static_cast<int>(SearchLanguageMode::Selected));
|
||||
}
|
||||
|
||||
// --- VisualDeckStorageSettings ---
|
||||
|
||||
TEST_F(SettingsDefaultsTest, VisualDeckStorage_SortingOrder_Default)
|
||||
|
|
@ -603,6 +669,19 @@ TEST_F(SettingsDefaultsTest, VisualDeckStorage_DefaultTagsList_SetAndGet)
|
|||
ASSERT_EQ(s.getVisualDeckStorageDefaultTagsList(), custom);
|
||||
}
|
||||
|
||||
TEST_F(SettingsDefaultsTest, VisualDeckStorage_ShowUploadTime_Default)
|
||||
{
|
||||
VisualDeckStorageSettings s(settingsPath, nullptr);
|
||||
ASSERT_EQ(s.getVisualDeckStorageShowUploadTime(), true);
|
||||
}
|
||||
|
||||
TEST_F(SettingsDefaultsTest, VisualDeckStorage_ShowUploadTime_SetAndGet)
|
||||
{
|
||||
VisualDeckStorageSettings s(settingsPath, nullptr);
|
||||
s.setVisualDeckStorageShowUploadTime(false);
|
||||
ASSERT_EQ(s.getVisualDeckStorageShowUploadTime(), false);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,11 @@ protected:
|
|||
|
||||
void SetUp() override
|
||||
{
|
||||
settingsPath = tempDir.path() + "/";
|
||||
// Mirror the production layout: the settings folder lives inside the data folder, so
|
||||
// migration backups (siblings of settings/) stay isolated inside tempDir instead of
|
||||
// landing in the shared system temp directory.
|
||||
settingsPath = tempDir.path() + "/settings/";
|
||||
QDir().mkpath(settingsPath);
|
||||
|
||||
// Isolate the settings used by the legacy migration tests inside the temporary
|
||||
// directory so the tests never read or write the real user config (registry on
|
||||
|
|
@ -64,6 +68,25 @@ protected:
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// The migration backups are timestamped, so tests address them by index rather than by name.
|
||||
QStringList backupFolderNames() const
|
||||
{
|
||||
return QDir(tempDir.path())
|
||||
.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name)
|
||||
.filter(QStringLiteral("settings-backup-"));
|
||||
}
|
||||
|
||||
QVariant readFromBackup(const QString &folderName, const QString &fileName, const QString &key) const
|
||||
{
|
||||
QSettings ini(QDir::cleanPath(tempDir.path() + '/' + folderName + '/' + fileName), QSettings::IniFormat);
|
||||
return ini.value(key);
|
||||
}
|
||||
|
||||
bool backupFileExists(const QString &folderName, const QString &fileName) const
|
||||
{
|
||||
return QFile::exists(QDir::cleanPath(tempDir.path() + '/' + folderName + '/' + fileName));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(SettingsMigrationTest, NoGlobalIniDoesNothing)
|
||||
|
|
@ -542,6 +565,34 @@ TEST_F(SettingsMigrationTest, PartialMigrationOnlyMigratesPresentKeys)
|
|||
ASSERT_FALSE(fileExists("chat.ini"));
|
||||
}
|
||||
|
||||
TEST_F(SettingsMigrationTest, ThemeNameDefaultIsRewrittenToSystem)
|
||||
{
|
||||
{
|
||||
QSettings g(settingsPath + "global.ini", QSettings::IniFormat);
|
||||
g.setValue("theme/name", "Default");
|
||||
g.sync();
|
||||
}
|
||||
|
||||
ASSERT_TRUE(SettingsMigration::migrateSettingsFromGlobalIni(settingsPath));
|
||||
|
||||
ASSERT_TRUE(fileExists("appearance.ini"));
|
||||
ASSERT_EQ(readFromIni("appearance.ini", "appearance/themeName"), QVariant("System"));
|
||||
}
|
||||
|
||||
TEST_F(SettingsMigrationTest, OtherThemeNamesAreLeftAlone)
|
||||
{
|
||||
{
|
||||
QSettings g(settingsPath + "global.ini", QSettings::IniFormat);
|
||||
g.setValue("theme/name", "VelvetMarble");
|
||||
g.sync();
|
||||
}
|
||||
|
||||
ASSERT_TRUE(SettingsMigration::migrateSettingsFromGlobalIni(settingsPath));
|
||||
|
||||
ASSERT_TRUE(fileExists("appearance.ini"));
|
||||
ASSERT_EQ(readFromIni("appearance.ini", "appearance/themeName"), QVariant("VelvetMarble"));
|
||||
}
|
||||
|
||||
TEST_F(SettingsMigrationTest, KeyMapTranslationIsCorrect)
|
||||
{
|
||||
{
|
||||
|
|
@ -697,6 +748,168 @@ TEST_F(SettingsMigrationTest, RenameFailureWithExistingBackup)
|
|||
ASSERT_FALSE(SettingsMigration::migrateSettingsFromGlobalIni(settingsPath));
|
||||
}
|
||||
|
||||
// --- pre-migration backup of the settings folder ---
|
||||
|
||||
TEST_F(SettingsMigrationTest, BackupHoldsPreMigrationStateOfPerDomainFiles)
|
||||
{
|
||||
// A user already migrated once, changed a setting, then ran an older build that wrote to
|
||||
// global.ini again. Re-migrating clobbers the per-domain file, so the backup has to hold the
|
||||
// pre-migration value.
|
||||
{
|
||||
QSettings tabs(settingsPath + "tabs.ini", QSettings::IniFormat);
|
||||
tabs.setValue("tabs/visualDeckStorage", false);
|
||||
tabs.sync();
|
||||
}
|
||||
{
|
||||
QSettings g(settingsPath + "global.ini", QSettings::IniFormat);
|
||||
g.setValue("tabs/visualDeckStorage", true);
|
||||
g.sync();
|
||||
}
|
||||
|
||||
const QString backupPath = SettingsMigration::backupSettingsDirectory(settingsPath);
|
||||
ASSERT_FALSE(backupPath.isEmpty());
|
||||
ASSERT_TRUE(SettingsMigration::migrateSettingsFromGlobalIni(settingsPath));
|
||||
|
||||
// The migration overwrote the user's change ...
|
||||
ASSERT_EQ(readFromIni("tabs.ini", "tabs/visualDeckStorage"), QVariant(true));
|
||||
|
||||
// ... but the backup still holds it, so it can be restored by hand.
|
||||
const QStringList backups = backupFolderNames();
|
||||
ASSERT_EQ(backups.size(), 1);
|
||||
ASSERT_EQ(readFromBackup(backups.at(0), "tabs.ini", "tabs/visualDeckStorage"), QVariant(false));
|
||||
ASSERT_EQ(readFromBackup(backups.at(0), "global.ini", "tabs/visualDeckStorage"), QVariant(true));
|
||||
}
|
||||
|
||||
TEST_F(SettingsMigrationTest, BackupIsASiblingOfTheSettingsFolder)
|
||||
{
|
||||
{
|
||||
QSettings g(settingsPath + "global.ini", QSettings::IniFormat);
|
||||
g.setValue("sound/enabled", true);
|
||||
g.sync();
|
||||
}
|
||||
|
||||
const QString backupPath = SettingsMigration::backupSettingsDirectory(settingsPath);
|
||||
ASSERT_FALSE(backupPath.isEmpty());
|
||||
|
||||
const QDir backupDir(backupPath);
|
||||
ASSERT_TRUE(backupDir.dirName().startsWith("settings-backup-"));
|
||||
// Same parent as the settings folder, and not inside it, so a backup is never copied into
|
||||
// another backup and "Open settings folder" shows only live files.
|
||||
ASSERT_EQ(QDir::cleanPath(backupDir.absolutePath() + "/.."), QDir::cleanPath(tempDir.path()));
|
||||
ASSERT_FALSE(backupDir.absolutePath().startsWith(QDir::cleanPath(settingsPath) + '/'));
|
||||
ASSERT_TRUE(backupFileExists(backupDir.dirName(), "global.ini"));
|
||||
}
|
||||
|
||||
TEST_F(SettingsMigrationTest, BackupCopiesNestedFolders)
|
||||
{
|
||||
ASSERT_TRUE(QDir().mkpath(settingsPath + "nested"));
|
||||
{
|
||||
QFile f(settingsPath + "nested/deep.ini");
|
||||
ASSERT_TRUE(f.open(QIODevice::WriteOnly));
|
||||
f.write("[visualDeckStorage]\nfirstDeck=1234\n");
|
||||
}
|
||||
{
|
||||
QSettings g(settingsPath + "global.ini", QSettings::IniFormat);
|
||||
g.setValue("sound/enabled", true);
|
||||
g.sync();
|
||||
}
|
||||
|
||||
const QString backupPath = SettingsMigration::backupSettingsDirectory(settingsPath);
|
||||
ASSERT_FALSE(backupPath.isEmpty());
|
||||
|
||||
const QStringList backups = backupFolderNames();
|
||||
ASSERT_EQ(backups.size(), 1);
|
||||
ASSERT_TRUE(backupFileExists(backups.at(0), "nested/deep.ini"));
|
||||
ASSERT_EQ(readFromBackup(backups.at(0), "nested/deep.ini", "visualDeckStorage/firstDeck"), QVariant("1234"));
|
||||
}
|
||||
|
||||
TEST_F(SettingsMigrationTest, NoBackupWhenSettingsFolderIsEmpty)
|
||||
{
|
||||
ASSERT_TRUE(SettingsMigration::backupSettingsDirectory(settingsPath).isEmpty());
|
||||
ASSERT_TRUE(backupFolderNames().isEmpty());
|
||||
}
|
||||
|
||||
TEST_F(SettingsMigrationTest, NoBackupWhenEverySettingsFileIsEmpty)
|
||||
{
|
||||
// A fresh profile: QSettings has created global.ini, but it holds nothing worth preserving.
|
||||
{
|
||||
QFile f(settingsPath + "global.ini");
|
||||
ASSERT_TRUE(f.open(QIODevice::WriteOnly));
|
||||
f.close();
|
||||
}
|
||||
|
||||
ASSERT_TRUE(SettingsMigration::backupSettingsDirectory(settingsPath).isEmpty());
|
||||
ASSERT_TRUE(backupFolderNames().isEmpty());
|
||||
}
|
||||
|
||||
TEST_F(SettingsMigrationTest, BackupFailsGracefullyOnMissingSettingsFolder)
|
||||
{
|
||||
ASSERT_TRUE(SettingsMigration::backupSettingsDirectory(tempDir.path() + "/does-not-exist/").isEmpty());
|
||||
}
|
||||
|
||||
TEST_F(SettingsMigrationTest, BackupKeepsEveryPreviousSnapshot)
|
||||
{
|
||||
{
|
||||
QSettings g(settingsPath + "global.ini", QSettings::IniFormat);
|
||||
g.setValue("sound/enabled", true);
|
||||
g.sync();
|
||||
}
|
||||
|
||||
ASSERT_FALSE(SettingsMigration::backupSettingsDirectory(settingsPath).isEmpty());
|
||||
ASSERT_FALSE(SettingsMigration::backupSettingsDirectory(settingsPath).isEmpty());
|
||||
|
||||
// A second snapshot in the same second must not merge into the first one.
|
||||
const QStringList backups = backupFolderNames();
|
||||
ASSERT_EQ(backups.size(), 2);
|
||||
ASSERT_NE(backups.at(0), backups.at(1));
|
||||
}
|
||||
|
||||
TEST_F(SettingsMigrationTest, IsMigrationPendingWhenGlobalIniHasKeys)
|
||||
{
|
||||
{
|
||||
QSettings g(settingsPath + "global.ini", QSettings::IniFormat);
|
||||
g.setValue("sound/enabled", true);
|
||||
g.sync();
|
||||
}
|
||||
|
||||
ASSERT_TRUE(SettingsMigration::isMigrationPending(settingsPath));
|
||||
}
|
||||
|
||||
TEST_F(SettingsMigrationTest, IsNotMigrationPendingAfterSentinelIsSet)
|
||||
{
|
||||
{
|
||||
QSettings g(settingsPath + "global.ini", QSettings::IniFormat);
|
||||
g.setValue("sound/enabled", true);
|
||||
g.sync();
|
||||
}
|
||||
ASSERT_TRUE(SettingsMigration::migrateSettingsFromGlobalIni(settingsPath));
|
||||
|
||||
// The sentinel-only global.ini and the legacy sentinel leave nothing to migrate.
|
||||
{
|
||||
QSettings personal(settingsPath + "personal.ini", QSettings::IniFormat);
|
||||
personal.setValue("migration/legacy_complete", true);
|
||||
personal.sync();
|
||||
}
|
||||
ASSERT_FALSE(SettingsMigration::isMigrationPending(settingsPath));
|
||||
}
|
||||
|
||||
TEST_F(SettingsMigrationTest, IsMigrationPendingWhenOnlyLegacySettingsRemain)
|
||||
{
|
||||
QSettings().setValue("server/host", "example.com");
|
||||
QSettings().sync();
|
||||
|
||||
ASSERT_TRUE(SettingsMigration::isMigrationPending(settingsPath));
|
||||
}
|
||||
|
||||
TEST_F(SettingsMigrationTest, IsNotMigrationPendingWithoutLegacyData)
|
||||
{
|
||||
// Nothing to migrate: a fresh profile must not leave a backup folder behind on every start.
|
||||
QSettings().clear();
|
||||
QSettings().sync();
|
||||
|
||||
ASSERT_FALSE(SettingsMigration::isMigrationPending(settingsPath));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue