github.com/bibaroc/wingman@v0.0.2-0.20200911182922-33c2085136b1/pkg/fst/string_test.go (about) 1 package fst_test 2 3 import ( 4 "crypto/rand" 5 "testing" 6 7 "github.com/bibaroc/wingman/pkg/fst" 8 "github.com/google/go-cmp/cmp" 9 ) 10 11 func TestSimpleConversion(t *testing.T) { 12 c := []byte{'w', 'h', 'a', 't', ' ', 'i', 's', ' ', 'i', 'm', 'm', 'u', 't', 'a', 'b', 'i', 'l', 'i', 't', 'y'} 13 want := string(c) 14 got := fst.String(&c[0]) 15 if diff := cmp.Diff(want, got); diff != "" { 16 t.Errorf("Simple conversion mismatch (-want +got):\n%s", diff) 17 } 18 got = fst.Str(&c[0], len(c)) 19 if diff := cmp.Diff(want, got); diff != "" { 20 t.Errorf("Simple conversion mismatch (-want +got):\n%s", diff) 21 } 22 } 23 func TestConvertedStringIsNOTImmutable(t *testing.T) { 24 c := []byte{'w', 'h', 'a', 't', ' ', 'i', 's', ' ', 'i', 'm', 'm', 'u', 't', 'a', 'b', 'i', 'l', 'i', 't', 'y'} 25 want := string(c) 26 got := fst.String(&c[0]) 27 28 // this capitalizes both Ms in iMMutability 29 c[9], c[10] = 'M', 'M' 30 if diff := cmp.Diff(want, got); diff == "" { 31 t.Errorf("A string created this way should not be immutable if you modify the underlying array\n") 32 } 33 got = fst.Str(&c[0], len(c)) 34 if diff := cmp.Diff(want, got); diff == "" { 35 t.Errorf("A string created this way should not be immutable if you modify the underlying array\n") 36 } 37 } 38 39 func TestConvertedResizing(t *testing.T) { 40 c := []byte{'w', 'h', 'a', 't', ' ', 'i', 's', ' ', 'i', 'm', 'm', 'u', 't', 'a', 'b', 'i', 'l', 'i', 't', 'y', 0, 0, 0, 0, 0, 0, 0} 41 42 c[7] = 0 43 got := fst.String(&c[0]) 44 if diff := cmp.Diff("what is", got); diff != "" { 45 t.Errorf("Setting a null byte should resize the string down, mismatch (-want +got):\n%s", diff) 46 } 47 48 c[7] = '-' 49 got = fst.String(&c[0]) 50 if diff := cmp.Diff("what is-immutability", got); diff != "" { 51 t.Errorf("Setting a previously null byte should resize the string up to the next one, mismatch (-want +got):\n%s", diff) 52 } 53 54 for i := 20; i < len(c); i++ { 55 c[i] = 'a' 56 } 57 got = fst.String(&c[0]) 58 if diff := cmp.Diff("what is-immutabilityaaaaaaa", got); diff != "" { 59 t.Errorf("Filling the array up to capacity should resize the string up, mismatch (-want +got):\n%s", diff) 60 } 61 } 62 63 func BenchmarkString32(b *testing.B) { benchmarkString(b, bytes(32)) } 64 func BenchmarkString64(b *testing.B) { benchmarkString(b, bytes(64)) } 65 func BenchmarkString128(b *testing.B) { benchmarkString(b, bytes(128)) } 66 func BenchmarkString256(b *testing.B) { benchmarkString(b, bytes(256)) } 67 func BenchmarkStr32(b *testing.B) { benchmarkStr(b, bytes(32)) } 68 func BenchmarkStr64(b *testing.B) { benchmarkStr(b, bytes(64)) } 69 func BenchmarkStr128(b *testing.B) { benchmarkStr(b, bytes(128)) } 70 func BenchmarkStr256(b *testing.B) { benchmarkStr(b, bytes(256)) } 71 func BenchmarkCastString32(b *testing.B) { benchmarkCastString(b, bytes(32)) } 72 func BenchmarkCastString64(b *testing.B) { benchmarkCastString(b, bytes(64)) } 73 func BenchmarkCastString128(b *testing.B) { benchmarkCastString(b, bytes(128)) } 74 func BenchmarkCastString256(b *testing.B) { benchmarkCastString(b, bytes(256)) } 75 76 func benchmarkString(b *testing.B, arr []byte) { 77 ln := len(arr) 78 c := make([]byte, ln) 79 b.ReportAllocs() 80 b.ResetTimer() 81 for i := 0; i < b.N; i++ { 82 copy(c, arr) 83 84 c[7] = 0 85 got := fst.String(&c[0]) 86 noop(got) 87 c[7] = '-' 88 got = fst.String(&c[0]) 89 noop(got) 90 91 for i := 0; i < len(c); i++ { 92 c[i] = 'a' 93 } 94 got = fst.String(&c[0]) 95 noop(got) 96 c = c[:cap(c)] 97 } 98 } 99 100 func benchmarkStr(b *testing.B, arr []byte) { 101 ln := len(arr) 102 c := make([]byte, ln) 103 b.ReportAllocs() 104 b.ResetTimer() 105 for i := 0; i < b.N; i++ { 106 copy(c, arr) 107 108 c[7] = 0 109 got := fst.Str(&c[0], len(c)) 110 noop(got) 111 c[7] = '-' 112 got = fst.Str(&c[0], len(c)) 113 noop(got) 114 115 for i := 0; i < len(c); i++ { 116 c[i] = 'a' 117 } 118 got = fst.Str(&c[0], len(c)) 119 noop(got) 120 c = c[:cap(c)] 121 } 122 } 123 124 func benchmarkCastString(b *testing.B, arr []byte) { 125 ln := len(arr) 126 c := make([]byte, ln) 127 128 b.ReportAllocs() 129 b.ResetTimer() 130 for i := 0; i < b.N; i++ { 131 copy(c, arr) 132 133 c[7] = 0 134 got := string(c) 135 noop(got) 136 c[7] = '-' 137 got = string(c) 138 139 noop(got) 140 141 for i := 0; i < len(c); i++ { 142 c[i] = 'a' 143 } 144 got = string(c) 145 noop(got) 146 c = c[:cap(c)] 147 } 148 } 149 150 func noop(v interface{}) {} 151 func bytes(count int64) []byte { 152 b := make([]byte, count) 153 _, err := rand.Read(b) 154 if err != nil { 155 panic(err) 156 } 157 return b 158 } 159 func str(count int64) string { 160 b := make([]byte, count) 161 _, err := rand.Read(b) 162 if err != nil { 163 panic(err) 164 } 165 return string(b) 166 }