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 }