package shared_test import ( "context" "fmt" "path/filepath" "testing" "github.com/woodpecker-ci/woodpecker/server/model" "github.com/woodpecker-ci/woodpecker/server/remote" "github.com/woodpecker-ci/woodpecker/server/remote/mocks" "github.com/woodpecker-ci/woodpecker/server/shared" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) func TestFetch(t *testing.T) { t.Parallel() type file struct { name string data []byte } dummyData := []byte("TEST") testTable := []struct { name string repoConfig string files []file expectedFileNames []string expectedError bool }{ { name: "Default config - .woodpecker/", repoConfig: "", files: []file{{ name: ".woodpecker/text.txt", data: dummyData, }, { name: ".woodpecker/release.yml", data: dummyData, }, { name: ".woodpecker/image.png", data: dummyData, }}, expectedFileNames: []string{ ".woodpecker/release.yml", }, expectedError: false, }, { name: "Default config - .woodpecker.yml", repoConfig: "", files: []file{{ name: ".woodpecker.yml", data: dummyData, }}, expectedFileNames: []string{ ".woodpecker.yml", }, expectedError: false, }, { name: "Default config - .drone.yml", repoConfig: "", files: []file{{ name: ".drone.yml", data: dummyData, }}, expectedFileNames: []string{ ".drone.yml", }, expectedError: false, }, { name: "Default config - Empty repo", repoConfig: "", files: []file{}, expectedFileNames: []string{}, expectedError: true, }, { name: "Default config - Additional sub-folders", repoConfig: "", files: []file{{ name: ".woodpecker/test.yml", data: dummyData, }, { name: ".woodpecker/sub-folder/config.yml", data: dummyData, }}, expectedFileNames: []string{ ".woodpecker/test.yml", }, expectedError: false, }, { name: "Default config - Additional none .yml files", repoConfig: "", files: []file{{ name: ".woodpecker/notes.txt", data: dummyData, }, { name: ".woodpecker/image.png", data: dummyData, }, { name: ".woodpecker/test.yml", data: dummyData, }}, expectedFileNames: []string{ ".woodpecker/test.yml", }, expectedError: false, }, { name: "Default config - Empty Folder", repoConfig: " ", files: []file{{ name: ".woodpecker/.keep", data: dummyData, }, { name: ".woodpecker.yml", data: nil, }, { name: ".drone.yml", data: dummyData, }}, expectedFileNames: []string{ ".drone.yml", }, expectedError: false, }, { name: "Special config - folder (ignoring default files)", repoConfig: ".my-ci-folder/", files: []file{{ name: ".woodpecker/test.yml", data: dummyData, }, { name: ".woodpecker.yml", data: dummyData, }, { name: ".drone.yml", data: dummyData, }, { name: ".my-ci-folder/test.yml", data: dummyData, }}, expectedFileNames: []string{ ".my-ci-folder/test.yml", }, expectedError: false, }, { name: "Special config - folder", repoConfig: ".my-ci-folder/", files: []file{{ name: ".my-ci-folder/test.yml", data: dummyData, }}, expectedFileNames: []string{ ".my-ci-folder/test.yml", }, expectedError: false, }, { name: "Special config - subfolder", repoConfig: ".my-ci-folder/my-config/", files: []file{{ name: ".my-ci-folder/my-config/test.yml", data: dummyData, }}, expectedFileNames: []string{ ".my-ci-folder/my-config/test.yml", }, expectedError: false, }, { name: "Special config - file", repoConfig: ".config.yml", files: []file{{ name: ".config.yml", data: dummyData, }}, expectedFileNames: []string{ ".config.yml", }, expectedError: false, }, { name: "Special config - file inside subfolder", repoConfig: ".my-ci-folder/sub-folder/config.yml", files: []file{{ name: ".my-ci-folder/sub-folder/config.yml", data: dummyData, }}, expectedFileNames: []string{ ".my-ci-folder/sub-folder/config.yml", }, expectedError: false, }, { name: "Special config - empty repo", repoConfig: ".config.yml", files: []file{}, expectedFileNames: []string{}, expectedError: true, }, } for _, tt := range testTable { t.Run(tt.name, func(t *testing.T) { repo := &model.Repo{Owner: "laszlocph", Name: "drone-multipipeline", Config: tt.repoConfig} r := new(mocks.Remote) dirs := map[string][]*remote.FileMeta{} for _, file := range tt.files { r.On("File", mock.Anything, mock.Anything, mock.Anything, mock.Anything, file.name).Return(file.data, nil) path := filepath.Dir(file.name) if path != "." { dirs[path] = append(dirs[path], &remote.FileMeta{ Name: file.name, Data: file.data, }) } } for path, files := range dirs { r.On("Dir", mock.Anything, mock.Anything, mock.Anything, mock.Anything, path).Return(files, nil) } // if the previous mocks do not match return not found errors r.On("File", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("File not found")) r.On("Dir", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("Directory not found")) configFetcher := shared.NewConfigFetcher( r, &model.User{Token: "xxx"}, repo, &model.Build{Commit: "89ab7b2d6bfb347144ac7c557e638ab402848fee"}, ) files, err := configFetcher.Fetch(context.Background()) if tt.expectedError && err == nil { t.Fatal("expected an error") } else if !tt.expectedError && err != nil { t.Fatal("error fetching config:", err) } matchingFiles := make([]string, len(files)) for i := range files { matchingFiles[i] = files[i].Name } assert.ElementsMatch(t, tt.expectedFileNames, matchingFiles, "expected some other pipeline files") }) } }