github.com/moby/docker@v26.1.3+incompatible/libnetwork/internal/setmatrix/setmatrix_test.go (about)

     1  package setmatrix
     2  
     3  import (
     4  	"context"
     5  	"strconv"
     6  	"strings"
     7  	"testing"
     8  	"time"
     9  )
    10  
    11  func TestSetSerialInsertDelete(t *testing.T) {
    12  	var s SetMatrix[string]
    13  
    14  	b, i := s.Insert("a", "1")
    15  	if !b || i != 1 {
    16  		t.Fatalf("error in insert %t %d", b, i)
    17  	}
    18  	b, i = s.Insert("a", "1")
    19  	if b || i != 1 {
    20  		t.Fatalf("error in insert %t %d", b, i)
    21  	}
    22  	b, i = s.Insert("a", "2")
    23  	if !b || i != 2 {
    24  		t.Fatalf("error in insert %t %d", b, i)
    25  	}
    26  	b, i = s.Insert("a", "1")
    27  	if b || i != 2 {
    28  		t.Fatalf("error in insert %t %d", b, i)
    29  	}
    30  	b, i = s.Insert("a", "3")
    31  	if !b || i != 3 {
    32  		t.Fatalf("error in insert %t %d", b, i)
    33  	}
    34  	b, i = s.Insert("a", "2")
    35  	if b || i != 3 {
    36  		t.Fatalf("error in insert %t %d", b, i)
    37  	}
    38  	b, i = s.Insert("a", "3")
    39  	if b || i != 3 {
    40  		t.Fatalf("error in insert %t %d", b, i)
    41  	}
    42  	b, i = s.Insert("a", "4")
    43  	if !b || i != 4 {
    44  		t.Fatalf("error in insert %t %d", b, i)
    45  	}
    46  
    47  	b, p := s.Contains("a", "1")
    48  	if !b || !p {
    49  		t.Fatalf("error in contains %t %t", b, p)
    50  	}
    51  	b, p = s.Contains("a", "2")
    52  	if !b || !p {
    53  		t.Fatalf("error in contains %t %t", b, p)
    54  	}
    55  	b, p = s.Contains("a", "3")
    56  	if !b || !p {
    57  		t.Fatalf("error in contains %t %t", b, p)
    58  	}
    59  	b, p = s.Contains("a", "4")
    60  	if !b || !p {
    61  		t.Fatalf("error in contains %t %t", b, p)
    62  	}
    63  
    64  	i, b = s.Cardinality("a")
    65  	if !b || i != 4 {
    66  		t.Fatalf("error in cardinality count %t %d", b, i)
    67  	}
    68  	keys := s.Keys()
    69  	if len(keys) != 1 {
    70  		t.Fatalf("error in keys %v", keys)
    71  	}
    72  	str, b := s.String("a")
    73  	if !b ||
    74  		!strings.Contains(str, "1") ||
    75  		!strings.Contains(str, "2") ||
    76  		!strings.Contains(str, "3") ||
    77  		!strings.Contains(str, "4") {
    78  		t.Fatalf("error in string %t %s", b, str)
    79  	}
    80  
    81  	_, b = s.Get("a")
    82  	if !b {
    83  		t.Fatalf("error in get %t", b)
    84  	}
    85  
    86  	b, i = s.Remove("a", "1")
    87  	if !b || i != 3 {
    88  		t.Fatalf("error in remove %t %d", b, i)
    89  	}
    90  	b, i = s.Remove("a", "3")
    91  	if !b || i != 2 {
    92  		t.Fatalf("error in remove %t %d", b, i)
    93  	}
    94  	b, i = s.Remove("a", "1")
    95  	if b || i != 2 {
    96  		t.Fatalf("error in remove %t %d", b, i)
    97  	}
    98  	b, i = s.Remove("a", "4")
    99  	if !b || i != 1 {
   100  		t.Fatalf("error in remove %t %d", b, i)
   101  	}
   102  	b, i = s.Remove("a", "2")
   103  	if !b || i != 0 {
   104  		t.Fatalf("error in remove %t %d", b, i)
   105  	}
   106  	b, i = s.Remove("a", "2")
   107  	if b || i != 0 {
   108  		t.Fatalf("error in remove %t %d", b, i)
   109  	}
   110  
   111  	i, b = s.Cardinality("a")
   112  	if b || i != 0 {
   113  		t.Fatalf("error in cardinality count %t %d", b, i)
   114  	}
   115  
   116  	str, b = s.String("a")
   117  	if b || str != "" {
   118  		t.Fatalf("error in string %t %s", b, str)
   119  	}
   120  
   121  	keys = s.Keys()
   122  	if len(keys) > 0 {
   123  		t.Fatalf("error in keys %v", keys)
   124  	}
   125  
   126  	// Negative tests
   127  	_, b = s.Get("not exists")
   128  	if b {
   129  		t.Fatalf("error should not happen %t", b)
   130  	}
   131  
   132  	b1, b := s.Contains("not exists", "a")
   133  	if b1 || b {
   134  		t.Fatalf("error should not happen %t %t", b1, b)
   135  	}
   136  }
   137  
   138  func insertDeleteRotuine(ctx context.Context, endCh chan int, s *SetMatrix[string], key, value string) {
   139  	for {
   140  		select {
   141  		case <-ctx.Done():
   142  			endCh <- 0
   143  			return
   144  		default:
   145  			b, _ := s.Insert(key, value)
   146  			if !b {
   147  				endCh <- 1
   148  				return
   149  			}
   150  
   151  			b, _ = s.Remove(key, value)
   152  			if !b {
   153  				endCh <- 2
   154  				return
   155  			}
   156  		}
   157  	}
   158  }
   159  
   160  func TestSetParallelInsertDelete(t *testing.T) {
   161  	var s SetMatrix[string]
   162  	parallelRoutines := 6
   163  	endCh := make(chan int)
   164  	// Let the routines running and competing for 10s
   165  	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
   166  	defer cancel()
   167  	for i := 0; i < parallelRoutines; i++ {
   168  		go insertDeleteRotuine(ctx, endCh, &s, "key-"+strconv.Itoa(i%3), strconv.Itoa(i))
   169  	}
   170  	for parallelRoutines > 0 {
   171  		v := <-endCh
   172  		if v == 1 {
   173  			t.Fatalf("error one goroutine failed on the insert")
   174  		}
   175  		if v == 2 {
   176  			t.Fatalf("error one goroutine failed on the remove")
   177  		}
   178  		parallelRoutines--
   179  	}
   180  	if i, b := s.Cardinality("key"); b || i > 0 {
   181  		t.Fatalf("error the set should be empty %t %d", b, i)
   182  	}
   183  }