go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/proto/gitiles/gitiles_fake_test.go (about)

     1  // Copyright 2020 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package gitiles
    16  
    17  import (
    18  	"context"
    19  	"strconv"
    20  	"testing"
    21  
    22  	. "github.com/smartystreets/goconvey/convey"
    23  	git "go.chromium.org/luci/common/proto/git"
    24  )
    25  
    26  func TestFake(t *testing.T) {
    27  	t.Parallel()
    28  
    29  	ctx := context.Background()
    30  	Convey("Edge cases", t, func() {
    31  		Convey("Empty", func() {
    32  			fake := Fake{}
    33  			Convey("Projects", func() {
    34  				resp, err := fake.Projects(ctx, &ProjectsRequest{})
    35  				So(err, ShouldBeNil)
    36  				So(resp.GetProjects(), ShouldBeEmpty)
    37  			})
    38  			Convey("Revs", func() {
    39  				in := &RefsRequest{
    40  					Project: "foo",
    41  				}
    42  				// Repository not found
    43  				_, err := fake.Refs(ctx, in)
    44  				So(err, ShouldBeError)
    45  			})
    46  		})
    47  
    48  		Convey("Empty project", func() {
    49  			fake := Fake{}
    50  			fake.SetRepository("foo", nil, nil)
    51  			Convey("Projects", func() {
    52  				resp, err := fake.Projects(ctx, &ProjectsRequest{})
    53  				So(err, ShouldBeNil)
    54  				So(resp.GetProjects(), ShouldResemble, []string{"foo"})
    55  			})
    56  
    57  			Convey("Revs", func() {
    58  				in := &RefsRequest{
    59  					Project: "foo",
    60  				}
    61  				// Repository not found
    62  				out, err := fake.Refs(ctx, in)
    63  				So(err, ShouldBeNil)
    64  				So(out.GetRevisions(), ShouldBeEmpty)
    65  			})
    66  		})
    67  
    68  		Convey("Empty repository", func() {
    69  			fake := Fake{}
    70  			refs := map[string]string{"refs/heads/main": ""}
    71  			fake.SetRepository("foo", refs, nil)
    72  			Convey("Projects", func() {
    73  				resp, err := fake.Projects(ctx, &ProjectsRequest{})
    74  				So(err, ShouldBeNil)
    75  				So(resp.GetProjects(), ShouldResemble, []string{"foo"})
    76  			})
    77  
    78  			Convey("Revs", func() {
    79  				in := &RefsRequest{
    80  					Project: "foo",
    81  				}
    82  				// Repository not found
    83  				out, err := fake.Refs(ctx, in)
    84  				So(err, ShouldBeNil)
    85  				So(out.GetRevisions(), ShouldResemble, refs)
    86  			})
    87  		})
    88  
    89  		Convey("Reference points to invalid revision", func() {
    90  			fake := Fake{}
    91  			So(func() {
    92  				fake.SetRepository("foo", map[string]string{"foo": "bar"}, nil)
    93  			}, ShouldPanic)
    94  		})
    95  
    96  		Convey("Duplicate commit", func() {
    97  			fake := Fake{}
    98  			So(func() {
    99  				commits := []*git.Commit{
   100  					{
   101  						Id: "bar",
   102  					},
   103  					{
   104  						Id: "bar",
   105  					},
   106  				}
   107  				fake.SetRepository("foo", map[string]string{"foo": "bar"}, commits)
   108  			}, ShouldPanic)
   109  		})
   110  
   111  		Convey("Broken commit chain", func() {
   112  			fake := Fake{}
   113  			commits := []*git.Commit{
   114  				{
   115  					Id:      "bar",
   116  					Parents: []string{"baz"},
   117  				},
   118  			}
   119  			fake.SetRepository("foo", map[string]string{"refs/heads/main": "bar"}, commits)
   120  			So(func() {
   121  				in := &LogRequest{
   122  					Project:    "foo",
   123  					Committish: "refs/heads/main",
   124  				}
   125  				fake.Log(ctx, in)
   126  			}, ShouldPanic)
   127  		})
   128  	})
   129  
   130  	Convey("Linear commits", t, func() {
   131  		// Commit structure: 9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0
   132  		commits := make([]*git.Commit, 10)
   133  		for i := 0; i < 10; i++ {
   134  			commits[i] = &git.Commit{
   135  				Id: strconv.Itoa(i),
   136  			}
   137  			if i > 0 {
   138  				commits[i].Parents = []string{commits[i-1].GetId()}
   139  			}
   140  		}
   141  		refs := map[string]string{
   142  			"refs/heads/main":   "9",
   143  			"refs/heads/stable": "1",
   144  		}
   145  		fake := Fake{}
   146  		fake.SetRepository("foo", refs, commits)
   147  
   148  		Convey("Revs", func() {
   149  			in := &RefsRequest{
   150  				Project: "foo",
   151  			}
   152  			out, err := fake.Refs(ctx, in)
   153  			So(err, ShouldBeNil)
   154  			So(out.GetRevisions(), ShouldResemble, refs)
   155  		})
   156  
   157  		Convey("Log pagination main", func() {
   158  			in := &LogRequest{
   159  				Project:    "foo",
   160  				Committish: "refs/heads/main",
   161  				PageSize:   5,
   162  			}
   163  			out, err := fake.Log(ctx, in)
   164  			So(err, ShouldBeNil)
   165  			So(len(out.GetLog()), ShouldEqual, 5)
   166  			// Last element returned is 5, which is the token
   167  			So(out.GetNextPageToken(), ShouldEqual, "5")
   168  
   169  			in.PageToken = out.GetNextPageToken()
   170  			out, err = fake.Log(ctx, in)
   171  			So(err, ShouldBeNil)
   172  			So(len(out.GetLog()), ShouldEqual, 5)
   173  			// Last element returned is 0, which is the token
   174  			So(out.GetNextPageToken(), ShouldEqual, "0")
   175  
   176  			// We reached the end
   177  			in.PageToken = out.GetNextPageToken()
   178  			out, err = fake.Log(ctx, in)
   179  			So(err, ShouldBeNil)
   180  			So(len(out.GetLog()), ShouldEqual, 0)
   181  			So(out.GetNextPageToken(), ShouldEqual, "")
   182  		})
   183  
   184  		Convey("Log stable branch", func() {
   185  			in := &LogRequest{
   186  				Project:    "foo",
   187  				Committish: "refs/heads/stable",
   188  				PageSize:   5,
   189  			}
   190  			out, err := fake.Log(ctx, in)
   191  			So(err, ShouldBeNil)
   192  			So(len(out.GetLog()), ShouldEqual, 2)
   193  			So(out.GetNextPageToken(), ShouldEqual, "")
   194  		})
   195  
   196  		Convey("Log Non existing branch", func() {
   197  			in := &LogRequest{
   198  				Project:    "foo",
   199  				Committish: "refs/heads/foo",
   200  				PageSize:   5,
   201  			}
   202  			_, err := fake.Log(ctx, in)
   203  			So(err, ShouldBeError)
   204  		})
   205  	})
   206  
   207  	Convey("Merge logs", t, func() {
   208  		// Commit structure: 9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0
   209  		//                          \_ b2      ->     b1  /
   210  		commits := make([]*git.Commit, 12)
   211  		for i := 0; i < 10; i++ {
   212  			commits[i] = &git.Commit{
   213  				Id: strconv.Itoa(i),
   214  			}
   215  			if i > 0 {
   216  				commits[i].Parents = []string{commits[i-1].GetId()}
   217  			}
   218  		}
   219  		commits[10] = &git.Commit{
   220  			Id:      "b1",
   221  			Parents: []string{"3"},
   222  		}
   223  		commits[11] = &git.Commit{
   224  			Id:      "b2",
   225  			Parents: []string{"b1"},
   226  		}
   227  		// Modify commit with ID 8 to merge commit include b2 as parent.
   228  		commits[8].Parents = []string{"7", "b2"}
   229  
   230  		refs := map[string]string{
   231  			"refs/heads/main":    "9",
   232  			"refs/heads/feature": "b2",
   233  			"refs/heads/stable":  "7",
   234  		}
   235  		fake := Fake{}
   236  		fake.SetRepository("foo", refs, commits)
   237  
   238  		Convey("Entire log", func() {
   239  			in := &LogRequest{
   240  				Project:    "foo",
   241  				Committish: "refs/heads/main",
   242  				PageSize:   100,
   243  			}
   244  			out, err := fake.Log(ctx, in)
   245  			So(err, ShouldBeNil)
   246  			So(out.GetNextPageToken(), ShouldBeEmpty)
   247  			So(len(out.GetLog()), ShouldEqual, 12)
   248  		})
   249  
   250  		Convey("Partial log, before merge", func() {
   251  			in := &LogRequest{
   252  				Project:    "foo",
   253  				Committish: "refs/heads/stable",
   254  				PageSize:   100,
   255  			}
   256  			out, err := fake.Log(ctx, in)
   257  			So(err, ShouldBeNil)
   258  			So(out.GetNextPageToken(), ShouldBeEmpty)
   259  			So(len(out.GetLog()), ShouldEqual, 8)
   260  		})
   261  
   262  		Convey("Partial log, before merge (feature branch)", func() {
   263  			in := &LogRequest{
   264  				Project:    "foo",
   265  				Committish: "refs/heads/feature",
   266  				PageSize:   100,
   267  			}
   268  			out, err := fake.Log(ctx, in)
   269  			So(err, ShouldBeNil)
   270  			So(out.GetNextPageToken(), ShouldBeEmpty)
   271  			So(len(out.GetLog()), ShouldEqual, 6)
   272  		})
   273  
   274  		Convey("Partial log, specific commit", func() {
   275  			in := &LogRequest{
   276  				Project:    "foo",
   277  				Committish: "8",
   278  				PageSize:   100,
   279  			}
   280  			out, err := fake.Log(ctx, in)
   281  			So(err, ShouldBeNil)
   282  			So(out.GetNextPageToken(), ShouldBeEmpty)
   283  			So(len(out.GetLog()), ShouldEqual, 11)
   284  		})
   285  	})
   286  }