github.com/SAP/jenkins-library@v1.362.0/cmd/gradleExecuteBuild_test.go (about)

     1  //go:build unit
     2  // +build unit
     3  
     4  package cmd
     5  
     6  import (
     7  	"fmt"
     8  	"io/fs"
     9  	"path/filepath"
    10  	"testing"
    11  
    12  	"github.com/pkg/errors"
    13  	"github.com/stretchr/testify/assert"
    14  
    15  	"github.com/SAP/jenkins-library/pkg/mock"
    16  	"github.com/SAP/jenkins-library/pkg/piperenv"
    17  )
    18  
    19  const moduleFileContent = `{"variants": [{"name": "apiElements","files": [{"name": "gradle-1.2.3-12234567890-plain.jar"}]}]}`
    20  
    21  type gradleExecuteBuildMockUtils struct {
    22  	*mock.ExecMockRunner
    23  	*mock.FilesMock
    24  	Filepath
    25  }
    26  
    27  type isDirEntryMock func() bool
    28  
    29  func (d isDirEntryMock) Name() string {
    30  	panic("not implemented")
    31  }
    32  
    33  func (d isDirEntryMock) IsDir() bool {
    34  	return d()
    35  }
    36  
    37  func (d isDirEntryMock) Type() fs.FileMode {
    38  	panic("not implemented")
    39  }
    40  func (d isDirEntryMock) Info() (fs.FileInfo, error) {
    41  	panic("not implemented")
    42  }
    43  
    44  func TestRunGradleExecuteBuild(t *testing.T) {
    45  	pipelineEnv := &gradleExecuteBuildCommonPipelineEnvironment{}
    46  
    47  	t.Run("failed case - build.gradle isn't present", func(t *testing.T) {
    48  		utils := gradleExecuteBuildMockUtils{
    49  			ExecMockRunner: &mock.ExecMockRunner{},
    50  			FilesMock:      &mock.FilesMock{},
    51  		}
    52  		options := &gradleExecuteBuildOptions{
    53  			Path:       "path/to",
    54  			Task:       "build",
    55  			UseWrapper: false,
    56  		}
    57  
    58  		err := runGradleExecuteBuild(options, nil, utils, pipelineEnv)
    59  		assert.Error(t, err)
    60  		assert.Contains(t, err.Error(), "the specified gradle build script could not be found")
    61  	})
    62  
    63  	t.Run("success case - only build", func(t *testing.T) {
    64  		utils := gradleExecuteBuildMockUtils{
    65  			ExecMockRunner: &mock.ExecMockRunner{},
    66  			FilesMock:      &mock.FilesMock{},
    67  		}
    68  		utils.FilesMock.AddFile("path/to/build.gradle", []byte{})
    69  		options := &gradleExecuteBuildOptions{
    70  			Path:       "path/to",
    71  			Task:       "build",
    72  			UseWrapper: false,
    73  		}
    74  
    75  		err := runGradleExecuteBuild(options, nil, utils, pipelineEnv)
    76  		assert.NoError(t, err)
    77  		assert.Equal(t, 1, len(utils.Calls))
    78  		assert.Equal(t, mock.ExecCall{Exec: "gradle", Params: []string{"build", "-p", "path/to"}}, utils.Calls[0])
    79  	})
    80  
    81  	t.Run("success case - build with flags", func(t *testing.T) {
    82  		utils := gradleExecuteBuildMockUtils{
    83  			ExecMockRunner: &mock.ExecMockRunner{},
    84  			FilesMock:      &mock.FilesMock{},
    85  		}
    86  		utils.FilesMock.AddFile("path/to/build.gradle", []byte{})
    87  		options := &gradleExecuteBuildOptions{
    88  			Path:       "path/to",
    89  			Task:       "build",
    90  			BuildFlags: []string{"clean", "build", "-x", "test"},
    91  			UseWrapper: false,
    92  		}
    93  
    94  		err := runGradleExecuteBuild(options, nil, utils, pipelineEnv)
    95  		assert.NoError(t, err)
    96  		assert.Equal(t, 1, len(utils.Calls))
    97  		assert.Equal(t, mock.ExecCall{Exec: "gradle", Params: []string{"clean", "build", "-x", "test", "-p", "path/to"}}, utils.Calls[0])
    98  	})
    99  
   100  	t.Run("success case - bom creation", func(t *testing.T) {
   101  		utils := gradleExecuteBuildMockUtils{
   102  			ExecMockRunner: &mock.ExecMockRunner{},
   103  			FilesMock:      &mock.FilesMock{},
   104  		}
   105  		utils.FilesMock.AddFile("path/to/build.gradle", []byte{})
   106  		options := &gradleExecuteBuildOptions{
   107  			Path:       "path/to",
   108  			Task:       "build",
   109  			UseWrapper: false,
   110  			CreateBOM:  true,
   111  		}
   112  
   113  		err := runGradleExecuteBuild(options, nil, utils, pipelineEnv)
   114  		assert.NoError(t, err)
   115  		assert.Equal(t, 3, len(utils.Calls))
   116  		assert.Equal(t, mock.ExecCall{Exec: "gradle", Params: []string{"tasks", "-p", "path/to"}}, utils.Calls[0])
   117  		assert.Equal(t, mock.ExecCall{Execution: (*mock.Execution)(nil), Async: false, Exec: "gradle", Params: []string{"cyclonedxBom", "-p", "path/to", "--init-script", "initScript.gradle.tmp"}}, utils.Calls[1])
   118  		assert.Equal(t, mock.ExecCall{Exec: "gradle", Params: []string{"build", "-p", "path/to"}}, utils.Calls[2])
   119  		assert.True(t, utils.HasWrittenFile("initScript.gradle.tmp"))
   120  		assert.True(t, utils.HasRemovedFile("initScript.gradle.tmp"))
   121  	})
   122  
   123  	t.Run("success case - publishing of artifacts", func(t *testing.T) {
   124  		var walkDir WalkDirFunc = func(root string, fn fs.WalkDirFunc) error {
   125  			var dirMock isDirEntryMock = func() bool {
   126  				return false
   127  			}
   128  			return fn(filepath.Join("test_subproject_path", "build", "publications", "maven", "module.json"), dirMock, nil)
   129  		}
   130  		utils := gradleExecuteBuildMockUtils{
   131  			ExecMockRunner: &mock.ExecMockRunner{},
   132  			FilesMock:      &mock.FilesMock{},
   133  			Filepath:       walkDir,
   134  		}
   135  		utils.FilesMock.AddFile("path/to/build.gradle", []byte{})
   136  		utils.FilesMock.AddFile(filepath.Join("test_subproject_path", "build", "publications", "maven", "module.json"), []byte(moduleFileContent))
   137  		options := &gradleExecuteBuildOptions{
   138  			Path:       "path/to",
   139  			Task:       "build",
   140  			UseWrapper: false,
   141  			Publish:    true,
   142  		}
   143  
   144  		err := runGradleExecuteBuild(options, nil, utils, pipelineEnv)
   145  		assert.NoError(t, err)
   146  		assert.Equal(t, 3, len(utils.Calls))
   147  		assert.Equal(t, mock.ExecCall{Exec: "gradle", Params: []string{"build", "-p", "path/to"}}, utils.Calls[0])
   148  		assert.Equal(t, mock.ExecCall{Exec: "gradle", Params: []string{"tasks", "-p", "path/to"}}, utils.Calls[1])
   149  		assert.Equal(t, mock.ExecCall{Execution: (*mock.Execution)(nil), Async: false, Exec: "gradle", Params: []string{"publish", "-p", "path/to", "--init-script", "initScript.gradle.tmp"}}, utils.Calls[2])
   150  		assert.Equal(t, "gradle-1.2.3-12234567890-plain.jar", pipelineEnv.custom.artifacts[0].Name)
   151  		assert.True(t, utils.HasWrittenFile("initScript.gradle.tmp"))
   152  		assert.True(t, utils.HasRemovedFile("initScript.gradle.tmp"))
   153  	})
   154  
   155  	t.Run("success case - build using wrapper", func(t *testing.T) {
   156  		utils := gradleExecuteBuildMockUtils{
   157  			ExecMockRunner: &mock.ExecMockRunner{},
   158  			FilesMock:      &mock.FilesMock{},
   159  		}
   160  		utils.FilesMock.AddFile("path/to/build.gradle", []byte{})
   161  		utils.FilesMock.AddFile("gradlew", []byte{})
   162  		options := &gradleExecuteBuildOptions{
   163  			Path:       "path/to",
   164  			Task:       "build",
   165  			UseWrapper: true,
   166  		}
   167  
   168  		err := runGradleExecuteBuild(options, nil, utils, pipelineEnv)
   169  		assert.NoError(t, err)
   170  		assert.Equal(t, 1, len(utils.Calls))
   171  		assert.Equal(t, mock.ExecCall{Exec: "./gradlew", Params: []string{"build", "-p", "path/to"}}, utils.Calls[0])
   172  	})
   173  
   174  	t.Run("failed case - build", func(t *testing.T) {
   175  		utils := gradleExecuteBuildMockUtils{
   176  			ExecMockRunner: &mock.ExecMockRunner{
   177  				ShouldFailOnCommand: map[string]error{"gradle build -p path/to": errors.New("failed to build")},
   178  			},
   179  			FilesMock: &mock.FilesMock{},
   180  		}
   181  		utils.FilesMock.AddFile("path/to/build.gradle", []byte{})
   182  		options := &gradleExecuteBuildOptions{
   183  			Path:       "path/to",
   184  			Task:       "build",
   185  			UseWrapper: false,
   186  		}
   187  
   188  		err := runGradleExecuteBuild(options, nil, utils, pipelineEnv)
   189  		assert.Error(t, err)
   190  		assert.Contains(t, err.Error(), "failed to build")
   191  	})
   192  
   193  	t.Run("failed case - build with flags", func(t *testing.T) {
   194  		utils := gradleExecuteBuildMockUtils{
   195  			ExecMockRunner: &mock.ExecMockRunner{
   196  				ShouldFailOnCommand: map[string]error{"gradle clean build -x test -p path/to": errors.New("failed to build with flags")},
   197  			},
   198  			FilesMock: &mock.FilesMock{},
   199  		}
   200  		utils.FilesMock.AddFile("path/to/build.gradle", []byte{})
   201  		options := &gradleExecuteBuildOptions{
   202  			Path:       "path/to",
   203  			Task:       "build",
   204  			BuildFlags: []string{"clean", "build", "-x", "test"},
   205  			UseWrapper: false,
   206  		}
   207  
   208  		err := runGradleExecuteBuild(options, nil, utils, pipelineEnv)
   209  		assert.Error(t, err)
   210  		assert.Contains(t, err.Error(), "failed to build with flags")
   211  	})
   212  
   213  	t.Run("failed case - bom creation", func(t *testing.T) {
   214  		utils := gradleExecuteBuildMockUtils{
   215  			ExecMockRunner: &mock.ExecMockRunner{
   216  				ShouldFailOnCommand: map[string]error{"./gradlew cyclonedxBom -p path/to --init-script initScript.gradle.tmp": errors.New("failed to create bom")},
   217  			},
   218  			FilesMock: &mock.FilesMock{},
   219  		}
   220  		utils.FilesMock.AddFile("path/to/build.gradle", []byte{})
   221  		utils.FilesMock.AddFile("gradlew", []byte{})
   222  		options := &gradleExecuteBuildOptions{
   223  			Path:       "path/to",
   224  			Task:       "build",
   225  			UseWrapper: true,
   226  			CreateBOM:  true,
   227  		}
   228  
   229  		err := runGradleExecuteBuild(options, nil, utils, pipelineEnv)
   230  		assert.Error(t, err)
   231  		assert.Contains(t, err.Error(), "failed to create bom")
   232  	})
   233  
   234  	t.Run("failed case - publish artifacts", func(t *testing.T) {
   235  		utils := gradleExecuteBuildMockUtils{
   236  			ExecMockRunner: &mock.ExecMockRunner{
   237  				ShouldFailOnCommand: map[string]error{"./gradlew publish -p path/to --init-script initScript.gradle.tmp": errors.New("failed to publish artifacts")},
   238  			},
   239  			FilesMock: &mock.FilesMock{},
   240  		}
   241  		utils.FilesMock.AddFile("path/to/build.gradle", []byte{})
   242  		utils.FilesMock.AddFile("gradlew", []byte{})
   243  		options := &gradleExecuteBuildOptions{
   244  			Path:       "path/to",
   245  			Task:       "build",
   246  			UseWrapper: true,
   247  			Publish:    true,
   248  		}
   249  
   250  		err := runGradleExecuteBuild(options, nil, utils, pipelineEnv)
   251  		assert.Error(t, err)
   252  		assert.Contains(t, err.Error(), "failed to publish artifacts")
   253  	})
   254  }
   255  
   256  func TestGetPublishedArtifactsNames(t *testing.T) {
   257  	tt := []struct {
   258  		name              string
   259  		utils             gradleExecuteBuildMockUtils
   260  		moduleFile        string
   261  		moduleFileContent string
   262  		expectedResult    piperenv.Artifacts
   263  		expectedErr       error
   264  	}{
   265  		{
   266  			name: "failed to check file existence",
   267  			utils: gradleExecuteBuildMockUtils{
   268  				ExecMockRunner: &mock.ExecMockRunner{},
   269  				FilesMock: &mock.FilesMock{
   270  					FileExistsErrors: map[string]error{"module.json": fmt.Errorf("err")},
   271  				},
   272  			},
   273  			moduleFile:        "module.json",
   274  			moduleFileContent: "",
   275  			expectedErr:       fmt.Errorf("failed to check existence of the file 'module.json': err"),
   276  		}, {
   277  			name: "failed to get file",
   278  			utils: gradleExecuteBuildMockUtils{
   279  				ExecMockRunner: &mock.ExecMockRunner{},
   280  				FilesMock:      &mock.FilesMock{},
   281  			},
   282  			moduleFile:        "",
   283  			moduleFileContent: "",
   284  			expectedErr:       fmt.Errorf("failed to get '': file does not exist"),
   285  		}, {
   286  			name: "failed to read file",
   287  			utils: gradleExecuteBuildMockUtils{
   288  				ExecMockRunner: &mock.ExecMockRunner{},
   289  				FilesMock: &mock.FilesMock{
   290  					FileReadErrors: map[string]error{"module.json": fmt.Errorf("err")},
   291  				},
   292  			},
   293  			moduleFile:        "module.json",
   294  			moduleFileContent: "",
   295  			expectedErr:       fmt.Errorf("failed to read 'module.json': err"),
   296  		}, {
   297  			name: "failed to unmarshal file",
   298  			utils: gradleExecuteBuildMockUtils{
   299  				ExecMockRunner: &mock.ExecMockRunner{},
   300  				FilesMock:      &mock.FilesMock{},
   301  			},
   302  			moduleFile:        "module.json",
   303  			moduleFileContent: "",
   304  			expectedErr:       fmt.Errorf("failed to unmarshal 'module.json': unexpected end of JSON input"),
   305  		}, {
   306  			name: "success - get name of published artifact",
   307  			utils: gradleExecuteBuildMockUtils{
   308  				ExecMockRunner: &mock.ExecMockRunner{},
   309  				FilesMock:      &mock.FilesMock{},
   310  			},
   311  			moduleFile:        "module.json",
   312  			moduleFileContent: moduleFileContent,
   313  			expectedResult:    piperenv.Artifacts{piperenv.Artifact{Name: "gradle-1.2.3-12234567890-plain.jar"}},
   314  			expectedErr:       nil,
   315  		},
   316  	}
   317  
   318  	for _, test := range tt {
   319  		test := test
   320  		t.Run(test.name, func(t *testing.T) {
   321  			t.Parallel()
   322  			if test.moduleFile != "" {
   323  				test.utils.FilesMock.AddFile(test.moduleFile, []byte(test.moduleFileContent))
   324  			}
   325  			artifacts, err := getPublishedArtifactsNames(test.moduleFile, test.utils)
   326  			assert.Equal(t, test.expectedResult, artifacts)
   327  			assert.Equal(t, test.expectedErr, err)
   328  		})
   329  	}
   330  }