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