cstruct_test.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package cstruct
  5. import (
  6. "errors"
  7. "fmt"
  8. "io"
  9. "testing"
  10. )
  11. func TestPadBytes(t *testing.T) {
  12. testCases := []struct {
  13. offset int
  14. size int
  15. want int
  16. }{
  17. // No padding at beginning of structure
  18. {0, 1, 0},
  19. {0, 2, 0},
  20. {0, 4, 0},
  21. {0, 8, 0},
  22. // No padding for single bytes
  23. {1, 1, 0},
  24. // Single byte padding
  25. {1, 2, 1},
  26. {3, 4, 1},
  27. // Multi-byte padding
  28. {1, 4, 3},
  29. {2, 8, 6},
  30. }
  31. for _, tc := range testCases {
  32. t.Run(fmt.Sprintf("%d_%d_%d", tc.offset, tc.size, tc.want), func(t *testing.T) {
  33. got := padBytes(tc.offset, tc.size)
  34. if got != tc.want {
  35. t.Errorf("got=%d; want=%d", got, tc.want)
  36. }
  37. })
  38. }
  39. }
  40. func TestDecoder(t *testing.T) {
  41. t.Run("UnsignedTypes", func(t *testing.T) {
  42. dec := func(n int) *Decoder {
  43. buf := make([]byte, n)
  44. buf[0] = 1
  45. d := NewDecoder(buf)
  46. // Use t.Cleanup to perform an assertion on this
  47. // decoder after the test code is finished with it.
  48. t.Cleanup(func() {
  49. if err := d.Err(); err != nil {
  50. t.Fatal(err)
  51. }
  52. })
  53. return d
  54. }
  55. if got := dec(2).Uint16(); got != 1 {
  56. t.Errorf("uint16: got=%d; want=1", got)
  57. }
  58. if got := dec(4).Uint32(); got != 1 {
  59. t.Errorf("uint32: got=%d; want=1", got)
  60. }
  61. if got := dec(8).Uint64(); got != 1 {
  62. t.Errorf("uint64: got=%d; want=1", got)
  63. }
  64. if got := dec(pointerSize / 8).Uintptr(); got != 1 {
  65. t.Errorf("uintptr: got=%d; want=1", got)
  66. }
  67. })
  68. t.Run("SignedTypes", func(t *testing.T) {
  69. dec := func(n int) *Decoder {
  70. // Make a buffer of the exact size that consists of 0xff bytes
  71. buf := make([]byte, n)
  72. for i := 0; i < n; i++ {
  73. buf[i] = 0xff
  74. }
  75. d := NewDecoder(buf)
  76. // Use t.Cleanup to perform an assertion on this
  77. // decoder after the test code is finished with it.
  78. t.Cleanup(func() {
  79. if err := d.Err(); err != nil {
  80. t.Fatal(err)
  81. }
  82. })
  83. return d
  84. }
  85. if got := dec(2).Int16(); got != -1 {
  86. t.Errorf("int16: got=%d; want=-1", got)
  87. }
  88. if got := dec(4).Int32(); got != -1 {
  89. t.Errorf("int32: got=%d; want=-1", got)
  90. }
  91. if got := dec(8).Int64(); got != -1 {
  92. t.Errorf("int64: got=%d; want=-1", got)
  93. }
  94. })
  95. t.Run("InsufficientData", func(t *testing.T) {
  96. dec := func(n int) *Decoder {
  97. // Make a buffer that's too small and contains arbitrary bytes
  98. buf := make([]byte, n-1)
  99. for i := 0; i < n-1; i++ {
  100. buf[i] = 0xAD
  101. }
  102. // Use t.Cleanup to perform an assertion on this
  103. // decoder after the test code is finished with it.
  104. d := NewDecoder(buf)
  105. t.Cleanup(func() {
  106. if err := d.Err(); err == nil || !errors.Is(err, io.EOF) {
  107. t.Errorf("(n=%d) expected io.EOF; got=%v", n, err)
  108. }
  109. })
  110. return d
  111. }
  112. dec(2).Uint16()
  113. dec(4).Uint32()
  114. dec(8).Uint64()
  115. dec(pointerSize / 8).Uintptr()
  116. dec(2).Int16()
  117. dec(4).Int32()
  118. dec(8).Int64()
  119. })
  120. t.Run("Bytes", func(t *testing.T) {
  121. d := NewDecoder([]byte("hello worldasdf"))
  122. t.Cleanup(func() {
  123. if err := d.Err(); err != nil {
  124. t.Fatal(err)
  125. }
  126. })
  127. buf := make([]byte, 11)
  128. d.Bytes(buf)
  129. if got := string(buf); got != "hello world" {
  130. t.Errorf("bytes: got=%q; want=%q", got, "hello world")
  131. }
  132. })
  133. }