github.com/atlassian/git-lob@v0.0.0-20150806085256-2386a5ed291a/providers/smart/persistent_test.go (about) 1 package smart 2 3 import ( 4 "bufio" 5 "bytes" 6 "encoding/json" 7 "fmt" 8 "io" 9 "net" 10 "strings" 11 12 . "github.com/atlassian/git-lob/Godeps/_workspace/src/github.com/onsi/ginkgo" 13 . "github.com/atlassian/git-lob/Godeps/_workspace/src/github.com/onsi/gomega" 14 ) 15 16 var _ = Describe("Persistent Transport", func() { 17 18 Context("Test JSON marshalling", func() { 19 type TestStruct struct { 20 Name string 21 Something int 22 } 23 It("Encodes JSON requests correctly", func() { 24 25 params := &TestStruct{Name: "Steve", Something: 99} 26 req, err := NewJsonRequest("TestMethod", params) 27 Expect(err).To(BeNil(), "Should create request without error") 28 reqbytes, err := json.Marshal(req) 29 Expect(err).To(BeNil(), "Should marshal without error") 30 Expect(string(reqbytes)).To(Equal(`{"Id":1,"Method":"TestMethod","Params":{"Name":"Steve","Something":99}}`), "Encoded JSON should be correct") 31 32 }) 33 It("Decodes JSON requests correctly", func() { 34 inputstruct := TestStruct{Name: "Steve", Something: 99} 35 resp, err := NewJsonResponse(1, inputstruct) 36 Expect(err).To(BeNil(), "Should create response without error") 37 outputstruct := TestStruct{} 38 // Now unmarshal nested result; need to extract json first 39 innerbytes, err := resp.Result.MarshalJSON() 40 Expect(err).To(BeNil(), "Extracting JSON from RawMessage should succeed") 41 err = json.Unmarshal(innerbytes, &outputstruct) 42 Expect(outputstruct).To(Equal(inputstruct), "Unmarshalled nested struct should match") 43 }) 44 45 }) 46 47 Context("Test individual server requests", func() { 48 metasThatExist := []string{ 49 "0000000000000000000000000000000000000000", 50 "0000012300000004560000000000789000000000", 51 } 52 chunksThatExist := []string{ 53 "0000000000000000000000000000000000000000", 54 "0000012300000004560000000000789000000000", 55 } 56 chunkIndexesThatExist := [][]int{ 57 []int{0, 1}, 58 []int{0, 1, 3, 4, 5, 7}, 59 } 60 chunkSizes := [][]int64{ // only for first couple of chunks, testing only 61 []int64{16777216, 150}, 62 []int64{16777216, 3210}, 63 } 64 65 testsha := "5e0865e76e8956900c3ef6fec2d2af1c05f31ec4" 66 metacontent := `{"SHA":"5e0865e76e8956900c3ef6fec2d2af1c05f31ec4","Size":21982,"NumChunks":4}` 67 // Content doesn't actually matter here, just create some random data 68 // Make sure it's big enough to require > 1 callback 69 testchunkdatasz := PersistentTransportBufferSize*3 + 157 70 testchunkidx := 3 71 testlobsize := 10002 72 var testchunkdata []byte 73 pickloblist := []string{"1234567890abcdef1234567890abcdef12345678", testsha, "0000000000000000000011111111112222222222"} 74 deltaBaseSHA := "1234567890abcdef1234567890abcdef12345678" 75 deltaTargetSHA := "5e0865e76e8956900c3ef6fec2d2af1c05f31ec4" 76 77 BeforeEach(func() { 78 testchunkdata = make([]byte, testchunkdatasz) 79 // put something interesting in it so we can detect it at each end 80 testchunkdata[0] = 'a' 81 testchunkdata[1] = '1' 82 testchunkdata[2] = '6' 83 testchunkdata[testchunkdatasz-1] = 'z' 84 testchunkdata[testchunkdatasz-2] = '2' 85 testchunkdata[testchunkdatasz-3] = '5' 86 87 }) 88 89 // Test server function here, just called over a pipe to test 90 serve := func(conn net.Conn) { 91 defer GinkgoRecover() 92 defer conn.Close() 93 // Run in a goroutine, be the server you seek 94 // Read a request 95 rdr := bufio.NewReader(conn) 96 for { 97 jsonbytes, err := rdr.ReadBytes(byte(0)) 98 if err != nil { 99 if err == io.EOF { 100 break 101 } 102 Fail(fmt.Sprintf("Test persistent server: unable to read from client: %v", err.Error())) 103 } 104 // slice off the terminator 105 jsonbytes = jsonbytes[:len(jsonbytes)-1] 106 var req JsonRequest 107 err = json.Unmarshal(jsonbytes, &req) 108 Expect(err).To(BeNil(), fmt.Sprintf("Test persistent server: unable to unmarshal json request from client:%v", string(jsonbytes))) 109 var resp *JsonResponse 110 allowedCaps := []string{"Feature1", "Feature2", "OMGSOAWESOME"} 111 switch req.Method { 112 case "QueryCaps": 113 result := QueryCapsResponse{Caps: allowedCaps} 114 resp, err = NewJsonResponse(req.Id, result) 115 Expect(err).To(BeNil(), "Test persistent server: unable to create response") 116 case "SetEnabledCaps": 117 capsreq := SetEnabledCapsRequest{} 118 ExtractStructFromJsonRawMessage(req.Params, &capsreq) 119 result := SetEnabledCapsResponse{} 120 resp, err = NewJsonResponse(req.Id, result) 121 Expect(err).To(BeNil(), "Test persistent server: unable to create response") 122 // test for error condition 123 for _, c := range capsreq.EnableCaps { 124 ok := false 125 for _, s := range allowedCaps { 126 if c == s { 127 ok = true 128 break 129 } 130 } 131 if !ok { 132 resp.Error = fmt.Sprintf("Unsupported capability: %v", c) 133 break 134 } 135 136 } 137 case "FileExists": 138 fereq := FileExistsRequest{} 139 var strerr string 140 ExtractStructFromJsonRawMessage(req.Params, &fereq) 141 result := FileExistsResponse{} 142 if fereq.Type == "chunk" { 143 for i, chunk := range chunksThatExist { 144 if fereq.LobSHA == chunk { 145 for _, chunkidx := range chunkIndexesThatExist[i] { 146 if fereq.ChunkIdx == chunkidx { 147 result.Exists = true 148 result.Size = testchunkdatasz 149 break 150 } 151 } 152 } 153 if result.Exists == true { 154 break 155 } 156 } 157 } else if fereq.Type == "meta" { 158 for _, meta := range metasThatExist { 159 if fereq.LobSHA == meta { 160 result.Exists = true 161 result.Size = int64(len(metacontent)) 162 break 163 } 164 } 165 166 } else { 167 strerr = fmt.Sprintf("Unsupported type: %v", fereq.Type) 168 } 169 170 if strerr != "" { 171 resp = NewJsonErrorResponse(req.Id, strerr) 172 } else { 173 resp, err = NewJsonResponse(req.Id, result) 174 Expect(err).To(BeNil(), "Test persistent server: unable to create response") 175 } 176 177 case "FileExistsOfSize": 178 fereq := FileExistsOfSizeRequest{} 179 ExtractStructFromJsonRawMessage(req.Params, &fereq) 180 result := FileExistsOfSizeResponse{} 181 for i, chunk := range chunksThatExist { 182 if fereq.LobSHA == chunk { 183 for chunkidx, sz := range chunkSizes[i] { 184 if fereq.ChunkIdx == chunkidx { 185 result.Result = (fereq.Size == sz) 186 break 187 } 188 } 189 break 190 } 191 } 192 resp, err = NewJsonResponse(req.Id, result) 193 Expect(err).To(BeNil(), "Test persistent server: unable to create response") 194 case "LOBExists": 195 fereq := LOBExistsRequest{} 196 ExtractStructFromJsonRawMessage(req.Params, &fereq) 197 result := LOBExistsResponse{} 198 if fereq.LobSHA == testsha { 199 result.Exists = true 200 result.Size = int64(testlobsize) 201 } 202 203 resp, err = NewJsonResponse(req.Id, result) 204 Expect(err).To(BeNil(), "Test persistent server: unable to create response") 205 case "UploadFile": 206 upreq := UploadFileRequest{} 207 ExtractStructFromJsonRawMessage(req.Params, &upreq) 208 Expect(upreq.LobSHA).To(Equal(testsha), "Test persistent server: SHA incorrect") 209 if upreq.Type == "chunk" { 210 Expect(upreq.ChunkIdx).To(BeEquivalentTo(testchunkidx), "Test persistent server: Chunk index incorrect") 211 } 212 startresult := UploadFileStartResponse{} 213 startresult.OKToSend = true 214 // Send start response immediately 215 resp, err = NewJsonResponse(req.Id, startresult) 216 Expect(err).To(BeNil(), "Test persistent server: unable to create response") 217 responseBytes, err := json.Marshal(resp) 218 Expect(err).To(BeNil(), "Test persistent server: unable to marshal response") 219 // null terminate response 220 responseBytes = append(responseBytes, byte(0)) 221 conn.Write(responseBytes) 222 // Next should by byte stream 223 // Must read from buffered reader since bytes may have been read already 224 receivedresult := UploadFileCompleteResponse{} 225 receivedresult.ReceivedOK = true 226 var receiveerr error 227 // make pre-sized buffer 228 contentbuf := bytes.NewBuffer(make([]byte, 0, upreq.Size)) 229 bytesLeft := upreq.Size 230 for bytesLeft > 0 { 231 c := PersistentTransportBufferSize 232 if c > bytesLeft { 233 c = bytesLeft 234 } 235 n, err := io.CopyN(contentbuf, rdr, c) 236 bytesLeft -= int64(n) 237 if err != nil { 238 receivedresult.ReceivedOK = false 239 receiveerr = fmt.Errorf("Test persistent server: unable to read data: %v", err.Error()) 240 break 241 } 242 } 243 // Check we received what we expected to receive 244 if upreq.Type == "meta" { 245 if string(contentbuf.Bytes()) != metacontent { 246 receiveerr = fmt.Errorf("Test persistent server: data didn't match") 247 } 248 } else { 249 // test first & last 5 bytes 250 contentbytes := contentbuf.Bytes() 251 for i := 0; i < 5; i++ { 252 if contentbytes[i] != testchunkdata[i] { 253 receiveerr = fmt.Errorf("Test persistent server: data didn't match") 254 break 255 } 256 } 257 for i := len(contentbytes) - 5; i < len(contentbytes); i++ { 258 if contentbytes[i] != testchunkdata[i] { 259 receiveerr = fmt.Errorf("Test persistent server: data didn't match") 260 break 261 } 262 } 263 } 264 // After we've read all the content bytes, send received response 265 if receiveerr != nil { 266 resp = NewJsonErrorResponse(req.Id, receiveerr.Error()) 267 } else { 268 resp, _ = NewJsonResponse(req.Id, receivedresult) 269 } 270 case "DownloadFilePrepare": 271 downreq := DownloadFilePrepareRequest{} 272 ExtractStructFromJsonRawMessage(req.Params, &downreq) 273 Expect(downreq.LobSHA).To(Equal(testsha), "Test persistent server: SHA incorrect") 274 if downreq.Type == "chunk" { 275 Expect(downreq.ChunkIdx).To(BeEquivalentTo(testchunkidx), "Test persistent server: Chunk index incorrect") 276 } 277 result := DownloadFilePrepareResponse{} 278 if downreq.Type == "meta" { 279 result.Size = int64(len(metacontent)) 280 } else { 281 result.Size = int64(len(testchunkdata)) 282 } 283 resp, err = NewJsonResponse(req.Id, result) 284 Expect(err).To(BeNil(), "Test persistent server: unable to create response") 285 case "DownloadFileStart": 286 // Can't return any error responses here (byte stream response only), have to just fail 287 downreq := DownloadFileStartRequest{} 288 ExtractStructFromJsonRawMessage(req.Params, &downreq) 289 // there is no response to this 290 var sz int64 291 var datasrc io.Reader 292 if downreq.Type == "meta" { 293 sz = int64(len(metacontent)) 294 datasrc = strings.NewReader(metacontent) 295 } else { 296 sz = int64(len(testchunkdata)) 297 datasrc = bytes.NewReader(testchunkdata) 298 } 299 // confirm size for testing 300 Expect(sz).To(BeEquivalentTo(downreq.Size), "Test persistent server: download size incorrect") 301 302 bytesLeft := sz 303 for bytesLeft > 0 { 304 c := PersistentTransportBufferSize 305 if c > bytesLeft { 306 c = bytesLeft 307 } 308 n, err := io.CopyN(conn, datasrc, c) 309 bytesLeft -= int64(n) 310 Expect(err).To(BeNil(), "Test persistent server: unable to read data") 311 } 312 case "PickCompleteLOB": 313 params := GetFirstCompleteLOBFromListRequest{} 314 ExtractStructFromJsonRawMessage(req.Params, ¶ms) 315 // check it's the list we expected 316 Expect(params.LobSHAs).To(ConsistOf(pickloblist), "Server should receive correct params") 317 result := GetFirstCompleteLOBFromListResponse{} 318 result.FirstSHA = testsha 319 resp, err = NewJsonResponse(req.Id, result) 320 Expect(err).To(BeNil(), "Test persistent server: unable to create response") 321 322 case "UploadDelta": 323 upreq := UploadDeltaRequest{} 324 ExtractStructFromJsonRawMessage(req.Params, &upreq) 325 Expect(upreq.BaseLobSHA).To(Equal(deltaBaseSHA), "Test persistent server: base SHA incorrect") 326 Expect(upreq.TargetLobSHA).To(Equal(deltaTargetSHA), "Test persistent server: base SHA incorrect") 327 startresult := UploadDeltaStartResponse{} 328 startresult.OKToSend = true 329 // Send start response immediately 330 resp, err = NewJsonResponse(req.Id, startresult) 331 Expect(err).To(BeNil(), "Test persistent server: unable to create response") 332 responseBytes, err := json.Marshal(resp) 333 Expect(err).To(BeNil(), "Test persistent server: unable to marshal response") 334 // null terminate response 335 responseBytes = append(responseBytes, byte(0)) 336 conn.Write(responseBytes) 337 // Next should by byte stream 338 // Must read from buffered reader since bytes may have been read already 339 receivedresult := UploadDeltaCompleteResponse{} 340 receivedresult.ReceivedOK = true 341 var receiveerr error 342 // make pre-sized buffer 343 contentbuf := bytes.NewBuffer(make([]byte, 0, upreq.Size)) 344 bytesLeft := upreq.Size 345 for bytesLeft > 0 { 346 c := PersistentTransportBufferSize 347 if c > bytesLeft { 348 c = bytesLeft 349 } 350 n, err := io.CopyN(contentbuf, rdr, c) 351 bytesLeft -= int64(n) 352 if err != nil { 353 receivedresult.ReceivedOK = false 354 receiveerr = fmt.Errorf("Test persistent server: unable to read data: %v", err.Error()) 355 break 356 } 357 } 358 // Check we received what we expected to receive 359 // test first & last 5 bytes 360 contentbytes := contentbuf.Bytes() 361 for i := 0; i < 5; i++ { 362 if contentbytes[i] != testchunkdata[i] { 363 receiveerr = fmt.Errorf("Test persistent server: data didn't match") 364 break 365 } 366 } 367 for i := len(contentbytes) - 5; i < len(contentbytes); i++ { 368 if contentbytes[i] != testchunkdata[i] { 369 receiveerr = fmt.Errorf("Test persistent server: data didn't match") 370 break 371 } 372 } 373 // After we've read all the content bytes, send received response 374 if receiveerr != nil { 375 resp = NewJsonErrorResponse(req.Id, receiveerr.Error()) 376 } else { 377 resp, _ = NewJsonResponse(req.Id, receivedresult) 378 } 379 case "DownloadDeltaPrepare": 380 downreq := DownloadDeltaPrepareRequest{} 381 ExtractStructFromJsonRawMessage(req.Params, &downreq) 382 Expect(downreq.BaseLobSHA).To(Equal(deltaBaseSHA), "Test persistent server: base SHA incorrect") 383 Expect(downreq.TargetLobSHA).To(Equal(deltaTargetSHA), "Test persistent server: base SHA incorrect") 384 result := DownloadDeltaPrepareResponse{} 385 result.Size = int64(len(testchunkdata)) 386 resp, err = NewJsonResponse(req.Id, result) 387 Expect(err).To(BeNil(), "Test persistent server: unable to create response") 388 case "DownloadDeltaStart": 389 // Can't return any error responses here (byte stream response only), have to just fail 390 downreq := DownloadDeltaStartRequest{} 391 ExtractStructFromJsonRawMessage(req.Params, &downreq) 392 // there is no response to this 393 Expect(downreq.BaseLobSHA).To(Equal(deltaBaseSHA), "Test persistent server: base SHA incorrect") 394 Expect(downreq.TargetLobSHA).To(Equal(deltaTargetSHA), "Test persistent server: base SHA incorrect") 395 sz := int64(len(testchunkdata)) 396 datasrc := bytes.NewReader(testchunkdata) 397 // confirm size for testing 398 Expect(sz).To(BeEquivalentTo(downreq.Size), "Test persistent server: download size incorrect") 399 400 bytesLeft := sz 401 for bytesLeft > 0 { 402 c := PersistentTransportBufferSize 403 if c > bytesLeft { 404 c = bytesLeft 405 } 406 n, err := io.CopyN(conn, datasrc, c) 407 bytesLeft -= int64(n) 408 Expect(err).To(BeNil(), "Test persistent server: unable to read data") 409 } 410 default: 411 resp = NewJsonErrorResponse(req.Id, fmt.Sprintf("Unknown method %v", req.Method)) 412 } 413 if resp != nil { 414 responseBytes, err := json.Marshal(resp) 415 Expect(err).To(BeNil(), "Test persistent server: unable to marshal response") 416 // null terminate response 417 responseBytes = append(responseBytes, byte(0)) 418 conn.Write(responseBytes) 419 } 420 } 421 conn.Close() 422 } 423 It("Queries capabilities (client)", func() { 424 cli, srv := net.Pipe() 425 go serve(srv) 426 defer cli.Close() 427 428 trans := NewPersistentTransport(cli) 429 caps, err := trans.QueryCaps() 430 Expect(err).To(BeNil(), "Should be no error") 431 Expect(caps).To(ConsistOf([]string{"Feature1", "Feature2", "OMGSOAWESOME"}), "Capabilities should match server") 432 433 }) 434 It("Sets capabilities (client)", func() { 435 cli, srv := net.Pipe() 436 go serve(srv) 437 defer cli.Close() 438 439 trans := NewPersistentTransport(cli) 440 err := trans.SetEnabledCaps([]string{"OMGSOAWESOME", "Feature1"}) 441 Expect(err).To(BeNil(), "Should be no error") 442 443 }) 444 It("Queries file existence (client)", func() { 445 // This also tests multiple requests in sequence (JSON only) 446 cli, srv := net.Pipe() 447 go serve(srv) 448 defer cli.Close() 449 450 trans := NewPersistentTransport(cli) 451 for _, meta := range metasThatExist { 452 exists, sz, err := trans.MetadataExists(meta) 453 Expect(err).To(BeNil(), "Should be no error") 454 Expect(exists).To(BeTrue(), "Metafile should exist") 455 Expect(sz).To(BeEquivalentTo(len(metacontent)), "Metafile should be right size") 456 } 457 for i, chunk := range chunksThatExist { 458 for _, chunkidx := range chunkIndexesThatExist[i] { 459 exists, sz, err := trans.ChunkExists(chunk, chunkidx) 460 Expect(err).To(BeNil(), "Should be no error") 461 Expect(exists).To(BeTrue(), "Chunk should exist") 462 Expect(sz).To(BeEquivalentTo(testchunkdatasz), "Chunk should be right size") 463 } 464 } 465 466 // Now try a few that should fail 467 exists, _, err := trans.MetadataExists("9999999999999999999999999999999999999999") 468 Expect(err).To(BeNil(), "Should be no error") 469 Expect(exists).To(BeFalse(), "Chunk should not exist") 470 exists, _, err = trans.ChunkExists("9999999999999999999999999999999999999999", 0) 471 Expect(err).To(BeNil(), "Should be no error") 472 Expect(exists).To(BeFalse(), "Chunk should not exist") 473 exists, _, err = trans.ChunkExists(chunksThatExist[0], 99) 474 Expect(err).To(BeNil(), "Should be no error") 475 Expect(exists).To(BeFalse(), "Chunk should not exist") 476 477 }) 478 479 It("Queries file sizes (client)", func() { 480 // This also tests multiple requests in sequence (JSON only) 481 cli, srv := net.Pipe() 482 go serve(srv) 483 defer cli.Close() 484 485 trans := NewPersistentTransport(cli) 486 for i, chunksz := range chunkSizes { 487 for chunkidx, sz := range chunksz { 488 sha := chunksThatExist[i] 489 exists, err := trans.ChunkExistsAndIsOfSize(sha, chunkidx, sz) 490 Expect(err).To(BeNil(), "Should be no error") 491 Expect(exists).To(BeTrue(), "Chunk should exist at this size") 492 493 // Try a failure 494 exists, err = trans.ChunkExistsAndIsOfSize(sha, chunkidx, sz+16) 495 Expect(err).To(BeNil(), "Should be no error") 496 Expect(exists).To(BeFalse(), "Chunk size shouldn't match") 497 498 } 499 } 500 // Also test just a case of not being there at all 501 exists, err := trans.ChunkExistsAndIsOfSize("9999999999999999999999999999999999999999", 0, 150) 502 Expect(err).To(BeNil(), "Should be no error") 503 Expect(exists).To(BeFalse(), "Chunk should not exist") 504 505 // Test entire LOB exists 506 exists, sz, err := trans.LOBExists(testsha) 507 Expect(err).To(BeNil(), "Should be no error") 508 Expect(exists).To(BeTrue(), "LOB should exist") 509 Expect(sz).To(BeEquivalentTo(testlobsize), "LOB should exist") 510 511 }) 512 513 It("Detects errors", func() { 514 // Request an invalid capability (as defined by this server) 515 cli, srv := net.Pipe() 516 go serve(srv) 517 defer cli.Close() 518 519 trans := NewPersistentTransport(cli) 520 err := trans.SetEnabledCaps([]string{"Feature1", "THISISWRONG"}) 521 Expect(err).ToNot(BeNil(), "Should be an error") 522 }) 523 524 It("Uploads metadata", func() { 525 rdr := strings.NewReader(metacontent) 526 527 cli, srv := net.Pipe() 528 go serve(srv) 529 defer cli.Close() 530 531 trans := NewPersistentTransport(cli) 532 err := trans.UploadMetadata(testsha, int64(len(metacontent)), rdr) 533 Expect(err).To(BeNil(), "Should not be an error in UploadFile") 534 Expect(rdr.Len()).To(BeZero(), "Server should have read all bytes") 535 }) 536 537 It("Uploads chunk data", func() { 538 rdr := bytes.NewReader(testchunkdata) 539 540 cli, srv := net.Pipe() 541 go serve(srv) 542 defer cli.Close() 543 544 numCallbacks := 0 545 var totalBytesDone int64 546 var totalBytesReported int64 547 callback := func(bytesDone, totalBytes int64) { 548 totalBytesDone = bytesDone 549 totalBytesReported = totalBytes 550 numCallbacks++ 551 } 552 553 trans := NewPersistentTransport(cli) 554 err := trans.UploadChunk(testsha, testchunkidx, testchunkdatasz, rdr, callback) 555 Expect(err).To(BeNil(), "Should not be an error in UploadFile") 556 Expect(rdr.Len()).To(BeZero(), "Server should have read all bytes") 557 Expect(totalBytesDone).To(BeEquivalentTo(testchunkdatasz), "Callback should have reported all bytes done") 558 Expect(totalBytesReported).To(BeEquivalentTo(testchunkdatasz), "Callback should have reported totalBytes correctly") 559 Expect(numCallbacks).To(BeEquivalentTo(4), "Should have been 4 callbacks in total") 560 561 }) 562 563 It("Downloads metadata", func() { 564 var buf bytes.Buffer 565 566 cli, srv := net.Pipe() 567 go serve(srv) 568 defer cli.Close() 569 570 trans := NewPersistentTransport(cli) 571 err := trans.DownloadMetadata(testsha, &buf) 572 Expect(err).To(BeNil(), "Should not be an error in DownloadFile") 573 Expect(string(buf.Bytes())).To(Equal(metacontent), "Should download expected metadata content") 574 }) 575 It("Downloads chunk data", func() { 576 var buf bytes.Buffer 577 578 cli, srv := net.Pipe() 579 go serve(srv) 580 defer cli.Close() 581 582 numCallbacks := 0 583 var totalBytesDone int64 584 var totalBytesReported int64 585 callback := func(bytesDone, totalBytes int64) { 586 totalBytesDone = bytesDone 587 totalBytesReported = totalBytes 588 numCallbacks++ 589 } 590 591 trans := NewPersistentTransport(cli) 592 err := trans.DownloadChunk(testsha, testchunkidx, &buf, callback) 593 Expect(err).To(BeNil(), "Should not be an error in DownloadFile") 594 Expect(buf.Len()).To(BeEquivalentTo(testchunkdatasz), "Should download the correct number of bytes") 595 // Just check start & end of buffers 596 contentbytes := buf.Bytes() 597 Expect(contentbytes[:20]).To(Equal(testchunkdata[:20]), "Start of downloaded buffer should match") 598 Expect(contentbytes[testchunkdatasz-20:]).To(Equal(testchunkdata[testchunkdatasz-20:]), "Start of downloaded buffer should match") 599 Expect(totalBytesDone).To(BeEquivalentTo(testchunkdatasz), "Callback should have reported all bytes done") 600 Expect(totalBytesReported).To(BeEquivalentTo(testchunkdatasz), "Callback should have reported totalBytes correctly") 601 Expect(numCallbacks).To(BeEquivalentTo(4), "Should have been 4 callbacks in total") 602 }) 603 604 It("Picks complete LOB from list", func() { 605 cli, srv := net.Pipe() 606 go serve(srv) 607 defer cli.Close() 608 trans := NewPersistentTransport(cli) 609 sha, err := trans.GetFirstCompleteLOBFromList(pickloblist) 610 Expect(err).To(BeNil(), "Should not be an error picking LOB") 611 Expect(sha).To(Equal(testsha), "Should pick the correct sha") 612 }) 613 614 It("Uploads a delta", func() { 615 rdr := bytes.NewReader(testchunkdata) 616 617 cli, srv := net.Pipe() 618 go serve(srv) 619 defer cli.Close() 620 621 numCallbacks := 0 622 var totalBytesDone int64 623 var totalBytesReported int64 624 callback := func(bytesDone, totalBytes int64) { 625 totalBytesDone = bytesDone 626 totalBytesReported = totalBytes 627 numCallbacks++ 628 } 629 630 trans := NewPersistentTransport(cli) 631 ok, err := trans.UploadDelta(deltaBaseSHA, deltaTargetSHA, testchunkdatasz, rdr, callback) 632 Expect(err).To(BeNil(), "Should not be an error in UploadDelta") 633 Expect(ok).To(BeTrue(), "UploadDelta should have worked") 634 Expect(rdr.Len()).To(BeZero(), "Server should have read all bytes") 635 Expect(totalBytesDone).To(BeEquivalentTo(testchunkdatasz), "Callback should have reported all bytes done") 636 Expect(totalBytesReported).To(BeEquivalentTo(testchunkdatasz), "Callback should have reported totalBytes correctly") 637 Expect(numCallbacks).To(BeEquivalentTo(4), "Should have been 4 callbacks in total") 638 639 }) 640 It("Downloads a delta", func() { 641 var buf bytes.Buffer 642 643 cli, srv := net.Pipe() 644 go serve(srv) 645 defer cli.Close() 646 647 numCallbacks := 0 648 var totalBytesDone int64 649 var totalBytesReported int64 650 callback := func(bytesDone, totalBytes int64) { 651 totalBytesDone = bytesDone 652 totalBytesReported = totalBytes 653 numCallbacks++ 654 } 655 656 trans := NewPersistentTransport(cli) 657 ok, err := trans.DownloadDelta(deltaBaseSHA, deltaTargetSHA, 10000000, &buf, callback) 658 Expect(err).To(BeNil(), "Should not be an error in DownloadFile") 659 Expect(ok).To(BeTrue(), "DownloadDelta should have worked") 660 Expect(buf.Len()).To(BeEquivalentTo(testchunkdatasz), "Should download the correct number of bytes") 661 // Just check start & end of buffers 662 contentbytes := buf.Bytes() 663 Expect(contentbytes[:20]).To(Equal(testchunkdata[:20]), "Start of downloaded buffer should match") 664 Expect(contentbytes[testchunkdatasz-20:]).To(Equal(testchunkdata[testchunkdatasz-20:]), "Start of downloaded buffer should match") 665 Expect(totalBytesDone).To(BeEquivalentTo(testchunkdatasz), "Callback should have reported all bytes done") 666 Expect(totalBytesReported).To(BeEquivalentTo(testchunkdatasz), "Callback should have reported totalBytes correctly") 667 Expect(numCallbacks).To(BeEquivalentTo(4), "Should have been 4 callbacks in total") 668 669 // Now check that a size limit works 670 buf.Reset() 671 ok, err = trans.DownloadDelta(deltaBaseSHA, deltaTargetSHA, 100, &buf, callback) 672 Expect(err).To(BeNil(), "Should not be an error in DownloadFile") 673 Expect(ok).To(BeFalse(), "DownloadDelta should return false when delta size is exceeded") 674 Expect(buf.Len()).To(BeZero(), "Nothing should be downloaded when size exceeded") 675 676 }) 677 678 It("Deals with chained server requests over one connection with interleaved data", func() { 679 cli, srv := net.Pipe() 680 go serve(srv) 681 defer cli.Close() 682 trans := NewPersistentTransport(cli) 683 684 // JSON request 685 caps, err := trans.QueryCaps() 686 Expect(err).To(BeNil(), "Should be no error") 687 Expect(caps).To(ConsistOf([]string{"Feature1", "Feature2", "OMGSOAWESOME"}), "Capabilities should match server") 688 689 // Byte transfer (upload) 690 rdr := strings.NewReader(metacontent) 691 err = trans.UploadMetadata(testsha, int64(len(metacontent)), rdr) 692 Expect(err).To(BeNil(), "Should not be an error in UploadFile") 693 Expect(rdr.Len()).To(BeZero(), "Server should have read all bytes") 694 695 // Another byte transfer (chunk) 696 rdr2 := bytes.NewReader(testchunkdata) 697 698 numCallbacks := 0 699 var totalBytesDone int64 700 var totalBytesReported int64 701 callback := func(bytesDone, totalBytes int64) { 702 totalBytesDone = bytesDone 703 totalBytesReported = totalBytes 704 numCallbacks++ 705 } 706 err = trans.UploadChunk(testsha, testchunkidx, testchunkdatasz, rdr2, callback) 707 Expect(err).To(BeNil(), "Should not be an error in UploadFile") 708 Expect(rdr2.Len()).To(BeZero(), "Server should have read all bytes") 709 Expect(totalBytesDone).To(BeEquivalentTo(testchunkdatasz), "Callback should have reported all bytes done") 710 Expect(totalBytesReported).To(BeEquivalentTo(testchunkdatasz), "Callback should have reported totalBytes correctly") 711 Expect(numCallbacks).To(BeEquivalentTo(4), "Should have been 4 callbacks in total") 712 713 // Another JSON request (pick LOB) 714 sha, err := trans.GetFirstCompleteLOBFromList(pickloblist) 715 Expect(err).To(BeNil(), "Should not be an error picking LOB") 716 Expect(sha).To(Equal(testsha), "Should pick the correct sha") 717 718 // Final byte transfer (delta) 719 numCallbacks = 0 720 var buf bytes.Buffer 721 ok, err := trans.DownloadDelta(deltaBaseSHA, deltaTargetSHA, 10000000, &buf, callback) 722 Expect(err).To(BeNil(), "Should not be an error in DownloadFile") 723 Expect(ok).To(BeTrue(), "DownloadDelta should have worked") 724 Expect(buf.Len()).To(BeEquivalentTo(testchunkdatasz), "Should download the correct number of bytes") 725 // Just check start & end of buffers 726 contentbytes := buf.Bytes() 727 Expect(contentbytes[:20]).To(Equal(testchunkdata[:20]), "Start of downloaded buffer should match") 728 Expect(contentbytes[testchunkdatasz-20:]).To(Equal(testchunkdata[testchunkdatasz-20:]), "Start of downloaded buffer should match") 729 Expect(totalBytesDone).To(BeEquivalentTo(testchunkdatasz), "Callback should have reported all bytes done") 730 Expect(totalBytesReported).To(BeEquivalentTo(testchunkdatasz), "Callback should have reported totalBytes correctly") 731 Expect(numCallbacks).To(BeEquivalentTo(4), "Should have been 4 callbacks in total") 732 }) 733 }) 734 735 })