github.com/olivere/camlistore@v0.0.0-20140121221811-1b7ac2da0199/pkg/test/fakeindex.go (about) 1 /* 2 Copyright 2011 Google Inc. 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 test 18 19 import ( 20 "fmt" 21 "log" 22 "math" 23 "os" 24 "strings" 25 "sync" 26 "time" 27 28 "camlistore.org/pkg/blob" 29 "camlistore.org/pkg/context" 30 "camlistore.org/pkg/types/camtypes" 31 ) 32 33 var ClockOrigin = time.Unix(1322443956, 123456) 34 35 // A FakeIndex implements parts of search.Index and provides methods 36 // to controls the results, such as AddMeta, AddClaim, 37 // AddSignerAttrValue. 38 type FakeIndex struct { 39 lk sync.Mutex 40 meta map[blob.Ref]camtypes.BlobMeta 41 claims map[blob.Ref][]camtypes.Claim // permanode -> claims 42 signerAttrValue map[string]blob.Ref // "<signer>\0<attr>\0<value>" -> blobref 43 path map[string]*camtypes.Path // "<signer>\0<base>\0<suffix>" -> path 44 45 cllk sync.RWMutex 46 clock time.Time 47 } 48 49 func NewFakeIndex() *FakeIndex { 50 return &FakeIndex{ 51 meta: make(map[blob.Ref]camtypes.BlobMeta), 52 claims: make(map[blob.Ref][]camtypes.Claim), 53 signerAttrValue: make(map[string]blob.Ref), 54 path: make(map[string]*camtypes.Path), 55 clock: ClockOrigin, 56 } 57 } 58 59 // 60 // Test methods 61 // 62 63 func (fi *FakeIndex) nextDate() time.Time { 64 fi.cllk.Lock() 65 defer fi.cllk.Unlock() 66 fi.clock = fi.clock.Add(1 * time.Second) 67 return fi.clock.UTC() 68 } 69 70 func (fi *FakeIndex) LastTime() time.Time { 71 fi.cllk.RLock() 72 defer fi.cllk.RUnlock() 73 return fi.clock 74 } 75 76 func camliTypeFromMime(mime string) string { 77 if v := strings.TrimPrefix(mime, "application/json; camliType="); v != mime { 78 return v 79 } 80 return "" 81 } 82 83 func (fi *FakeIndex) AddMeta(br blob.Ref, camliType string, size int64) { 84 if size < 0 || size > math.MaxUint32 { 85 panic("bad size") 86 } 87 fi.lk.Lock() 88 defer fi.lk.Unlock() 89 fi.meta[br] = camtypes.BlobMeta{ 90 Ref: br, 91 Size: uint32(size), 92 CamliType: camliType, 93 } 94 } 95 96 func (fi *FakeIndex) AddClaim(owner, permanode blob.Ref, claimType, attr, value string) { 97 fi.lk.Lock() 98 defer fi.lk.Unlock() 99 date := fi.nextDate() 100 101 claim := camtypes.Claim{ 102 Permanode: permanode, 103 Signer: owner, 104 BlobRef: blob.Ref{}, 105 Date: date, 106 Type: claimType, 107 Attr: attr, 108 Value: value, 109 } 110 fi.claims[permanode] = append(fi.claims[permanode], claim) 111 112 if claimType == "set-attribute" && strings.HasPrefix(attr, "camliPath:") { 113 suffix := attr[len("camliPath:"):] 114 path := &camtypes.Path{ 115 Target: blob.MustParse(value), 116 Suffix: suffix, 117 } 118 fi.path[fmt.Sprintf("%s\x00%s\x00%s", owner, permanode, suffix)] = path 119 } 120 } 121 122 func (fi *FakeIndex) AddSignerAttrValue(signer blob.Ref, attr, val string, latest blob.Ref) { 123 fi.lk.Lock() 124 defer fi.lk.Unlock() 125 fi.signerAttrValue[fmt.Sprintf("%s\x00%s\x00%s", signer, attr, val)] = latest 126 } 127 128 // 129 // Interface implementation 130 // 131 132 func (fi *FakeIndex) KeyId(blob.Ref) (string, error) { 133 panic("NOIMPL") 134 } 135 136 func (fi *FakeIndex) GetRecentPermanodes(dest chan<- camtypes.RecentPermanode, owner blob.Ref, limit int, before time.Time) error { 137 panic("NOIMPL") 138 } 139 140 // TODO(mpl): write real tests 141 func (fi *FakeIndex) SearchPermanodesWithAttr(dest chan<- blob.Ref, request *camtypes.PermanodeByAttrRequest) error { 142 panic("NOIMPL") 143 } 144 145 func (fi *FakeIndex) AppendClaims(dst []camtypes.Claim, permaNode blob.Ref, 146 signerFilter blob.Ref, 147 attrFilter string) ([]camtypes.Claim, error) { 148 fi.lk.Lock() 149 defer fi.lk.Unlock() 150 151 for _, cl := range fi.claims[permaNode] { 152 if signerFilter.Valid() && cl.Signer != signerFilter { 153 continue 154 } 155 if attrFilter != "" && cl.Attr != attrFilter { 156 continue 157 } 158 dst = append(dst, cl) 159 } 160 return dst, nil 161 } 162 163 func (fi *FakeIndex) GetBlobMeta(br blob.Ref) (camtypes.BlobMeta, error) { 164 fi.lk.Lock() 165 defer fi.lk.Unlock() 166 bm, ok := fi.meta[br] 167 if !ok { 168 return camtypes.BlobMeta{}, os.ErrNotExist 169 } 170 return bm, nil 171 } 172 173 func (fi *FakeIndex) ExistingFileSchemas(bytesRef blob.Ref) ([]blob.Ref, error) { 174 panic("NOIMPL") 175 } 176 177 func (fi *FakeIndex) GetFileInfo(fileRef blob.Ref) (camtypes.FileInfo, error) { 178 panic("NOIMPL") 179 } 180 181 func (fi *FakeIndex) GetImageInfo(fileRef blob.Ref) (camtypes.ImageInfo, error) { 182 panic("NOIMPL") 183 } 184 185 func (fi *FakeIndex) GetDirMembers(dir blob.Ref, dest chan<- blob.Ref, limit int) error { 186 panic("NOIMPL") 187 } 188 189 func (fi *FakeIndex) PermanodeOfSignerAttrValue(signer blob.Ref, attr, val string) (blob.Ref, error) { 190 fi.lk.Lock() 191 defer fi.lk.Unlock() 192 if b, ok := fi.signerAttrValue[fmt.Sprintf("%s\x00%s\x00%s", signer, attr, val)]; ok { 193 return b, nil 194 } 195 return blob.Ref{}, os.ErrNotExist 196 } 197 198 func (fi *FakeIndex) PathsOfSignerTarget(signer, target blob.Ref) ([]*camtypes.Path, error) { 199 panic("NOIMPL") 200 } 201 202 func (fi *FakeIndex) PathsLookup(signer, base blob.Ref, suffix string) ([]*camtypes.Path, error) { 203 panic("NOIMPL") 204 } 205 206 func (fi *FakeIndex) PathLookup(signer, base blob.Ref, suffix string, at time.Time) (*camtypes.Path, error) { 207 if !at.IsZero() { 208 panic("PathLookup with non-zero 'at' time not supported") 209 } 210 fi.lk.Lock() 211 defer fi.lk.Unlock() 212 if p, ok := fi.path[fmt.Sprintf("%s\x00%s\x00%s", signer, base, suffix)]; ok { 213 return p, nil 214 } 215 log.Printf("PathLookup miss for signer %q, base %q, suffix %q", signer, base, suffix) 216 return nil, os.ErrNotExist 217 } 218 219 func (fi *FakeIndex) EdgesTo(ref blob.Ref, opts *camtypes.EdgesToOpts) ([]*camtypes.Edge, error) { 220 panic("NOIMPL") 221 } 222 223 func (fi *FakeIndex) EnumerateBlobMeta(ctx *context.Context, ch chan<- camtypes.BlobMeta) error { 224 panic("NOIMPL") 225 }