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  }