github.com/chrislusf/greenpack@v3.7.1-0.20170911073826-ad5bd10b7c47+incompatible/msgp/edit_test.go (about)

     1  package msgp
     2  
     3  import (
     4  	"bytes"
     5  	"reflect"
     6  	"testing"
     7  )
     8  
     9  func TestRemove(t *testing.T) {
    10  	var nbs *NilBitsStack
    11  	var buf bytes.Buffer
    12  	w := NewWriter(&buf)
    13  	w.WriteMapHeader(3)
    14  	w.WriteString("first")
    15  	w.WriteFloat64(-3.1)
    16  	w.WriteString("second")
    17  	w.WriteString("DELETE ME!!!")
    18  	w.WriteString("third")
    19  	w.WriteBytes([]byte("blah"))
    20  	w.Flush()
    21  
    22  	raw := Remove("second", buf.Bytes())
    23  
    24  	m, _, err := nbs.ReadMapStrIntfBytes(raw, nil)
    25  	if err != nil {
    26  		t.Fatal(err)
    27  	}
    28  	if len(m) != 2 {
    29  		t.Errorf("expected %d fields; found %d", 2, len(m))
    30  	}
    31  	if _, ok := m["first"]; !ok {
    32  		t.Errorf("field %q not found", "first")
    33  	}
    34  	if _, ok := m["third"]; !ok {
    35  		t.Errorf("field %q not found", "third")
    36  	}
    37  	if _, ok := m["second"]; ok {
    38  		t.Errorf("field %q (deleted field) still present", "second")
    39  	}
    40  }
    41  
    42  func TestLocate(t *testing.T) {
    43  	var buf bytes.Buffer
    44  	en := NewWriter(&buf)
    45  	en.WriteMapHeader(2)
    46  	en.WriteString("thing_one")
    47  	en.WriteString("value_one")
    48  	en.WriteString("thing_two")
    49  	en.WriteFloat64(2.0)
    50  	en.Flush()
    51  
    52  	field := Locate("thing_one", buf.Bytes())
    53  	if len(field) == 0 {
    54  		t.Fatal("field not found")
    55  	}
    56  
    57  	if !HasKey("thing_one", buf.Bytes()) {
    58  		t.Fatal("field not found")
    59  	}
    60  
    61  	var zbuf bytes.Buffer
    62  	w := NewWriter(&zbuf)
    63  	w.WriteString("value_one")
    64  	w.Flush()
    65  
    66  	if !bytes.Equal(zbuf.Bytes(), field) {
    67  		t.Errorf("got %q; wanted %q", field, zbuf.Bytes())
    68  	}
    69  
    70  	zbuf.Reset()
    71  	w.WriteFloat64(2.0)
    72  	w.Flush()
    73  	field = Locate("thing_two", buf.Bytes())
    74  	if len(field) == 0 {
    75  		t.Fatal("field not found")
    76  	}
    77  	if !bytes.Equal(zbuf.Bytes(), field) {
    78  		t.Errorf("got %q; wanted %q", field, zbuf.Bytes())
    79  	}
    80  
    81  	field = Locate("nope", buf.Bytes())
    82  	if len(field) != 0 {
    83  		t.Fatalf("wanted a zero-length returned slice")
    84  	}
    85  
    86  }
    87  
    88  func TestReplace(t *testing.T) {
    89  	// there are 4 cases that need coverage:
    90  	//  - new value is smaller than old value
    91  	//  - new value is the same size as the old value
    92  	//  - new value is larger than old, but fits within cap(b)
    93  	//  - new value is larger than old, and doesn't fit within cap(b)
    94  
    95  	var nbs *NilBitsStack
    96  	var buf bytes.Buffer
    97  	en := NewWriter(&buf)
    98  	en.WriteMapHeader(3)
    99  	en.WriteString("thing_one")
   100  	en.WriteString("value_one")
   101  	en.WriteString("thing_two")
   102  	en.WriteFloat64(2.0)
   103  	en.WriteString("some_bytes")
   104  	en.WriteBytes([]byte("here are some bytes"))
   105  	en.Flush()
   106  
   107  	// same-size replacement
   108  	var fbuf bytes.Buffer
   109  	w := NewWriter(&fbuf)
   110  	w.WriteFloat64(4.0)
   111  	w.Flush()
   112  
   113  	// replace 2.0 with 4.0 in field two
   114  	raw := Replace("thing_two", buf.Bytes(), fbuf.Bytes())
   115  	if len(raw) == 0 {
   116  		t.Fatal("field not found")
   117  	}
   118  	var err error
   119  	m := make(map[string]interface{})
   120  	m, _, err = nbs.ReadMapStrIntfBytes(raw, m)
   121  	if err != nil {
   122  		t.Logf("%q", raw)
   123  		t.Fatal(err)
   124  	}
   125  
   126  	if !reflect.DeepEqual(m["thing_two"], 4.0) {
   127  		t.Errorf("wanted %v; got %v", 4.0, m["thing_two"])
   128  	}
   129  
   130  	// smaller-size replacement
   131  	// replace 2.0 with []byte("hi!")
   132  	fbuf.Reset()
   133  	w.WriteBytes([]byte("hi!"))
   134  	w.Flush()
   135  	raw = Replace("thing_two", raw, fbuf.Bytes())
   136  	if len(raw) == 0 {
   137  		t.Fatal("field not found")
   138  	}
   139  
   140  	m, _, err = nbs.ReadMapStrIntfBytes(raw, m)
   141  	if err != nil {
   142  		t.Logf("%q", raw)
   143  		t.Fatal(err)
   144  	}
   145  
   146  	if !reflect.DeepEqual(m["thing_two"], []byte("hi!")) {
   147  		t.Errorf("wanted %v; got %v", []byte("hi!"), m["thing_two"])
   148  	}
   149  
   150  	// larger-size replacement
   151  	fbuf.Reset()
   152  	w.WriteBytes([]byte("some even larger bytes than before"))
   153  	w.Flush()
   154  	raw = Replace("some_bytes", raw, fbuf.Bytes())
   155  	if len(raw) == 0 {
   156  		t.Logf("%q", raw)
   157  		t.Fatal(err)
   158  	}
   159  
   160  	m, _, err = nbs.ReadMapStrIntfBytes(raw, m)
   161  	if err != nil {
   162  		t.Logf("%q", raw)
   163  		t.Fatal(err)
   164  	}
   165  
   166  	if !reflect.DeepEqual(m["some_bytes"], []byte("some even larger bytes than before")) {
   167  		t.Errorf("wanted %v; got %v", []byte("hello there!"), m["some_bytes"])
   168  	}
   169  
   170  	// identical in-place replacement
   171  	field := Locate("some_bytes", raw)
   172  	newraw := CopyReplace("some_bytes", raw, field)
   173  
   174  	if !bytes.Equal(newraw, raw) {
   175  		t.Logf("in: %q", raw)
   176  		t.Logf("out: %q", newraw)
   177  		t.Error("bytes not equal after copyreplace")
   178  	}
   179  }
   180  
   181  func BenchmarkLocate(b *testing.B) {
   182  	var buf bytes.Buffer
   183  	en := NewWriter(&buf)
   184  	en.WriteMapHeader(3)
   185  	en.WriteString("thing_one")
   186  	en.WriteString("value_one")
   187  	en.WriteString("thing_two")
   188  	en.WriteFloat64(2.0)
   189  	en.WriteString("thing_three")
   190  	en.WriteBytes([]byte("hello!"))
   191  	en.Flush()
   192  
   193  	raw := buf.Bytes()
   194  	// bytes/s will be the number of bytes traversed per unit of time
   195  	field := Locate("thing_three", raw)
   196  	b.SetBytes(int64(len(raw) - len(field)))
   197  	b.ReportAllocs()
   198  	b.ResetTimer()
   199  	for i := 0; i < b.N; i++ {
   200  		Locate("thing_three", raw)
   201  	}
   202  }