bytespipe_test.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package ioutils
  2. import (
  3. "crypto/sha1"
  4. "encoding/hex"
  5. "math/rand"
  6. "testing"
  7. "time"
  8. )
  9. func TestBytesPipeRead(t *testing.T) {
  10. buf := NewBytesPipe()
  11. buf.Write([]byte("12"))
  12. buf.Write([]byte("34"))
  13. buf.Write([]byte("56"))
  14. buf.Write([]byte("78"))
  15. buf.Write([]byte("90"))
  16. rd := make([]byte, 4)
  17. n, err := buf.Read(rd)
  18. if err != nil {
  19. t.Fatal(err)
  20. }
  21. if n != 4 {
  22. t.Fatalf("Wrong number of bytes read: %d, should be %d", n, 4)
  23. }
  24. if string(rd) != "1234" {
  25. t.Fatalf("Read %s, but must be %s", rd, "1234")
  26. }
  27. n, err = buf.Read(rd)
  28. if err != nil {
  29. t.Fatal(err)
  30. }
  31. if n != 4 {
  32. t.Fatalf("Wrong number of bytes read: %d, should be %d", n, 4)
  33. }
  34. if string(rd) != "5678" {
  35. t.Fatalf("Read %s, but must be %s", rd, "5679")
  36. }
  37. n, err = buf.Read(rd)
  38. if err != nil {
  39. t.Fatal(err)
  40. }
  41. if n != 2 {
  42. t.Fatalf("Wrong number of bytes read: %d, should be %d", n, 2)
  43. }
  44. if string(rd[:n]) != "90" {
  45. t.Fatalf("Read %s, but must be %s", rd, "90")
  46. }
  47. }
  48. func TestBytesPipeWrite(t *testing.T) {
  49. buf := NewBytesPipe()
  50. buf.Write([]byte("12"))
  51. buf.Write([]byte("34"))
  52. buf.Write([]byte("56"))
  53. buf.Write([]byte("78"))
  54. buf.Write([]byte("90"))
  55. if buf.buf[0].String() != "1234567890" {
  56. t.Fatalf("Buffer %q, must be %q", buf.buf[0].String(), "1234567890")
  57. }
  58. }
  59. // Write and read in different speeds/chunk sizes and check valid data is read.
  60. func TestBytesPipeWriteRandomChunks(t *testing.T) {
  61. cases := []struct{ iterations, writesPerLoop, readsPerLoop int }{
  62. {100, 10, 1},
  63. {1000, 10, 5},
  64. {1000, 100, 0},
  65. {1000, 5, 6},
  66. {10000, 50, 25},
  67. }
  68. testMessage := []byte("this is a random string for testing")
  69. // random slice sizes to read and write
  70. writeChunks := []int{25, 35, 15, 20}
  71. readChunks := []int{5, 45, 20, 25}
  72. for _, c := range cases {
  73. // first pass: write directly to hash
  74. hash := sha1.New()
  75. for i := 0; i < c.iterations*c.writesPerLoop; i++ {
  76. if _, err := hash.Write(testMessage[:writeChunks[i%len(writeChunks)]]); err != nil {
  77. t.Fatal(err)
  78. }
  79. }
  80. expected := hex.EncodeToString(hash.Sum(nil))
  81. // write/read through buffer
  82. buf := NewBytesPipe()
  83. hash.Reset()
  84. done := make(chan struct{})
  85. go func() {
  86. // random delay before read starts
  87. <-time.After(time.Duration(rand.Intn(10)) * time.Millisecond)
  88. for i := 0; ; i++ {
  89. p := make([]byte, readChunks[(c.iterations*c.readsPerLoop+i)%len(readChunks)])
  90. n, _ := buf.Read(p)
  91. if n == 0 {
  92. break
  93. }
  94. hash.Write(p[:n])
  95. }
  96. close(done)
  97. }()
  98. for i := 0; i < c.iterations; i++ {
  99. for w := 0; w < c.writesPerLoop; w++ {
  100. buf.Write(testMessage[:writeChunks[(i*c.writesPerLoop+w)%len(writeChunks)]])
  101. }
  102. }
  103. buf.Close()
  104. <-done
  105. actual := hex.EncodeToString(hash.Sum(nil))
  106. if expected != actual {
  107. t.Fatalf("BytesPipe returned invalid data. Expected checksum %v, got %v", expected, actual)
  108. }
  109. }
  110. }
  111. func BenchmarkBytesPipeWrite(b *testing.B) {
  112. testData := []byte("pretty short line, because why not?")
  113. for i := 0; i < b.N; i++ {
  114. readBuf := make([]byte, 1024)
  115. buf := NewBytesPipe()
  116. go func() {
  117. var err error
  118. for err == nil {
  119. _, err = buf.Read(readBuf)
  120. }
  121. }()
  122. for j := 0; j < 1000; j++ {
  123. buf.Write(testData)
  124. }
  125. buf.Close()
  126. }
  127. }
  128. func BenchmarkBytesPipeRead(b *testing.B) {
  129. rd := make([]byte, 512)
  130. for i := 0; i < b.N; i++ {
  131. b.StopTimer()
  132. buf := NewBytesPipe()
  133. for j := 0; j < 500; j++ {
  134. buf.Write(make([]byte, 1024))
  135. }
  136. b.StartTimer()
  137. for j := 0; j < 1000; j++ {
  138. if n, _ := buf.Read(rd); n != 512 {
  139. b.Fatalf("Wrong number of bytes: %d", n)
  140. }
  141. }
  142. }
  143. }