github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/encoding/hex/hex_test.go (about) 1 // Copyright 2009 The Go 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 5 package hex 6 7 import ( 8 "bytes" 9 "fmt" 10 "io" 11 "strings" 12 "testing" 13 ) 14 15 type encDecTest struct { 16 enc string 17 dec []byte 18 } 19 20 var encDecTests = []encDecTest{ 21 {"", []byte{}}, 22 {"0001020304050607", []byte{0, 1, 2, 3, 4, 5, 6, 7}}, 23 {"08090a0b0c0d0e0f", []byte{8, 9, 10, 11, 12, 13, 14, 15}}, 24 {"f0f1f2f3f4f5f6f7", []byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7}}, 25 {"f8f9fafbfcfdfeff", []byte{0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}}, 26 {"67", []byte{'g'}}, 27 {"e3a1", []byte{0xe3, 0xa1}}, 28 } 29 30 func TestEncode(t *testing.T) { 31 for i, test := range encDecTests { 32 dst := make([]byte, EncodedLen(len(test.dec))) 33 n := Encode(dst, test.dec) 34 if n != len(dst) { 35 t.Errorf("#%d: bad return value: got: %d want: %d", i, n, len(dst)) 36 } 37 if string(dst) != test.enc { 38 t.Errorf("#%d: got: %#v want: %#v", i, dst, test.enc) 39 } 40 } 41 } 42 43 func TestDecode(t *testing.T) { 44 // Case for decoding uppercase hex characters, since 45 // Encode always uses lowercase. 46 decTests := append(encDecTests, encDecTest{"F8F9FAFBFCFDFEFF", []byte{0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}}) 47 for i, test := range decTests { 48 dst := make([]byte, DecodedLen(len(test.enc))) 49 n, err := Decode(dst, []byte(test.enc)) 50 if err != nil { 51 t.Errorf("#%d: bad return value: got:%d want:%d", i, n, len(dst)) 52 } else if !bytes.Equal(dst, test.dec) { 53 t.Errorf("#%d: got: %#v want: %#v", i, dst, test.dec) 54 } 55 } 56 } 57 58 func TestEncodeToString(t *testing.T) { 59 for i, test := range encDecTests { 60 s := EncodeToString(test.dec) 61 if s != test.enc { 62 t.Errorf("#%d got:%s want:%s", i, s, test.enc) 63 } 64 } 65 } 66 67 func TestDecodeString(t *testing.T) { 68 for i, test := range encDecTests { 69 dst, err := DecodeString(test.enc) 70 if err != nil { 71 t.Errorf("#%d: unexpected err value: %s", i, err) 72 continue 73 } 74 if !bytes.Equal(dst, test.dec) { 75 t.Errorf("#%d: got: %#v want: #%v", i, dst, test.dec) 76 } 77 } 78 } 79 80 var errTests = []struct { 81 in string 82 out string 83 err error 84 }{ 85 {"", "", nil}, 86 {"0", "", ErrLength}, 87 {"zd4aa", "", InvalidByteError('z')}, 88 {"d4aaz", "\xd4\xaa", InvalidByteError('z')}, 89 {"30313", "01", ErrLength}, 90 {"0g", "", InvalidByteError('g')}, 91 {"00gg", "\x00", InvalidByteError('g')}, 92 {"0\x01", "", InvalidByteError('\x01')}, 93 {"ffeed", "\xff\xee", ErrLength}, 94 } 95 96 func TestDecodeErr(t *testing.T) { 97 for _, tt := range errTests { 98 out := make([]byte, len(tt.in)+10) 99 n, err := Decode(out, []byte(tt.in)) 100 if string(out[:n]) != tt.out || err != tt.err { 101 t.Errorf("Decode(%q) = %q, %v, want %q, %v", tt.in, string(out[:n]), err, tt.out, tt.err) 102 } 103 } 104 } 105 106 func TestDecodeStringErr(t *testing.T) { 107 for _, tt := range errTests { 108 out, err := DecodeString(tt.in) 109 if string(out) != tt.out || err != tt.err { 110 t.Errorf("DecodeString(%q) = %q, %v, want %q, %v", tt.in, out, err, tt.out, tt.err) 111 } 112 } 113 } 114 115 func TestEncoderDecoder(t *testing.T) { 116 for _, multiplier := range []int{1, 128, 192} { 117 for _, test := range encDecTests { 118 input := bytes.Repeat(test.dec, multiplier) 119 output := strings.Repeat(test.enc, multiplier) 120 121 var buf bytes.Buffer 122 enc := NewEncoder(&buf) 123 r := struct{ io.Reader }{bytes.NewReader(input)} // io.Reader only; not io.WriterTo 124 if n, err := io.CopyBuffer(enc, r, make([]byte, 7)); n != int64(len(input)) || err != nil { 125 t.Errorf("encoder.Write(%q*%d) = (%d, %v), want (%d, nil)", test.dec, multiplier, n, err, len(input)) 126 continue 127 } 128 129 if encDst := buf.String(); encDst != output { 130 t.Errorf("buf(%q*%d) = %v, want %v", test.dec, multiplier, encDst, output) 131 continue 132 } 133 134 dec := NewDecoder(&buf) 135 var decBuf bytes.Buffer 136 w := struct{ io.Writer }{&decBuf} // io.Writer only; not io.ReaderFrom 137 if _, err := io.CopyBuffer(w, dec, make([]byte, 7)); err != nil || decBuf.Len() != len(input) { 138 t.Errorf("decoder.Read(%q*%d) = (%d, %v), want (%d, nil)", test.enc, multiplier, decBuf.Len(), err, len(input)) 139 } 140 141 if !bytes.Equal(decBuf.Bytes(), input) { 142 t.Errorf("decBuf(%q*%d) = %v, want %v", test.dec, multiplier, decBuf.Bytes(), input) 143 continue 144 } 145 } 146 } 147 } 148 149 func TestDecoderErr(t *testing.T) { 150 for _, tt := range errTests { 151 dec := NewDecoder(strings.NewReader(tt.in)) 152 out, err := io.ReadAll(dec) 153 wantErr := tt.err 154 // Decoder is reading from stream, so it reports io.ErrUnexpectedEOF instead of ErrLength. 155 if wantErr == ErrLength { 156 wantErr = io.ErrUnexpectedEOF 157 } 158 if string(out) != tt.out || err != wantErr { 159 t.Errorf("NewDecoder(%q) = %q, %v, want %q, %v", tt.in, out, err, tt.out, wantErr) 160 } 161 } 162 } 163 164 func TestDumper(t *testing.T) { 165 var in [40]byte 166 for i := range in { 167 in[i] = byte(i + 30) 168 } 169 170 for stride := 1; stride < len(in); stride++ { 171 var out bytes.Buffer 172 dumper := Dumper(&out) 173 done := 0 174 for done < len(in) { 175 todo := done + stride 176 if todo > len(in) { 177 todo = len(in) 178 } 179 dumper.Write(in[done:todo]) 180 done = todo 181 } 182 183 dumper.Close() 184 if !bytes.Equal(out.Bytes(), expectedHexDump) { 185 t.Errorf("stride: %d failed. got:\n%s\nwant:\n%s", stride, out.Bytes(), expectedHexDump) 186 } 187 } 188 } 189 190 func TestDumper_doubleclose(t *testing.T) { 191 var out strings.Builder 192 dumper := Dumper(&out) 193 194 dumper.Write([]byte(`gopher`)) 195 dumper.Close() 196 dumper.Close() 197 dumper.Write([]byte(`gopher`)) 198 dumper.Close() 199 200 expected := "00000000 67 6f 70 68 65 72 |gopher|\n" 201 if out.String() != expected { 202 t.Fatalf("got:\n%#v\nwant:\n%#v", out.String(), expected) 203 } 204 } 205 206 func TestDumper_earlyclose(t *testing.T) { 207 var out strings.Builder 208 dumper := Dumper(&out) 209 210 dumper.Close() 211 dumper.Write([]byte(`gopher`)) 212 213 expected := "" 214 if out.String() != expected { 215 t.Fatalf("got:\n%#v\nwant:\n%#v", out.String(), expected) 216 } 217 } 218 219 func TestDump(t *testing.T) { 220 var in [40]byte 221 for i := range in { 222 in[i] = byte(i + 30) 223 } 224 225 out := []byte(Dump(in[:])) 226 if !bytes.Equal(out, expectedHexDump) { 227 t.Errorf("got:\n%s\nwant:\n%s", out, expectedHexDump) 228 } 229 } 230 231 var expectedHexDump = []byte(`00000000 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d |.. !"#$%&'()*+,-| 232 00000010 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d |./0123456789:;<=| 233 00000020 3e 3f 40 41 42 43 44 45 |>?@ABCDE| 234 `) 235 236 var sink []byte 237 238 func BenchmarkEncode(b *testing.B) { 239 for _, size := range []int{256, 1024, 4096, 16384} { 240 src := bytes.Repeat([]byte{2, 3, 5, 7, 9, 11, 13, 17}, size/8) 241 sink = make([]byte, 2*size) 242 243 b.Run(fmt.Sprintf("%v", size), func(b *testing.B) { 244 b.SetBytes(int64(size)) 245 for i := 0; i < b.N; i++ { 246 Encode(sink, src) 247 } 248 }) 249 } 250 } 251 252 func BenchmarkDecode(b *testing.B) { 253 for _, size := range []int{256, 1024, 4096, 16384} { 254 src := bytes.Repeat([]byte{'2', 'b', '7', '4', '4', 'f', 'a', 'a'}, size/8) 255 sink = make([]byte, size/2) 256 257 b.Run(fmt.Sprintf("%v", size), func(b *testing.B) { 258 b.SetBytes(int64(size)) 259 for i := 0; i < b.N; i++ { 260 Decode(sink, src) 261 } 262 }) 263 } 264 } 265 266 func BenchmarkDump(b *testing.B) { 267 for _, size := range []int{256, 1024, 4096, 16384} { 268 src := bytes.Repeat([]byte{2, 3, 5, 7, 9, 11, 13, 17}, size/8) 269 270 b.Run(fmt.Sprintf("%v", size), func(b *testing.B) { 271 b.SetBytes(int64(size)) 272 for i := 0; i < b.N; i++ { 273 Dump(src) 274 } 275 }) 276 } 277 }