package cloudmigration import ( "testing" "github.com/stretchr/testify/require" ) func TestResourceDependencyParse(t *testing.T) { t.Run("empty input returns an empty set", func(t *testing.T) { result, err := ResourceDependency.Parse(nil) require.NoError(t, err) require.Empty(t, result) }) t.Run("input with duplicates returns an error", func(t *testing.T) { _, err := ResourceDependency.Parse([]MigrateDataType{FolderDataType, FolderDataType}) require.ErrorIs(t, err, ErrDuplicateResourceType) }) t.Run("unknown resource type returns an error", func(t *testing.T) { _, err := ResourceDependency.Parse([]MigrateDataType{"does not exist"}) require.ErrorIs(t, err, ErrUnknownResourceType) }) t.Run("PluginDataType has no dependencies", func(t *testing.T) { result, err := ResourceDependency.Parse([]MigrateDataType{PluginDataType}) require.NoError(t, err) require.Len(t, result, 1) require.Contains(t, result, PluginDataType) }) t.Run("FolderDataType has no dependencies", func(t *testing.T) { result, err := ResourceDependency.Parse([]MigrateDataType{FolderDataType}) require.NoError(t, err) require.Len(t, result, 1) require.Contains(t, result, FolderDataType) }) t.Run("DatasourceDataType requires PluginDataType", func(t *testing.T) { t.Run("when the dependency is missing returns an error", func(t *testing.T) { _, err := ResourceDependency.Parse([]MigrateDataType{DatasourceDataType}) require.ErrorIs(t, err, ErrMissingDependency) require.Contains(t, err.Error(), string(PluginDataType)) }) t.Run("when the dependency is present returns the correct set", func(t *testing.T) { input := []MigrateDataType{DatasourceDataType, PluginDataType} result, err := ResourceDependency.Parse(input) require.NoError(t, err) require.Len(t, result, 2) }) }) t.Run("LibraryElementDataType requires FolderDataType", func(t *testing.T) { t.Run("when the dependency is missing returns an error", func(t *testing.T) { _, err := ResourceDependency.Parse([]MigrateDataType{LibraryElementDataType}) require.ErrorIs(t, err, ErrMissingDependency) require.Contains(t, err.Error(), string(FolderDataType)) }) t.Run("when the dependency is present returns the correct set", func(t *testing.T) { input := []MigrateDataType{LibraryElementDataType, FolderDataType} result, err := ResourceDependency.Parse(input) require.NoError(t, err) require.Len(t, result, 2) }) }) t.Run("DashboardDataType requires multiple dependencies", func(t *testing.T) { t.Run("when the dependency is missing returns an error", func(t *testing.T) { // Missing: FolderDataType, DatasourceDataType, LibraryElementDataType, PluginDataType _, err := ResourceDependency.Parse([]MigrateDataType{DashboardDataType}) require.ErrorIs(t, err, ErrMissingDependency) // Missing: DatasourceDataType, PluginDataType _, err = ResourceDependency.Parse([]MigrateDataType{ DashboardDataType, LibraryElementDataType, FolderDataType, }) require.ErrorIs(t, err, ErrMissingDependency) }) t.Run("when the dependency is present returns the correct set", func(t *testing.T) { input := []MigrateDataType{ DashboardDataType, FolderDataType, DatasourceDataType, LibraryElementDataType, PluginDataType, } result, err := ResourceDependency.Parse(input) require.NoError(t, err) require.Len(t, result, len(input)) }) }) t.Run("MuteTimingType has no dependencies", func(t *testing.T) { result, err := ResourceDependency.Parse([]MigrateDataType{MuteTimingType}) require.NoError(t, err) require.Len(t, result, 1) require.Contains(t, result, MuteTimingType) }) t.Run("NotificationTemplateType has no dependencies", func(t *testing.T) { result, err := ResourceDependency.Parse([]MigrateDataType{NotificationTemplateType}) require.NoError(t, err) require.Len(t, result, 1) require.Contains(t, result, NotificationTemplateType) }) t.Run("ContactPointType requires NotificationTemplateType", func(t *testing.T) { t.Run("when the dependency is missing returns an error", func(t *testing.T) { _, err := ResourceDependency.Parse([]MigrateDataType{ContactPointType}) require.ErrorIs(t, err, ErrMissingDependency) require.Contains(t, err.Error(), string(NotificationTemplateType)) }) t.Run("when the dependency is present returns the correct set", func(t *testing.T) { input := []MigrateDataType{ContactPointType, NotificationTemplateType} result, err := ResourceDependency.Parse(input) require.NoError(t, err) require.Len(t, result, 2) }) }) t.Run("NotificationPolicyType requires multiple dependencies", func(t *testing.T) { t.Run("when the dependency is missing returns an error", func(t *testing.T) { // Missing: ContactPointType, NotificationTemplateType _, err := ResourceDependency.Parse([]MigrateDataType{NotificationPolicyType}) require.ErrorIs(t, err, ErrMissingDependency) // Missing: NotificationTemplateType _, err = ResourceDependency.Parse([]MigrateDataType{ NotificationPolicyType, ContactPointType, }) require.ErrorIs(t, err, ErrMissingDependency) }) t.Run("when the dependency is present returns the correct set", func(t *testing.T) { input := []MigrateDataType{ NotificationPolicyType, ContactPointType, NotificationTemplateType, MuteTimingType, } result, err := ResourceDependency.Parse(input) require.NoError(t, err) require.Len(t, result, len(input)) }) }) t.Run("AlertRuleType requires multiple dependencies", func(t *testing.T) { t.Run("when the dependency is missing returns an error", func(t *testing.T) { // Missing all dependencies _, err := ResourceDependency.Parse([]MigrateDataType{AlertRuleType}) require.ErrorIs(t, err, ErrMissingDependency) // Missing some dependencies _, err = ResourceDependency.Parse([]MigrateDataType{ AlertRuleType, DatasourceDataType, FolderDataType, }) require.ErrorIs(t, err, ErrMissingDependency) }) t.Run("when the dependency is present returns the correct set", func(t *testing.T) { input := []MigrateDataType{ AlertRuleType, DatasourceDataType, FolderDataType, DashboardDataType, MuteTimingType, ContactPointType, NotificationPolicyType, PluginDataType, LibraryElementDataType, NotificationTemplateType, } result, err := ResourceDependency.Parse(input) require.NoError(t, err) require.Len(t, result, len(input)) }) }) t.Run("AlertRuleGroupType requires AlertRuleType and all its dependencies", func(t *testing.T) { t.Run("when the dependency is missing returns an error", func(t *testing.T) { // Missing all dependencies _, err := ResourceDependency.Parse([]MigrateDataType{AlertRuleGroupType}) require.ErrorIs(t, err, ErrMissingDependency) // With partial dependencies _, err = ResourceDependency.Parse([]MigrateDataType{ AlertRuleGroupType, AlertRuleType, FolderDataType, DashboardDataType, MuteTimingType, }) require.ErrorIs(t, err, ErrMissingDependency) }) t.Run("when the dependency is present returns the correct set", func(t *testing.T) { input := []MigrateDataType{ AlertRuleGroupType, AlertRuleType, DatasourceDataType, FolderDataType, DashboardDataType, MuteTimingType, ContactPointType, NotificationPolicyType, PluginDataType, LibraryElementDataType, NotificationTemplateType, } result, err := ResourceDependency.Parse(input) require.NoError(t, err) require.Len(t, result, len(input)) }) }) t.Run("multiple resources with shared dependencies", func(t *testing.T) { t.Run("resources with no dependencies", func(t *testing.T) { input := []MigrateDataType{ FolderDataType, PluginDataType, MuteTimingType, NotificationTemplateType, } result, err := ResourceDependency.Parse(input) require.NoError(t, err) require.Len(t, result, 4) }) t.Run("overlapping dependencies", func(t *testing.T) { // DashboardDataType -> LibraryElementDataType -> FolderDataType // \-> DatasourceDataType -> PluginDataType // ContactPointType -> NotificationTemplateType input := []MigrateDataType{ DashboardDataType, LibraryElementDataType, FolderDataType, DatasourceDataType, PluginDataType, ContactPointType, NotificationTemplateType, } result, err := ResourceDependency.Parse(input) require.NoError(t, err) require.Len(t, result, 7) }) t.Run("missing shared dependency fails", func(t *testing.T) { // ContactPointType -> NotificationTemplateType // DatasourceDataType -> PluginDataType input := []MigrateDataType{ ContactPointType, DatasourceDataType, } _, err := ResourceDependency.Parse(input) require.ErrorIs(t, err, ErrMissingDependency) }) }) }