golang.org/x/build@v0.0.0-20240506185731-218518f32b70/gerrit/gerrit_test.go (about)

     1  // Copyright 2017 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package gerrit
     6  
     7  import (
     8  	"context"
     9  	"errors"
    10  	"io"
    11  	"net/http"
    12  	"net/http/httptest"
    13  	"net/url"
    14  	"strings"
    15  	"testing"
    16  	"time"
    17  )
    18  
    19  // taken from https://go-review.googlesource.com/projects/go
    20  var exampleProjectResponse = []byte(`)]}'
    21  {
    22    "id": "go",
    23    "name": "go",
    24    "parent": "All-Projects",
    25    "description": "The Go Programming Language",
    26    "state": "ACTIVE",
    27    "web_links": [
    28      {
    29        "name": "gitiles",
    30        "url": "https://go.googlesource.com/go/",
    31        "target": "_blank"
    32      }
    33    ]
    34  }
    35  `)
    36  
    37  func TestGetProjectInfo(t *testing.T) {
    38  	hitServer := false
    39  	path := ""
    40  	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    41  		hitServer = true
    42  		path = r.URL.Path
    43  		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    44  		w.WriteHeader(200)
    45  		w.Write(exampleProjectResponse)
    46  	}))
    47  	defer s.Close()
    48  	c := NewClient(s.URL, NoAuth)
    49  	info, err := c.GetProjectInfo(context.Background(), "go")
    50  	if err != nil {
    51  		t.Fatal(err)
    52  	}
    53  	if !hitServer {
    54  		t.Errorf("expected to hit test server, didn't")
    55  	}
    56  	if path != "/projects/go" {
    57  		t.Errorf("expected Path to be '/projects/go', got %s", path)
    58  	}
    59  	if info.Name != "go" {
    60  		t.Errorf("expected Name to be 'go', got %s", info.Name)
    61  	}
    62  }
    63  
    64  func TestProjectNotFound(t *testing.T) {
    65  	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    66  		w.Header().Set("Content-Type", "text/plain; charset=UTF-8")
    67  		w.WriteHeader(404)
    68  		w.Write([]byte("Not found: unknown"))
    69  	}))
    70  	defer s.Close()
    71  	c := NewClient(s.URL, NoAuth)
    72  	_, err := c.GetProjectInfo(context.Background(), "unknown")
    73  	if !errors.Is(err, ErrResourceNotExist) {
    74  		t.Errorf("expected to get ErrResourceNotExist, got %v", err)
    75  	}
    76  }
    77  
    78  func TestContextError(t *testing.T) {
    79  	c := NewClient("http://localhost", NoAuth)
    80  	yearsAgo, _ := time.Parse("2006", "2006")
    81  	ctx, cancel := context.WithDeadline(context.Background(), yearsAgo)
    82  	defer cancel()
    83  	_, err := c.GetProjectInfo(ctx, "unknown")
    84  	if err == nil {
    85  		t.Errorf("expected non-nil error, got nil")
    86  	}
    87  	uerr, ok := err.(*url.Error)
    88  	if !ok {
    89  		t.Errorf("expected url.Error, got %#v", err)
    90  	}
    91  	if uerr.Err != context.DeadlineExceeded {
    92  		t.Errorf("expected DeadlineExceeded error, got %v", uerr.Err)
    93  	}
    94  }
    95  
    96  var getChangeResponse = []byte(`)]}'
    97  {
    98    "id": "build~master~I92989e0231299ed305ddfbbe6034d293f1c87470",
    99    "project": "build",
   100    "branch": "master",
   101    "hashtags": [],
   102    "change_id": "I92989e0231299ed305ddfbbe6034d293f1c87470",
   103    "subject": "devapp: fix tests",
   104    "status": "ABANDONED",
   105    "created": "2017-07-13 06:09:10.000000000",
   106    "updated": "2017-07-14 16:31:32.000000000",
   107    "insertions": 1,
   108    "deletions": 1,
   109    "unresolved_comment_count": 0,
   110    "has_review_started": true,
   111    "_number": 48330,
   112    "owner": {
   113      "_account_id": 13437
   114    },
   115    "messages": [
   116      {
   117        "id": "f9fcf0ff9eb58fc8edd989f8bbb3500ff73f9b11",
   118        "author": {
   119          "_account_id": 22285
   120        },
   121        "real_author": {
   122          "_account_id": 22285
   123        },
   124        "date": "2017-07-13 06:14:48.000000000",
   125        "message": "Patch Set 1:\n\nCheck out https://go-review.googlesource.com/c/48350/ :)",
   126        "_revision_number": 1
   127      }
   128    ]
   129  }`)
   130  
   131  func TestGetChange(t *testing.T) {
   132  	hitServer := false
   133  	uri := ""
   134  	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   135  		hitServer = true
   136  		uri = r.URL.RequestURI()
   137  		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
   138  		w.WriteHeader(200)
   139  		w.Write(getChangeResponse)
   140  	}))
   141  	defer s.Close()
   142  	c := NewClient(s.URL, NoAuth)
   143  	info, err := c.GetChange(context.Background(), "48330", QueryChangesOpt{
   144  		Fields: []string{"MESSAGES"},
   145  	})
   146  	if err != nil {
   147  		t.Fatal(err)
   148  	}
   149  	if !hitServer {
   150  		t.Errorf("expected to hit test server, didn't")
   151  	}
   152  	if want := "/changes/48330?o=MESSAGES"; uri != want {
   153  		t.Errorf("expected RequestURI to be %q, got %q", want, uri)
   154  	}
   155  	if len(info.Messages) != 1 {
   156  		t.Errorf("expected message length to be 1, got %d", len(info.Messages))
   157  	}
   158  	msg := info.Messages[0].Message
   159  	if !strings.Contains(msg, "Check out") {
   160  		t.Errorf("expected to find string in Message, got %s", msg)
   161  	}
   162  }
   163  
   164  func TestGetChangeError(t *testing.T) {
   165  	hitServer := false
   166  	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   167  		hitServer = true
   168  		w.Header().Set("Content-Type", "text/plain; charset=UTF-8")
   169  		w.WriteHeader(404)
   170  		io.WriteString(w, "Not found: 99999")
   171  	}))
   172  	defer s.Close()
   173  	c := NewClient(s.URL, NoAuth)
   174  	_, err := c.GetChange(context.Background(), "99999", QueryChangesOpt{
   175  		Fields: []string{"MESSAGES"},
   176  	})
   177  	if !hitServer {
   178  		t.Errorf("expected to hit test server, didn't")
   179  	}
   180  	if !errors.Is(err, ErrResourceNotExist) {
   181  		t.Errorf("expected ErrResourceNotExist, got %v", err)
   182  	}
   183  }
   184  
   185  var queryAccountsResponse = []byte(`)]}'
   186  [
   187    {
   188      "_account_id": 1,
   189      "name": "John Doe",
   190      "email": "john@doe.com"
   191    },
   192    {
   193      "_account_id": 2,
   194      "name": "Jane Doe",
   195      "email": "jane@doe.com",
   196      "_more_accounts": true
   197    }
   198  ]`)
   199  
   200  func TestQueryAccounts(t *testing.T) {
   201  	hitServer := false
   202  	uri := ""
   203  
   204  	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   205  		hitServer = true
   206  		uri = r.URL.RequestURI()
   207  		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
   208  		w.WriteHeader(200)
   209  		w.Write(queryAccountsResponse)
   210  	}))
   211  	defer s.Close()
   212  	c := NewClient(s.URL, NoAuth)
   213  	info, err := c.QueryAccounts(context.Background(), "is:active", QueryAccountsOpt{
   214  		Fields: []string{"DETAILS"},
   215  		N:      2,
   216  	})
   217  	if err != nil {
   218  		t.Fatal(err.Error())
   219  	}
   220  	if !hitServer {
   221  		t.Errorf("expected to hit test server, didn't")
   222  	}
   223  	if want := "/accounts/?n=2&o=DETAILS&q=is%3Aactive"; uri != want {
   224  		t.Errorf("expected RequestURI to be %q, got %q", want, uri)
   225  	}
   226  	if len(info) != 2 {
   227  		t.Errorf("expected accounts length to be 2, got %d", len(info))
   228  	}
   229  	if info[0].NumericID != 1 || info[0].Name != "John Doe" || info[0].Email != "john@doe.com" {
   230  		t.Errorf("expected to match John Doe in account, got %v", info[0])
   231  	}
   232  	if info[1].NumericID != 2 || info[1].Name != "Jane Doe" || info[1].Email != "jane@doe.com" {
   233  		t.Errorf("expected to match Jane Doe in account, got %v", info[1])
   234  	}
   235  	if info[0].MoreAccounts {
   236  		t.Errorf("expected to MoreAccounts to be false for John Doe")
   237  	}
   238  	if !info[1].MoreAccounts {
   239  		t.Errorf("expected to MoreAccounts to be true for Jane Doe")
   240  	}
   241  }
   242  
   243  func TestTimeStampMarshalJson(t *testing.T) {
   244  	ts := TimeStamp(time.Date(1888, 6, 24, 6, 8, 30, 123456789, time.FixedZone("+1", 3600)))
   245  	b, err := ts.MarshalJSON()
   246  	if err != nil {
   247  		t.Errorf("unexpected err %v", err)
   248  	}
   249  	expected := `"1888-06-24 05:08:30.123456789"`
   250  	if string(b) != expected {
   251  		t.Errorf("expected %q, got %q", expected, b)
   252  	}
   253  }
   254  
   255  func TestTimeStampUnmarshalJson(t *testing.T) {
   256  	var ts TimeStamp
   257  	err := ts.UnmarshalJSON([]byte(`"1888-06-24 05:08:30.123456789"`))
   258  	if err != nil {
   259  		t.Errorf("unexpected err %v", err)
   260  	}
   261  	expected := time.Date(1888, 6, 24, 5, 8, 30, 123456789, time.UTC)
   262  	if !ts.Time().Equal(expected) {
   263  		t.Errorf("expected %v, got %v", expected, ts.Time())
   264  	}
   265  }
   266  
   267  // taken from https://gerrit-review.googlesource.com/Documentation/rest-api-projects.html#list-tags
   268  var exampleProjectTagsResponse = []byte(`  )]}'
   269    [
   270      {
   271        "ref": "refs/tags/v1.0",
   272        "revision": "49ce77fdcfd3398dc0dedbe016d1a425fd52d666",
   273        "object": "1624f5af8ae89148d1a3730df8c290413e3dcf30",
   274        "message": "Annotated tag",
   275        "tagger": {
   276          "name": "David Pursehouse",
   277          "email": "david.pursehouse@sonymobile.com",
   278          "date": "2014-10-06 07:35:03.000000000",
   279          "tz": 540
   280        }
   281      },
   282      {
   283        "ref": "refs/tags/v2.0",
   284        "revision": "1624f5af8ae89148d1a3730df8c290413e3dcf30"
   285      }
   286    ]
   287  `)
   288  
   289  func TestGetProjectTags(t *testing.T) {
   290  	hitServer := false
   291  	path := ""
   292  	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   293  		hitServer = true
   294  		path = r.URL.Path
   295  		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
   296  		w.WriteHeader(200)
   297  		w.Write(exampleProjectTagsResponse)
   298  	}))
   299  	defer s.Close()
   300  	c := NewClient(s.URL, NoAuth)
   301  	tags, err := c.GetProjectTags(context.Background(), "go")
   302  	if err != nil {
   303  		t.Fatal(err)
   304  	}
   305  	if !hitServer {
   306  		t.Errorf("expected to hit test server, didn't")
   307  	}
   308  	if path != "/projects/go/tags/" {
   309  		t.Errorf("expected Path to be '/projects/go/tags/', got %s", path)
   310  	}
   311  	expectedTags := map[string]TagInfo{
   312  		"refs/tags/v1.0": TagInfo{
   313  			Ref:      "refs/tags/v1.0",
   314  			Revision: "49ce77fdcfd3398dc0dedbe016d1a425fd52d666",
   315  			Object:   "1624f5af8ae89148d1a3730df8c290413e3dcf30",
   316  			Message:  "Annotated tag",
   317  			Tagger: &GitPersonInfo{
   318  				Name:     "David Pursehouse",
   319  				Email:    "david.pursehouse@sonymobile.com",
   320  				Date:     TimeStamp(time.Date(2014, 10, 6, 7, 35, 3, 0, time.UTC)),
   321  				TZOffset: 540,
   322  			},
   323  		},
   324  		"refs/tags/v2.0": TagInfo{
   325  			Ref:      "refs/tags/v2.0",
   326  			Revision: "1624f5af8ae89148d1a3730df8c290413e3dcf30",
   327  		},
   328  	}
   329  	if len(tags) != len(expectedTags) {
   330  		t.Errorf("expected %d tags, got %d", len(expectedTags), len(tags))
   331  	}
   332  	for ref, tag := range tags {
   333  		expectedTag, found := expectedTags[ref]
   334  		if !found {
   335  			t.Errorf("unexpected tag %q", ref)
   336  		}
   337  		if !tag.Equal(&expectedTag) {
   338  			t.Errorf("tags don't match (expected %#v and got %#v)", expectedTag, tag)
   339  		}
   340  	}
   341  }