1// Copyright 2014 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 6package github 7 8import ( 9 "context" 10 "fmt" 11 "io/ioutil" 12 "net/http" 13 "reflect" 14 "testing" 15) 16 17func TestRepositoryContent_GetContent(t *testing.T) { 18 tests := []struct { 19 encoding, content *string // input encoding and content 20 want string // desired output 21 wantErr bool // whether an error is expected 22 }{ 23 { 24 encoding: String(""), 25 content: String("hello"), 26 want: "hello", 27 wantErr: false, 28 }, 29 { 30 encoding: nil, 31 content: String("hello"), 32 want: "hello", 33 wantErr: false, 34 }, 35 { 36 encoding: nil, 37 content: nil, 38 want: "", 39 wantErr: false, 40 }, 41 { 42 encoding: String("base64"), 43 content: String("aGVsbG8="), 44 want: "hello", 45 wantErr: false, 46 }, 47 { 48 encoding: String("bad"), 49 content: String("aGVsbG8="), 50 want: "", 51 wantErr: true, 52 }, 53 } 54 55 for _, tt := range tests { 56 r := RepositoryContent{Encoding: tt.encoding, Content: tt.content} 57 got, err := r.GetContent() 58 if err != nil && !tt.wantErr { 59 t.Errorf("RepositoryContent(%s, %s) returned unexpected error: %v", 60 stringOrNil(tt.encoding), stringOrNil(tt.content), err) 61 } 62 if err == nil && tt.wantErr { 63 t.Errorf("RepositoryContent(%s, %s) did not return unexpected error", 64 stringOrNil(tt.encoding), stringOrNil(tt.content)) 65 } 66 if want := tt.want; got != want { 67 t.Errorf("RepositoryContent.GetContent returned %+v, want %+v", got, want) 68 } 69 } 70} 71 72// stringOrNil converts a potentially null string pointer to string. 73// For non-nil input pointer, the returned string is enclosed in double-quotes. 74func stringOrNil(s *string) string { 75 if s == nil { 76 return "<nil>" 77 } 78 return fmt.Sprintf("%q", *s) 79} 80 81func TestRepositoriesService_GetReadme(t *testing.T) { 82 client, mux, _, teardown := setup() 83 defer teardown() 84 mux.HandleFunc("/repos/o/r/readme", func(w http.ResponseWriter, r *http.Request) { 85 testMethod(t, r, "GET") 86 fmt.Fprint(w, `{ 87 "type": "file", 88 "encoding": "base64", 89 "size": 5362, 90 "name": "README.md", 91 "path": "README.md" 92 }`) 93 }) 94 readme, _, err := client.Repositories.GetReadme(context.Background(), "o", "r", &RepositoryContentGetOptions{}) 95 if err != nil { 96 t.Errorf("Repositories.GetReadme returned error: %v", err) 97 } 98 want := &RepositoryContent{Type: String("file"), Name: String("README.md"), Size: Int(5362), Encoding: String("base64"), Path: String("README.md")} 99 if !reflect.DeepEqual(readme, want) { 100 t.Errorf("Repositories.GetReadme returned %+v, want %+v", readme, want) 101 } 102} 103 104func TestRepositoriesService_DownloadContents_Success(t *testing.T) { 105 client, mux, serverURL, teardown := setup() 106 defer teardown() 107 mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) { 108 testMethod(t, r, "GET") 109 fmt.Fprint(w, `[{ 110 "type": "file", 111 "name": "f", 112 "download_url": "`+serverURL+baseURLPath+`/download/f" 113 }]`) 114 }) 115 mux.HandleFunc("/download/f", func(w http.ResponseWriter, r *http.Request) { 116 testMethod(t, r, "GET") 117 fmt.Fprint(w, "foo") 118 }) 119 120 r, err := client.Repositories.DownloadContents(context.Background(), "o", "r", "d/f", nil) 121 if err != nil { 122 t.Errorf("Repositories.DownloadContents returned error: %v", err) 123 } 124 125 bytes, err := ioutil.ReadAll(r) 126 if err != nil { 127 t.Errorf("Error reading response body: %v", err) 128 } 129 r.Close() 130 131 if got, want := string(bytes), "foo"; got != want { 132 t.Errorf("Repositories.DownloadContents returned %v, want %v", got, want) 133 } 134} 135 136func TestRepositoriesService_DownloadContents_NoDownloadURL(t *testing.T) { 137 client, mux, _, teardown := setup() 138 defer teardown() 139 mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) { 140 testMethod(t, r, "GET") 141 fmt.Fprint(w, `[{ 142 "type": "file", 143 "name": "f", 144 }]`) 145 }) 146 147 _, err := client.Repositories.DownloadContents(context.Background(), "o", "r", "d/f", nil) 148 if err == nil { 149 t.Errorf("Repositories.DownloadContents did not return expected error") 150 } 151} 152 153func TestRepositoriesService_DownloadContents_NoFile(t *testing.T) { 154 client, mux, _, teardown := setup() 155 defer teardown() 156 mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) { 157 testMethod(t, r, "GET") 158 fmt.Fprint(w, `[]`) 159 }) 160 161 _, err := client.Repositories.DownloadContents(context.Background(), "o", "r", "d/f", nil) 162 if err == nil { 163 t.Errorf("Repositories.DownloadContents did not return expected error") 164 } 165} 166 167func TestRepositoriesService_GetContents_File(t *testing.T) { 168 client, mux, _, teardown := setup() 169 defer teardown() 170 mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { 171 testMethod(t, r, "GET") 172 fmt.Fprint(w, `{ 173 "type": "file", 174 "encoding": "base64", 175 "size": 20678, 176 "name": "LICENSE", 177 "path": "LICENSE" 178 }`) 179 }) 180 fileContents, _, _, err := client.Repositories.GetContents(context.Background(), "o", "r", "p", &RepositoryContentGetOptions{}) 181 if err != nil { 182 t.Errorf("Repositories.GetContents returned error: %v", err) 183 } 184 want := &RepositoryContent{Type: String("file"), Name: String("LICENSE"), Size: Int(20678), Encoding: String("base64"), Path: String("LICENSE")} 185 if !reflect.DeepEqual(fileContents, want) { 186 t.Errorf("Repositories.GetContents returned %+v, want %+v", fileContents, want) 187 } 188} 189 190func TestRepositoriesService_GetContents_FilenameNeedsEscape(t *testing.T) { 191 client, mux, _, teardown := setup() 192 defer teardown() 193 mux.HandleFunc("/repos/o/r/contents/p#?%/中.go", func(w http.ResponseWriter, r *http.Request) { 194 testMethod(t, r, "GET") 195 fmt.Fprint(w, `{}`) 196 }) 197 _, _, _, err := client.Repositories.GetContents(context.Background(), "o", "r", "p#?%/中.go", &RepositoryContentGetOptions{}) 198 if err != nil { 199 t.Fatalf("Repositories.GetContents returned error: %v", err) 200 } 201} 202 203func TestRepositoriesService_GetContents_DirectoryWithSpaces(t *testing.T) { 204 client, mux, _, teardown := setup() 205 defer teardown() 206 mux.HandleFunc("/repos/o/r/contents/some directory/file.go", func(w http.ResponseWriter, r *http.Request) { 207 testMethod(t, r, "GET") 208 fmt.Fprint(w, `{}`) 209 }) 210 _, _, _, err := client.Repositories.GetContents(context.Background(), "o", "r", "some directory/file.go", &RepositoryContentGetOptions{}) 211 if err != nil { 212 t.Fatalf("Repositories.GetContents returned error: %v", err) 213 } 214} 215 216func TestRepositoriesService_GetContents_DirectoryWithPlusChars(t *testing.T) { 217 client, mux, _, teardown := setup() 218 defer teardown() 219 mux.HandleFunc("/repos/o/r/contents/some directory+name/file.go", func(w http.ResponseWriter, r *http.Request) { 220 testMethod(t, r, "GET") 221 fmt.Fprint(w, `{}`) 222 }) 223 _, _, _, err := client.Repositories.GetContents(context.Background(), "o", "r", "some directory+name/file.go", &RepositoryContentGetOptions{}) 224 if err != nil { 225 t.Fatalf("Repositories.GetContents returned error: %v", err) 226 } 227} 228 229func TestRepositoriesService_GetContents_Directory(t *testing.T) { 230 client, mux, _, teardown := setup() 231 defer teardown() 232 mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { 233 testMethod(t, r, "GET") 234 fmt.Fprint(w, `[{ 235 "type": "dir", 236 "name": "lib", 237 "path": "lib" 238 }, 239 { 240 "type": "file", 241 "size": 20678, 242 "name": "LICENSE", 243 "path": "LICENSE" 244 }]`) 245 }) 246 _, directoryContents, _, err := client.Repositories.GetContents(context.Background(), "o", "r", "p", &RepositoryContentGetOptions{}) 247 if err != nil { 248 t.Errorf("Repositories.GetContents returned error: %v", err) 249 } 250 want := []*RepositoryContent{{Type: String("dir"), Name: String("lib"), Path: String("lib")}, 251 {Type: String("file"), Name: String("LICENSE"), Size: Int(20678), Path: String("LICENSE")}} 252 if !reflect.DeepEqual(directoryContents, want) { 253 t.Errorf("Repositories.GetContents_Directory returned %+v, want %+v", directoryContents, want) 254 } 255} 256 257func TestRepositoriesService_CreateFile(t *testing.T) { 258 client, mux, _, teardown := setup() 259 defer teardown() 260 mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { 261 testMethod(t, r, "PUT") 262 fmt.Fprint(w, `{ 263 "content":{ 264 "name":"p" 265 }, 266 "commit":{ 267 "message":"m", 268 "sha":"f5f369044773ff9c6383c087466d12adb6fa0828" 269 } 270 }`) 271 }) 272 message := "m" 273 content := []byte("c") 274 repositoryContentsOptions := &RepositoryContentFileOptions{ 275 Message: &message, 276 Content: content, 277 Committer: &CommitAuthor{Name: String("n"), Email: String("e")}, 278 } 279 createResponse, _, err := client.Repositories.CreateFile(context.Background(), "o", "r", "p", repositoryContentsOptions) 280 if err != nil { 281 t.Errorf("Repositories.CreateFile returned error: %v", err) 282 } 283 want := &RepositoryContentResponse{ 284 Content: &RepositoryContent{Name: String("p")}, 285 Commit: Commit{ 286 Message: String("m"), 287 SHA: String("f5f369044773ff9c6383c087466d12adb6fa0828"), 288 }, 289 } 290 if !reflect.DeepEqual(createResponse, want) { 291 t.Errorf("Repositories.CreateFile returned %+v, want %+v", createResponse, want) 292 } 293} 294 295func TestRepositoriesService_UpdateFile(t *testing.T) { 296 client, mux, _, teardown := setup() 297 defer teardown() 298 mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { 299 testMethod(t, r, "PUT") 300 fmt.Fprint(w, `{ 301 "content":{ 302 "name":"p" 303 }, 304 "commit":{ 305 "message":"m", 306 "sha":"f5f369044773ff9c6383c087466d12adb6fa0828" 307 } 308 }`) 309 }) 310 message := "m" 311 content := []byte("c") 312 sha := "f5f369044773ff9c6383c087466d12adb6fa0828" 313 repositoryContentsOptions := &RepositoryContentFileOptions{ 314 Message: &message, 315 Content: content, 316 SHA: &sha, 317 Committer: &CommitAuthor{Name: String("n"), Email: String("e")}, 318 } 319 updateResponse, _, err := client.Repositories.UpdateFile(context.Background(), "o", "r", "p", repositoryContentsOptions) 320 if err != nil { 321 t.Errorf("Repositories.UpdateFile returned error: %v", err) 322 } 323 want := &RepositoryContentResponse{ 324 Content: &RepositoryContent{Name: String("p")}, 325 Commit: Commit{ 326 Message: String("m"), 327 SHA: String("f5f369044773ff9c6383c087466d12adb6fa0828"), 328 }, 329 } 330 if !reflect.DeepEqual(updateResponse, want) { 331 t.Errorf("Repositories.UpdateFile returned %+v, want %+v", updateResponse, want) 332 } 333} 334 335func TestRepositoriesService_DeleteFile(t *testing.T) { 336 client, mux, _, teardown := setup() 337 defer teardown() 338 mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { 339 testMethod(t, r, "DELETE") 340 fmt.Fprint(w, `{ 341 "content": null, 342 "commit":{ 343 "message":"m", 344 "sha":"f5f369044773ff9c6383c087466d12adb6fa0828" 345 } 346 }`) 347 }) 348 message := "m" 349 sha := "f5f369044773ff9c6383c087466d12adb6fa0828" 350 repositoryContentsOptions := &RepositoryContentFileOptions{ 351 Message: &message, 352 SHA: &sha, 353 Committer: &CommitAuthor{Name: String("n"), Email: String("e")}, 354 } 355 deleteResponse, _, err := client.Repositories.DeleteFile(context.Background(), "o", "r", "p", repositoryContentsOptions) 356 if err != nil { 357 t.Errorf("Repositories.DeleteFile returned error: %v", err) 358 } 359 want := &RepositoryContentResponse{ 360 Content: nil, 361 Commit: Commit{ 362 Message: String("m"), 363 SHA: String("f5f369044773ff9c6383c087466d12adb6fa0828"), 364 }, 365 } 366 if !reflect.DeepEqual(deleteResponse, want) { 367 t.Errorf("Repositories.DeleteFile returned %+v, want %+v", deleteResponse, want) 368 } 369} 370 371func TestRepositoriesService_GetArchiveLink(t *testing.T) { 372 client, mux, _, teardown := setup() 373 defer teardown() 374 mux.HandleFunc("/repos/o/r/tarball", func(w http.ResponseWriter, r *http.Request) { 375 testMethod(t, r, "GET") 376 http.Redirect(w, r, "http://github.com/a", http.StatusFound) 377 }) 378 url, resp, err := client.Repositories.GetArchiveLink(context.Background(), "o", "r", Tarball, &RepositoryContentGetOptions{}) 379 if err != nil { 380 t.Errorf("Repositories.GetArchiveLink returned error: %v", err) 381 } 382 if resp.StatusCode != http.StatusFound { 383 t.Errorf("Repositories.GetArchiveLink returned status: %d, want %d", resp.StatusCode, http.StatusFound) 384 } 385 want := "http://github.com/a" 386 if url.String() != want { 387 t.Errorf("Repositories.GetArchiveLink returned %+v, want %+v", url.String(), want) 388 } 389} 390