github.com/janelia-flyem/dvid@v1.0.0/datatype/labelmap/equiv_test.go (about) 1 package labelmap 2 3 import ( 4 "bytes" 5 "encoding/csv" 6 "encoding/json" 7 "fmt" 8 "io" 9 "strconv" 10 "testing" 11 12 "github.com/janelia-flyem/dvid/datastore" 13 "github.com/janelia-flyem/dvid/datatype/common/labels" 14 "github.com/janelia-flyem/dvid/dvid" 15 "github.com/janelia-flyem/dvid/server" 16 ) 17 18 func (vc *VCache) checkMapping(t *testing.T, mappedVersions distFromRoot, from, to uint64) { 19 mappedLabel, found := vc.mapLabel(from, mappedVersions) 20 if !found { 21 t.Fatalf("expected mapping of %d to be found\n", from) 22 } 23 if mappedLabel != to { 24 t.Fatalf("expected mapping of %d -> %d, got %d\n", from, to, mappedLabel) 25 } 26 } 27 28 func checkMappings(t *testing.T, v dvid.VersionID, in io.Reader, expected map[uint64]uint64) { 29 r := csv.NewReader(in) 30 r.Comma = ' ' 31 records, err := r.ReadAll() 32 if err != nil { 33 t.Fatal(err) 34 } 35 got := map[uint64]uint64{} 36 var from, to uint64 37 for _, line := range records { 38 if len(line) == 2 { 39 if from, err = strconv.ParseUint(line[0], 10, 64); err != nil { 40 t.Fatal(err) 41 } 42 if to, err = strconv.ParseUint(line[1], 10, 64); err != nil { 43 t.Fatal(err) 44 } 45 got[from] = to 46 } else { 47 t.Fatalf("version %d: bad response received for mapping: %v\n", v, records) 48 } 49 } 50 if len(expected) != len(got) { 51 t.Fatalf("version %d: got mapping of size %d != expected %d: %v\n", v, len(got), len(expected), got) 52 } 53 for from, to := range got { 54 expectedTo, found := expected[from] 55 if !found || expectedTo != to { 56 t.Fatalf("version %d: expected %v not same as received mapping %v\n", v, expected, got) 57 } 58 } 59 } 60 61 func mapUpdate(m0, m1 map[uint64]uint64) map[uint64]uint64 { 62 out := map[uint64]uint64{} 63 for k, v := range m0 { 64 out[k] = v 65 } 66 for k, v := range m1 { 67 out[k] = v 68 } 69 return out 70 } 71 72 func TestSVMap(t *testing.T) { 73 if err := server.OpenTest(); err != nil { 74 t.Fatalf("can't open test server: %v\n", err) 75 } 76 defer server.CloseTest() 77 uuid, v := initTestRepo() 78 var config dvid.Config 79 server.CreateTestInstance(t, uuid, "labelmap", "labels", config) 80 81 d, err := GetByVersionName(v, "labels") 82 if err != nil { 83 t.Fatalf("can't get labelmap data service: %v\n", err) 84 } 85 vc := initMapping(d, v) 86 87 mapping := map[uint64]uint64{ 88 1: 3, 89 2: 3, 90 4: 6, 91 5: 6, 92 } 93 for from, to := range mapping { 94 vc.setMapping(v, from, to) 95 } 96 97 mappedVersions := vc.getMappedVersionsDist(v) 98 99 for from, to := range mapping { 100 vc.checkMapping(t, mappedVersions, from, to) 101 } 102 103 // Create a new version 104 apiStr := fmt.Sprintf("%snode/%s/commit", server.WebAPIPath, uuid) 105 payload := bytes.NewBufferString(`{"note": "first version"}`) 106 server.TestHTTP(t, "POST", apiStr, payload) 107 108 versionReq := fmt.Sprintf("%snode/%s/newversion", server.WebAPIPath, uuid) 109 respData := server.TestHTTP(t, "POST", versionReq, nil) 110 resp := struct { 111 Child dvid.UUID `json:"child"` 112 }{} 113 if err := json.Unmarshal(respData, &resp); err != nil { 114 t.Errorf("Expected 'child' JSON response. Got %s\n", string(respData)) 115 } 116 v2, err := datastore.VersionFromUUID(resp.Child) 117 if err != nil { 118 t.Fatalf("error getting version from UUID: %v\n", err) 119 } 120 121 // Add a different mapping to the new version 122 mapping2 := map[uint64]uint64{ 123 2: 5, 124 4: 7, 125 5: 8, 126 } 127 for from, to := range mapping2 { 128 vc.setMapping(v2, from, to) 129 } 130 expected2 := mapUpdate(mapping, mapping2) 131 132 // Make sure that the mapping is the new one 133 mappedVersions2 := vc.getMappedVersionsDist(v2) 134 135 vc.checkMapping(t, mappedVersions2, 1, 3) // unset should fall back to version 1 136 for from, to := range mapping2 { 137 vc.checkMapping(t, mappedVersions2, from, to) 138 } 139 140 // Verify that the old mapping is still there 141 mappedVersions = vc.getMappedVersionsDist(v) 142 143 for from, to := range mapping { 144 vc.checkMapping(t, mappedVersions, from, to) 145 } 146 147 // Create a new branch off of the first version 148 apiStr = fmt.Sprintf("%snode/%s/branch", server.WebAPIPath, uuid) 149 payload = bytes.NewBufferString(`{"branch": "branch 1", "note": "version 3"}`) 150 respData = server.TestHTTP(t, "POST", apiStr, payload) 151 if err := json.Unmarshal(respData, &resp); err != nil { 152 t.Errorf("Expected 'child' JSON response. Got %s\n", string(respData)) 153 } 154 v3, err := datastore.VersionFromUUID(resp.Child) 155 if err != nil { 156 t.Fatalf("error getting version from UUID: %v\n", err) 157 } 158 159 // Get a new mapping 160 mapping3 := map[uint64]uint64{ 161 3: 15, 162 4: 17, 163 6: 18, 164 } 165 for from, to := range mapping3 { 166 vc.setMapping(v3, from, to) 167 } 168 expected3 := mapUpdate(mapping, mapping3) 169 170 // Make sure that the mapping is the new one 171 mappedVersions3 := vc.getMappedVersionsDist(v3) 172 173 vc.checkMapping(t, mappedVersions3, 1, 3) // unset should fall back to version 1 174 vc.checkMapping(t, mappedVersions3, 2, 3) // unset should fall back to version 1 175 vc.checkMapping(t, mappedVersions3, 5, 6) // unset should fall back to version 1 176 for from, to := range mapping3 { 177 vc.checkMapping(t, mappedVersions3, from, to) 178 } 179 180 // Verify that the old mapping is still there 181 mappedVersions = vc.getMappedVersionsDist(v) 182 183 for from, to := range mapping { 184 vc.checkMapping(t, mappedVersions, from, to) 185 } 186 187 // check mappings 188 buf := new(bytes.Buffer) 189 if err := d.writeMappings(buf, v, false); err != nil { 190 t.Fatal(err) 191 } 192 checkMappings(t, v, buf, mapping) 193 buf.Reset() 194 if err := d.writeMappings(buf, v2, false); err != nil { 195 t.Fatal(err) 196 } 197 checkMappings(t, v2, buf, expected2) 198 if err := d.writeMappings(buf, v3, false); err != nil { 199 t.Fatal(err) 200 } 201 checkMappings(t, v3, buf, expected3) 202 } 203 204 // Tests the logging of various mutations and whether they are properly 205 // reloaded from the log. 206 func TestMappingIngest(t *testing.T) { 207 if err := server.OpenTest(); err != nil { 208 t.Fatalf("can't open test server: %v\n", err) 209 } 210 defer server.CloseTest() 211 212 uuid, v := initTestRepo() 213 var config dvid.Config 214 server.CreateTestInstance(t, uuid, "labelmap", "labels", config) 215 216 d, err := GetByVersionName(v, "labels") 217 if err != nil { 218 t.Fatalf("can't get labelmap data service: %v\n", err) 219 } 220 vc := initMapping(d, v) 221 222 mapping := map[uint64]uint64{ 223 1: 1, 224 5: 1, 225 226 2: 2, 227 3: 3, 228 4: 4, 229 } 230 for from, to := range mapping { 231 vc.setMapping(v, from, to) 232 } 233 234 // Renumber of label 4 to 50. 235 mutID := d.NewMutationID() 236 supervoxels := labels.Set{4: struct{}{}} 237 addRenumberToMapping(d, v, mutID, 4, 50, supervoxels) 238 239 // Merge label 2 into 3. 240 mutID = d.NewMutationID() 241 supervoxels = labels.Set{2: struct{}{}} 242 addMergeToMapping(d, v, mutID, 3, supervoxels) 243 244 // Cleave label 1 so that sv 1 remains and sv 5 -> 6. 245 mutID = d.NewMutationID() 246 op := labels.CleaveOp{ 247 MutID: mutID, 248 Target: 1, 249 CleavedLabel: 6, 250 CleavedSupervoxels: []uint64{5}, 251 } 252 addCleaveToMapping(d, v, op) 253 254 // Check current in-memory map. 255 expected := map[uint64]uint64{ 256 1: 1, 257 5: 6, 258 2: 3, 259 3: 3, 260 4: 50, 261 } 262 mappedVersions := vc.getMappedVersionsDist(v) 263 for from, to := range expected { 264 vc.checkMapping(t, mappedVersions, from, to) 265 } 266 267 // Reload the mapping from the log. 268 vc2 := initMapping(d, v) 269 vc2.initToVersion(d, v, true) 270 271 // Test that the mapping is correct. 272 mappedVersions = vc2.getMappedVersionsDist(v) 273 for from, to := range expected { 274 vc2.checkMapping(t, mappedVersions, from, to) 275 } 276 }