github.com/slspeek/camlistore_namedsearch@v0.0.0-20140519202248-ed6f70f7721a/pkg/index/corpus_test.go (about) 1 /* 2 Copyright 2013 The Camlistore Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package index_test 18 19 import ( 20 "reflect" 21 "testing" 22 "time" 23 24 "camlistore.org/pkg/blob" 25 "camlistore.org/pkg/context" 26 "camlistore.org/pkg/index" 27 "camlistore.org/pkg/index/indextest" 28 "camlistore.org/pkg/types" 29 "camlistore.org/pkg/types/camtypes" 30 ) 31 32 func TestCorpusAppendPermanodeAttrValues(t *testing.T) { 33 c := index.ExpNewCorpus() 34 pn := blob.MustParse("abc-123") 35 tm := time.Unix(99, 0) 36 claim := func(verb, attr, val string) *camtypes.Claim { 37 tm = tm.Add(time.Second) 38 return &camtypes.Claim{ 39 Type: verb + "-attribute", 40 Attr: attr, 41 Value: val, 42 Date: tm, 43 } 44 } 45 s := func(s ...string) []string { return s } 46 47 c.SetClaims(pn, &index.PermanodeMeta{ 48 Claims: []*camtypes.Claim{ 49 claim("set", "foo", "foov"), // time 100 50 51 claim("add", "tag", "a"), // time 101 52 claim("add", "tag", "b"), // time 102 53 claim("del", "tag", ""), 54 claim("add", "tag", "c"), 55 claim("add", "tag", "d"), 56 claim("add", "tag", "e"), 57 claim("del", "tag", "d"), 58 59 claim("add", "DelAll", "a"), 60 claim("add", "DelAll", "b"), 61 claim("add", "DelAll", "c"), 62 claim("del", "DelAll", ""), 63 64 claim("add", "DelOne", "a"), 65 claim("add", "DelOne", "b"), 66 claim("add", "DelOne", "c"), 67 claim("add", "DelOne", "d"), 68 claim("del", "DelOne", "d"), 69 claim("del", "DelOne", "a"), 70 71 claim("add", "SetAfterAdd", "a"), 72 claim("add", "SetAfterAdd", "b"), 73 claim("set", "SetAfterAdd", "setv"), 74 }, 75 }) 76 77 tests := []struct { 78 attr string 79 want []string 80 t time.Time 81 }{ 82 {attr: "not-exist", want: s()}, 83 {attr: "DelAll", want: s()}, 84 {attr: "DelOne", want: s("b", "c")}, 85 {attr: "foo", want: s("foov")}, 86 {attr: "tag", want: s("c", "e")}, 87 {attr: "tag", want: s("a", "b"), t: time.Unix(102, 0)}, 88 {attr: "SetAfterAdd", want: s("setv")}, 89 } 90 for i, tt := range tests { 91 got := c.AppendPermanodeAttrValues(nil, pn, tt.attr, tt.t, blob.Ref{}) 92 if len(got) == 0 && len(tt.want) == 0 { 93 continue 94 } 95 if !reflect.DeepEqual(got, tt.want) { 96 t.Errorf("%d. attr %q = %q; want %q", 97 i, tt.attr, got, tt.want) 98 } 99 } 100 101 } 102 103 func TestKVClaimAllocs(t *testing.T) { 104 n := testing.AllocsPerRun(20, func() { 105 index.ExpKvClaim("claim|sha1-b380b3080f9c71faa5c1d82bbd4d583a473bc77d|2931A67C26F5ABDA|2011-11-28T01:32:37.000123456Z|sha1-b3d93daee62e40d36237ff444022f42d7d0e43f2", 106 "set-attribute|tag|foo1|sha1-ad87ca5c78bd0ce1195c46f7c98e6025abbaf007", 107 blob.Parse) 108 }) 109 t.Logf("%v allocations", n) 110 } 111 112 func TestKVClaim(t *testing.T) { 113 tests := []struct { 114 k, v string 115 ok bool 116 want camtypes.Claim 117 }{ 118 { 119 k: "claim|sha1-b380b3080f9c71faa5c1d82bbd4d583a473bc77d|2931A67C26F5ABDA|2011-11-28T01:32:37.000123456Z|sha1-b3d93daee62e40d36237ff444022f42d7d0e43f2", 120 v: "set-attribute|tag|foo1|sha1-ad87ca5c78bd0ce1195c46f7c98e6025abbaf007", 121 ok: true, 122 want: camtypes.Claim{ 123 BlobRef: blob.MustParse("sha1-b3d93daee62e40d36237ff444022f42d7d0e43f2"), 124 Signer: blob.MustParse("sha1-ad87ca5c78bd0ce1195c46f7c98e6025abbaf007"), 125 Permanode: blob.MustParse("sha1-b380b3080f9c71faa5c1d82bbd4d583a473bc77d"), 126 Type: "set-attribute", 127 Attr: "tag", 128 Value: "foo1", 129 Date: time.Time(types.ParseTime3339OrZero("2011-11-28T01:32:37.000123456Z")), 130 }, 131 }, 132 } 133 for _, tt := range tests { 134 got, ok := index.ExpKvClaim(tt.k, tt.v, blob.Parse) 135 if ok != tt.ok { 136 t.Errorf("kvClaim(%q, %q) = ok %v; want %v", tt.k, tt.v, ok, tt.ok) 137 continue 138 } 139 if got != tt.want { 140 t.Errorf("kvClaim(%q, %q) = %+v; want %+v", tt.k, tt.v, got, tt.want) 141 continue 142 } 143 } 144 } 145 146 func TestDeletePermanode_Modtime(t *testing.T) { 147 testDeletePermanodes(t, 148 func(c *index.Corpus, ctx *context.Context, ch chan<- camtypes.BlobMeta) error { 149 return c.EnumeratePermanodesLastModifiedLocked(ctx, ch) 150 }, 151 ) 152 } 153 154 func TestDeletePermanode_CreateTime(t *testing.T) { 155 testDeletePermanodes(t, 156 func(c *index.Corpus, ctx *context.Context, ch chan<- camtypes.BlobMeta) error { 157 return c.EnumeratePermanodesCreatedLocked(ctx, ch, true) 158 }, 159 ) 160 } 161 162 func testDeletePermanodes(t *testing.T, 163 enumFunc func(*index.Corpus, *context.Context, chan<- camtypes.BlobMeta) error) { 164 idx := index.NewMemoryIndex() 165 idxd := indextest.NewIndexDeps(idx) 166 167 foopn := idxd.NewPlannedPermanode("foo") 168 idxd.SetAttribute(foopn, "tag", "foo") 169 barpn := idxd.NewPlannedPermanode("bar") 170 idxd.SetAttribute(barpn, "tag", "bar") 171 bazpn := idxd.NewPlannedPermanode("baz") 172 idxd.SetAttribute(bazpn, "tag", "baz") 173 idxd.Delete(barpn) 174 c, err := idxd.Index.KeepInMemory() 175 if err != nil { 176 t.Fatalf("error slurping index to memory: %v", err) 177 } 178 179 // check that we initially only find permanodes foo and baz, 180 // because bar is already marked as deleted. 181 want := []blob.Ref{foopn, bazpn} 182 ch := make(chan camtypes.BlobMeta, 10) 183 var got []camtypes.BlobMeta 184 errc := make(chan error, 1) 185 c.RLock() 186 go func() { errc <- enumFunc(c, context.TODO(), ch) }() 187 for blobMeta := range ch { 188 got = append(got, blobMeta) 189 } 190 err = <-errc 191 c.RUnlock() 192 if err != nil { 193 t.Fatalf("Could not enumerate permanodes: %v", err) 194 } 195 if len(got) != len(want) { 196 t.Fatalf("Saw %d permanodes in corpus; want %d", len(got), len(want)) 197 } 198 for _, bm := range got { 199 found := false 200 for _, perm := range want { 201 if bm.Ref == perm { 202 found = true 203 break 204 } 205 } 206 if !found { 207 t.Fatalf("permanode %v was not found in corpus", bm.Ref) 208 } 209 } 210 211 // now add a delete claim for permanode baz, and check that we're only left with foo permanode 212 delbaz := idxd.Delete(bazpn) 213 want = []blob.Ref{foopn} 214 got = got[:0] 215 ch = make(chan camtypes.BlobMeta, 10) 216 c.RLock() 217 go func() { errc <- enumFunc(c, context.TODO(), ch) }() 218 for blobMeta := range ch { 219 got = append(got, blobMeta) 220 } 221 err = <-errc 222 c.RUnlock() 223 if err != nil { 224 t.Fatalf("Could not enumerate permanodes: %v", err) 225 } 226 if len(got) != len(want) { 227 t.Fatalf("Saw %d permanodes in corpus; want %d", len(got), len(want)) 228 } 229 if got[0].Ref != foopn { 230 t.Fatalf("Wrong permanode found in corpus. Wanted %v, got %v", foopn, got[0].Ref) 231 } 232 233 // baz undeletion. delete delbaz. 234 idxd.Delete(delbaz) 235 want = []blob.Ref{foopn, bazpn} 236 got = got[:0] 237 ch = make(chan camtypes.BlobMeta, 10) 238 c.RLock() 239 go func() { errc <- enumFunc(c, context.TODO(), ch) }() 240 for blobMeta := range ch { 241 got = append(got, blobMeta) 242 } 243 err = <-errc 244 c.RUnlock() 245 if err != nil { 246 t.Fatalf("Could not enumerate permanodes: %v", err) 247 } 248 if len(got) != len(want) { 249 t.Fatalf("Saw %d permanodes in corpus; want %d", len(got), len(want)) 250 } 251 for _, bm := range got { 252 found := false 253 for _, perm := range want { 254 if bm.Ref == perm { 255 found = true 256 break 257 } 258 } 259 if !found { 260 t.Fatalf("permanode %v was not found in corpus", bm.Ref) 261 } 262 } 263 } 264 265 func TestEnumerateOrder_Modtime(t *testing.T) { 266 testEnumerateOrder(t, 267 func(c *index.Corpus, ctx *context.Context, ch chan<- camtypes.BlobMeta) error { 268 return c.EnumeratePermanodesLastModifiedLocked(ctx, ch) 269 }, 270 modtimeOrder, 271 ) 272 } 273 274 func TestEnumerateOrder_CreateTime(t *testing.T) { 275 testEnumerateOrder(t, 276 func(c *index.Corpus, ctx *context.Context, ch chan<- camtypes.BlobMeta) error { 277 return c.EnumeratePermanodesCreatedLocked(ctx, ch, true) 278 }, 279 createOrder, 280 ) 281 } 282 283 const ( 284 modtimeOrder = iota 285 createOrder 286 ) 287 288 func testEnumerateOrder(t *testing.T, 289 enumFunc func(*index.Corpus, *context.Context, chan<- camtypes.BlobMeta) error, 290 order int) { 291 idx := index.NewMemoryIndex() 292 idxd := indextest.NewIndexDeps(idx) 293 294 // permanode with no contents 295 foopn := idxd.NewPlannedPermanode("foo") 296 idxd.SetAttribute(foopn, "tag", "foo") 297 // permanode with file contents 298 // we set the time of the contents 1 second older than the modtime of foopn 299 fooModTime := idxd.LastTime() 300 fileTime := fooModTime.Add(-1 * time.Second) 301 fileRef, _ := idxd.UploadFile("foo.html", "<html>I am an html file.</html>", fileTime) 302 barpn := idxd.NewPlannedPermanode("bar") 303 idxd.SetAttribute(barpn, "camliContent", fileRef.String()) 304 305 c, err := idxd.Index.KeepInMemory() 306 if err != nil { 307 t.Fatalf("error slurping index to memory: %v", err) 308 } 309 310 // check that we get a different order whether with enumerate according to 311 // contents time, or to permanode modtime. 312 var want []blob.Ref 313 if order == modtimeOrder { 314 // modtime. 315 want = []blob.Ref{barpn, foopn} 316 } else { 317 // creation time. 318 want = []blob.Ref{foopn, barpn} 319 } 320 ch := make(chan camtypes.BlobMeta, 10) 321 var got []camtypes.BlobMeta 322 errc := make(chan error, 1) 323 c.RLock() 324 go func() { errc <- enumFunc(c, context.TODO(), ch) }() 325 for blobMeta := range ch { 326 got = append(got, blobMeta) 327 } 328 err = <-errc 329 c.RUnlock() 330 if err != nil { 331 t.Fatalf("Could not enumerate permanodes: %v", err) 332 } 333 if len(got) != len(want) { 334 t.Fatalf("Saw %d permanodes in corpus; want %d", len(got), len(want)) 335 } 336 for k, v := range got { 337 if v.Ref != want[k] { 338 t.Fatalf("Wrong result from enumeration. Got %v, wanted %v.", v.Ref, want[k]) 339 } 340 } 341 }