github.com/google/go-github/v33@v33.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 "fmt" 12 "net/http" 13 "reflect" 14 "strings" 15 "testing" 16 "time" 17 18 "golang.org/x/crypto/openpgp" 19 ) 20 21 func TestCommit_Marshal(t *testing.T) { 22 testJSONMarshal(t, &Commit{}, "{}") 23 24 u := &Commit{ 25 SHA: String("s"), 26 Author: &CommitAuthor{ 27 Date: &referenceTime, 28 Name: String("n"), 29 Email: String("e"), 30 Login: String("u"), 31 }, 32 Committer: &CommitAuthor{ 33 Date: &referenceTime, 34 Name: String("n"), 35 Email: String("e"), 36 Login: String("u"), 37 }, 38 Message: String("m"), 39 Tree: &Tree{ 40 SHA: String("s"), 41 Entries: []*TreeEntry{{ 42 SHA: String("s"), 43 Path: String("p"), 44 Mode: String("m"), 45 Type: String("t"), 46 Size: Int(1), 47 Content: String("c"), 48 URL: String("u"), 49 }}, 50 Truncated: Bool(false), 51 }, 52 Parents: nil, 53 Stats: &CommitStats{ 54 Additions: Int(1), 55 Deletions: Int(1), 56 Total: Int(1), 57 }, 58 HTMLURL: String("h"), 59 URL: String("u"), 60 Verification: &SignatureVerification{ 61 Verified: Bool(false), 62 Reason: String("r"), 63 Signature: String("s"), 64 Payload: String("p"), 65 }, 66 NodeID: String("n"), 67 CommentCount: Int(1), 68 SigningKey: &openpgp.Entity{}, 69 } 70 71 want := `{ 72 "sha": "s", 73 "author": { 74 "date": ` + referenceTimeStr + `, 75 "name": "n", 76 "email": "e", 77 "username": "u" 78 }, 79 "committer": { 80 "date": ` + referenceTimeStr + `, 81 "name": "n", 82 "email": "e", 83 "username": "u" 84 }, 85 "message": "m", 86 "tree": { 87 "sha": "s", 88 "tree": [ 89 { 90 "sha": "s", 91 "path": "p", 92 "mode": "m", 93 "type": "t", 94 "size": 1, 95 "content": "c", 96 "url": "u" 97 } 98 ], 99 "truncated": false 100 }, 101 "stats": { 102 "additions": 1, 103 "deletions": 1, 104 "total": 1 105 }, 106 "html_url": "h", 107 "url": "u", 108 "verification": { 109 "verified": false, 110 "reason": "r", 111 "signature": "s", 112 "payload": "p" 113 }, 114 "node_id": "n", 115 "comment_count": 1 116 }` 117 118 testJSONMarshal(t, u, want) 119 } 120 121 func TestGitService_GetCommit(t *testing.T) { 122 client, mux, _, teardown := setup() 123 defer teardown() 124 125 mux.HandleFunc("/repos/o/r/git/commits/s", func(w http.ResponseWriter, r *http.Request) { 126 testMethod(t, r, "GET") 127 fmt.Fprint(w, `{"sha":"s","message":"Commit Message.","author":{"name":"n"}}`) 128 }) 129 130 commit, _, err := client.Git.GetCommit(context.Background(), "o", "r", "s") 131 if err != nil { 132 t.Errorf("Git.GetCommit returned error: %v", err) 133 } 134 135 want := &Commit{SHA: String("s"), Message: String("Commit Message."), Author: &CommitAuthor{Name: String("n")}} 136 if !reflect.DeepEqual(commit, want) { 137 t.Errorf("Git.GetCommit returned %+v, want %+v", commit, want) 138 } 139 } 140 141 func TestGitService_GetCommit_invalidOwner(t *testing.T) { 142 client, _, _, teardown := setup() 143 defer teardown() 144 145 _, _, err := client.Git.GetCommit(context.Background(), "%", "%", "%") 146 testURLParseError(t, err) 147 } 148 149 func TestGitService_CreateCommit(t *testing.T) { 150 client, mux, _, teardown := setup() 151 defer teardown() 152 153 input := &Commit{ 154 Message: String("Commit Message."), 155 Tree: &Tree{SHA: String("t")}, 156 Parents: []*Commit{{SHA: String("p")}}, 157 } 158 159 mux.HandleFunc("/repos/o/r/git/commits", func(w http.ResponseWriter, r *http.Request) { 160 v := new(createCommit) 161 json.NewDecoder(r.Body).Decode(v) 162 163 testMethod(t, r, "POST") 164 165 want := &createCommit{ 166 Message: input.Message, 167 Tree: String("t"), 168 Parents: []string{"p"}, 169 } 170 if !reflect.DeepEqual(v, want) { 171 t.Errorf("Request body = %+v, want %+v", v, want) 172 } 173 fmt.Fprint(w, `{"sha":"s"}`) 174 }) 175 176 commit, _, err := client.Git.CreateCommit(context.Background(), "o", "r", input) 177 if err != nil { 178 t.Errorf("Git.CreateCommit returned error: %v", err) 179 } 180 181 want := &Commit{SHA: String("s")} 182 if !reflect.DeepEqual(commit, want) { 183 t.Errorf("Git.CreateCommit returned %+v, want %+v", commit, want) 184 } 185 } 186 187 func TestGitService_CreateSignedCommit(t *testing.T) { 188 client, mux, _, teardown := setup() 189 defer teardown() 190 191 signature := "----- BEGIN PGP SIGNATURE -----\n\naaaa\naaaa\n----- END PGP SIGNATURE -----" 192 193 input := &Commit{ 194 Message: String("Commit Message."), 195 Tree: &Tree{SHA: String("t")}, 196 Parents: []*Commit{{SHA: String("p")}}, 197 Verification: &SignatureVerification{ 198 Signature: String(signature), 199 }, 200 } 201 202 mux.HandleFunc("/repos/o/r/git/commits", func(w http.ResponseWriter, r *http.Request) { 203 v := new(createCommit) 204 json.NewDecoder(r.Body).Decode(v) 205 206 testMethod(t, r, "POST") 207 208 want := &createCommit{ 209 Message: input.Message, 210 Tree: String("t"), 211 Parents: []string{"p"}, 212 Signature: String(signature), 213 } 214 if !reflect.DeepEqual(v, want) { 215 t.Errorf("Request body = %+v, want %+v", v, want) 216 } 217 fmt.Fprint(w, `{"sha":"commitSha"}`) 218 }) 219 220 commit, _, err := client.Git.CreateCommit(context.Background(), "o", "r", input) 221 if err != nil { 222 t.Errorf("Git.CreateCommit returned error: %v", err) 223 } 224 225 want := &Commit{SHA: String("commitSha")} 226 if !reflect.DeepEqual(commit, want) { 227 t.Errorf("Git.CreateCommit returned %+v, want %+v", commit, want) 228 } 229 } 230 func TestGitService_CreateSignedCommitWithInvalidParams(t *testing.T) { 231 client, _, _, teardown := setup() 232 defer teardown() 233 234 input := &Commit{ 235 SigningKey: &openpgp.Entity{}, 236 } 237 238 _, _, err := client.Git.CreateCommit(context.Background(), "o", "r", input) 239 if err == nil { 240 t.Errorf("Expected error to be returned because invalid params was passed") 241 } 242 } 243 244 func TestGitService_CreateSignedCommitWithKey(t *testing.T) { 245 client, mux, _, teardown := setup() 246 defer teardown() 247 s := strings.NewReader(testGPGKey) 248 keyring, err := openpgp.ReadArmoredKeyRing(s) 249 if err != nil { 250 t.Errorf("Error reading keyring: %+v", err) 251 } 252 253 date, _ := time.Parse("Mon Jan 02 15:04:05 2006 -0700", "Thu May 04 00:03:43 2017 +0200") 254 author := CommitAuthor{ 255 Name: String("go-github"), 256 Email: String("go-github@github.com"), 257 Date: &date, 258 } 259 input := &Commit{ 260 Message: String("Commit Message."), 261 Tree: &Tree{SHA: String("t")}, 262 Parents: []*Commit{{SHA: String("p")}}, 263 SigningKey: keyring[0], 264 Author: &author, 265 } 266 267 messageReader := strings.NewReader(`tree t 268 parent p 269 author go-github <go-github@github.com> 1493849023 +0200 270 committer go-github <go-github@github.com> 1493849023 +0200 271 272 Commit Message.`) 273 274 mux.HandleFunc("/repos/o/r/git/commits", func(w http.ResponseWriter, r *http.Request) { 275 v := new(createCommit) 276 json.NewDecoder(r.Body).Decode(v) 277 278 testMethod(t, r, "POST") 279 280 want := &createCommit{ 281 Message: input.Message, 282 Tree: String("t"), 283 Parents: []string{"p"}, 284 Author: &author, 285 } 286 287 sigReader := strings.NewReader(*v.Signature) 288 signer, err := openpgp.CheckArmoredDetachedSignature(keyring, messageReader, sigReader) 289 if err != nil { 290 t.Errorf("Error verifying signature: %+v", err) 291 } 292 if signer.Identities["go-github <go-github@github.com>"].Name != "go-github <go-github@github.com>" { 293 t.Errorf("Signer is incorrect. got: %+v, want %+v", signer.Identities["go-github <go-github@github.com>"].Name, "go-github <go-github@github.com>") 294 } 295 // Nullify Signature since we checked it above 296 v.Signature = nil 297 if !reflect.DeepEqual(v, want) { 298 t.Errorf("Request body = %+v, want %+v", v, want) 299 } 300 fmt.Fprint(w, `{"sha":"commitSha"}`) 301 }) 302 303 commit, _, err := client.Git.CreateCommit(context.Background(), "o", "r", input) 304 if err != nil { 305 t.Errorf("Git.CreateCommit returned error: %v", err) 306 } 307 308 want := &Commit{SHA: String("commitSha")} 309 if !reflect.DeepEqual(commit, want) { 310 t.Errorf("Git.CreateCommit returned %+v, want %+v", commit, want) 311 } 312 } 313 314 func TestGitService_createSignature_nilSigningKey(t *testing.T) { 315 a := &createCommit{ 316 Message: String("Commit Message."), 317 Tree: String("t"), 318 Parents: []string{"p"}, 319 } 320 321 _, err := createSignature(nil, a) 322 323 if err == nil { 324 t.Errorf("Expected error to be returned because no author was passed") 325 } 326 } 327 328 func TestGitService_createSignature_nilCommit(t *testing.T) { 329 _, err := createSignature(&openpgp.Entity{}, nil) 330 331 if err == nil { 332 t.Errorf("Expected error to be returned because no author was passed") 333 } 334 } 335 336 func TestGitService_createSignature_noAuthor(t *testing.T) { 337 a := &createCommit{ 338 Message: String("Commit Message."), 339 Tree: String("t"), 340 Parents: []string{"p"}, 341 } 342 343 _, err := createSignature(&openpgp.Entity{}, a) 344 345 if err == nil { 346 t.Errorf("Expected error to be returned because no author was passed") 347 } 348 } 349 350 func TestGitService_createSignature_invalidKey(t *testing.T) { 351 date, _ := time.Parse("Mon Jan 02 15:04:05 2006 -0700", "Thu May 04 00:03:43 2017 +0200") 352 353 _, err := createSignature(&openpgp.Entity{}, &createCommit{ 354 Message: String("Commit Message."), 355 Tree: String("t"), 356 Parents: []string{"p"}, 357 Author: &CommitAuthor{ 358 Name: String("go-github"), 359 Email: String("go-github@github.com"), 360 Date: &date, 361 }, 362 }) 363 364 if err == nil { 365 t.Errorf("Expected error to be returned due to invalid key") 366 } 367 } 368 369 func TestGitService_createSignatureMessage_nilCommit(t *testing.T) { 370 _, err := createSignatureMessage(nil) 371 if err == nil { 372 t.Errorf("Expected error to be returned due to nil key") 373 } 374 } 375 376 func TestGitService_createSignatureMessage_nilMessage(t *testing.T) { 377 date, _ := time.Parse("Mon Jan 02 15:04:05 2006 -0700", "Thu May 04 00:03:43 2017 +0200") 378 379 _, err := createSignatureMessage(&createCommit{ 380 Message: nil, 381 Parents: []string{"p"}, 382 Author: &CommitAuthor{ 383 Name: String("go-github"), 384 Email: String("go-github@github.com"), 385 Date: &date, 386 }, 387 }) 388 if err == nil { 389 t.Errorf("Expected error to be returned due to nil key") 390 } 391 } 392 393 func TestGitService_createSignatureMessage_emptyMessage(t *testing.T) { 394 date, _ := time.Parse("Mon Jan 02 15:04:05 2006 -0700", "Thu May 04 00:03:43 2017 +0200") 395 emptyString := "" 396 _, err := createSignatureMessage(&createCommit{ 397 Message: &emptyString, 398 Parents: []string{"p"}, 399 Author: &CommitAuthor{ 400 Name: String("go-github"), 401 Email: String("go-github@github.com"), 402 Date: &date, 403 }, 404 }) 405 if err == nil { 406 t.Errorf("Expected error to be returned due to nil key") 407 } 408 } 409 410 func TestGitService_createSignatureMessage_nilAuthor(t *testing.T) { 411 _, err := createSignatureMessage(&createCommit{ 412 Message: String("Commit Message."), 413 Parents: []string{"p"}, 414 Author: nil, 415 }) 416 if err == nil { 417 t.Errorf("Expected error to be returned due to nil key") 418 } 419 } 420 421 func TestGitService_createSignatureMessage_withoutTree(t *testing.T) { 422 date, _ := time.Parse("Mon Jan 02 15:04:05 2006 -0700", "Thu May 04 00:03:43 2017 +0200") 423 424 msg, _ := createSignatureMessage(&createCommit{ 425 Message: String("Commit Message."), 426 Parents: []string{"p"}, 427 Author: &CommitAuthor{ 428 Name: String("go-github"), 429 Email: String("go-github@github.com"), 430 Date: &date, 431 }, 432 }) 433 expected := `parent p 434 author go-github <go-github@github.com> 1493849023 +0200 435 committer go-github <go-github@github.com> 1493849023 +0200 436 437 Commit Message.` 438 if msg != expected { 439 t.Errorf("Returned message incorrect. returned %s, want %s", msg, expected) 440 } 441 } 442 443 func TestGitService_createSignatureMessage_withoutCommitter(t *testing.T) { 444 date, _ := time.Parse("Mon Jan 02 15:04:05 2006 -0700", "Thu May 04 00:03:43 2017 +0200") 445 446 msg, _ := createSignatureMessage(&createCommit{ 447 Message: String("Commit Message."), 448 Parents: []string{"p"}, 449 Author: &CommitAuthor{ 450 Name: String("go-github"), 451 Email: String("go-github@github.com"), 452 Date: &date, 453 }, 454 Committer: &CommitAuthor{ 455 Name: String("foo"), 456 Email: String("foo@bar.com"), 457 Date: &date, 458 }, 459 }) 460 expected := `parent p 461 author go-github <go-github@github.com> 1493849023 +0200 462 committer foo <foo@bar.com> 1493849023 +0200 463 464 Commit Message.` 465 if msg != expected { 466 t.Errorf("Returned message incorrect. returned %s, want %s", msg, expected) 467 } 468 } 469 470 func TestGitService_CreateCommit_invalidOwner(t *testing.T) { 471 client, _, _, teardown := setup() 472 defer teardown() 473 474 _, _, err := client.Git.CreateCommit(context.Background(), "%", "%", &Commit{}) 475 testURLParseError(t, err) 476 } 477 478 const testGPGKey = ` 479 -----BEGIN PGP PRIVATE KEY BLOCK----- 480 481 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 534 =VFSn 535 -----END PGP PRIVATE KEY BLOCK-----`