github.com/google/go-github/v49@v49.1.0/github/git_trees_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 "bytes" 10 "context" 11 "fmt" 12 "io" 13 "net/http" 14 "testing" 15 16 "github.com/google/go-cmp/cmp" 17 ) 18 19 func TestMarshalJSON_withNilContentAndSHA(t *testing.T) { 20 te := &TreeEntry{ 21 Path: String("path"), 22 Mode: String("mode"), 23 Type: String("type"), 24 Size: Int(1), 25 URL: String("url"), 26 } 27 28 got, err := te.MarshalJSON() 29 if err != nil { 30 t.Errorf("MarshalJSON: %v", err) 31 } 32 33 want := `{"sha":null,"path":"path","mode":"mode","type":"type"}` 34 if string(got) != want { 35 t.Errorf("MarshalJSON = %s, want %v", got, want) 36 } 37 } 38 39 func TestGitService_GetTree(t *testing.T) { 40 client, mux, _, teardown := setup() 41 defer teardown() 42 43 mux.HandleFunc("/repos/o/r/git/trees/s", func(w http.ResponseWriter, r *http.Request) { 44 testMethod(t, r, "GET") 45 fmt.Fprint(w, `{ 46 "sha": "s", 47 "tree": [ { "type": "blob" } ], 48 "truncated": true 49 }`) 50 }) 51 52 ctx := context.Background() 53 tree, _, err := client.Git.GetTree(ctx, "o", "r", "s", true) 54 if err != nil { 55 t.Errorf("Git.GetTree returned error: %v", err) 56 } 57 58 want := Tree{ 59 SHA: String("s"), 60 Entries: []*TreeEntry{ 61 { 62 Type: String("blob"), 63 }, 64 }, 65 Truncated: Bool(true), 66 } 67 if !cmp.Equal(*tree, want) { 68 t.Errorf("Tree.Get returned %+v, want %+v", *tree, want) 69 } 70 71 const methodName = "GetTree" 72 testBadOptions(t, methodName, func() (err error) { 73 _, _, err = client.Git.GetTree(ctx, "\n", "\n", "\n", true) 74 return err 75 }) 76 77 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 78 got, resp, err := client.Git.GetTree(ctx, "o", "r", "s", true) 79 if got != nil { 80 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 81 } 82 return resp, err 83 }) 84 } 85 86 func TestGitService_GetTree_invalidOwner(t *testing.T) { 87 client, _, _, teardown := setup() 88 defer teardown() 89 90 ctx := context.Background() 91 _, _, err := client.Git.GetTree(ctx, "%", "%", "%", false) 92 testURLParseError(t, err) 93 } 94 95 func TestGitService_CreateTree(t *testing.T) { 96 client, mux, _, teardown := setup() 97 defer teardown() 98 99 input := []*TreeEntry{ 100 { 101 Path: String("file.rb"), 102 Mode: String("100644"), 103 Type: String("blob"), 104 SHA: String("7c258a9869f33c1e1e1f74fbb32f07c86cb5a75b"), 105 }, 106 } 107 108 mux.HandleFunc("/repos/o/r/git/trees", func(w http.ResponseWriter, r *http.Request) { 109 got, err := io.ReadAll(r.Body) 110 if err != nil { 111 t.Fatalf("unable to read body: %v", err) 112 } 113 114 testMethod(t, r, "POST") 115 116 want := []byte(`{"base_tree":"b","tree":[{"sha":"7c258a9869f33c1e1e1f74fbb32f07c86cb5a75b","path":"file.rb","mode":"100644","type":"blob"}]}` + "\n") 117 if !bytes.Equal(got, want) { 118 t.Errorf("Git.CreateTree request body: %s, want %s", got, want) 119 } 120 121 fmt.Fprint(w, `{ 122 "sha": "cd8274d15fa3ae2ab983129fb037999f264ba9a7", 123 "tree": [ 124 { 125 "path": "file.rb", 126 "mode": "100644", 127 "type": "blob", 128 "size": 132, 129 "sha": "7c258a9869f33c1e1e1f74fbb32f07c86cb5a75b" 130 } 131 ] 132 }`) 133 }) 134 135 ctx := context.Background() 136 tree, _, err := client.Git.CreateTree(ctx, "o", "r", "b", input) 137 if err != nil { 138 t.Errorf("Git.CreateTree returned error: %v", err) 139 } 140 141 want := Tree{ 142 String("cd8274d15fa3ae2ab983129fb037999f264ba9a7"), 143 []*TreeEntry{ 144 { 145 Path: String("file.rb"), 146 Mode: String("100644"), 147 Type: String("blob"), 148 Size: Int(132), 149 SHA: String("7c258a9869f33c1e1e1f74fbb32f07c86cb5a75b"), 150 }, 151 }, 152 nil, 153 } 154 155 if !cmp.Equal(*tree, want) { 156 t.Errorf("Git.CreateTree returned %+v, want %+v", *tree, want) 157 } 158 159 const methodName = "CreateTree" 160 testBadOptions(t, methodName, func() (err error) { 161 _, _, err = client.Git.CreateTree(ctx, "\n", "\n", "\n", input) 162 return err 163 }) 164 165 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 166 got, resp, err := client.Git.CreateTree(ctx, "o", "r", "b", input) 167 if got != nil { 168 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 169 } 170 return resp, err 171 }) 172 } 173 174 func TestGitService_CreateTree_Content(t *testing.T) { 175 client, mux, _, teardown := setup() 176 defer teardown() 177 178 input := []*TreeEntry{ 179 { 180 Path: String("content.md"), 181 Mode: String("100644"), 182 Content: String("file content"), 183 }, 184 } 185 186 mux.HandleFunc("/repos/o/r/git/trees", func(w http.ResponseWriter, r *http.Request) { 187 got, err := io.ReadAll(r.Body) 188 if err != nil { 189 t.Fatalf("unable to read body: %v", err) 190 } 191 192 testMethod(t, r, "POST") 193 194 want := []byte(`{"base_tree":"b","tree":[{"path":"content.md","mode":"100644","content":"file content"}]}` + "\n") 195 if !bytes.Equal(got, want) { 196 t.Errorf("Git.CreateTree request body: %s, want %s", got, want) 197 } 198 199 fmt.Fprint(w, `{ 200 "sha": "5c6780ad2c68743383b740fd1dab6f6a33202b11", 201 "url": "https://api.github.com/repos/o/r/git/trees/5c6780ad2c68743383b740fd1dab6f6a33202b11", 202 "tree": [ 203 { 204 "mode": "100644", 205 "type": "blob", 206 "sha": "aad8feacf6f8063150476a7b2bd9770f2794c08b", 207 "path": "content.md", 208 "size": 12, 209 "url": "https://api.github.com/repos/o/r/git/blobs/aad8feacf6f8063150476a7b2bd9770f2794c08b" 210 } 211 ] 212 }`) 213 }) 214 215 ctx := context.Background() 216 tree, _, err := client.Git.CreateTree(ctx, "o", "r", "b", input) 217 if err != nil { 218 t.Errorf("Git.CreateTree returned error: %v", err) 219 } 220 221 want := Tree{ 222 String("5c6780ad2c68743383b740fd1dab6f6a33202b11"), 223 []*TreeEntry{ 224 { 225 Path: String("content.md"), 226 Mode: String("100644"), 227 Type: String("blob"), 228 Size: Int(12), 229 SHA: String("aad8feacf6f8063150476a7b2bd9770f2794c08b"), 230 URL: String("https://api.github.com/repos/o/r/git/blobs/aad8feacf6f8063150476a7b2bd9770f2794c08b"), 231 }, 232 }, 233 nil, 234 } 235 236 if !cmp.Equal(*tree, want) { 237 t.Errorf("Git.CreateTree returned %+v, want %+v", *tree, want) 238 } 239 240 const methodName = "CreateTree" 241 testBadOptions(t, methodName, func() (err error) { 242 _, _, err = client.Git.CreateTree(ctx, "\n", "\n", "\n", input) 243 return err 244 }) 245 246 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 247 got, resp, err := client.Git.CreateTree(ctx, "o", "r", "b", input) 248 if got != nil { 249 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 250 } 251 return resp, err 252 }) 253 } 254 255 func TestGitService_CreateTree_Delete(t *testing.T) { 256 client, mux, _, teardown := setup() 257 defer teardown() 258 259 input := []*TreeEntry{ 260 { 261 Path: String("content.md"), 262 Mode: String("100644"), 263 }, 264 } 265 266 mux.HandleFunc("/repos/o/r/git/trees", func(w http.ResponseWriter, r *http.Request) { 267 got, err := io.ReadAll(r.Body) 268 if err != nil { 269 t.Fatalf("unable to read body: %v", err) 270 } 271 272 testMethod(t, r, "POST") 273 274 want := []byte(`{"base_tree":"b","tree":[{"sha":null,"path":"content.md","mode":"100644"}]}` + "\n") 275 if !bytes.Equal(got, want) { 276 t.Errorf("Git.CreateTree request body: %s, want %s", got, want) 277 } 278 279 fmt.Fprint(w, `{ 280 "sha": "5c6780ad2c68743383b740fd1dab6f6a33202b11", 281 "url": "https://api.github.com/repos/o/r/git/trees/5c6780ad2c68743383b740fd1dab6f6a33202b11", 282 "tree": [ 283 { 284 "mode": "100644", 285 "type": "blob", 286 "sha": null, 287 "path": "content.md", 288 "size": 12, 289 "url": "https://api.github.com/repos/o/r/git/blobs/aad8feacf6f8063150476a7b2bd9770f2794c08b" 290 } 291 ] 292 }`) 293 }) 294 295 ctx := context.Background() 296 tree, _, err := client.Git.CreateTree(ctx, "o", "r", "b", input) 297 if err != nil { 298 t.Errorf("Git.CreateTree returned error: %v", err) 299 } 300 301 want := Tree{ 302 String("5c6780ad2c68743383b740fd1dab6f6a33202b11"), 303 []*TreeEntry{ 304 { 305 Path: String("content.md"), 306 Mode: String("100644"), 307 Type: String("blob"), 308 Size: Int(12), 309 SHA: nil, 310 URL: String("https://api.github.com/repos/o/r/git/blobs/aad8feacf6f8063150476a7b2bd9770f2794c08b"), 311 }, 312 }, 313 nil, 314 } 315 316 if !cmp.Equal(*tree, want) { 317 t.Errorf("Git.CreateTree returned %+v, want %+v", *tree, want) 318 } 319 320 const methodName = "CreateTree" 321 testBadOptions(t, methodName, func() (err error) { 322 _, _, err = client.Git.CreateTree(ctx, "\n", "\n", "\n", input) 323 return err 324 }) 325 326 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 327 got, resp, err := client.Git.CreateTree(ctx, "o", "r", "b", input) 328 if got != nil { 329 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 330 } 331 return resp, err 332 }) 333 } 334 335 func TestGitService_CreateTree_invalidOwner(t *testing.T) { 336 client, _, _, teardown := setup() 337 defer teardown() 338 339 ctx := context.Background() 340 _, _, err := client.Git.CreateTree(ctx, "%", "%", "", nil) 341 testURLParseError(t, err) 342 } 343 344 func TestTree_Marshal(t *testing.T) { 345 testJSONMarshal(t, &Tree{}, "{}") 346 347 u := &Tree{ 348 SHA: String("sha"), 349 Entries: []*TreeEntry{ 350 { 351 SHA: String("sha"), 352 Path: String("path"), 353 Mode: String("mode"), 354 Type: String("type"), 355 Size: Int(1), 356 Content: String("content"), 357 URL: String("url"), 358 }, 359 }, 360 Truncated: Bool(false), 361 } 362 363 want := `{ 364 "sha": "sha", 365 "tree": [ 366 { 367 "sha": "sha", 368 "path": "path", 369 "mode": "mode", 370 "type": "type", 371 "size": 1, 372 "content": "content", 373 "url": "url" 374 } 375 ], 376 "truncated": false 377 }` 378 379 testJSONMarshal(t, u, want) 380 } 381 382 func TestTreeEntry_Marshal(t *testing.T) { 383 testJSONMarshal(t, &TreeEntry{}, "{}") 384 385 u := &TreeEntry{ 386 SHA: String("sha"), 387 Path: String("path"), 388 Mode: String("mode"), 389 Type: String("type"), 390 Size: Int(1), 391 Content: String("content"), 392 URL: String("url"), 393 } 394 395 want := `{ 396 "sha": "sha", 397 "path": "path", 398 "mode": "mode", 399 "type": "type", 400 "size": 1, 401 "content": "content", 402 "url": "url" 403 }` 404 405 testJSONMarshal(t, u, want) 406 } 407 408 func TestTreeEntryWithFileDelete_Marshal(t *testing.T) { 409 testJSONMarshal(t, &treeEntryWithFileDelete{}, "{}") 410 411 u := &treeEntryWithFileDelete{ 412 SHA: String("sha"), 413 Path: String("path"), 414 Mode: String("mode"), 415 Type: String("type"), 416 Size: Int(1), 417 Content: String("content"), 418 URL: String("url"), 419 } 420 421 want := `{ 422 "sha": "sha", 423 "path": "path", 424 "mode": "mode", 425 "type": "type", 426 "size": 1, 427 "content": "content", 428 "url": "url" 429 }` 430 431 testJSONMarshal(t, u, want) 432 } 433 434 func TestCreateTree_Marshal(t *testing.T) { 435 testJSONMarshal(t, &createTree{}, "{}") 436 437 u := &createTree{ 438 BaseTree: "bt", 439 Entries: []interface{}{"e"}, 440 } 441 442 want := `{ 443 "base_tree": "bt", 444 "tree": ["e"] 445 }` 446 447 testJSONMarshal(t, u, want) 448 }