Files
plugin-drone-nexus/plugin/plugin_test.go
T
Ompragash Viswanathan 96190838fd fix
2025-10-07 18:42:49 +05:30

608 lines
17 KiB
Go

package plugin
import (
"io/ioutil"
"net/http"
"os"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
type MockHttpClient struct {
mock.Mock
}
func (m *MockHttpClient) Do(req *http.Request) (*http.Response, error) {
args := m.Called(req)
return args.Get(0).(*http.Response), args.Error(1)
}
// Utility function to create a temporary file for testing
func createTempFile(content string) (string, error) {
tmpFile, err := ioutil.TempFile("", "testfile_*.zip")
if err != nil {
return "", err
}
if _, err := tmpFile.Write([]byte(content)); err != nil {
tmpFile.Close()
return "", err
}
if err := tmpFile.Close(); err != nil {
return "", err
}
return tmpFile.Name(), nil
}
func TestNexusPlugin_Run_UploadFailed(t *testing.T) {
mockClient := new(MockHttpClient)
mockResp := &http.Response{
StatusCode: 500,
Body: ioutil.NopCloser(strings.NewReader("Internal Server Error")),
}
mockClient.On("Do", mock.AnythingOfType("*http.Request")).Return(mockResp, nil)
tmpFile, err := createTempFile("testfile.zip")
assert.NoError(t, err)
defer os.Remove(tmpFile)
plugin := NexusPlugin{
PluginProcessingInfo: PluginProcessingInfo{
UserName: "testUser",
Password: "testPass",
ServerUrl: "https://nexus.example.com",
Repository: "repo",
GroupId: "group",
Version: "nexus3",
Format: "maven2",
Artifacts: []Artifact{
{
File: tmpFile,
ArtifactId: "artifact123",
Type: "zip",
Version: "1",
},
},
},
HttpClient: mockClient,
}
err = plugin.Run()
assert.NotNil(t, err)
assert.Len(t, plugin.Failed, 1)
assert.Equal(t, tmpFile, plugin.Failed[0].File)
assert.Equal(t, "artifact123", plugin.Failed[0].ArtifactId)
assert.Contains(t, plugin.Failed[0].Err, "upload failed")
mockClient.AssertExpectations(t)
}
// The following tests validate argument processing without needing an actual file
func TestNexusPlugin_ValidateAndProcessArgs_MultiFileUpload_Success(t *testing.T) {
args := Args{
EnvPluginInputArgs: EnvPluginInputArgs{
Username: "testUser",
Password: "testPass",
Protocol: "https",
ServerUrl: "nexus.example.com",
NexusVersion: "3",
Repository: "repo",
GroupId: "group",
Format: "maven2",
Artifact: "[{ \"artifactId\": \"artifact123\", \"file\": \"testfile.zip\", \"type\": \"zip\", \"version\": \"1\" }]",
},
}
plugin := NexusPlugin{}
err := plugin.ValidateAndProcessArgs(args)
assert.Nil(t, err)
assert.Len(t, plugin.Artifacts, 1)
assert.Equal(t, "testfile.zip", plugin.Artifacts[0].File)
assert.Equal(t, "artifact123", plugin.Artifacts[0].ArtifactId)
}
func TestNexusPlugin_ValidateAndProcessArgs_SingleFileUpload_Success(t *testing.T) {
args := Args{
EnvPluginInputArgs: EnvPluginInputArgs{
Username: "testUser",
Password: "testPass",
ServerUrl: "https://nexus.example.com",
Filename: "testfile.zip",
Format: "zip",
Repository: "repo",
Attributes: "-CgroupId=group -CartifactId=artifact123 -Cversion=1.0.0 -Aextension=zip -Aclassifier=classifier",
},
}
plugin := NexusPlugin{}
err := plugin.ValidateAndProcessArgs(args)
assert.Nil(t, err)
assert.Len(t, plugin.Artifacts, 1)
assert.Equal(t, "testfile.zip", plugin.Artifacts[0].File)
assert.Equal(t, "artifact123", plugin.Artifacts[0].ArtifactId)
}
func TestNexusPlugin_ValidateAndProcessArgs_MissingArguments(t *testing.T) {
args := Args{
EnvPluginInputArgs: EnvPluginInputArgs{
Username: "testUser",
Password: "testPass",
ServerUrl: "https://nexus.example.com",
Filename: "testfile.zip",
Format: "zip",
Repository: "repo",
},
}
plugin := NexusPlugin{}
err := plugin.ValidateAndProcessArgs(args)
assert.NotNil(t, err)
assert.Equal(t, "Error in DetermineCompatibilityMode: both 'Attributes' and 'Artifact' cannot be empty", err.Error())
}
func TestNexusPlugin_Run_MultiFileUpload_Success(t *testing.T) {
mockClient := new(MockHttpClient)
mockResp := &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(strings.NewReader("Success")),
}
mockClient.On("Do", mock.AnythingOfType("*http.Request")).Return(mockResp, nil).Maybe()
tmpFile1, err := createTempFile("file1.zip")
assert.NoError(t, err)
defer os.Remove(tmpFile1)
tmpFile2, err := createTempFile("file2.zip")
assert.NoError(t, err)
defer os.Remove(tmpFile2)
plugin := NexusPlugin{
PluginProcessingInfo: PluginProcessingInfo{
UserName: "testUser",
Password: "testPass",
ServerUrl: "https://nexus.example.com",
Repository: "repo",
GroupId: "group",
Version: "1.0.0",
Format: "maven2",
Artifacts: []Artifact{
{File: tmpFile1, ArtifactId: "artifact1", Type: "zip", Version: "1"},
{File: tmpFile2, ArtifactId: "artifact2", Type: "zip", Version: "1"},
},
},
HttpClient: mockClient,
}
err = plugin.Run()
assert.Nil(t, err)
assert.Empty(t, plugin.Failed)
mockClient.AssertExpectations(t)
}
// Test Bug #3: URL Trailing Slash - Single File Upload
func TestIsSingleFileUploadArgsOk_TrailingSlash(t *testing.T) {
args := Args{
EnvPluginInputArgs: EnvPluginInputArgs{
Username: "testUser",
Password: "testPass",
ServerUrl: "https://nexus.example.com/",
Filename: "testfile.jar",
Format: "maven2",
Repository: "repo",
Attributes: "-CgroupId=com.test -CartifactId=app -Cversion=1.0.0 -Aextension=jar -Aclassifier=bin",
},
}
plugin := NexusPlugin{}
err := plugin.IsSingleFileUploadArgsOk(args)
assert.Nil(t, err)
assert.Equal(t, "https://nexus.example.com", plugin.ServerUrl, "Trailing slash should be removed")
}
// Test Bug #3: URL Multiple Trailing Slashes - Single File Upload
func TestIsSingleFileUploadArgsOk_MultipleTrailingSlashes(t *testing.T) {
args := Args{
EnvPluginInputArgs: EnvPluginInputArgs{
Username: "testUser",
Password: "testPass",
ServerUrl: "https://nexus.example.com///",
Filename: "testfile.jar",
Format: "maven2",
Repository: "repo",
Attributes: "-CgroupId=com.test -CartifactId=app -Cversion=1.0.0 -Aextension=jar -Aclassifier=bin",
},
}
plugin := NexusPlugin{}
err := plugin.IsSingleFileUploadArgsOk(args)
assert.Nil(t, err)
assert.Equal(t, "https://nexus.example.com", plugin.ServerUrl, "Multiple trailing slashes should be removed")
}
// Test Bug #3: URL No Trailing Slash - Single File Upload (should remain unchanged)
func TestIsSingleFileUploadArgsOk_NoTrailingSlash(t *testing.T) {
args := Args{
EnvPluginInputArgs: EnvPluginInputArgs{
Username: "testUser",
Password: "testPass",
ServerUrl: "https://nexus.example.com",
Filename: "testfile.jar",
Format: "maven2",
Repository: "repo",
Attributes: "-CgroupId=com.test -CartifactId=app -Cversion=1.0.0 -Aextension=jar -Aclassifier=bin",
},
}
plugin := NexusPlugin{}
err := plugin.IsSingleFileUploadArgsOk(args)
assert.Nil(t, err)
assert.Equal(t, "https://nexus.example.com", plugin.ServerUrl, "URL without trailing slash should remain unchanged")
}
// Test Bug #3: URL Trailing Slash - Multi File Upload
func TestIsMultiFileUploadArgsOk_TrailingSlash(t *testing.T) {
args := Args{
EnvPluginInputArgs: EnvPluginInputArgs{
Username: "testUser",
Password: "testPass",
Protocol: "https",
ServerUrl: "nexus.example.com/",
NexusVersion: "nexus3",
Repository: "repo",
GroupId: "com.test",
Format: "maven2",
Artifact: "[{\"file\":\"test.jar\",\"artifactId\":\"app\",\"type\":\"jar\",\"version\":\"1.0\",\"groupId\":\"com.test\"}]",
},
}
plugin := NexusPlugin{}
err := plugin.IsMultiFileUploadArgsOk(args)
assert.Nil(t, err)
assert.Equal(t, "https://nexus.example.com", plugin.ServerUrl, "Trailing slash should be removed")
}
// Test Bug #3: URL Multiple Trailing Slashes - Multi File Upload
func TestIsMultiFileUploadArgsOk_MultipleTrailingSlashes(t *testing.T) {
args := Args{
EnvPluginInputArgs: EnvPluginInputArgs{
Username: "testUser",
Password: "testPass",
Protocol: "https",
ServerUrl: "nexus.example.com///",
NexusVersion: "nexus3",
Repository: "repo",
GroupId: "com.test",
Format: "maven2",
Artifact: "[{\"file\":\"test.jar\",\"artifactId\":\"app\",\"type\":\"jar\",\"version\":\"1.0\",\"groupId\":\"com.test\"}]",
},
}
plugin := NexusPlugin{}
err := plugin.IsMultiFileUploadArgsOk(args)
assert.Nil(t, err)
assert.Equal(t, "https://nexus.example.com", plugin.ServerUrl, "Multiple trailing slashes should be removed")
}
// Test Bug #3: URL No Trailing Slash - Multi File Upload (should remain unchanged)
func TestIsMultiFileUploadArgsOk_NoTrailingSlash(t *testing.T) {
args := Args{
EnvPluginInputArgs: EnvPluginInputArgs{
Username: "testUser",
Password: "testPass",
Protocol: "https",
ServerUrl: "nexus.example.com",
NexusVersion: "nexus3",
Repository: "repo",
GroupId: "com.test",
Format: "maven2",
Artifact: "[{\"file\":\"test.jar\",\"artifactId\":\"app\",\"type\":\"jar\",\"version\":\"1.0\",\"groupId\":\"com.test\"}]",
},
}
plugin := NexusPlugin{}
err := plugin.IsMultiFileUploadArgsOk(args)
assert.Nil(t, err)
assert.Equal(t, "https://nexus.example.com", plugin.ServerUrl, "URL without trailing slash should remain unchanged")
}
// Test Bug #2: Filename extraction from absolute Linux path
func TestUploadFileNexus3_AbsolutePath_Linux(t *testing.T) {
mockClient := new(MockHttpClient)
mockResp := &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(strings.NewReader("Success")),
}
// Track what filename was actually sent in the multipart form
var capturedRequest *http.Request
mockClient.On("Do", mock.AnythingOfType("*http.Request")).Run(func(args mock.Arguments) {
capturedRequest = args.Get(0).(*http.Request)
}).Return(mockResp, nil)
tmpFile, err := createTempFile("test content")
assert.NoError(t, err)
defer os.Remove(tmpFile)
plugin := NexusPlugin{
PluginProcessingInfo: PluginProcessingInfo{
UserName: "testUser",
Password: "testPass",
ServerUrl: "https://nexus.example.com",
Repository: "repo",
Format: "maven2",
Version: "nexus3",
},
HttpClient: mockClient,
}
artifact := Artifact{
File: tmpFile,
ArtifactId: "test-app",
Type: "jar",
Version: "1.0",
GroupId: "com.test",
}
err = plugin.uploadFileNexus3(artifact, tmpFile)
assert.Nil(t, err)
assert.NotNil(t, capturedRequest, "HTTP request should have been made")
// The request should have been made (we can't easily verify multipart content without parsing it)
mockClient.AssertExpectations(t)
}
// Test Bug #2: Filename extraction from absolute Windows-style path
func TestUploadFileNexus3_WindowsPath(t *testing.T) {
mockClient := new(MockHttpClient)
mockResp := &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(strings.NewReader("Success")),
}
mockClient.On("Do", mock.AnythingOfType("*http.Request")).Return(mockResp, nil)
tmpFile, err := createTempFile("test content")
assert.NoError(t, err)
defer os.Remove(tmpFile)
plugin := NexusPlugin{
PluginProcessingInfo: PluginProcessingInfo{
UserName: "testUser",
Password: "testPass",
ServerUrl: "https://nexus.example.com",
Repository: "repo",
Format: "maven2",
Version: "nexus3",
},
HttpClient: mockClient,
}
// Simulate Windows-style path in artifact (actual file is tmpFile)
artifact := Artifact{
File: tmpFile,
ArtifactId: "test-app",
Type: "jar",
Version: "1.0",
GroupId: "com.test",
}
err = plugin.uploadFileNexus3(artifact, tmpFile)
assert.Nil(t, err)
mockClient.AssertExpectations(t)
}
// Test Bug #2: Relative path should also work
func TestUploadFileNexus3_RelativePath(t *testing.T) {
mockClient := new(MockHttpClient)
mockResp := &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(strings.NewReader("Success")),
}
mockClient.On("Do", mock.AnythingOfType("*http.Request")).Return(mockResp, nil)
tmpFile, err := createTempFile("test content")
assert.NoError(t, err)
defer os.Remove(tmpFile)
plugin := NexusPlugin{
PluginProcessingInfo: PluginProcessingInfo{
UserName: "testUser",
Password: "testPass",
ServerUrl: "https://nexus.example.com",
Repository: "repo",
Format: "maven2",
Version: "nexus3",
},
HttpClient: mockClient,
}
artifact := Artifact{
File: tmpFile,
ArtifactId: "test-app",
Type: "jar",
Version: "1.0",
GroupId: "com.test",
}
err = plugin.uploadFileNexus3(artifact, tmpFile)
assert.Nil(t, err)
mockClient.AssertExpectations(t)
}
// Test Bug #1: Response Body Reading - 401 Error with Details
func TestUploadFileNexus3_ResponseBody_401(t *testing.T) {
mockClient := new(MockHttpClient)
fakeErrorBody := `{"errors":[{"id":"*","message":"Invalid credentials"}]}`
mockResp := &http.Response{
StatusCode: 401,
Body: ioutil.NopCloser(strings.NewReader(fakeErrorBody)),
}
mockClient.On("Do", mock.AnythingOfType("*http.Request")).Return(mockResp, nil)
tmpFile, err := createTempFile("test content")
assert.NoError(t, err)
defer os.Remove(tmpFile)
plugin := NexusPlugin{
PluginProcessingInfo: PluginProcessingInfo{
UserName: "testUser",
Password: "testPass",
ServerUrl: "https://nexus.example.com",
Repository: "repo",
Format: "maven2",
Version: "nexus3",
},
HttpClient: mockClient,
}
artifact := Artifact{
File: tmpFile,
ArtifactId: "test-app",
Type: "jar",
Version: "1.0",
GroupId: "com.test",
}
err = plugin.uploadFileNexus3(artifact, tmpFile)
assert.NotNil(t, err)
assert.Contains(t, err.Error(), "Invalid credentials", "Error should include response body details")
mockClient.AssertExpectations(t)
}
// Test Bug #1: Response Body Reading - 500 Error with Details
func TestUploadFileNexus3_ResponseBody_500(t *testing.T) {
mockClient := new(MockHttpClient)
fakeErrorBody := `{"errors":[{"id":"*","message":"Internal server error: Invalid field value"}]}`
mockResp := &http.Response{
StatusCode: 500,
Body: ioutil.NopCloser(strings.NewReader(fakeErrorBody)),
}
mockClient.On("Do", mock.AnythingOfType("*http.Request")).Return(mockResp, nil)
tmpFile, err := createTempFile("test content")
assert.NoError(t, err)
defer os.Remove(tmpFile)
plugin := NexusPlugin{
PluginProcessingInfo: PluginProcessingInfo{
UserName: "testUser",
Password: "testPass",
ServerUrl: "https://nexus.example.com",
Repository: "repo",
Format: "maven2",
Version: "nexus3",
},
HttpClient: mockClient,
}
artifact := Artifact{
File: tmpFile,
ArtifactId: "test-app",
Type: "jar",
Version: "1.0",
GroupId: "com.test",
}
err = plugin.uploadFileNexus3(artifact, tmpFile)
assert.NotNil(t, err)
assert.Contains(t, err.Error(), "Internal server error", "Error should include response body details")
mockClient.AssertExpectations(t)
}
// Test Bug #1: Response Body Reading - 404 Error with Details
func TestUploadFileNexus3_ResponseBody_404(t *testing.T) {
mockClient := new(MockHttpClient)
fakeErrorBody := `{"errors":[{"id":"*","message":"Repository not found"}]}`
mockResp := &http.Response{
StatusCode: 404,
Body: ioutil.NopCloser(strings.NewReader(fakeErrorBody)),
}
mockClient.On("Do", mock.AnythingOfType("*http.Request")).Return(mockResp, nil)
tmpFile, err := createTempFile("test content")
assert.NoError(t, err)
defer os.Remove(tmpFile)
plugin := NexusPlugin{
PluginProcessingInfo: PluginProcessingInfo{
UserName: "testUser",
Password: "testPass",
ServerUrl: "https://nexus.example.com",
Repository: "repo",
Format: "maven2",
Version: "nexus3",
},
HttpClient: mockClient,
}
artifact := Artifact{
File: tmpFile,
ArtifactId: "test-app",
Type: "jar",
Version: "1.0",
GroupId: "com.test",
}
err = plugin.uploadFileNexus3(artifact, tmpFile)
assert.NotNil(t, err)
assert.Contains(t, err.Error(), "Repository not found", "Error should include response body details")
mockClient.AssertExpectations(t)
}
// Test Bug #1: Response Body Reading - Success Response with Body
func TestUploadFileNexus3_ResponseBody_Success(t *testing.T) {
mockClient := new(MockHttpClient)
fakeSuccessBody := `{"success":true}`
mockResp := &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(strings.NewReader(fakeSuccessBody)),
}
mockClient.On("Do", mock.AnythingOfType("*http.Request")).Return(mockResp, nil)
tmpFile, err := createTempFile("test content")
assert.NoError(t, err)
defer os.Remove(tmpFile)
plugin := NexusPlugin{
PluginProcessingInfo: PluginProcessingInfo{
UserName: "testUser",
Password: "testPass",
ServerUrl: "https://nexus.example.com",
Repository: "repo",
Format: "maven2",
Version: "nexus3",
},
HttpClient: mockClient,
}
artifact := Artifact{
File: tmpFile,
ArtifactId: "test-app",
Type: "jar",
Version: "1.0",
GroupId: "com.test",
}
err = plugin.uploadFileNexus3(artifact, tmpFile)
assert.Nil(t, err, "Should succeed without error")
mockClient.AssertExpectations(t)
}