github.com/janelia-flyem/dvid@v1.0.0/datatype/common/labels/labels_test.go (about) 1 package labels 2 3 import ( 4 "math/rand" 5 "sync" 6 "testing" 7 8 "github.com/janelia-flyem/dvid/dvid" 9 ) 10 11 func TestMapping(t *testing.T) { 12 var m Mapping 13 m.set(1, 4) 14 m.set(2, 5) 15 m.set(20, 6) 16 m.set(6, 32) 17 m.set(15, 3) 18 m.set(3, 32) 19 m.set(8, 32) 20 m.set(32, 21) 21 if v, ok := m.Get(1); v != 4 || !ok { 22 t.Errorf("Incorrect mapping on Get. Got %d, %t\n", v, ok) 23 } 24 if v, ok := m.Get(2); v != 5 || !ok { 25 t.Errorf("Incorrect mapping on Get. Got %d, %t\n", v, ok) 26 } 27 if v, ok := m.Get(20); v != 6 || !ok { 28 t.Errorf("Incorrect mapping on Get. Got %d, %t\n", v, ok) 29 } 30 if v, ok := m.Get(32); v != 21 || !ok { 31 t.Errorf("Incorrect mapping on Get. Got %d, %t\n", v, ok) 32 } 33 if v, ok := m.Get(10); ok { 34 t.Errorf("Got mapping for 10 when none was inserted. Received %d, %t\n", v, ok) 35 } 36 if v, ok := m.FinalLabel(20); v != 21 || !ok { 37 t.Errorf("Couldn't get final mapping label from 20->6->32->21. Got %d, %t\n", v, ok) 38 } 39 40 c := m.ConstituentLabels(21) 41 42 expected := []uint64{20, 6, 32, 3, 8, 15, 21} 43 if len(c) != len(expected) { 44 t.Errorf("Expected %d constituent labels, got %d instead: %s\n", len(expected), len(c), c) 45 } 46 for _, label := range expected { 47 if _, found := c[label]; !found { 48 t.Errorf("Expected label %d as constituent but wasn't found.\n", label) 49 } 50 } 51 } 52 53 func TestCounts(t *testing.T) { 54 var c Counts 55 if !c.Empty() { 56 t.Errorf("Expected Counts to be empty") 57 } 58 c.Incr(7) 59 c.Incr(21) 60 c.Decr(21) 61 c.Decr(7) 62 if !c.Empty() { 63 t.Errorf("Expected Counts to be empty after incr/decr cycles") 64 } 65 66 c.Incr(9) 67 if v := c.Value(9); v != 1 { 68 t.Errorf("Bad count. Expected 1 got %d\n", v) 69 } 70 // Test thread-safety 71 var wg sync.WaitGroup 72 wg.Add(500) 73 expected := 1 74 for i := 0; i < 500; i++ { 75 r := rand.Intn(3) 76 if r == 0 { 77 expected-- 78 go func() { 79 c.Decr(9) 80 wg.Done() 81 }() 82 } else { 83 expected++ 84 go func() { 85 c.Incr(9) 86 wg.Done() 87 }() 88 } 89 } 90 wg.Wait() 91 if v := c.Value(9); v != expected { 92 t.Errorf("After concurrent, random incr/decr, got %d, expected %d\n", v, expected) 93 } 94 95 } 96 97 func TestMergeCache(t *testing.T) { 98 merges := []MergeTuple{ 99 MergeTuple{4, 1, 2, 3}, 100 MergeTuple{9, 10, 11, 12}, 101 MergeTuple{21, 100, 18, 85, 97, 45}, 102 } 103 merges2 := []MergeTuple{ 104 MergeTuple{9, 5, 11, 6}, 105 MergeTuple{9, 100, 3, 22}, 106 MergeTuple{21, 44, 55, 66, 77, 88}, 107 } 108 expectmap := map[uint64]uint64{ 109 1: 4, 110 2: 4, 111 3: 4, 112 10: 9, 113 11: 9, 114 12: 9, 115 100: 21, 116 18: 21, 117 85: 21, 118 97: 21, 119 45: 21, 120 } 121 122 expectmap2 := map[uint64]uint64{ 123 5: 9, 124 6: 9, 125 11: 9, 126 3: 9, 127 22: 9, 128 100: 9, 129 44: 21, 130 55: 21, 131 66: 21, 132 77: 21, 133 88: 21, 134 } 135 136 iv := dvid.InstanceVersion{"foobar", 23} 137 for _, tuple := range merges { 138 op, err := tuple.Op() 139 if err != nil { 140 t.Errorf("Error converting tuple %v to MergeOp: %v\n", tuple, err) 141 } 142 if err := MergeStart(iv, op); err != nil { 143 t.Errorf("Error on starting merge (%v): %v\n", op, err) 144 } 145 } 146 badop, _ := MergeTuple{72, 9, 47}.Op() 147 if err := MergeStart(iv, badop); err == nil { 148 t.Errorf("Expected error on starting merge (%v): %v\n", badop, err) 149 } 150 151 iv2 := dvid.InstanceVersion{"foobar", 24} 152 for _, tuple := range merges2 { 153 op, err := tuple.Op() 154 if err != nil { 155 t.Errorf("Error converting tuple %v to MergeOp: %v\n", tuple, err) 156 } 157 if err := MergeStart(iv2, op); err != nil { 158 t.Errorf("Error on starting merge (%v): %v\n", op, err) 159 } 160 } 161 162 mapping := LabelMap(iv) 163 for a, b := range expectmap { 164 c, ok := mapping.FinalLabel(a) 165 if !ok || c != b { 166 t.Errorf("Expected mapping of %d -> %d, got %d (%t) instead\n", a, b, c, ok) 167 } 168 } 169 if _, ok := mapping.FinalLabel(66); ok { 170 t.Errorf("Got mapping even though none existed for this version.") 171 } 172 if label, ok := mapping.FinalLabel(1); !ok || label != 4 { 173 t.Errorf("Bad final mapping of label 1. Got %d, expected 4\n", label) 174 } 175 176 mapping2 := LabelMap(iv2) 177 for a, b := range expectmap2 { 178 c, ok := mapping2.Get(a) 179 if !ok || c != b { 180 t.Errorf("Expected mapping of %d -> %d, got %d (%t) instead\n", a, b, c, ok) 181 } 182 } 183 if _, ok := mapping2.Get(12); ok { 184 t.Errorf("Got mapping even though none existed for this version.") 185 } 186 if label, ok := mapping2.Get(100); !ok || label != 9 { 187 t.Errorf("Bad final mapping of label 100. Got %d, expected 9\n", label) 188 } 189 190 // Add another merge into label 4 191 op1, err := MergeTuple{4, 1000, 1001, 1002}.Op() 192 if err != nil { 193 t.Errorf("Error converting [4, 1000, 1001, 1002] to MergeOp: %v\n", err) 194 } 195 if err := MergeStart(iv, op1); err != nil { 196 t.Fatalf("Couldn't start merge op %v: %v\n", op1, err) 197 } 198 199 constituents := mapping.ConstituentLabels(4) 200 if len(constituents) != 7 { 201 t.Errorf("Expected 7 merged labels into label 4, got: %s\n", constituents) 202 } 203 for _, label := range []uint64{4, 1, 2, 3, 1000, 1001, 1002} { 204 _, found := constituents[label] 205 if !found { 206 t.Errorf("Expected a constituent label for 4 to be %d but wasn't found: %v\n", label, constituents) 207 } 208 if !labelsMerging.IsDirty(iv, label) { 209 t.Errorf("Expected label %d to be marked Dirty but wasn't.\n", label) 210 } 211 } 212 213 // Remove the first merge (1,2,3 -> 4) and test that it's gone. 214 op2, err := merges[0].Op() 215 if err != nil { 216 t.Errorf("Error converting tuple %v to MergeOp: %v\n", merges[0], err) 217 } 218 MergeStop(iv, op2) 219 220 constituents = mapping.ConstituentLabels(4) 221 if len(constituents) != 4 { 222 t.Errorf("Stoped merge %v for iv %v, but found weird constituents: %s\n", op2, iv, constituents) 223 } 224 for _, label := range []uint64{4, 1000, 1001, 1002} { 225 _, found := constituents[label] 226 if !found { 227 t.Errorf("Expected constituent label for 4 to be %d but wasn't found: %v\n", label, constituents) 228 } 229 if !labelsMerging.IsDirty(iv, label) { 230 t.Errorf("Expected label %d to be marked Dirty but wasn't.\n", label) 231 } 232 } 233 234 for _, label := range []uint64{1, 2, 3} { 235 _, found := mapping.Get(label) 236 if found { 237 t.Errorf("Found mapping for label %d when it should have been removed\n", label) 238 } 239 _, found = mapping.FinalLabel(label) 240 if found { 241 t.Errorf("Found final mapping for label %d when it should have been removed\n", label) 242 } 243 if labelsMerging.IsDirty(iv, label) { 244 t.Errorf("Expected label %d to be marked NOT Dirty but was marked Dirty.\n", label) 245 } 246 } 247 248 // Remove other merge op into 4 and test there are no more mappings. 249 MergeStop(iv, op1) 250 251 constituents = mapping.ConstituentLabels(4) 252 if len(constituents) != 1 { 253 t.Errorf("Stoped merge %v for iv %v, but found weird constituents: %s\n", op1, iv, constituents) 254 } 255 _, found := constituents[4] 256 if !found { 257 t.Errorf("Expected constituent label for 4 to be just 4 but found: %v\n", constituents) 258 } 259 if labelsMerging.IsDirty(iv, 4) { 260 t.Errorf("Expected label 4 to be marked NOT Dirty but was marked Dirty.\n") 261 } 262 263 for _, label := range []uint64{1001, 1002, 1004} { 264 _, found := mapping.Get(label) 265 if found { 266 t.Errorf("Found mapping for label %d when it should have been removed\n", label) 267 } 268 _, found = mapping.FinalLabel(label) 269 if found { 270 t.Errorf("Found final mapping for label %d when it should have been removed\n", label) 271 } 272 if labelsMerging.IsDirty(iv, label) { 273 t.Errorf("Expected label %d to be marked NOT Dirty but was marked Dirty.\n", label) 274 } 275 } 276 } 277 278 func TestDirtyCache(t *testing.T) { 279 var c dirtyCache 280 iv := dvid.InstanceVersion{"foobar", 23} 281 iv2 := dvid.InstanceVersion{"foobar", 24} 282 if !c.Empty(iv) && !c.Empty(iv2) { 283 t.Errorf("DirtyCache should be considered empty but it's not.") 284 } 285 c.Incr(iv, 390) 286 c.Incr(iv, 84) 287 c.Incr(iv, 390) 288 if c.Empty(iv) { 289 t.Errorf("DirtyCache should be non-empty.") 290 } 291 if !c.Empty(iv2) { 292 t.Errorf("DirtyCache should be empty") 293 } 294 c.Incr(iv2, 24) 295 c.Incr(iv2, 390) 296 if c.IsDirty(iv, 1) { 297 t.Errorf("Label is marked dirty when it's not.") 298 } 299 if !c.IsDirty(iv, 84) { 300 t.Errorf("Label is not marked dirty when it is.") 301 } 302 if c.IsDirty(iv, 24) { 303 t.Errorf("Label is marked dirty when it's not.") 304 } 305 if !c.IsDirty(iv2, 24) { 306 t.Errorf("Label is not marked dirty when it is.") 307 } 308 if !c.IsDirty(iv, 390) { 309 t.Errorf("Label is not marked dirty when it is.") 310 } 311 c.Decr(iv, 390) 312 if !c.IsDirty(iv, 390) { 313 t.Errorf("Label is not marked dirty when it is.") 314 } 315 c.Decr(iv, 390) 316 if c.IsDirty(iv, 390) { 317 t.Errorf("Label is marked dirty when it's not.") 318 } 319 if !c.IsDirty(iv2, 390) { 320 t.Errorf("Label is not marked dirty when it is.") 321 } 322 }