decode_test.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package lz4block
  2. import (
  3. "bytes"
  4. "strings"
  5. "testing"
  6. )
  7. func TestBlockDecode(t *testing.T) {
  8. appendLen := func(p []byte, size int) []byte {
  9. for size > 0xFF {
  10. p = append(p, 0xFF)
  11. size -= 0xFF
  12. }
  13. p = append(p, byte(size))
  14. return p
  15. }
  16. emitSeq := func(lit string, offset uint16, matchLen int) []byte {
  17. var b byte
  18. litLen := len(lit)
  19. if litLen < 15 {
  20. b = byte(litLen << 4)
  21. litLen = -1
  22. } else {
  23. b = 0xF0
  24. litLen -= 15
  25. }
  26. if matchLen < 4 || offset == 0 {
  27. out := []byte{b}
  28. if litLen >= 0 {
  29. out = appendLen(out, litLen)
  30. }
  31. return append(out, lit...)
  32. }
  33. matchLen -= 4
  34. if matchLen < 15 {
  35. b |= byte(matchLen)
  36. matchLen = -1
  37. } else {
  38. b |= 0x0F
  39. matchLen -= 15
  40. }
  41. out := []byte{b}
  42. if litLen >= 0 {
  43. out = appendLen(out, litLen)
  44. }
  45. if len(lit) > 0 {
  46. out = append(out, lit...)
  47. }
  48. out = append(out, byte(offset), byte(offset>>8))
  49. if matchLen >= 0 {
  50. out = appendLen(out, matchLen)
  51. }
  52. return out
  53. }
  54. concat := func(in ...[]byte) []byte {
  55. var p []byte
  56. for _, b := range in {
  57. p = append(p, b...)
  58. }
  59. return p
  60. }
  61. tests := []struct {
  62. name string
  63. src []byte
  64. exp []byte
  65. }{
  66. {
  67. "empty_input",
  68. []byte{0},
  69. []byte{},
  70. },
  71. {
  72. "literal_only_short",
  73. emitSeq("hello", 0, 0),
  74. []byte("hello"),
  75. },
  76. {
  77. "literal_only_long",
  78. emitSeq(strings.Repeat("A", 15+255+255+1), 0, 0),
  79. bytes.Repeat([]byte("A"), 15+255+255+1),
  80. },
  81. {
  82. "literal_only_long_1",
  83. emitSeq(strings.Repeat("A", 15), 0, 0),
  84. bytes.Repeat([]byte("A"), 15),
  85. },
  86. {
  87. "repeat_match_len",
  88. emitSeq("a", 1, 4),
  89. []byte("aaaaa"),
  90. },
  91. {
  92. "repeat_match_len_2_seq",
  93. concat(emitSeq("a", 1, 4), emitSeq("B", 1, 4)),
  94. []byte("aaaaaBBBBB"),
  95. },
  96. {
  97. "long_match",
  98. emitSeq("A", 1, 16),
  99. bytes.Repeat([]byte("A"), 17),
  100. },
  101. {
  102. "repeat_match_log_len_2_seq",
  103. concat(emitSeq("a", 1, 15), emitSeq("B", 1, 15), emitSeq("end", 0, 0)),
  104. []byte(strings.Repeat("a", 16) + strings.Repeat("B", 16) + "end"),
  105. },
  106. }
  107. for _, test := range tests {
  108. t.Run(test.name, func(t *testing.T) {
  109. buf := make([]byte, len(test.exp))
  110. n := decodeBlock(buf, test.src)
  111. if n <= 0 {
  112. t.Log(-n)
  113. }
  114. if !bytes.Equal(buf, test.exp) {
  115. t.Fatalf("expected %q got %q", test.exp, buf)
  116. }
  117. })
  118. }
  119. }
  120. func TestDecodeBlockInvalid(t *testing.T) {
  121. t.Parallel()
  122. dst := make([]byte, 100)
  123. for _, test := range []struct {
  124. name string
  125. src string
  126. }{
  127. {
  128. "empty_input",
  129. "",
  130. },
  131. {
  132. "final_lit_too_short",
  133. "\x20a", // litlen = 2 but only a single-byte literal
  134. },
  135. } {
  136. r := decodeBlock(dst, []byte(test.src))
  137. if r >= 0 {
  138. t.Errorf("no error for %s", test.name)
  139. }
  140. }
  141. }