From d83d8ce57b8b39b4da849f5403198ecf706117ba Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Wed, 30 Aug 2023 15:45:44 +0200 Subject: [PATCH] [TESTS] verify facts for the admin storage documentation (squash) --- modules/setting/forgejo_storage_test.go | 272 ++++++++++++++++++++---- 1 file changed, 235 insertions(+), 37 deletions(-) diff --git a/modules/setting/forgejo_storage_test.go b/modules/setting/forgejo_storage_test.go index c24d340154..9071067cde 100644 --- a/modules/setting/forgejo_storage_test.go +++ b/modules/setting/forgejo_storage_test.go @@ -16,50 +16,248 @@ import ( "github.com/stretchr/testify/assert" ) -func testForgejoStoragePath(t *testing.T, appDataPath, iniStr string, loader func(rootCfg ConfigProvider) error, storagePtr **Storage, expectedPath string) { - cfg, err := NewConfigProviderFromData(iniStr) - assert.NoError(t, err) - AppDataPath = appDataPath - assert.NoError(t, loader(cfg)) - storage := *storagePtr - - assert.EqualValues(t, "local", storage.Type) - assert.True(t, filepath.IsAbs(storage.Path)) - assert.EqualValues(t, filepath.Clean(expectedPath), filepath.Clean(storage.Path)) +func TestForgejoDocs_StorageTypes(t *testing.T) { + iniStr := ` +[server] +APP_DATA_PATH = / +` + testStorageTypesDefaultAndSpecificStorage(t, iniStr) } -func TestForgejoDocs_StorageOverride(t *testing.T) { - for _, c := range []struct { - name string - basePath string - section string - loader func(rootCfg ConfigProvider) error - storage **Storage - }{ - {"Attachements", "attachments", "attachment", loadAttachmentFrom, &Attachment.Storage}, - {"LFS", "lfs", "lfs", loadLFSFrom, &LFS.Storage}, - {"Avatars", "avatars", "avatar", loadAvatarsFrom, &Avatar.Storage}, - {"Repository avatars", "repo-avatars", "repo-avatar", loadRepoAvatarFrom, &RepoAvatar.Storage}, - {"Repository archives", "repo-archive", "repo-archive", loadRepoArchiveFrom, &RepoArchive.Storage}, - {"Packages", "packages", "packages", loadPackagesFrom, &Packages.Storage}, - {"Actions logs", "actions_log", "storage.actions_log", loadActionsFrom, &Actions.LogStorage}, - {"Actions Artifacts", "actions_artifacts", "actions.artifacts", loadActionsFrom, &Actions.ArtifactStorage}, - } { - t.Run(c.name, func(t *testing.T) { - testForgejoStoragePath(t, "/appdata", "", c.loader, c.storage, fmt.Sprintf("/appdata/%s", c.basePath)) +func testStorageGetPath(storage *Storage) string { + if storage.Type == MinioStorageType { + return storage.MinioConfig.BasePath + } + return storage.Path +} - testForgejoStoragePath(t, "/appdata", ` +var testSectionToBasePath = map[string]string{ + "attachment": "attachments", + "lfs": "lfs", + "avatar": "avatars", + "repo-avatar": "repo-avatars", + "repo-archive": "repo-archive", + "packages": "packages", + "storage.actions_log": "actions_log", + "actions.artifacts": "actions_artifacts", +} + +type testSectionToPathFun func(StorageType, string) string + +func testBuildPath(t StorageType, path string) string { + if t == LocalStorageType { + return "/" + path + } + return path + "/" +} + +func testSectionToPath(t StorageType, section string) string { + return testBuildPath(t, testSectionToBasePath[section]) +} + +func testSpecificPath(t StorageType, section string) string { + if t == LocalStorageType { + return "/specific_local_path" + } + return "specific_s3_base_path/" +} + +func testDefaultDir(t StorageType) string { + if t == LocalStorageType { + return "default_local_path" + } + return "default_s3_base_path" +} + +func testDefaultPath(t StorageType) string { + return testBuildPath(t, testDefaultDir(t)) +} + +func testSectionToDefaultPath(t StorageType, section string) string { + return testBuildPath(t, filepath.Join(testDefaultDir(t), testSectionToPath(t, section))) +} + +func testLegacyPath(t StorageType, section string) string { + return testBuildPath(t, fmt.Sprintf("legacy_%s_path", section)) +} + +func testStorageTypeToSetting(t StorageType) string { + if t == LocalStorageType { + return "PATH" + } + return "MINIO_BASE_PATH" +} + +var testSectionToLegacy = map[string]string{ + "lfs": fmt.Sprintf(` +[server] +APP_DATA_PATH = / +LFS_CONTENT_PATH = %s +`, testLegacyPath(LocalStorageType, "lfs")), + "avatar": fmt.Sprintf(` +[picture] +AVATAR_UPLOAD_PATH = %s +`, testLegacyPath(LocalStorageType, "avatar")), + "repo-avatar": fmt.Sprintf(` +[picture] +REPOSITORY_AVATAR_UPLOAD_PATH = %s +`, testLegacyPath(LocalStorageType, "repo-avatar")), +} + +func testStorageTypesDefaultAndSpecificStorage(t *testing.T, iniStr string) { + storageType := MinioStorageType + t.Run(string(storageType), func(t *testing.T) { + t.Run("override type minio", func(t *testing.T) { + storageSection := ` +[storage] +STORAGE_TYPE = minio +` + testStorageTypesSpecificStorages(t, iniStr+storageSection, storageType, testSectionToPath, testSectionToPath) + }) + }) + + storageType = LocalStorageType + + t.Run(string(storageType), func(t *testing.T) { + storageSection := "" + testStorageTypesSpecificStorages(t, iniStr+storageSection, storageType, testSectionToPath, testSectionToPath) + + t.Run("override type local", func(t *testing.T) { + storageSection := ` [storage] STORAGE_TYPE = local -PATH = /storagepath -`, c.loader, c.storage, fmt.Sprintf("/storagepath/%s", c.basePath)) +` + testStorageTypesSpecificStorages(t, iniStr+storageSection, storageType, testSectionToPath, testSectionToPath) - section := fmt.Sprintf(` -[%s] + storageSection = fmt.Sprintf(` +[storage] STORAGE_TYPE = local -PATH = /sectionpath -`, c.section) - testForgejoStoragePath(t, "/appdata", section, c.loader, c.storage, "/sectionpath") +PATH = %s +`, testDefaultPath(LocalStorageType)) + testStorageTypesSpecificStorageSections(t, iniStr+storageSection, storageType, testSectionToDefaultPath, testSectionToPath) + }) + }) +} + +func testStorageTypesSpecificStorageSections(t *testing.T, iniStr string, defaultStorageType StorageType, defaultStorageTypePath, testSectionToPath testSectionToPathFun) { + testSectionsMap := map[string]**Storage{ + "attachment": &Attachment.Storage, + "lfs": &LFS.Storage, + "avatar": &Avatar.Storage, + "repo-avatar": &RepoAvatar.Storage, + "repo-archive": &RepoArchive.Storage, + "packages": &Packages.Storage, + // there are inconsistencies in how actions storage is determined in v1.20 + // it is still alpha and undocumented and is ignored for now + //"storage.actions_log": &Actions.LogStorage, + //"actions.artifacts": &Actions.ArtifactStorage, + } + + for sectionName, storage := range testSectionsMap { + t.Run(sectionName, func(t *testing.T) { + testStorageTypesSpecificStorage(t, iniStr, defaultStorageType, defaultStorageTypePath, testSectionToPath, sectionName, storage) }) } } + +func testStorageTypesSpecificStorages(t *testing.T, iniStr string, defaultStorageType StorageType, defaultStorageTypePath, testSectionToPath testSectionToPathFun) { + testSectionsMap := map[string]**Storage{ + "attachment": &Attachment.Storage, + "lfs": &LFS.Storage, + "avatar": &Avatar.Storage, + "repo-avatar": &RepoAvatar.Storage, + "repo-archive": &RepoArchive.Storage, + "packages": &Packages.Storage, + "storage.actions_log": &Actions.LogStorage, + "actions.artifacts": &Actions.ArtifactStorage, + } + + for sectionName, storage := range testSectionsMap { + t.Run(sectionName, func(t *testing.T) { + if legacy, ok := testSectionToLegacy[sectionName]; ok { + if defaultStorageType == LocalStorageType { + t.Run("legacy local", func(t *testing.T) { + testStorageTypesSpecificStorage(t, iniStr+legacy, LocalStorageType, testLegacyPath, testSectionToPath, sectionName, storage) + testStorageTypesSpecificStorageTypeOverride(t, iniStr+legacy, LocalStorageType, testLegacyPath, testSectionToPath, sectionName, storage) + }) + } else { + t.Run("legacy minio", func(t *testing.T) { + testStorageTypesSpecificStorage(t, iniStr+legacy, MinioStorageType, defaultStorageTypePath, testSectionToPath, sectionName, storage) + testStorageTypesSpecificStorageTypeOverride(t, iniStr+legacy, LocalStorageType, testLegacyPath, testSectionToPath, sectionName, storage) + }) + } + } + for _, specificStorageType := range storageTypes { + testStorageTypesSpecificStorageTypeOverride(t, iniStr, specificStorageType, defaultStorageTypePath, testSectionToPath, sectionName, storage) + } + }) + } +} + +func testStorageTypesSpecificStorage(t *testing.T, iniStr string, defaultStorageType StorageType, defaultStorageTypePath, testSectionToPath testSectionToPathFun, sectionName string, storage **Storage) { + var section string + + // + // Specific section is absent + // + testStoragePathMatch(t, iniStr, defaultStorageType, defaultStorageTypePath, sectionName, storage) + + // + // Specific section is empty + // + section = fmt.Sprintf(` +[%s] +`, + sectionName) + testStoragePathMatch(t, iniStr+section, defaultStorageType, defaultStorageTypePath, sectionName, storage) + + // + // Specific section with a path override + // + section = fmt.Sprintf(` +[%s] +%s = %s +`, + sectionName, + testStorageTypeToSetting(defaultStorageType), + testSpecificPath(defaultStorageType, "")) + testStoragePathMatch(t, iniStr+section, defaultStorageType, testSpecificPath, sectionName, storage) +} + +func testStorageTypesSpecificStorageTypeOverride(t *testing.T, iniStr string, overrideStorageType StorageType, defaultStorageTypePath, testSectionToPath testSectionToPathFun, sectionName string, storage **Storage) { + var section string + t.Run("specific-"+string(overrideStorageType), func(t *testing.T) { + // + // Specific section with a path and storage type override + // + section = fmt.Sprintf(` +[%s] +STORAGE_TYPE = %s +%s = %s +`, + sectionName, + overrideStorageType, + testStorageTypeToSetting(overrideStorageType), + testSpecificPath(overrideStorageType, "")) + testStoragePathMatch(t, iniStr+section, overrideStorageType, testSpecificPath, sectionName, storage) + + // + // Specific section with type override + // + section = fmt.Sprintf(` +[%s] +STORAGE_TYPE = %s +`, + sectionName, + overrideStorageType) + testStoragePathMatch(t, iniStr+section, overrideStorageType, defaultStorageTypePath, sectionName, storage) + }) +} + +func testStoragePathMatch(t *testing.T, iniStr string, storageType StorageType, testSectionToPath testSectionToPathFun, section string, storage **Storage) { + cfg, err := NewConfigProviderFromData(iniStr) + assert.NoError(t, err, iniStr) + assert.NoError(t, loadCommonSettingsFrom(cfg), iniStr) + assert.EqualValues(t, testSectionToPath(storageType, section), testStorageGetPath(*storage), iniStr) + assert.EqualValues(t, storageType, (*storage).Type, iniStr) +}