go.etcd.io/etcd@v3.3.27+incompatible/pkg/types/set_test.go (about) 1 // Copyright 2015 The etcd Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package types 16 17 import ( 18 "reflect" 19 "sort" 20 "testing" 21 ) 22 23 func TestUnsafeSet(t *testing.T) { 24 driveSetTests(t, NewUnsafeSet()) 25 } 26 27 func TestThreadsafeSet(t *testing.T) { 28 driveSetTests(t, NewThreadsafeSet()) 29 } 30 31 // Check that two slices contents are equal; order is irrelevant 32 func equal(a, b []string) bool { 33 as := sort.StringSlice(a) 34 bs := sort.StringSlice(b) 35 as.Sort() 36 bs.Sort() 37 return reflect.DeepEqual(as, bs) 38 } 39 40 func driveSetTests(t *testing.T, s Set) { 41 // Verify operations on an empty set 42 eValues := []string{} 43 values := s.Values() 44 if !reflect.DeepEqual(values, eValues) { 45 t.Fatalf("Expect values=%v got %v", eValues, values) 46 } 47 if l := s.Length(); l != 0 { 48 t.Fatalf("Expected length=0, got %d", l) 49 } 50 for _, v := range []string{"foo", "bar", "baz"} { 51 if s.Contains(v) { 52 t.Fatalf("Expect s.Contains(%q) to be fale, got true", v) 53 } 54 } 55 56 // Add three items, ensure they show up 57 s.Add("foo") 58 s.Add("bar") 59 s.Add("baz") 60 61 eValues = []string{"foo", "bar", "baz"} 62 values = s.Values() 63 if !equal(values, eValues) { 64 t.Fatalf("Expect values=%v got %v", eValues, values) 65 } 66 67 for _, v := range eValues { 68 if !s.Contains(v) { 69 t.Fatalf("Expect s.Contains(%q) to be true, got false", v) 70 } 71 } 72 73 if l := s.Length(); l != 3 { 74 t.Fatalf("Expected length=3, got %d", l) 75 } 76 77 // Add the same item a second time, ensuring it is not duplicated 78 s.Add("foo") 79 80 values = s.Values() 81 if !equal(values, eValues) { 82 t.Fatalf("Expect values=%v got %v", eValues, values) 83 } 84 if l := s.Length(); l != 3 { 85 t.Fatalf("Expected length=3, got %d", l) 86 } 87 88 // Remove all items, ensure they are gone 89 s.Remove("foo") 90 s.Remove("bar") 91 s.Remove("baz") 92 93 eValues = []string{} 94 values = s.Values() 95 if !equal(values, eValues) { 96 t.Fatalf("Expect values=%v got %v", eValues, values) 97 } 98 99 if l := s.Length(); l != 0 { 100 t.Fatalf("Expected length=0, got %d", l) 101 } 102 103 // Create new copies of the set, and ensure they are unlinked to the 104 // original Set by making modifications 105 s.Add("foo") 106 s.Add("bar") 107 cp1 := s.Copy() 108 cp2 := s.Copy() 109 s.Remove("foo") 110 cp3 := s.Copy() 111 cp1.Add("baz") 112 113 for i, tt := range []struct { 114 want []string 115 got []string 116 }{ 117 {[]string{"bar"}, s.Values()}, 118 {[]string{"foo", "bar", "baz"}, cp1.Values()}, 119 {[]string{"foo", "bar"}, cp2.Values()}, 120 {[]string{"bar"}, cp3.Values()}, 121 } { 122 if !equal(tt.want, tt.got) { 123 t.Fatalf("case %d: expect values=%v got %v", i, tt.want, tt.got) 124 } 125 } 126 127 for i, tt := range []struct { 128 want bool 129 got bool 130 }{ 131 {true, s.Equals(cp3)}, 132 {true, cp3.Equals(s)}, 133 {false, s.Equals(cp2)}, 134 {false, s.Equals(cp1)}, 135 {false, cp1.Equals(s)}, 136 {false, cp2.Equals(s)}, 137 {false, cp2.Equals(cp1)}, 138 } { 139 if tt.got != tt.want { 140 t.Fatalf("case %d: want %t, got %t", i, tt.want, tt.got) 141 142 } 143 } 144 145 // Subtract values from a Set, ensuring a new Set is created and 146 // the original Sets are unmodified 147 sub1 := cp1.Sub(s) 148 sub2 := cp2.Sub(cp1) 149 150 for i, tt := range []struct { 151 want []string 152 got []string 153 }{ 154 {[]string{"foo", "bar", "baz"}, cp1.Values()}, 155 {[]string{"foo", "bar"}, cp2.Values()}, 156 {[]string{"bar"}, s.Values()}, 157 {[]string{"foo", "baz"}, sub1.Values()}, 158 {[]string{}, sub2.Values()}, 159 } { 160 if !equal(tt.want, tt.got) { 161 t.Fatalf("case %d: expect values=%v got %v", i, tt.want, tt.got) 162 } 163 } 164 } 165 166 func TestUnsafeSetContainsAll(t *testing.T) { 167 vals := []string{"foo", "bar", "baz"} 168 s := NewUnsafeSet(vals...) 169 170 tests := []struct { 171 strs []string 172 wcontain bool 173 }{ 174 {[]string{}, true}, 175 {vals[:1], true}, 176 {vals[:2], true}, 177 {vals, true}, 178 {[]string{"cuz"}, false}, 179 {[]string{vals[0], "cuz"}, false}, 180 } 181 for i, tt := range tests { 182 if g := s.ContainsAll(tt.strs); g != tt.wcontain { 183 t.Errorf("#%d: ok = %v, want %v", i, g, tt.wcontain) 184 } 185 } 186 }