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

     1  // Copyright 2017 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  	"fmt"
    20  	"net/http"
    21  	"net/http/httptest"
    22  	"sort"
    23  	"testing"
    24  
    25  	"go.chromium.org/luci/common/proto/git"
    26  	"go.chromium.org/luci/common/proto/gitiles"
    27  
    28  	. "github.com/smartystreets/goconvey/convey"
    29  	. "go.chromium.org/luci/common/testing/assertions"
    30  )
    31  
    32  func TestLog(t *testing.T) {
    33  	t.Parallel()
    34  	ctx := context.Background()
    35  
    36  	Convey("Log with bad project", t, func() {
    37  		srv, c := newMockClient(func(w http.ResponseWriter, r *http.Request) {})
    38  		defer srv.Close()
    39  		_, err := c.Log(ctx, &gitiles.LogRequest{})
    40  		So(err, ShouldErrLike, "project is required")
    41  	})
    42  
    43  	Convey("Log w/o pages", t, func() {
    44  		srv, c := newMockClient(func(w http.ResponseWriter, r *http.Request) {
    45  			w.WriteHeader(200)
    46  			w.Header().Set("Content-Type", "application/json")
    47  			fmt.Fprintf(w, ")]}'\n{\"log\": [%s, %s]}\n", fakeCommit1Str, fakeCommit2Str)
    48  		})
    49  		defer srv.Close()
    50  
    51  		Convey("Return All", func() {
    52  			res, err := c.Log(ctx, &gitiles.LogRequest{
    53  				Project:            "repo",
    54  				Committish:         "8de6836858c99e48f3c58164ab717bda728e95dd",
    55  				ExcludeAncestorsOf: "master",
    56  				PageSize:           10,
    57  			})
    58  			So(err, ShouldBeNil)
    59  			So(len(res.Log), ShouldEqual, 2)
    60  			So(res.Log[0].Author.Name, ShouldEqual, "Author 1")
    61  			So(res.Log[1].Id, ShouldEqual, "dc1dbf1aa56e4dd4cbfaab61c4d30a35adce5f40")
    62  		})
    63  	})
    64  }
    65  
    66  func TestRefs(t *testing.T) {
    67  	t.Parallel()
    68  	ctx := context.Background()
    69  
    70  	Convey("bad project", t, func() {
    71  		c := &client{BaseURL: "https://a.googlesource.com/a"}
    72  		_, err := c.Refs(ctx, &gitiles.RefsRequest{
    73  			RefsPath: gitiles.AllRefs,
    74  		})
    75  		So(err, ShouldErrLike, `project is required`)
    76  	})
    77  
    78  	Convey("bad RefsPath", t, func() {
    79  		c := &client{BaseURL: "https://a.googlesource.com/a"}
    80  		_, err := c.Refs(ctx, &gitiles.RefsRequest{
    81  			Project:  "repo",
    82  			RefsPath: "bad",
    83  		})
    84  		So(err, ShouldErrLike, `refsPath must be "refs" or start with "refs/"`)
    85  	})
    86  
    87  	Convey("Refs All", t, func() {
    88  		srv, c := newMockClient(func(w http.ResponseWriter, r *http.Request) {
    89  			w.WriteHeader(200)
    90  			w.Header().Set("Content-Type", "application/json")
    91  			fmt.Fprintln(w, `)]}'
    92  				{
    93  					"refs/heads/master": { "value": "deadbeef" },
    94  					"refs/heads/infra/config": { "value": "0000beef" },
    95  					"refs/changes/01/123001/1": { "value": "123dead001beef1" },
    96  					"refs/other/ref": { "value": "ba6" },
    97  					"123deadbeef123": { "target": "f00" },
    98  					"HEAD": {
    99  						"value": "deadbeef",
   100  						"target": "refs/heads/master"
   101  					}
   102  				}
   103  			`)
   104  		})
   105  		defer srv.Close()
   106  
   107  		res, err := c.Refs(ctx, &gitiles.RefsRequest{
   108  			Project:  "repo",
   109  			RefsPath: gitiles.AllRefs,
   110  		})
   111  		So(err, ShouldBeNil)
   112  		So(res.Revisions, ShouldResemble, map[string]string{
   113  			"HEAD":                     "refs/heads/master",
   114  			"refs/heads/master":        "deadbeef",
   115  			"refs/heads/infra/config":  "0000beef",
   116  			"refs/other/ref":           "ba6",
   117  			"refs/changes/01/123001/1": "123dead001beef1",
   118  			// Skipping "123dead001beef1" which has no value.
   119  		})
   120  	})
   121  	Convey("Refs heads", t, func() {
   122  		srv, c := newMockClient(func(w http.ResponseWriter, r *http.Request) {
   123  			w.WriteHeader(200)
   124  			w.Header().Set("Content-Type", "application/json")
   125  			fmt.Fprintln(w, `)]}'
   126  				{
   127  					"master": { "value": "deadbeef" },
   128  					"infra/config": { "value": "0000beef" }
   129  				}
   130  			`)
   131  		})
   132  		defer srv.Close()
   133  
   134  		res, err := c.Refs(ctx, &gitiles.RefsRequest{
   135  			Project:  "repo",
   136  			RefsPath: gitiles.Branches,
   137  		})
   138  		So(err, ShouldBeNil)
   139  		So(res.Revisions, ShouldResemble, map[string]string{
   140  			"refs/heads/master":       "deadbeef",
   141  			"refs/heads/infra/config": "0000beef",
   142  		})
   143  	})
   144  }
   145  
   146  func TestProjects(t *testing.T) {
   147  	t.Parallel()
   148  	ctx := context.Background()
   149  
   150  	Convey("List Projects", t, func() {
   151  		srv, c := newMockClient(func(w http.ResponseWriter, r *http.Request) {
   152  			w.WriteHeader(200)
   153  			w.Header().Set("Content-Type", "application/json")
   154  			fmt.Fprintln(w, `)]}'
   155  				{
   156  					"All-Projects": {
   157  						"name": "All-Projects",
   158  						"clone_url": "https://foo.googlesource.com/All-Projects",
   159  						"description": "foo"
   160  					},
   161  					"bar": {
   162  						"name": "bar",
   163  						"clone_url": "https://foo.googlesource.com/bar",
   164  						"description": "bar description"
   165  					}
   166  				}
   167  			`)
   168  		})
   169  		defer srv.Close()
   170  
   171  		res, err := c.Projects(ctx, &gitiles.ProjectsRequest{})
   172  		So(err, ShouldBeNil)
   173  		// Sort project to make it deterministic
   174  		sort.Strings(res.Projects)
   175  		So(res.Projects, ShouldResemble, []string{
   176  			"All-Projects",
   177  			"bar",
   178  		})
   179  	})
   180  }
   181  func TestList(t *testing.T) {
   182  	t.Parallel()
   183  	ctx := context.Background()
   184  
   185  	Convey("ListFiles", t, func() {
   186  		srv, c := newMockClient(func(w http.ResponseWriter, r *http.Request) {
   187  			w.WriteHeader(200)
   188  			w.Header().Set("Content-Type", "application/json")
   189  			fmt.Fprintln(w, `)]}'
   190  				{
   191  					"id": "860c9c8901a8de14bf9f6210257f2400ac19d11e",
   192  					"entries": [
   193  					{
   194  						"mode": 33188,
   195  						"type": "blob",
   196  						"id": "7e5b457d492b50762386611fc7f1302f23b313cf",
   197  						"name": "foo.txt"
   198  					},
   199  					{
   200  						"mode": 33188,
   201  						"type": "blob",
   202  						"id": "a07e845539145d1fb697c20b75689b25e266d6d6",
   203  						"name": "bar.txt"
   204  					},
   205  					{
   206  						"mode": 33188,
   207  						"type": "tree",
   208  						"id": "b90e845539145d1fb697c20b75689b25e266d6c3",
   209  						"name": "directory"
   210  					},
   211  					{
   212  						"mode": 33188,
   213  						"type": "random type",
   214  						"id": "k93b845539145d1fb697c20b75689b25e266d6q1",
   215  						"name": "new"
   216  					}
   217  					]
   218  				}
   219  			`)
   220  		})
   221  		defer srv.Close()
   222  
   223  		res, err := c.ListFiles(ctx, &gitiles.ListFilesRequest{
   224  			Project:    "project",
   225  			Committish: "main",
   226  			Path:       "path/to/dir",
   227  		})
   228  		So(err, ShouldBeNil)
   229  		So(res.Files, ShouldResemble, []*git.File{
   230  			{
   231  				Mode: 33188,
   232  				Id:   "7e5b457d492b50762386611fc7f1302f23b313cf",
   233  				Path: "foo.txt",
   234  				Type: git.File_BLOB,
   235  			},
   236  			{
   237  				Mode: 33188,
   238  				Id:   "a07e845539145d1fb697c20b75689b25e266d6d6",
   239  				Path: "bar.txt",
   240  				Type: git.File_BLOB,
   241  			},
   242  			{
   243  				Mode: 33188,
   244  				Id:   "b90e845539145d1fb697c20b75689b25e266d6c3",
   245  				Path: "directory",
   246  				Type: git.File_TREE,
   247  			},
   248  			{
   249  				Mode: 33188,
   250  				Id:   "k93b845539145d1fb697c20b75689b25e266d6q1",
   251  				Path: "new",
   252  				Type: git.File_UNKNOWN,
   253  			},
   254  		})
   255  	})
   256  }
   257  
   258  func newMockClient(handler func(w http.ResponseWriter, r *http.Request)) (*httptest.Server, gitiles.GitilesClient) {
   259  	srv := httptest.NewServer(http.HandlerFunc(handler))
   260  	return srv, &client{BaseURL: srv.URL}
   261  }
   262  
   263  var (
   264  	fakeCommit1Str = `{
   265  		"commit": "0b2c5409e58a71c691b05454b55cc5580cc822d1",
   266  		"tree": "3c6f95bc757698cd6aca3c49f88f640fd145ea69",
   267  		"parents": [ "dc1dbf1aa56e4dd4cbfaab61c4d30a35adce5f40" ],
   268  		"author": {
   269  			"name": "Author 1",
   270  			"email": "author1@example.com",
   271  			"time": "Mon Jul 17 15:02:43 2017 -0800"
   272  		},
   273  		"committer": {
   274  			"name": "Commit Bot",
   275  			"email": "commit-bot@chromium.org",
   276  			"time": "Mon Jul 17 15:02:43 2017 +0000"
   277  		},
   278  		"message": "Import wpt@d96d68ed964f9bfc2bb248c2d2fab7a8870dc685\\n\\nCr-Commit-Position: refs/heads/master@{#487078}"
   279  	}`
   280  	fakeCommit2Str = `{
   281  		"commit": "dc1dbf1aa56e4dd4cbfaab61c4d30a35adce5f40",
   282  		"tree": "1ba2335c07915c31597b97a8d824aecc85a996f6",
   283  		"parents": ["8de6836858c99e48f3c58164ab717bda728e95dd"],
   284  		"author": {
   285  			"name": "Author 2",
   286  			"email": "author-2@example.com",
   287  			"time": "Mon Jul 17 15:01:13 2017"
   288  		},
   289  		"committer": {
   290  			"name": "Commit Bot",
   291  			"email": "commit-bot@chromium.org",
   292  			"time": "Mon Jul 17 15:01:13 2017"
   293  		},
   294  		"message": "[Web Payments] User weak ptr in Payment Request\u0027s error callback\\n\\nBug: 742329\\nReviewed-on: https://chromium-review.googlesource.com/570982\\nCr-Commit-Position: refs/heads/master@{#487077}"
   295    }`
   296  )