refactor(folders): use set to detect circular references (#113665)
This commit is contained in:
@@ -891,6 +891,141 @@ func TestBuildFolderFullPaths(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildFolderFullPaths_CircularReference(t *testing.T) {
|
||||
type args struct {
|
||||
f *folder.Folder
|
||||
relations map[string]string
|
||||
folderMap map[string]*folder.Folder
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
name: "should detect direct circular reference (A -> B -> A)",
|
||||
args: args{
|
||||
f: &folder.Folder{
|
||||
Title: "FolderA",
|
||||
UID: "folder-a",
|
||||
ParentUID: "folder-b",
|
||||
},
|
||||
relations: map[string]string{
|
||||
"folder-a": "folder-b",
|
||||
"folder-b": "folder-a", // circular: B points back to A
|
||||
},
|
||||
folderMap: map[string]*folder.Folder{
|
||||
"folder-a": {
|
||||
Title: "FolderA",
|
||||
UID: "folder-a",
|
||||
ParentUID: "folder-b",
|
||||
},
|
||||
"folder-b": {
|
||||
Title: "FolderB",
|
||||
UID: "folder-b",
|
||||
ParentUID: "folder-a",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErr: "circular reference detected",
|
||||
},
|
||||
{
|
||||
name: "should detect self-reference (A -> A)",
|
||||
args: args{
|
||||
f: &folder.Folder{
|
||||
Title: "FolderA",
|
||||
UID: "folder-a",
|
||||
ParentUID: "folder-a", // points to itself
|
||||
},
|
||||
relations: map[string]string{
|
||||
"folder-a": "folder-a",
|
||||
},
|
||||
folderMap: map[string]*folder.Folder{
|
||||
"folder-a": {
|
||||
Title: "FolderA",
|
||||
UID: "folder-a",
|
||||
ParentUID: "folder-a",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErr: "circular reference detected",
|
||||
},
|
||||
{
|
||||
name: "should detect longer circular reference (A -> B -> C -> A)",
|
||||
args: args{
|
||||
f: &folder.Folder{
|
||||
Title: "FolderA",
|
||||
UID: "folder-a",
|
||||
ParentUID: "folder-b",
|
||||
},
|
||||
relations: map[string]string{
|
||||
"folder-a": "folder-b",
|
||||
"folder-b": "folder-c",
|
||||
"folder-c": "folder-a", // circular: C points back to A
|
||||
},
|
||||
folderMap: map[string]*folder.Folder{
|
||||
"folder-a": {
|
||||
Title: "FolderA",
|
||||
UID: "folder-a",
|
||||
ParentUID: "folder-b",
|
||||
},
|
||||
"folder-b": {
|
||||
Title: "FolderB",
|
||||
UID: "folder-b",
|
||||
ParentUID: "folder-c",
|
||||
},
|
||||
"folder-c": {
|
||||
Title: "FolderC",
|
||||
UID: "folder-c",
|
||||
ParentUID: "folder-a",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErr: "circular reference detected",
|
||||
},
|
||||
{
|
||||
name: "should detect circular reference starting from middle (B in A -> B -> C -> A)",
|
||||
args: args{
|
||||
f: &folder.Folder{
|
||||
Title: "FolderB",
|
||||
UID: "folder-b",
|
||||
ParentUID: "folder-c",
|
||||
},
|
||||
relations: map[string]string{
|
||||
"folder-a": "folder-b",
|
||||
"folder-b": "folder-c",
|
||||
"folder-c": "folder-a",
|
||||
},
|
||||
folderMap: map[string]*folder.Folder{
|
||||
"folder-a": {
|
||||
Title: "FolderA",
|
||||
UID: "folder-a",
|
||||
ParentUID: "folder-b",
|
||||
},
|
||||
"folder-b": {
|
||||
Title: "FolderB",
|
||||
UID: "folder-b",
|
||||
ParentUID: "folder-c",
|
||||
},
|
||||
"folder-c": {
|
||||
Title: "FolderC",
|
||||
UID: "folder-c",
|
||||
ParentUID: "folder-a",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErr: "circular reference detected",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := buildFolderFullPaths(tt.args.f, tt.args.relations, tt.args.folderMap)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tt.expectedErr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
|
||||
Reference in New Issue
Block a user