github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/transportrequest/gitutils_test.go (about)

     1  //go:build unit
     2  // +build unit
     3  
     4  package transportrequest
     5  
     6  import (
     7  	pipergit "github.com/SAP/jenkins-library/pkg/git"
     8  	"github.com/go-git/go-billy/v5/memfs"
     9  	"github.com/go-git/go-git/v5"
    10  	"github.com/go-git/go-git/v5/plumbing"
    11  	"github.com/go-git/go-git/v5/plumbing/object"
    12  	"github.com/go-git/go-git/v5/plumbing/storer"
    13  	"github.com/go-git/go-git/v5/storage/memory"
    14  	"github.com/stretchr/testify/assert"
    15  	"io"
    16  	"testing"
    17  )
    18  
    19  type commitIteratorMock struct {
    20  	commits []object.Commit
    21  	index   int
    22  }
    23  
    24  func (iter *commitIteratorMock) Next() (*object.Commit, error) {
    25  	i := iter.index
    26  	iter.index++
    27  
    28  	if i >= len(iter.commits) {
    29  		return nil, io.EOF // real iterators also behave like this
    30  	}
    31  	return &iter.commits[i], nil
    32  }
    33  
    34  func (iter *commitIteratorMock) ForEach(cb func(c *object.Commit) error) error {
    35  	for {
    36  		c, err := iter.Next()
    37  		if err == io.EOF {
    38  			break
    39  		}
    40  		if err != nil {
    41  			return err
    42  		}
    43  
    44  		err = cb(c)
    45  		if err == storer.ErrStop {
    46  			break
    47  		}
    48  		if err != nil {
    49  			return err
    50  		}
    51  	}
    52  
    53  	return nil
    54  }
    55  
    56  func (iter *commitIteratorMock) Close() {
    57  
    58  }
    59  
    60  type TrGitUtilsMock struct {
    61  }
    62  
    63  func (m *TrGitUtilsMock) PlainOpen(path string) (*git.Repository, error) {
    64  	return git.Init(memory.NewStorage(), memfs.New())
    65  }
    66  
    67  func TestRetrieveLabelStraightForward(t *testing.T) {
    68  
    69  	t.Run("single commit tests", func(t *testing.T) {
    70  
    71  		runTest := func(testConfig []string) {
    72  			t.Run(testConfig[0], func(t *testing.T) {
    73  				commitIter := &commitIteratorMock{
    74  					commits: []object.Commit{
    75  						object.Commit{
    76  							Hash:    plumbing.NewHash("3434343434343434343434343434343434343434"),
    77  							Message: testConfig[1],
    78  						},
    79  					},
    80  				}
    81  				labels, err := FindLabelsInCommits(commitIter, "TransportRequest")
    82  				if assert.NoError(t, err) {
    83  					expected := testConfig[2:]
    84  					if assert.Len(t, labels, len(expected)) {
    85  						assert.Subset(t, expected, labels)
    86  					}
    87  				}
    88  			})
    89  		}
    90  
    91  		tests := [][]string{
    92  			[]string{
    93  				"straight forward",
    94  				"this is a commit with TransportRequestId\n\nThis is the first line of the message body\nTransportRequest: 12345678",
    95  				"12345678",
    96  			},
    97  			[]string{
    98  				"trailing spaces after our value",
    99  				"this is a commit with TransportRequestId\n\nThis is the first line of the message body\nTransportRequest: 12345678  ",
   100  				"12345678",
   101  			},
   102  			[]string{
   103  				"trailing text after our value",
   104  				"this is a commit with TransportRequestId\n\nThis is the first line of the message body\nTransportRequest: 12345678 aaa",
   105  			},
   106  			[]string{
   107  				"leading whitespace before our label",
   108  				"this is a commit with TransportRequestId\n\nThis is the first line of the message body\n   TransportRequest: 12345678",
   109  				"12345678",
   110  			},
   111  			[]string{
   112  				"leading text before our label",
   113  				"this is a commit with TransportRequestId\n\nThis is the first line of the message body\naaa TransportRequest: 12345678",
   114  			},
   115  			[]string{
   116  				"whitespaces before column",
   117  				"this is a commit with TransportRequestId\n\nThis is the first line of the message body\nTransportRequest  : 12345678",
   118  				"12345678",
   119  			},
   120  			[]string{
   121  				"no whitespaces after column",
   122  				"this is a commit with TransportRequestId\n\nThis is the first line of the message body\nTransportRequest  :12345678",
   123  				"12345678",
   124  			},
   125  			[]string{
   126  				"two times the same id in the same commit",
   127  				"this is a commit with TransportRequestId\n\nThis is the first line of the message body\nTransportRequest : 12345678\nTransportRequest : 12345678",
   128  				"12345678",
   129  			},
   130  			[]string{
   131  				// we report the ids, this is basically an invalid state, but needs to be filtered out by the caller
   132  				"two different ids in the same commit",
   133  				"this is a commit with TransportRequestId\n\nThis is the first line of the message body\nTransportRequest : 12345678\nTransportRequest : 87654321",
   134  				"12345678", "87654321",
   135  			},
   136  		}
   137  
   138  		for _, testConfig := range tests {
   139  			runTest(testConfig)
   140  		}
   141  	})
   142  
   143  	t.Run("multi commit tests", func(t *testing.T) {
   144  
   145  		t.Run("two different ids in different commits", func(t *testing.T) {
   146  			commitIter := &commitIteratorMock{
   147  				commits: []object.Commit{
   148  					object.Commit{
   149  						Hash:    plumbing.NewHash("3434343434343434343434343434343434343434"),
   150  						Message: "this is a commit with TransportRequestId\n\nThis is the first line of the message body\nTransportRequest: 12345678",
   151  					},
   152  					object.Commit{
   153  						Hash:    plumbing.NewHash("1212121212121212121212121212121212121212"),
   154  						Message: "this is a commit with TransportRequestId\n\nThis is the first line of the message body\nTransportRequest: 87654321",
   155  					},
   156  				},
   157  			}
   158  			labels, err := FindLabelsInCommits(commitIter, "TransportRequest")
   159  			if assert.NoError(t, err) {
   160  				assert.Equal(t, []string{"12345678", "87654321"}, labels)
   161  			}
   162  		})
   163  
   164  		t.Run("two different ids in different commits agains, order needs to be the same", func(t *testing.T) {
   165  			commitIter := &commitIteratorMock{
   166  				commits: []object.Commit{
   167  					object.Commit{
   168  						Hash:    plumbing.NewHash("1212121212121212121212121212121212121212"),
   169  						Message: "this is a commit with TransportRequestId\n\nThis is the first line of the message body\nTransportRequest: 87654321",
   170  					},
   171  					object.Commit{
   172  						Hash:    plumbing.NewHash("3434343434343434343434343434343434343434"),
   173  						Message: "this is a commit with TransportRequestId\n\nThis is the first line of the message body\nTransportRequest: 12345678",
   174  					},
   175  				},
   176  			}
   177  			labels, err := FindLabelsInCommits(commitIter, "TransportRequest")
   178  			if assert.NoError(t, err) {
   179  				assert.Equal(t, []string{"12345678", "87654321"}, labels)
   180  			}
   181  		})
   182  
   183  		t.Run("the same id in different commits", func(t *testing.T) {
   184  			commitIter := &commitIteratorMock{
   185  				commits: []object.Commit{
   186  					object.Commit{
   187  						Hash:    plumbing.NewHash("3434343434343434343434343434343434343434"),
   188  						Message: "this is a commit with TransportRequestId\n\nThis is the first line of the message body\nTransportRequest: 12345678",
   189  					},
   190  					object.Commit{
   191  						Hash:    plumbing.NewHash("1212121212121212121212121212121212121212"),
   192  						Message: "this is a commit with TransportRequestId\n\nThis is the first line of the message body\nTransportRequest: 12345678",
   193  					},
   194  				},
   195  			}
   196  			labels, err := FindLabelsInCommits(commitIter, "TransportRequest")
   197  			if assert.NoError(t, err) {
   198  				expected := []string{"12345678"}
   199  				if assert.Len(t, labels, len(expected)) {
   200  					assert.Subset(t, expected, labels)
   201  				}
   202  			}
   203  		})
   204  		t.Run("default label with default reg ex", func(t *testing.T) {
   205  			commitIter := &commitIteratorMock{
   206  				commits: []object.Commit{
   207  					object.Commit{
   208  						Hash:    plumbing.NewHash("3434343434343434343434343434343434343434"),
   209  						Message: "TransportRequest: 12345678",
   210  					},
   211  				},
   212  			}
   213  			labels, err := FindLabelsInCommits(commitIter, "TransportRequest\\s?:")
   214  			if assert.NoError(t, err) {
   215  				assert.Equal(t, "12345678", labels[0])
   216  			}
   217  		})
   218  	})
   219  }
   220  
   221  func TestFinishLabel(t *testing.T) {
   222  	t.Parallel()
   223  	t.Run("default label old", func(t *testing.T) {
   224  		assert.Equal(t, `(?m)^\s*TransportRequest\s?:\s*(\S*)\s*$`, finishLabel("TransportRequest\\s?:"))
   225  	})
   226  	t.Run("default label new", func(t *testing.T) {
   227  		assert.Equal(t, `(?m)^\s*TransportRequest\s*:\s*(\S*)\s*$`, finishLabel("TransportRequest"))
   228  	})
   229  
   230  }
   231  
   232  func TestFindIDInRange(t *testing.T) {
   233  
   234  	// For these functions we have already tests. In order to avoid re-testing
   235  	// we set mocks for these functions.
   236  	logRange = func(repo *git.Repository, from, to string) (object.CommitIter, error) {
   237  		return &commitIteratorMock{}, nil
   238  	}
   239  
   240  	defer func() {
   241  		logRange = pipergit.LogRange
   242  		findLabelsInCommits = FindLabelsInCommits
   243  	}()
   244  
   245  	t.Run("range is forwarded correctly", func(t *testing.T) {
   246  
   247  		var receivedFrom, receivedTo string
   248  
   249  		oldLogRangeFunc := logRange
   250  		logRange = func(repo *git.Repository, from, to string) (object.CommitIter, error) {
   251  			receivedFrom = from
   252  			receivedTo = to
   253  			return &commitIteratorMock{}, nil
   254  		}
   255  		defer func() {
   256  			logRange = oldLogRangeFunc
   257  		}()
   258  
   259  		findIDInRange("TransportRequest", "master", "HEAD", &TrGitUtilsMock{})
   260  
   261  		assert.Equal(t, "master", receivedFrom)
   262  		assert.Equal(t, "HEAD", receivedTo)
   263  	})
   264  
   265  	t.Run("no label is found", func(t *testing.T) {
   266  
   267  		findLabelsInCommits = func(commits object.CommitIter, label string) ([]string, error) {
   268  			return []string{}, nil
   269  		}
   270  
   271  		defer func() {
   272  			findLabelsInCommits = FindLabelsInCommits
   273  		}()
   274  
   275  		_, err := findIDInRange("TransportRequest", "master", "HEAD", &TrGitUtilsMock{})
   276  
   277  		assert.EqualError(t, err, "No values found for 'TransportRequest' in range 'master..HEAD'")
   278  	})
   279  
   280  	t.Run("one label is found", func(t *testing.T) {
   281  
   282  		findLabelsInCommits = func(commits object.CommitIter, label string) ([]string, error) {
   283  			return []string{"123456789"}, nil
   284  		}
   285  
   286  		defer func() {
   287  			findLabelsInCommits = FindLabelsInCommits
   288  		}()
   289  
   290  		label, err := findIDInRange("TransportRequest", "master", "HEAD", &TrGitUtilsMock{})
   291  		if assert.NoError(t, err) {
   292  			assert.Equal(t, "123456789", label)
   293  		}
   294  	})
   295  
   296  	t.Run("more than one label is found", func(t *testing.T) {
   297  
   298  		findLabelsInCommits = func(commits object.CommitIter, label string) ([]string, error) {
   299  			return []string{"123456789", "987654321"}, nil
   300  		}
   301  
   302  		defer func() {
   303  			findLabelsInCommits = FindLabelsInCommits
   304  		}()
   305  
   306  		_, err := findIDInRange("TransportRequest", "master", "HEAD", &TrGitUtilsMock{})
   307  		if assert.Error(t, err) {
   308  			// don't want to rely on the order
   309  			assert.Contains(t, err.Error(), "More than one values found for label 'TransportRequest' in range 'master..HEAD'")
   310  			assert.Contains(t, err.Error(), "123456789")
   311  			assert.Contains(t, err.Error(), "987654321")
   312  		}
   313  	})
   314  
   315  }