buffer_test.go 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. package util
  2. import (
  3. "bytes"
  4. "io"
  5. "math"
  6. "math/rand/v2"
  7. "runtime"
  8. "strings"
  9. "testing"
  10. "time"
  11. )
  12. func TestBufferReadWrite(t *testing.T) {
  13. buf := NewBuffer()
  14. buf.WriteBool(true)
  15. buf.WriteInt(42)
  16. buf.WriteFloat64(3.14)
  17. buf.WriteString("Testing, 1, 2, 3!")
  18. readBuf := NewBufferFromBytes(buf.Bytes())
  19. boolVal := readBuf.ReadBool()
  20. intVal := readBuf.ReadInt()
  21. floatVal := readBuf.ReadFloat64()
  22. stringVal := readBuf.ReadString()
  23. if boolVal != true {
  24. t.Errorf("Expected bool value to be true, got %v", boolVal)
  25. }
  26. if intVal != 42 {
  27. t.Errorf("Expected int value to be 42, got %v", intVal)
  28. }
  29. if floatVal != 3.14 {
  30. t.Errorf("Expected float value to be 3.14, got %v", floatVal)
  31. }
  32. if stringVal != "Testing, 1, 2, 3!" {
  33. t.Errorf("Expected string value to be 'Hello, World!', got %v", stringVal)
  34. }
  35. }
  36. func TestBufferReadStringBytesMatchesReadString(t *testing.T) {
  37. buf := NewBuffer()
  38. buf.WriteString("alpha")
  39. buf.WriteString("")
  40. buf.WriteString("β")
  41. readBuf := NewBufferFromBytes(buf.Bytes())
  42. b0, err := readBuf.ReadStringBytes()
  43. if err != nil {
  44. t.Fatal(err)
  45. }
  46. if string(b0) != "alpha" {
  47. t.Fatalf("got %q", b0)
  48. }
  49. b1, err := readBuf.ReadStringBytes()
  50. if err != nil {
  51. t.Fatal(err)
  52. }
  53. if len(b1) != 0 {
  54. t.Fatalf("expected empty slice")
  55. }
  56. b2, err := readBuf.ReadStringBytes()
  57. if err != nil {
  58. t.Fatal(err)
  59. }
  60. if string(b2) != "β" {
  61. t.Fatalf("got %q", b2)
  62. }
  63. }
  64. func TestBufferWriteReadBytes(t *testing.T) {
  65. buf := NewBuffer()
  66. bytesToWrite := []byte{0x01, 0x02, 0x03, 0x04}
  67. buf.WriteBytes(bytesToWrite)
  68. readBuf := NewBufferFromBytes(buf.Bytes())
  69. readBytes := readBuf.ReadBytes(len(bytesToWrite))
  70. if !bytes.Equal(readBytes, bytesToWrite) {
  71. t.Errorf("Expected bytes to be %v, got %v", bytesToWrite, readBytes)
  72. }
  73. }
  74. func TestBufferWriteReadUInt64(t *testing.T) {
  75. buf := NewBuffer()
  76. uint64Val := uint64(1234567890)
  77. buf.WriteUInt64(uint64Val)
  78. readBuf := NewBufferFromBytes(buf.Bytes())
  79. readUInt64 := readBuf.ReadUInt64()
  80. if readUInt64 != uint64Val {
  81. t.Errorf("Expected uint64 value to be %v, got %v", uint64Val, readUInt64)
  82. }
  83. }
  84. func TestBufferWriteReadFloat32(t *testing.T) {
  85. buf := NewBuffer()
  86. float32Val := float32(3.14159)
  87. buf.WriteFloat32(float32Val)
  88. readBuf := NewBufferFromBytes(buf.Bytes())
  89. readFloat32 := readBuf.ReadFloat32()
  90. if readFloat32 != float32Val {
  91. t.Errorf("Expected float32 value to be %v, got %v", float32Val, readFloat32)
  92. }
  93. }
  94. func TestBufferWriteReadInt8(t *testing.T) {
  95. buf := NewBuffer()
  96. int8Val := int8(-42)
  97. buf.WriteInt8(int8Val)
  98. readBuf := NewBufferFromBytes(buf.Bytes())
  99. readInt8 := readBuf.ReadInt8()
  100. if readInt8 != int8Val {
  101. t.Errorf("Expected int8 value to be %v, got %v", int8Val, readInt8)
  102. }
  103. }
  104. func TestBufferWriteReadUInt16(t *testing.T) {
  105. buf := NewBuffer()
  106. uint16Val := uint16(65535)
  107. buf.WriteUInt16(uint16Val)
  108. readBuf := NewBufferFromBytes(buf.Bytes())
  109. readUInt16 := readBuf.ReadUInt16()
  110. if readUInt16 != uint16Val {
  111. t.Errorf("Expected uint16 value to be %v, got %v", uint16Val, readUInt16)
  112. }
  113. }
  114. func TestBufferWriteReadInt32(t *testing.T) {
  115. buf := NewBuffer()
  116. int32Val := int32(-1234567890)
  117. buf.WriteInt32(int32Val)
  118. readBuf := NewBufferFromBytes(buf.Bytes())
  119. readInt32 := readBuf.ReadInt32()
  120. if readInt32 != int32Val {
  121. t.Errorf("Expected int32 value to be %v, got %v", int32Val, readInt32)
  122. }
  123. }
  124. func TestBufferWriteReadUInt8(t *testing.T) {
  125. buf := NewBuffer()
  126. uint8Val := uint8(255)
  127. buf.WriteUInt8(uint8Val)
  128. readBuf := NewBufferFromBytes(buf.Bytes())
  129. readUInt8 := readBuf.ReadUInt8()
  130. if readUInt8 != uint8Val {
  131. t.Errorf("Expected uint8 value to be %v, got %v", uint8Val, readUInt8)
  132. }
  133. }
  134. func TestBufferWriteReadInt16(t *testing.T) {
  135. buf := NewBuffer()
  136. int16Val := int16(-32768)
  137. buf.WriteInt16(int16Val)
  138. readBuf := NewBufferFromBytes(buf.Bytes())
  139. readInt16 := readBuf.ReadInt16()
  140. if readInt16 != int16Val {
  141. t.Errorf("Expected int16 value to be %v, got %v", int16Val, readInt16)
  142. }
  143. }
  144. func TestBufferWriteReadUInt32(t *testing.T) {
  145. buf := NewBuffer()
  146. uint32Val := uint32(4294967295)
  147. buf.WriteUInt32(uint32Val)
  148. readBuf := NewBufferFromBytes(buf.Bytes())
  149. readUInt32 := readBuf.ReadUInt32()
  150. if readUInt32 != uint32Val {
  151. t.Errorf("Expected uint32 value to be %v, got %v", uint32Val, readUInt32)
  152. }
  153. }
  154. func TestBufferWriteReadInt64(t *testing.T) {
  155. buf := NewBuffer()
  156. int64Val := int64(-9223372036854775808)
  157. buf.WriteInt64(int64Val)
  158. readBuf := NewBufferFromBytes(buf.Bytes())
  159. readInt64 := readBuf.ReadInt64()
  160. if readInt64 != int64Val {
  161. t.Errorf("Expected int64 value to be %v, got %v", int64Val, readInt64)
  162. }
  163. }
  164. func TestBufferBytes(t *testing.T) {
  165. buf := NewBuffer()
  166. buf.WriteInt(42)
  167. buf.WriteFloat64(3.14)
  168. unreadBytes := buf.Bytes()
  169. newBuf := NewBufferFromBytes(unreadBytes)
  170. intVal := newBuf.ReadInt()
  171. floatVal := newBuf.ReadFloat64()
  172. if intVal != 42 {
  173. t.Errorf("Expected int value to be 42, got %v", intVal)
  174. }
  175. if floatVal != 3.14 {
  176. t.Errorf("Expected float value to be 3.14, got %v", floatVal)
  177. }
  178. }
  179. func TestBufferNewBufferFrom(t *testing.T) {
  180. buf := NewBuffer()
  181. buf.WriteInt(42)
  182. buf.WriteFloat64(3.14)
  183. newBuf := NewBufferFrom(buf)
  184. intVal := newBuf.ReadInt()
  185. floatVal := newBuf.ReadFloat64()
  186. if intVal != 42 {
  187. t.Errorf("Expected int value to be 42, got %v", intVal)
  188. }
  189. if floatVal != 3.14 {
  190. t.Errorf("Expected float value to be 3.14, got %v", floatVal)
  191. }
  192. }
  193. const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  194. func generateRandomString(ln int) string {
  195. b := make([]byte, ln)
  196. for i := range b {
  197. b[i] = letters[rand.IntN(len(letters))]
  198. }
  199. return string(b)
  200. }
  201. func memMib() float64 {
  202. var m runtime.MemStats
  203. runtime.ReadMemStats(&m)
  204. return float64(m.Alloc) / 1024.0 / 1024.0
  205. }
  206. func TestStringBytes(t *testing.T) {
  207. baselineMem := memMib()
  208. b := make([]byte, 10<<20)
  209. afterMem := memMib()
  210. delta := afterMem - baselineMem
  211. t.Logf("Allocated %v MiB, Delta: %v MiB", afterMem, delta)
  212. s := "Hello World!"
  213. sl := b[512 : 512+len(s)]
  214. copy(sl, stringToBytes(s))
  215. afterMem = memMib()
  216. delta = afterMem - baselineMem
  217. t.Logf("Allocated %v MiB, Delta: %v MiB", afterMem, delta)
  218. // this should pin the large backing array in memory, preventing it from being GC'd
  219. newS := bytesToString(sl)
  220. runtime.GC()
  221. time.Sleep(time.Second)
  222. afterMem = memMib()
  223. delta = afterMem - baselineMem
  224. t.Logf("S: %s, Allocated %v MiB, Delta: %v MiB", newS, afterMem, delta)
  225. // copy the string into a new string and clear out pinned string
  226. sCopy := strings.Clone(newS)
  227. newS = ""
  228. // Now that we've dropped the reference to the pinned backing array, it should be GC'd
  229. runtime.GC()
  230. time.Sleep(time.Second)
  231. afterMem = memMib()
  232. delta = afterMem - baselineMem
  233. t.Logf("S: %s, Allocated %v MiB, Delta: %v MiB", sCopy, afterMem, delta)
  234. if sCopy != s {
  235. t.Errorf("Expected string to be %v, got %v", s, sCopy)
  236. }
  237. if delta > 0.5 {
  238. t.Errorf("Expected memory delta to be less than 0.5 MiB, got %v MiB", delta)
  239. }
  240. }
  241. type randomByteReader struct {
  242. bytes []byte
  243. pos int
  244. }
  245. func newRandomByteReader(bytes []byte) *randomByteReader {
  246. return &randomByteReader{
  247. bytes: bytes,
  248. pos: 0,
  249. }
  250. }
  251. // reads a random number of bytes from 1-4 each time Read is called.
  252. // simulates partial buffered reads
  253. func (sbr *randomByteReader) Read(b []byte) (int, error) {
  254. if sbr.pos >= len(sbr.bytes) {
  255. return 0, io.EOF
  256. }
  257. toCopy := rand.IntN(4) + 1
  258. if toCopy > len(b) {
  259. toCopy = len(b)
  260. }
  261. var err error
  262. remaining := len(sbr.bytes) - sbr.pos
  263. if toCopy > remaining {
  264. err = io.EOF
  265. toCopy = remaining
  266. }
  267. bytesCopied := copy(b, sbr.bytes[sbr.pos:sbr.pos+toCopy])
  268. sbr.pos += bytesCopied
  269. return bytesCopied, err
  270. }
  271. func TestBufferReaderSupport(t *testing.T) {
  272. buf := NewBuffer()
  273. buf.WriteBool(true)
  274. buf.WriteInt(42)
  275. buf.WriteFloat64(3.14)
  276. buf.WriteString("Testing, 1, 2, 3!")
  277. buf.WriteUInt64(uint64(123456))
  278. buf.WriteInt16(44)
  279. buf.WriteFloat32(float32(5.0))
  280. reader := newRandomByteReader(buf.Bytes())
  281. readerBuff := NewBufferFromReader(reader)
  282. b := readerBuff.ReadBool()
  283. i := readerBuff.ReadInt()
  284. f := readerBuff.ReadFloat64()
  285. s := readerBuff.ReadString()
  286. ui64 := readerBuff.ReadUInt64()
  287. i16 := readerBuff.ReadInt16()
  288. f32 := readerBuff.ReadFloat32()
  289. if !b {
  290. t.Errorf("expected true, got: false")
  291. }
  292. if i != 42 {
  293. t.Errorf("expected 42, got: %d", i)
  294. }
  295. if f != 3.14 {
  296. t.Errorf("expected 3.14, got: %f", f)
  297. }
  298. if s != "Testing, 1, 2, 3!" {
  299. t.Errorf("expected 'Testing, 1, 2, 3!', got: '%s'", s)
  300. }
  301. if ui64 != uint64(123456) {
  302. t.Errorf("expected 123456, got: %d", ui64)
  303. }
  304. if i16 != int16(44) {
  305. t.Errorf("expected 44, got: %d", i16)
  306. }
  307. if f32 != float32(5.0) {
  308. t.Errorf("expected 5.0, got: %f", f32)
  309. }
  310. }
  311. func TestTooLargeStringTruncate(t *testing.T) {
  312. normalStr := generateRandomString(100)
  313. bigStr := generateRandomString(math.MaxUint16 + (math.MaxUint16 / 2))
  314. expectedBigStrRead := bigStr[:math.MaxUint16]
  315. otherBigStr := generateRandomString(math.MaxUint16)
  316. plusOne := generateRandomString(math.MaxUint16 + 1)
  317. expectedPlusOne := plusOne[:math.MaxUint16]
  318. buf := NewBuffer()
  319. buf.WriteInt(42)
  320. buf.WriteFloat64(3.14)
  321. buf.WriteString(normalStr)
  322. buf.WriteString(bigStr)
  323. buf.WriteString(otherBigStr)
  324. buf.WriteString(plusOne)
  325. readBuf := NewBufferFromBytes(buf.Bytes())
  326. intVal := readBuf.ReadInt()
  327. floatVal := readBuf.ReadFloat64()
  328. normalStrRead := readBuf.ReadString()
  329. bigStrRead := readBuf.ReadString()
  330. otherBigStrRead := readBuf.ReadString()
  331. plusOneRead := readBuf.ReadString()
  332. if intVal != 42 {
  333. t.Errorf("Expected int value to be 42, got %v", intVal)
  334. }
  335. if floatVal != 3.14 {
  336. t.Errorf("Expected float value to be 3.14, got %v", floatVal)
  337. }
  338. if normalStrRead != normalStr {
  339. t.Errorf("Expected string value to be %v, got %v", normalStr, normalStrRead)
  340. }
  341. if bigStrRead != expectedBigStrRead {
  342. t.Errorf("Expected large string values to be equivalent!")
  343. }
  344. if otherBigStrRead != otherBigStr {
  345. t.Errorf("Expected large string values to be equivalent!")
  346. }
  347. if plusOneRead != expectedPlusOne {
  348. t.Errorf("Expected large string values to be equivalent!")
  349. }
  350. }