github.com/janelia-flyem/dvid@v1.0.0/datatype/imagetile/imagetile_test.go (about) 1 package imagetile 2 3 import ( 4 "bytes" 5 "encoding/hex" 6 "encoding/json" 7 "fmt" 8 "io" 9 "log" 10 "reflect" 11 "sync" 12 "testing" 13 14 "github.com/janelia-flyem/dvid/datastore" 15 "github.com/janelia-flyem/dvid/datatype/imageblk" 16 "github.com/janelia-flyem/dvid/datatype/roi" 17 "github.com/janelia-flyem/dvid/dvid" 18 "github.com/janelia-flyem/dvid/server" 19 "github.com/janelia-flyem/dvid/storage" 20 ) 21 22 var ( 23 mstype, grayscaleT, roitype datastore.TypeService 24 testMu sync.Mutex 25 ) 26 27 // Sets package-level testRepo and TestVersionID 28 func initTestRepo() (dvid.UUID, dvid.VersionID) { 29 testMu.Lock() 30 defer testMu.Unlock() 31 if mstype == nil { 32 var err error 33 mstype, err = datastore.TypeServiceByName(TypeName) 34 if err != nil { 35 log.Fatalf("Can't get imagetile type: %s\n", err) 36 } 37 grayscaleT, err = datastore.TypeServiceByName("uint8blk") 38 if err != nil { 39 log.Fatalf("Can't get grayscale type: %s\n", err) 40 } 41 roitype, err = datastore.TypeServiceByName(roi.TypeName) 42 if err != nil { 43 log.Fatalf("Can't get ROI type: %v\n", err) 44 } 45 } 46 return datastore.NewTestRepo() 47 } 48 49 func makeGrayscale(uuid dvid.UUID, t *testing.T, name dvid.InstanceName) *imageblk.Data { 50 config := dvid.NewConfig() 51 dataservice, err := datastore.NewData(uuid, grayscaleT, name, config) 52 if err != nil { 53 t.Errorf("Unable to create grayscale instance %q: %v\n", name, err) 54 } 55 grayscale, ok := dataservice.(*imageblk.Data) 56 if !ok { 57 t.Errorf("Can't cast data service into imageblk Data\n") 58 } 59 return grayscale 60 } 61 62 const testTileSpec = ` 63 { 64 "0": { "Resolution": [10.0, 10.0, 10.0], "TileSize": [512, 512, 512] }, 65 "1": { "Resolution": [20.0, 20.0, 20.0], "TileSize": [512, 512, 512] }, 66 "2": { "Resolution": [40.0, 40.0, 40.0], "TileSize": [512, 512, 512] }, 67 "3": { "Resolution": [80.0, 80.0, 80.0], "TileSize": [512, 512, 512] } 68 } 69 ` 70 71 func TestLoadTileSpec(t *testing.T) { 72 tileSpec, err := LoadTileSpec([]byte(testTileSpec)) 73 if err != nil { 74 t.Errorf("Unable to load tile spec: %v\n", err) 75 } 76 if len(tileSpec) != 4 { 77 t.Errorf("Bad tile spec load: only %d elements != 4\n", len(tileSpec)) 78 } 79 if tileSpec[2].Resolution.GetMax() != 40.0 { 80 t.Errorf("Bad tile spec at level 2: %v\n", tileSpec[2]) 81 } 82 if tileSpec[3].TileSize.Value(2) != 512 { 83 t.Errorf("Bad tile spec at level 3: %v\n", tileSpec[3]) 84 } 85 } 86 87 const testMetadata = ` 88 { 89 "MinTileCoord": [0,0,0], 90 "MaxTileCoord": [5,5,4], 91 "Levels": { 92 "0": { "Resolution": [10.0, 10.0, 10.0], "TileSize": [512, 512, 512] }, 93 "1": { "Resolution": [20.0, 20.0, 20.0], "TileSize": [512, 512, 512] }, 94 "2": { "Resolution": [40.0, 40.0, 40.0], "TileSize": [512, 512, 512] }, 95 "3": { "Resolution": [80.0, 80.0, 80.0], "TileSize": [512, 512, 512] } 96 } 97 } 98 ` 99 100 func TestSetMetadata(t *testing.T) { 101 if err := server.OpenTest(); err != nil { 102 t.Fatalf("can't open test server: %v\n", err) 103 } 104 defer server.CloseTest() 105 106 uuid, _ := initTestRepo() 107 server.CreateTestInstance(t, uuid, "imagetile", "tiles", dvid.Config{}) 108 109 // Store Metadata 110 url := fmt.Sprintf("%snode/%s/tiles/metadata", server.WebAPIPath, uuid) 111 server.TestHTTP(t, "POST", url, bytes.NewBufferString(testMetadata)) 112 113 // Check instance really has it set. 114 var metadata metadataJSON 115 respStr := server.TestHTTP(t, "GET", url, nil) 116 if err := json.Unmarshal(respStr, &metadata); err != nil { 117 t.Fatalf("Couldn't parse JSON response to metadata request (%v):\n%s\n", err, respStr) 118 } 119 expectMin := dvid.Point3d{0, 0, 0} 120 expectMax := dvid.Point3d{5, 5, 4} 121 if !expectMin.Equals(metadata.MinTileCoord) { 122 t.Errorf("Expected min tile coord %s, got %s\n", expectMin, metadata.MinTileCoord) 123 } 124 if !expectMax.Equals(metadata.MaxTileCoord) { 125 t.Errorf("Expected max tile coord %s, got %s\n", expectMax, metadata.MaxTileCoord) 126 } 127 tileSpec, err := parseTileSpec(metadata.Levels) 128 if err != nil { 129 t.Errorf("Error parsing returned tile level spec:\n%v\n", metadata.Levels) 130 } 131 if len(tileSpec) != 4 { 132 t.Errorf("Bad tile spec load: only %d elements != 4\n", len(tileSpec)) 133 } 134 if tileSpec[2].Resolution.GetMax() != 40.0 { 135 t.Errorf("Bad tile spec at level 2: %v\n", tileSpec[2]) 136 } 137 if tileSpec[3].TileSize.Value(2) != 512 { 138 t.Errorf("Bad tile spec at level 3: %v\n", tileSpec[3]) 139 } 140 } 141 142 func TestMultiscale2dRepoPersistence(t *testing.T) { 143 if err := server.OpenTest(); err != nil { 144 t.Fatalf("can't open test server: %v\n", err) 145 } 146 defer server.CloseTest() 147 148 // Make source 149 uuid, _ := initTestRepo() 150 makeGrayscale(uuid, t, "grayscale") 151 152 // Make labels and set various properties 153 config := dvid.NewConfig() 154 config.Set("Placeholder", "true") 155 config.Set("Format", "jpg") 156 config.Set("Source", "grayscale") 157 dataservice, err := datastore.NewData(uuid, mstype, "myimagetile", config) 158 if err != nil { 159 t.Errorf("Unable to create imagetile instance: %v\n", err) 160 } 161 msdata, ok := dataservice.(*Data) 162 if !ok { 163 t.Fatalf("Can't cast imagetile data service into imagetile.Data\n") 164 } 165 oldData := *msdata 166 167 // Restart test datastore and see if datasets are still there. 168 if err = datastore.SaveDataByUUID(uuid, msdata); err != nil { 169 t.Fatalf("Unable to save repo during imagetile persistence test: %v\n", err) 170 } 171 datastore.CloseReopenTest() 172 173 dataservice2, err := datastore.GetDataByUUIDName(uuid, "myimagetile") 174 if err != nil { 175 t.Fatalf("Can't get keyvalue instance from reloaded test db: %v\n", err) 176 } 177 msdata2, ok := dataservice2.(*Data) 178 if !ok { 179 t.Errorf("Returned new data instance 2 is not imagetile.Data\n") 180 } 181 182 if !reflect.DeepEqual(oldData.Properties, msdata2.Properties) { 183 t.Errorf("Expected properties %v, got %v\n", oldData.Properties, msdata2.Properties) 184 } 185 } 186 187 func TestTileKey(t *testing.T) { 188 if err := server.OpenTest(); err != nil { 189 t.Fatalf("can't open test server: %v\n", err) 190 } 191 defer server.CloseTest() 192 193 uuid, _ := initTestRepo() 194 server.CreateTestInstance(t, uuid, "imagetile", "tiles", dvid.Config{}) 195 196 keyURL := fmt.Sprintf("%snode/%s/tiles/tilekey/xy/0/1_2_3", server.WebAPIPath, uuid) 197 respStr := server.TestHTTP(t, "GET", keyURL, nil) 198 keyResp := struct { 199 Key string `json:"key"` 200 }{} 201 if err := json.Unmarshal(respStr, &keyResp); err != nil { 202 t.Fatalf("Couldn't parse JSON response to tilekey request (%v):\n%s\n", err, keyResp) 203 } 204 kb := make([]byte, hex.DecodedLen(len(keyResp.Key))) 205 _, err := hex.Decode(kb, []byte(keyResp.Key)) 206 if err != nil { 207 t.Fatalf("Couldn't parse return hex key: %s", keyResp.Key) 208 } 209 210 // Decipher TKey portion to make sure it's correct. 211 key := storage.Key(kb) 212 tk, err := storage.TKeyFromKey(key) 213 if err != nil { 214 t.Fatalf("Couldn't get TKey from returned key (%v): %x", err, kb) 215 } 216 tile, plane, scale, err := DecodeTKey(tk) 217 if err != nil { 218 t.Fatalf("Bad decode of TKey (%v): %x", err, tk) 219 } 220 expectTile := dvid.ChunkPoint3d{1, 2, 3} 221 if tile != expectTile { 222 t.Errorf("Expected tile %v, got %v\n", expectTile, tile) 223 } 224 if !plane.Equals(dvid.XY) { 225 t.Errorf("Expected plane to be XY, got %v\n", plane) 226 } 227 if scale != 0 { 228 t.Errorf("Expected scale to be 0, got %d\n", scale) 229 } 230 } 231 232 const testMetadata2 = ` 233 { 234 "MinTileCoord": [0,0,0], 235 "MaxTileCoord": [30,30,30], 236 "Levels": { 237 "0": { "Resolution": [10.0, 10.0, 10.0], "TileSize": [512, 512, 512] }, 238 "1": { "Resolution": [20.0, 20.0, 20.0], "TileSize": [512, 512, 512] }, 239 "2": { "Resolution": [40.0, 40.0, 40.0], "TileSize": [512, 512, 512] }, 240 "3": { "Resolution": [80.0, 80.0, 80.0], "TileSize": [512, 512, 512] } 241 } 242 } 243 ` 244 245 var testSpans = []dvid.Span{ 246 dvid.Span{100, 101, 200, 210}, dvid.Span{100, 102, 200, 210}, dvid.Span{100, 103, 201, 212}, 247 dvid.Span{101, 101, 201, 213}, dvid.Span{101, 102, 202, 215}, dvid.Span{101, 103, 202, 216}, 248 dvid.Span{102, 101, 200, 210}, dvid.Span{102, 103, 201, 216}, dvid.Span{102, 104, 203, 217}, 249 dvid.Span{103, 101, 200, 210}, dvid.Span{103, 103, 200, 210}, dvid.Span{103, 105, 201, 212}, 250 } 251 252 func getSpansJSON(spans []dvid.Span) io.Reader { 253 jsonBytes, err := json.Marshal(spans) 254 if err != nil { 255 log.Fatalf("Can't encode spans into JSON: %v\n", err) 256 } 257 return bytes.NewReader(jsonBytes) 258 } 259 260 func TestTileCheck(t *testing.T) { 261 if err := server.OpenTest(); err != nil { 262 t.Fatalf("can't open test server: %v\n", err) 263 } 264 defer server.CloseTest() 265 266 // Make source 267 uuid, _ := initTestRepo() 268 makeGrayscale(uuid, t, "grayscale") 269 270 // Make imagetile and set various properties 271 config := dvid.NewConfig() 272 config.Set("Placeholder", "true") 273 config.Set("Format", "jpg") 274 config.Set("Source", "grayscale") 275 tileservice, err := datastore.NewData(uuid, mstype, "myimagetile", config) 276 if err != nil { 277 t.Errorf("Unable to create imagetile instance: %v\n", err) 278 } 279 msdata, ok := tileservice.(*Data) 280 if !ok { 281 t.Fatalf("Can't cast imagetile data service into imagetile.Data\n") 282 } 283 284 // Store Metadata 285 url := fmt.Sprintf("%snode/%s/myimagetile/metadata", server.WebAPIPath, uuid) 286 server.TestHTTP(t, "POST", url, bytes.NewBufferString(testMetadata2)) 287 288 // Create the ROI 289 _, err = datastore.NewData(uuid, roitype, "myroi", dvid.NewConfig()) 290 if err != nil { 291 t.Errorf("Error creating new roi instance: %v\n", err) 292 } 293 294 // PUT an ROI 295 roiRequest := fmt.Sprintf("%snode/%s/myroi/roi", server.WebAPIPath, uuid) 296 server.TestHTTP(t, "POST", roiRequest, getSpansJSON(testSpans)) 297 298 // Create fake filter 299 spec := fmt.Sprintf("roi:myroi,%s", uuid) 300 f, err := msdata.NewFilter(storage.FilterSpec(spec)) 301 if err != nil { 302 t.Errorf("Couldn't make filter: %v\n", err) 303 } 304 if f == nil { 305 t.Fatalf("Couldn't detect myroi data instance\n") 306 } 307 308 // Check various key values for proper spatial checks. 309 var tx, ty int32 310 tx = (205 * 32) / 512 311 ty = (101 * 32) / 512 312 tile := dvid.ChunkPoint3d{tx, ty, 101 * 32} 313 scale := Scaling(0) 314 tk, err := NewTKey(tile, dvid.XY, scale) 315 if err != nil { 316 t.Errorf("bad tkey: %v\n", err) 317 } 318 tkv := &storage.TKeyValue{K: tk} 319 skip, err := f.Check(tkv) 320 if err != nil { 321 t.Errorf("Error on Check of key %q: %v\n", tkv.K, err) 322 } 323 if skip { 324 t.Errorf("Expected false skip, got %v for tile %s\n", skip, tile) 325 } 326 327 tile = dvid.ChunkPoint3d{tx, ty, 106 * 32} 328 tk, err = NewTKey(tile, dvid.XY, scale) 329 if err != nil { 330 t.Errorf("bad tkey: %v\n", err) 331 } 332 tkv = &storage.TKeyValue{K: tk} 333 skip, err = f.Check(tkv) 334 if err != nil { 335 t.Errorf("Error on Check of key %q: %v\n", tkv.K, err) 336 } 337 if !skip { 338 t.Errorf("Expected true skip, got %v for tile %s\n", skip, tile) 339 } 340 341 tx = (205 * 32) / 512 342 ty = (121 * 32) / 512 343 tile = dvid.ChunkPoint3d{tx, ty, 101 * 32} 344 tk, err = NewTKey(tile, dvid.XY, scale) 345 if err != nil { 346 t.Errorf("bad tkey: %v\n", err) 347 } 348 tkv = &storage.TKeyValue{K: tk} 349 skip, err = f.Check(tkv) 350 if err != nil { 351 t.Errorf("Error on Check of key %q: %v\n", tkv.K, err) 352 } 353 if !skip { 354 t.Errorf("Expected true skip, got %v for tile %s\n", skip, tile) 355 } 356 357 tx = (225 * 32) / 512 358 ty = (101 * 32) / 512 359 tile = dvid.ChunkPoint3d{tx, ty, 101 * 32} 360 tk, err = NewTKey(tile, dvid.XY, scale) 361 if err != nil { 362 t.Errorf("bad tkey: %v\n", err) 363 } 364 tkv = &storage.TKeyValue{K: tk} 365 skip, err = f.Check(tkv) 366 if err != nil { 367 t.Errorf("Error on Check of key %q: %v\n", tkv.K, err) 368 } 369 if !skip { 370 t.Errorf("Expected true skip, got %v for tile %s\n", skip, tile) 371 } 372 373 }