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  }