github.com/google/go-github/v70@v70.0.0/github/git_commits_test.go (about)

     1  // Copyright 2013 The go-github AUTHORS. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package github
     7  
     8  import (
     9  	"context"
    10  	"encoding/json"
    11  	"errors"
    12  	"fmt"
    13  	"io"
    14  	"net/http"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/google/go-cmp/cmp"
    19  )
    20  
    21  func mockSigner(t *testing.T, signature string, emitErr error, wantMessage string) MessageSignerFunc {
    22  	return func(w io.Writer, r io.Reader) error {
    23  		t.Helper()
    24  		message, err := io.ReadAll(r)
    25  		assertNilError(t, err)
    26  		if wantMessage != "" && string(message) != wantMessage {
    27  			t.Errorf("MessageSignerFunc got %q, want %q", string(message), wantMessage)
    28  		}
    29  		assertWrite(t, w, []byte(signature))
    30  		return emitErr
    31  	}
    32  }
    33  
    34  func uncalledSigner(t *testing.T) MessageSignerFunc {
    35  	return func(w io.Writer, r io.Reader) error {
    36  		t.Error("MessageSignerFunc should not be called")
    37  		return nil
    38  	}
    39  }
    40  
    41  func TestCommit_Marshal(t *testing.T) {
    42  	t.Parallel()
    43  	testJSONMarshal(t, &Commit{}, "{}")
    44  
    45  	u := &Commit{
    46  		SHA: Ptr("s"),
    47  		Author: &CommitAuthor{
    48  			Date:  &Timestamp{referenceTime},
    49  			Name:  Ptr("n"),
    50  			Email: Ptr("e"),
    51  			Login: Ptr("u"),
    52  		},
    53  		Committer: &CommitAuthor{
    54  			Date:  &Timestamp{referenceTime},
    55  			Name:  Ptr("n"),
    56  			Email: Ptr("e"),
    57  			Login: Ptr("u"),
    58  		},
    59  		Message: Ptr("m"),
    60  		Tree: &Tree{
    61  			SHA: Ptr("s"),
    62  			Entries: []*TreeEntry{{
    63  				SHA:     Ptr("s"),
    64  				Path:    Ptr("p"),
    65  				Mode:    Ptr("m"),
    66  				Type:    Ptr("t"),
    67  				Size:    Ptr(1),
    68  				Content: Ptr("c"),
    69  				URL:     Ptr("u"),
    70  			}},
    71  			Truncated: Ptr(false),
    72  		},
    73  		Parents: nil,
    74  		HTMLURL: Ptr("h"),
    75  		URL:     Ptr("u"),
    76  		Verification: &SignatureVerification{
    77  			Verified:  Ptr(false),
    78  			Reason:    Ptr("r"),
    79  			Signature: Ptr("s"),
    80  			Payload:   Ptr("p"),
    81  		},
    82  		NodeID:       Ptr("n"),
    83  		CommentCount: Ptr(1),
    84  	}
    85  
    86  	want := `{
    87  		"sha": "s",
    88  		"author": {
    89  			"date": ` + referenceTimeStr + `,
    90  			"name": "n",
    91  			"email": "e",
    92  			"username": "u"
    93  		},
    94  		"committer": {
    95  			"date": ` + referenceTimeStr + `,
    96  			"name": "n",
    97  			"email": "e",
    98  			"username": "u"
    99  		},
   100  		"message": "m",
   101  		"tree": {
   102  			"sha": "s",
   103  			"tree": [
   104  				{
   105  					"sha": "s",
   106  					"path": "p",
   107  					"mode": "m",
   108  					"type": "t",
   109  					"size": 1,
   110  					"content": "c",
   111  					"url": "u"
   112  				}
   113  			],
   114  			"truncated": false
   115  		},
   116  		"html_url": "h",
   117  		"url": "u",
   118  		"verification": {
   119  			"verified": false,
   120  			"reason": "r",
   121  			"signature": "s",
   122  			"payload": "p"
   123  		},
   124  		"node_id": "n",
   125  		"comment_count": 1
   126  	}`
   127  
   128  	testJSONMarshal(t, u, want)
   129  }
   130  
   131  func TestGitService_GetCommit(t *testing.T) {
   132  	t.Parallel()
   133  	client, mux, _ := setup(t)
   134  
   135  	mux.HandleFunc("/repos/o/r/git/commits/s", func(w http.ResponseWriter, r *http.Request) {
   136  		testMethod(t, r, "GET")
   137  		fmt.Fprint(w, `{"sha":"s","message":"Commit Message.","author":{"name":"n"}}`)
   138  	})
   139  
   140  	ctx := context.Background()
   141  	commit, _, err := client.Git.GetCommit(ctx, "o", "r", "s")
   142  	if err != nil {
   143  		t.Errorf("Git.GetCommit returned error: %v", err)
   144  	}
   145  
   146  	want := &Commit{SHA: Ptr("s"), Message: Ptr("Commit Message."), Author: &CommitAuthor{Name: Ptr("n")}}
   147  	if !cmp.Equal(commit, want) {
   148  		t.Errorf("Git.GetCommit returned %+v, want %+v", commit, want)
   149  	}
   150  
   151  	const methodName = "GetCommit"
   152  	testBadOptions(t, methodName, func() (err error) {
   153  		_, _, err = client.Git.GetCommit(ctx, "\n", "\n", "\n")
   154  		return err
   155  	})
   156  
   157  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   158  		got, resp, err := client.Git.GetCommit(ctx, "o", "r", "s")
   159  		if got != nil {
   160  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   161  		}
   162  		return resp, err
   163  	})
   164  }
   165  
   166  func TestGitService_GetCommit_invalidOwner(t *testing.T) {
   167  	t.Parallel()
   168  	client, _, _ := setup(t)
   169  
   170  	ctx := context.Background()
   171  	_, _, err := client.Git.GetCommit(ctx, "%", "%", "%")
   172  	testURLParseError(t, err)
   173  }
   174  
   175  func TestGitService_CreateCommit(t *testing.T) {
   176  	t.Parallel()
   177  	client, mux, _ := setup(t)
   178  
   179  	input := &Commit{
   180  		Message: Ptr("Commit Message."),
   181  		Tree:    &Tree{SHA: Ptr("t")},
   182  		Parents: []*Commit{{SHA: Ptr("p")}},
   183  	}
   184  
   185  	mux.HandleFunc("/repos/o/r/git/commits", func(w http.ResponseWriter, r *http.Request) {
   186  		v := new(createCommit)
   187  		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
   188  
   189  		testMethod(t, r, "POST")
   190  
   191  		want := &createCommit{
   192  			Message: input.Message,
   193  			Tree:    Ptr("t"),
   194  			Parents: []string{"p"},
   195  		}
   196  		if !cmp.Equal(v, want) {
   197  			t.Errorf("Request body = %+v, want %+v", v, want)
   198  		}
   199  		fmt.Fprint(w, `{"sha":"s"}`)
   200  	})
   201  
   202  	ctx := context.Background()
   203  	commit, _, err := client.Git.CreateCommit(ctx, "o", "r", input, nil)
   204  	if err != nil {
   205  		t.Errorf("Git.CreateCommit returned error: %v", err)
   206  	}
   207  
   208  	want := &Commit{SHA: Ptr("s")}
   209  	if !cmp.Equal(commit, want) {
   210  		t.Errorf("Git.CreateCommit returned %+v, want %+v", commit, want)
   211  	}
   212  
   213  	const methodName = "CreateCommit"
   214  	testBadOptions(t, methodName, func() (err error) {
   215  		_, _, err = client.Git.CreateCommit(ctx, "\n", "\n", input, nil)
   216  		return err
   217  	})
   218  
   219  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   220  		got, resp, err := client.Git.CreateCommit(ctx, "o", "r", input, nil)
   221  		if got != nil {
   222  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   223  		}
   224  		return resp, err
   225  	})
   226  }
   227  
   228  func TestGitService_CreateSignedCommit(t *testing.T) {
   229  	t.Parallel()
   230  	client, mux, _ := setup(t)
   231  
   232  	signature := "----- BEGIN PGP SIGNATURE -----\n\naaaa\naaaa\n----- END PGP SIGNATURE -----"
   233  
   234  	input := &Commit{
   235  		Message: Ptr("Commit Message."),
   236  		Tree:    &Tree{SHA: Ptr("t")},
   237  		Parents: []*Commit{{SHA: Ptr("p")}},
   238  		Verification: &SignatureVerification{
   239  			Signature: Ptr(signature),
   240  		},
   241  	}
   242  
   243  	mux.HandleFunc("/repos/o/r/git/commits", func(w http.ResponseWriter, r *http.Request) {
   244  		v := new(createCommit)
   245  		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
   246  
   247  		testMethod(t, r, "POST")
   248  
   249  		want := &createCommit{
   250  			Message:   input.Message,
   251  			Tree:      Ptr("t"),
   252  			Parents:   []string{"p"},
   253  			Signature: Ptr(signature),
   254  		}
   255  		if !cmp.Equal(v, want) {
   256  			t.Errorf("Request body = %+v, want %+v", v, want)
   257  		}
   258  		fmt.Fprint(w, `{"sha":"commitSha"}`)
   259  	})
   260  
   261  	ctx := context.Background()
   262  	commit, _, err := client.Git.CreateCommit(ctx, "o", "r", input, nil)
   263  	if err != nil {
   264  		t.Errorf("Git.CreateCommit returned error: %v", err)
   265  	}
   266  
   267  	want := &Commit{SHA: Ptr("commitSha")}
   268  	if !cmp.Equal(commit, want) {
   269  		t.Errorf("Git.CreateCommit returned %+v, want %+v", commit, want)
   270  	}
   271  
   272  	const methodName = "CreateCommit"
   273  	testBadOptions(t, methodName, func() (err error) {
   274  		_, _, err = client.Git.CreateCommit(ctx, "\n", "\n", input, nil)
   275  		return err
   276  	})
   277  
   278  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   279  		got, resp, err := client.Git.CreateCommit(ctx, "o", "r", input, nil)
   280  		if got != nil {
   281  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   282  		}
   283  		return resp, err
   284  	})
   285  }
   286  
   287  func TestGitService_CreateSignedCommitWithInvalidParams(t *testing.T) {
   288  	t.Parallel()
   289  	client, _, _ := setup(t)
   290  
   291  	input := &Commit{}
   292  
   293  	ctx := context.Background()
   294  	opts := CreateCommitOptions{Signer: uncalledSigner(t)}
   295  	_, _, err := client.Git.CreateCommit(ctx, "o", "r", input, &opts)
   296  	if err == nil {
   297  		t.Errorf("Expected error to be returned because invalid params were passed")
   298  	}
   299  }
   300  
   301  func TestGitService_CreateCommitWithNilCommit(t *testing.T) {
   302  	t.Parallel()
   303  	client, _, _ := setup(t)
   304  
   305  	ctx := context.Background()
   306  	_, _, err := client.Git.CreateCommit(ctx, "o", "r", nil, nil)
   307  	if err == nil {
   308  		t.Errorf("Expected error to be returned because commit=nil")
   309  	}
   310  }
   311  
   312  func TestGitService_CreateCommit_WithSigner(t *testing.T) {
   313  	t.Parallel()
   314  	client, mux, _ := setup(t)
   315  
   316  	signature := "my voice is my password"
   317  	date := time.Date(2017, time.May, 4, 0, 3, 43, 0, time.FixedZone("CEST", 2*3600))
   318  	author := CommitAuthor{
   319  		Name:  Ptr("go-github"),
   320  		Email: Ptr("go-github@github.com"),
   321  		Date:  &Timestamp{date},
   322  	}
   323  	wantMessage := `tree t
   324  parent p
   325  author go-github <go-github@github.com> 1493849023 +0200
   326  committer go-github <go-github@github.com> 1493849023 +0200
   327  
   328  Commit Message.`
   329  	sha := "commitSha"
   330  	input := &Commit{
   331  		SHA:     &sha,
   332  		Message: Ptr("Commit Message."),
   333  		Tree:    &Tree{SHA: Ptr("t")},
   334  		Parents: []*Commit{{SHA: Ptr("p")}},
   335  		Author:  &author,
   336  	}
   337  	wantBody := createCommit{
   338  		Message:   input.Message,
   339  		Tree:      Ptr("t"),
   340  		Parents:   []string{"p"},
   341  		Author:    &author,
   342  		Signature: &signature,
   343  	}
   344  	var gotBody createCommit
   345  	mux.HandleFunc("/repos/o/r/git/commits", func(w http.ResponseWriter, r *http.Request) {
   346  		assertNilError(t, json.NewDecoder(r.Body).Decode(&gotBody))
   347  		testMethod(t, r, "POST")
   348  		fmt.Fprintf(w, `{"sha":"%s"}`, sha)
   349  	})
   350  	ctx := context.Background()
   351  	wantCommit := &Commit{SHA: Ptr(sha)}
   352  	opts := CreateCommitOptions{Signer: mockSigner(t, signature, nil, wantMessage)}
   353  	commit, _, err := client.Git.CreateCommit(ctx, "o", "r", input, &opts)
   354  	assertNilError(t, err)
   355  	if cmp.Diff(gotBody, wantBody) != "" {
   356  		t.Errorf("Request body = %+v, want %+v\n%s", gotBody, wantBody, cmp.Diff(gotBody, wantBody))
   357  	}
   358  	if cmp.Diff(commit, wantCommit) != "" {
   359  		t.Errorf("Git.CreateCommit returned %+v, want %+v\n%s", commit, wantCommit, cmp.Diff(commit, wantCommit))
   360  	}
   361  }
   362  
   363  func TestGitService_createSignature_nilSigner(t *testing.T) {
   364  	t.Parallel()
   365  	a := &createCommit{
   366  		Message: Ptr("Commit Message."),
   367  		Tree:    Ptr("t"),
   368  		Parents: []string{"p"},
   369  	}
   370  
   371  	_, err := createSignature(nil, a)
   372  
   373  	if err == nil {
   374  		t.Errorf("Expected error to be returned because no author was passed")
   375  	}
   376  }
   377  
   378  func TestGitService_createSignature_nilCommit(t *testing.T) {
   379  	t.Parallel()
   380  	_, err := createSignature(uncalledSigner(t), nil)
   381  
   382  	if err == nil {
   383  		t.Errorf("Expected error to be returned because no author was passed")
   384  	}
   385  }
   386  
   387  func TestGitService_createSignature_signerError(t *testing.T) {
   388  	t.Parallel()
   389  	a := &createCommit{
   390  		Message: Ptr("Commit Message."),
   391  		Tree:    Ptr("t"),
   392  		Parents: []string{"p"},
   393  		Author:  &CommitAuthor{Name: Ptr("go-github")},
   394  	}
   395  
   396  	signer := mockSigner(t, "", errors.New("signer error"), "")
   397  	_, err := createSignature(signer, a)
   398  
   399  	if err == nil {
   400  		t.Errorf("Expected error to be returned because signer returned an error")
   401  	}
   402  }
   403  
   404  func TestGitService_createSignatureMessage_nilCommit(t *testing.T) {
   405  	t.Parallel()
   406  	_, err := createSignatureMessage(nil)
   407  	if err == nil {
   408  		t.Errorf("Expected error to be returned due to nil key")
   409  	}
   410  }
   411  
   412  func TestGitService_createSignatureMessage_nilMessage(t *testing.T) {
   413  	t.Parallel()
   414  	date, _ := time.Parse("Mon Jan 02 15:04:05 2006 -0700", "Thu May 04 00:03:43 2017 +0200")
   415  
   416  	_, err := createSignatureMessage(&createCommit{
   417  		Message: nil,
   418  		Parents: []string{"p"},
   419  		Author: &CommitAuthor{
   420  			Name:  Ptr("go-github"),
   421  			Email: Ptr("go-github@github.com"),
   422  			Date:  &Timestamp{date},
   423  		},
   424  	})
   425  	if err == nil {
   426  		t.Errorf("Expected error to be returned due to nil key")
   427  	}
   428  }
   429  
   430  func TestGitService_createSignatureMessage_emptyMessage(t *testing.T) {
   431  	t.Parallel()
   432  	date, _ := time.Parse("Mon Jan 02 15:04:05 2006 -0700", "Thu May 04 00:03:43 2017 +0200")
   433  	emptyString := ""
   434  	_, err := createSignatureMessage(&createCommit{
   435  		Message: &emptyString,
   436  		Parents: []string{"p"},
   437  		Author: &CommitAuthor{
   438  			Name:  Ptr("go-github"),
   439  			Email: Ptr("go-github@github.com"),
   440  			Date:  &Timestamp{date},
   441  		},
   442  	})
   443  	if err == nil {
   444  		t.Errorf("Expected error to be returned due to nil key")
   445  	}
   446  }
   447  
   448  func TestGitService_createSignatureMessage_nilAuthor(t *testing.T) {
   449  	t.Parallel()
   450  	_, err := createSignatureMessage(&createCommit{
   451  		Message: Ptr("Commit Message."),
   452  		Parents: []string{"p"},
   453  		Author:  nil,
   454  	})
   455  	if err == nil {
   456  		t.Errorf("Expected error to be returned due to nil key")
   457  	}
   458  }
   459  
   460  func TestGitService_createSignatureMessage_withoutTree(t *testing.T) {
   461  	t.Parallel()
   462  	date, _ := time.Parse("Mon Jan 02 15:04:05 2006 -0700", "Thu May 04 00:03:43 2017 +0200")
   463  
   464  	msg, _ := createSignatureMessage(&createCommit{
   465  		Message: Ptr("Commit Message."),
   466  		Parents: []string{"p"},
   467  		Author: &CommitAuthor{
   468  			Name:  Ptr("go-github"),
   469  			Email: Ptr("go-github@github.com"),
   470  			Date:  &Timestamp{date},
   471  		},
   472  	})
   473  	expected := `parent p
   474  author go-github <go-github@github.com> 1493849023 +0200
   475  committer go-github <go-github@github.com> 1493849023 +0200
   476  
   477  Commit Message.`
   478  	if msg != expected {
   479  		t.Errorf("Returned message incorrect. returned %s, want %s", msg, expected)
   480  	}
   481  }
   482  
   483  func TestGitService_createSignatureMessage_withoutCommitter(t *testing.T) {
   484  	t.Parallel()
   485  	date, _ := time.Parse("Mon Jan 02 15:04:05 2006 -0700", "Thu May 04 00:03:43 2017 +0200")
   486  
   487  	msg, _ := createSignatureMessage(&createCommit{
   488  		Message: Ptr("Commit Message."),
   489  		Parents: []string{"p"},
   490  		Author: &CommitAuthor{
   491  			Name:  Ptr("go-github"),
   492  			Email: Ptr("go-github@github.com"),
   493  			Date:  &Timestamp{date},
   494  		},
   495  		Committer: &CommitAuthor{
   496  			Name:  Ptr("foo"),
   497  			Email: Ptr("foo@bar.com"),
   498  			Date:  &Timestamp{date},
   499  		},
   500  	})
   501  	expected := `parent p
   502  author go-github <go-github@github.com> 1493849023 +0200
   503  committer foo <foo@bar.com> 1493849023 +0200
   504  
   505  Commit Message.`
   506  	if msg != expected {
   507  		t.Errorf("Returned message incorrect. returned %s, want %s", msg, expected)
   508  	}
   509  }
   510  
   511  func TestGitService_CreateCommit_invalidOwner(t *testing.T) {
   512  	t.Parallel()
   513  	client, _, _ := setup(t)
   514  
   515  	ctx := context.Background()
   516  	_, _, err := client.Git.CreateCommit(ctx, "%", "%", &Commit{}, nil)
   517  	testURLParseError(t, err)
   518  }
   519  
   520  func TestSignatureVerification_Marshal(t *testing.T) {
   521  	t.Parallel()
   522  	testJSONMarshal(t, &SignatureVerification{}, "{}")
   523  
   524  	u := &SignatureVerification{
   525  		Verified:  Ptr(true),
   526  		Reason:    Ptr("reason"),
   527  		Signature: Ptr("sign"),
   528  		Payload:   Ptr("payload"),
   529  	}
   530  
   531  	want := `{
   532  		"verified": true,
   533  		"reason": "reason",
   534  		"signature": "sign",
   535  		"payload": "payload"
   536  	}`
   537  
   538  	testJSONMarshal(t, u, want)
   539  }
   540  
   541  func TestCommitAuthor_Marshal(t *testing.T) {
   542  	t.Parallel()
   543  	testJSONMarshal(t, &CommitAuthor{}, "{}")
   544  
   545  	u := &CommitAuthor{
   546  		Date:  &Timestamp{referenceTime},
   547  		Name:  Ptr("name"),
   548  		Email: Ptr("email"),
   549  		Login: Ptr("login"),
   550  	}
   551  
   552  	want := `{
   553  		"date": ` + referenceTimeStr + `,
   554  		"name": "name",
   555  		"email": "email",
   556  		"username": "login"
   557  	}`
   558  
   559  	testJSONMarshal(t, u, want)
   560  }
   561  
   562  func TestCreateCommit_Marshal(t *testing.T) {
   563  	t.Parallel()
   564  	testJSONMarshal(t, &createCommit{}, "{}")
   565  
   566  	u := &createCommit{
   567  		Author: &CommitAuthor{
   568  			Date:  &Timestamp{referenceTime},
   569  			Name:  Ptr("name"),
   570  			Email: Ptr("email"),
   571  			Login: Ptr("login"),
   572  		},
   573  		Committer: &CommitAuthor{
   574  			Date:  &Timestamp{referenceTime},
   575  			Name:  Ptr("name"),
   576  			Email: Ptr("email"),
   577  			Login: Ptr("login"),
   578  		},
   579  		Message:   Ptr("message"),
   580  		Tree:      Ptr("tree"),
   581  		Parents:   []string{"p"},
   582  		Signature: Ptr("sign"),
   583  	}
   584  
   585  	want := `{
   586  		"author": {
   587  			"date": ` + referenceTimeStr + `,
   588  			"name": "name",
   589  			"email": "email",
   590  			"username": "login"
   591  		},
   592  		"committer": {
   593  			"date": ` + referenceTimeStr + `,
   594  			"name": "name",
   595  			"email": "email",
   596  			"username": "login"
   597  		},
   598  		"message": "message",
   599  		"tree": "tree",
   600  		"parents": [
   601  			"p"
   602  		],
   603  		"signature": "sign"
   604  	}`
   605  
   606  	testJSONMarshal(t, u, want)
   607  }