[ Tianon Gravi ]
[ Debian Janitor ]
New upstream release.
Debian Janitor
2 years ago
0 | on: [push, pull_request] | |
1 | name: CI | |
2 | jobs: | |
3 | test: | |
4 | strategy: | |
5 | matrix: | |
6 | go-version: [1.17.x] | |
7 | os: [ubuntu-latest, macos-latest, windows-latest] | |
8 | runs-on: ${{ matrix.os }} | |
9 | steps: | |
10 | - name: Install Go | |
11 | uses: actions/setup-go@v2 | |
12 | with: | |
13 | go-version: ${{ matrix.go-version }} | |
14 | - name: Checkout code | |
15 | uses: actions/checkout@v2 | |
16 | - name: Test | |
17 | run: | | |
18 | #go vet ./... | |
19 | go test -v -race ./... | |
20 | go test -bench=. |
0 | [![Build Status](https://travis-ci.org/deckarep/golang-set.png?branch=master)](https://travis-ci.org/deckarep/golang-set) | |
1 | [![GoDoc](https://godoc.org/github.com/deckarep/golang-set?status.png)](http://godoc.org/github.com/deckarep/golang-set) | |
0 | [![Build Status](https://travis-ci.org/deckarep/golang-set.svg?branch=master)](https://travis-ci.org/deckarep/golang-set) | |
1 | [![Go Report Card](https://goreportcard.com/badge/github.com/deckarep/golang-set)](https://goreportcard.com/report/github.com/deckarep/golang-set) | |
2 | [![GoDoc](https://godoc.org/github.com/deckarep/golang-set?status.svg)](http://godoc.org/github.com/deckarep/golang-set) | |
2 | 3 | |
3 | 4 | ## golang-set |
4 | 5 |
285 | 285 | benchIsSuperset(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet()) |
286 | 286 | } |
287 | 287 | |
288 | func benchIsProperSubset(b *testing.B, n int, s, t Set) { | |
289 | nums := nrand(n) | |
290 | for _, v := range nums { | |
291 | s.Add(v) | |
292 | t.Add(v) | |
293 | } | |
294 | ||
295 | b.ResetTimer() | |
296 | for i := 0; i < b.N; i++ { | |
297 | s.IsProperSubset(t) | |
298 | } | |
299 | } | |
300 | ||
301 | func BenchmarkIsProperSubset1Safe(b *testing.B) { | |
302 | benchIsProperSubset(b, 1, NewSet(), NewSet()) | |
303 | } | |
304 | ||
305 | func BenchmarkIsProperSubset1Unsafe(b *testing.B) { | |
306 | benchIsProperSubset(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet()) | |
307 | } | |
308 | ||
309 | func BenchmarkIsProperSubset10Safe(b *testing.B) { | |
310 | benchIsProperSubset(b, 10, NewSet(), NewSet()) | |
311 | } | |
312 | ||
313 | func BenchmarkIsProperSubset10Unsafe(b *testing.B) { | |
314 | benchIsProperSubset(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet()) | |
315 | } | |
316 | ||
317 | func BenchmarkIsProperSubset100Safe(b *testing.B) { | |
318 | benchIsProperSubset(b, 100, NewSet(), NewSet()) | |
319 | } | |
320 | ||
321 | func BenchmarkIsProperSubset100Unsafe(b *testing.B) { | |
322 | benchIsProperSubset(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet()) | |
323 | } | |
324 | ||
325 | func benchIsProperSuperset(b *testing.B, n int, s, t Set) { | |
326 | nums := nrand(n) | |
327 | for _, v := range nums { | |
328 | s.Add(v) | |
329 | t.Add(v) | |
330 | } | |
331 | ||
332 | b.ResetTimer() | |
333 | for i := 0; i < b.N; i++ { | |
334 | s.IsProperSuperset(t) | |
335 | } | |
336 | } | |
337 | ||
338 | func BenchmarkIsProperSuperset1Safe(b *testing.B) { | |
339 | benchIsProperSuperset(b, 1, NewSet(), NewSet()) | |
340 | } | |
341 | ||
342 | func BenchmarkIsProperSuperset1Unsafe(b *testing.B) { | |
343 | benchIsProperSuperset(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet()) | |
344 | } | |
345 | ||
346 | func BenchmarkIsProperSuperset10Safe(b *testing.B) { | |
347 | benchIsProperSuperset(b, 10, NewSet(), NewSet()) | |
348 | } | |
349 | ||
350 | func BenchmarkIsProperSuperset10Unsafe(b *testing.B) { | |
351 | benchIsProperSuperset(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet()) | |
352 | } | |
353 | ||
354 | func BenchmarkIsProperSuperset100Safe(b *testing.B) { | |
355 | benchIsProperSuperset(b, 100, NewSet(), NewSet()) | |
356 | } | |
357 | ||
358 | func BenchmarkIsProperSuperset100Unsafe(b *testing.B) { | |
359 | benchIsProperSuperset(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet()) | |
360 | } | |
361 | ||
288 | 362 | func BenchmarkDifference1Safe(b *testing.B) { |
289 | 363 | benchDifference(b, 1, NewSet(), NewSet()) |
290 | 364 | } |
426 | 500 | benchUnion(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet()) |
427 | 501 | } |
428 | 502 | |
503 | func benchEach(b *testing.B, n int, s Set) { | |
504 | nums := nrand(n) | |
505 | for _, v := range nums { | |
506 | s.Add(v) | |
507 | } | |
508 | ||
509 | b.ResetTimer() | |
510 | for i := 0; i < b.N; i++ { | |
511 | s.Each(func(elem interface{}) bool { | |
512 | return false | |
513 | }) | |
514 | } | |
515 | } | |
516 | ||
517 | func BenchmarkEach1Safe(b *testing.B) { | |
518 | benchEach(b, 1, NewSet()) | |
519 | } | |
520 | ||
521 | func BenchmarkEach1Unsafe(b *testing.B) { | |
522 | benchEach(b, 1, NewThreadUnsafeSet()) | |
523 | } | |
524 | ||
525 | func BenchmarkEach10Safe(b *testing.B) { | |
526 | benchEach(b, 10, NewSet()) | |
527 | } | |
528 | ||
529 | func BenchmarkEach10Unsafe(b *testing.B) { | |
530 | benchEach(b, 10, NewThreadUnsafeSet()) | |
531 | } | |
532 | ||
533 | func BenchmarkEach100Safe(b *testing.B) { | |
534 | benchEach(b, 100, NewSet()) | |
535 | } | |
536 | ||
537 | func BenchmarkEach100Unsafe(b *testing.B) { | |
538 | benchEach(b, 100, NewThreadUnsafeSet()) | |
539 | } | |
540 | ||
429 | 541 | func benchIter(b *testing.B, n int, s Set) { |
430 | 542 | nums := nrand(n) |
431 | 543 | for _, v := range nums { |
435 | 547 | b.ResetTimer() |
436 | 548 | for i := 0; i < b.N; i++ { |
437 | 549 | c := s.Iter() |
438 | for _ = range c { | |
550 | for range c { | |
439 | 551 | |
440 | 552 | } |
441 | 553 | } |
465 | 577 | benchIter(b, 100, NewThreadUnsafeSet()) |
466 | 578 | } |
467 | 579 | |
580 | func benchIterator(b *testing.B, n int, s Set) { | |
581 | nums := nrand(n) | |
582 | for _, v := range nums { | |
583 | s.Add(v) | |
584 | } | |
585 | ||
586 | b.ResetTimer() | |
587 | for i := 0; i < b.N; i++ { | |
588 | c := s.Iterator().C | |
589 | for range c { | |
590 | ||
591 | } | |
592 | } | |
593 | } | |
594 | ||
595 | func BenchmarkIterator1Safe(b *testing.B) { | |
596 | benchIterator(b, 1, NewSet()) | |
597 | } | |
598 | ||
599 | func BenchmarkIterator1Unsafe(b *testing.B) { | |
600 | benchIterator(b, 1, NewThreadUnsafeSet()) | |
601 | } | |
602 | ||
603 | func BenchmarkIterator10Safe(b *testing.B) { | |
604 | benchIterator(b, 10, NewSet()) | |
605 | } | |
606 | ||
607 | func BenchmarkIterator10Unsafe(b *testing.B) { | |
608 | benchIterator(b, 10, NewThreadUnsafeSet()) | |
609 | } | |
610 | ||
611 | func BenchmarkIterator100Safe(b *testing.B) { | |
612 | benchIterator(b, 100, NewSet()) | |
613 | } | |
614 | ||
615 | func BenchmarkIterator100Unsafe(b *testing.B) { | |
616 | benchIterator(b, 100, NewThreadUnsafeSet()) | |
617 | } | |
618 | ||
468 | 619 | func benchString(b *testing.B, n int, s Set) { |
469 | 620 | nums := nrand(n) |
470 | 621 | for _, v := range nums { |
473 | 624 | |
474 | 625 | b.ResetTimer() |
475 | 626 | for i := 0; i < b.N; i++ { |
476 | s.String() | |
627 | _ = s.String() | |
477 | 628 | } |
478 | 629 | } |
479 | 630 |
0 | golang-github-deckarep-golang-set (1.5-3) UNRELEASED; urgency=medium | |
0 | golang-github-deckarep-golang-set (1.8.0-1) UNRELEASED; urgency=medium | |
1 | 1 | |
2 | [ Tianon Gravi ] | |
2 | 3 | * Team upload. |
3 | 4 | * Remove self from Uploaders |
4 | 5 | |
5 | -- Tianon Gravi <tianon@debian.org> Wed, 23 Feb 2022 11:11:30 -0800 | |
6 | [ Debian Janitor ] | |
7 | * New upstream release. | |
8 | ||
9 | -- Tianon Gravi <tianon@debian.org> Thu, 10 Mar 2022 05:12:37 -0000 | |
6 | 10 | |
7 | 11 | golang-github-deckarep-golang-set (1.5-2) unstable; urgency=medium |
8 | 12 |
0 | /* | |
1 | Open Source Initiative OSI - The MIT License (MIT):Licensing | |
2 | ||
3 | The MIT License (MIT) | |
4 | Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com) | |
5 | ||
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of | |
7 | this software and associated documentation files (the "Software"), to deal in | |
8 | the Software without restriction, including without limitation the rights to | |
9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |
10 | of the Software, and to permit persons to whom the Software is furnished to do | |
11 | so, subject to the following conditions: | |
12 | ||
13 | The above copyright notice and this permission notice shall be included in all | |
14 | copies or substantial portions of the Software. | |
15 | ||
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
22 | SOFTWARE. | |
23 | */ | |
24 | ||
25 | package mapset | |
26 | ||
27 | // Iterator defines an iterator over a Set, its C channel can be used to range over the Set's | |
28 | // elements. | |
29 | type Iterator struct { | |
30 | C <-chan interface{} | |
31 | stop chan struct{} | |
32 | } | |
33 | ||
34 | // Stop stops the Iterator, no further elements will be received on C, C will be closed. | |
35 | func (i *Iterator) Stop() { | |
36 | // Allows for Stop() to be called multiple times | |
37 | // (close() panics when called on already closed channel) | |
38 | defer func() { | |
39 | recover() | |
40 | }() | |
41 | ||
42 | close(i.stop) | |
43 | ||
44 | // Exhaust any remaining elements. | |
45 | for range i.C { | |
46 | } | |
47 | } | |
48 | ||
49 | // newIterator returns a new Iterator instance together with its item and stop channels. | |
50 | func newIterator() (*Iterator, chan<- interface{}, <-chan struct{}) { | |
51 | itemChan := make(chan interface{}) | |
52 | stopChan := make(chan struct{}) | |
53 | return &Iterator{ | |
54 | C: itemChan, | |
55 | stop: stopChan, | |
56 | }, itemChan, stopChan | |
57 | } |
0 | package mapset | |
1 | ||
2 | import ( | |
3 | "fmt" | |
4 | ) | |
5 | ||
6 | type YourType struct { | |
7 | Name string | |
8 | } | |
9 | ||
10 | func ExampleIterator() { | |
11 | set := NewSetFromSlice([]interface{}{ | |
12 | &YourType{Name: "Alise"}, | |
13 | &YourType{Name: "Bob"}, | |
14 | &YourType{Name: "John"}, | |
15 | &YourType{Name: "Nick"}, | |
16 | }) | |
17 | ||
18 | var found *YourType | |
19 | it := set.Iterator() | |
20 | ||
21 | for elem := range it.C { | |
22 | if elem.(*YourType).Name == "John" { | |
23 | found = elem.(*YourType) | |
24 | it.Stop() | |
25 | } | |
26 | } | |
27 | ||
28 | fmt.Printf("Found %+v\n", found) | |
29 | ||
30 | // Output: Found &{Name:John} | |
31 | } |
27 | 27 | // typical set operations: membership testing, intersection, union, |
28 | 28 | // difference, symmetric difference and cloning. |
29 | 29 | // |
30 | // Package mapset provides two implementations. The default | |
31 | // implementation is safe for concurrent access. There is a non-threadsafe | |
32 | // implementation which is slightly more performant. | |
30 | // Package mapset provides two implementations of the Set | |
31 | // interface. The default implementation is safe for concurrent | |
32 | // access, but a non-thread-safe implementation is also provided for | |
33 | // programs that can benefit from the slight speed improvement and | |
34 | // that can enforce mutual exclusion through other means. | |
33 | 35 | package mapset |
34 | 36 | |
37 | // Set is the primary interface provided by the mapset package. It | |
38 | // represents an unordered set of data and a large number of | |
39 | // operations that can be applied to that set. | |
35 | 40 | type Set interface { |
36 | 41 | // Adds an element to the set. Returns whether |
37 | 42 | // the item was added. |
41 | 46 | Cardinality() int |
42 | 47 | |
43 | 48 | // Removes all elements from the set, leaving |
44 | // the emtpy set. | |
49 | // the empty set. | |
45 | 50 | Clear() |
46 | 51 | |
47 | 52 | // Returns a clone of the set using the same |
83 | 88 | // panic. |
84 | 89 | Intersect(other Set) Set |
85 | 90 | |
91 | // Determines if every element in this set is in | |
92 | // the other set but the two sets are not equal. | |
93 | // | |
94 | // Note that the argument to IsProperSubset | |
95 | // must be of the same type as the receiver | |
96 | // of the method. Otherwise, IsProperSubset | |
97 | // will panic. | |
98 | IsProperSubset(other Set) bool | |
99 | ||
100 | // Determines if every element in the other set | |
101 | // is in this set but the two sets are not | |
102 | // equal. | |
103 | // | |
104 | // Note that the argument to IsSuperset | |
105 | // must be of the same type as the receiver | |
106 | // of the method. Otherwise, IsSuperset will | |
107 | // panic. | |
108 | IsProperSuperset(other Set) bool | |
109 | ||
110 | // Determines if every element in this set is in | |
111 | // the other set. | |
112 | // | |
113 | // Note that the argument to IsSubset | |
114 | // must be of the same type as the receiver | |
115 | // of the method. Otherwise, IsSubset will | |
116 | // panic. | |
117 | IsSubset(other Set) bool | |
118 | ||
86 | 119 | // Determines if every element in the other set |
87 | 120 | // is in this set. |
88 | 121 | // |
89 | // Note that the argument to IsSubset | |
90 | // must be of the same type as the receiver | |
91 | // of the method. Otherwise, IsSubset will | |
92 | // panic. | |
93 | IsSubset(other Set) bool | |
94 | ||
95 | // Determines if every element in this set is in | |
96 | // the other set. | |
97 | // | |
98 | 122 | // Note that the argument to IsSuperset |
99 | 123 | // must be of the same type as the receiver |
100 | 124 | // of the method. Otherwise, IsSuperset will |
101 | 125 | // panic. |
102 | 126 | IsSuperset(other Set) bool |
127 | ||
128 | // Iterates over elements and executes the passed func against each element. | |
129 | // If passed func returns true, stop iteration at the time. | |
130 | Each(func(interface{}) bool) | |
103 | 131 | |
104 | 132 | // Returns a channel of elements that you can |
105 | 133 | // range over. |
106 | 134 | Iter() <-chan interface{} |
107 | 135 | |
136 | // Returns an Iterator object that you can | |
137 | // use to range over the set. | |
138 | Iterator() *Iterator | |
139 | ||
108 | 140 | // Remove a single element from the set. |
109 | 141 | Remove(i interface{}) |
110 | 142 | |
124 | 156 | // Returns a new set with all elements in both sets. |
125 | 157 | // |
126 | 158 | // Note that the argument to Union must be of the |
159 | ||
127 | 160 | // same type as the receiver of the method. |
128 | 161 | // Otherwise, IsSuperset will panic. |
129 | 162 | Union(other Set) Set |
130 | 163 | |
164 | // Pop removes and returns an arbitrary item from the set. | |
165 | Pop() interface{} | |
166 | ||
131 | 167 | // Returns all subsets of a given set (Power Set). |
132 | 168 | PowerSet() Set |
133 | 169 | |
138 | 174 | ToSlice() []interface{} |
139 | 175 | } |
140 | 176 | |
141 | // Creates and returns a reference to an empty set. | |
142 | func NewSet() Set { | |
177 | // NewSet creates and returns a reference to an empty set. Operations | |
178 | // on the resulting set are thread-safe. | |
179 | func NewSet(s ...interface{}) Set { | |
143 | 180 | set := newThreadSafeSet() |
181 | for _, item := range s { | |
182 | set.Add(item) | |
183 | } | |
144 | 184 | return &set |
145 | 185 | } |
146 | 186 | |
147 | // Creates and returns a reference to a set from an existing slice | |
187 | // NewSetWith creates and returns a new set with the given elements. | |
188 | // Operations on the resulting set are thread-safe. | |
189 | func NewSetWith(elts ...interface{}) Set { | |
190 | return NewSetFromSlice(elts) | |
191 | } | |
192 | ||
193 | // NewSetFromSlice creates and returns a reference to a set from an | |
194 | // existing slice. Operations on the resulting set are thread-safe. | |
148 | 195 | func NewSetFromSlice(s []interface{}) Set { |
149 | a := NewSet() | |
150 | for _, item := range s { | |
151 | a.Add(item) | |
152 | } | |
196 | a := NewSet(s...) | |
153 | 197 | return a |
154 | 198 | } |
155 | 199 | |
200 | // NewThreadUnsafeSet creates and returns a reference to an empty set. | |
201 | // Operations on the resulting set are not thread-safe. | |
156 | 202 | func NewThreadUnsafeSet() Set { |
157 | 203 | set := newThreadUnsafeSet() |
158 | 204 | return &set |
159 | 205 | } |
160 | 206 | |
207 | // NewThreadUnsafeSetFromSlice creates and returns a reference to a | |
208 | // set from an existing slice. Operations on the resulting set are | |
209 | // not thread-safe. | |
161 | 210 | func NewThreadUnsafeSetFromSlice(s []interface{}) Set { |
162 | 211 | a := NewThreadUnsafeSet() |
163 | 212 | for _, item := range s { |
42 | 42 | return set |
43 | 43 | } |
44 | 44 | |
45 | func assertEqual(a, b Set, t *testing.T) { | |
46 | if !a.Equal(b) { | |
47 | t.Errorf("%v != %v\n", a, b) | |
48 | } | |
49 | } | |
50 | ||
45 | 51 | func Test_NewSet(t *testing.T) { |
46 | 52 | a := NewSet() |
47 | ||
48 | 53 | if a.Cardinality() != 0 { |
49 | 54 | t.Error("NewSet should start out as an empty set") |
50 | 55 | } |
56 | ||
57 | assertEqual(NewSetFromSlice([]interface{}{}), NewSet(), t) | |
58 | assertEqual(NewSetFromSlice([]interface{}{1}), NewSet(1), t) | |
59 | assertEqual(NewSetFromSlice([]interface{}{1, 2}), NewSet(1, 2), t) | |
60 | assertEqual(NewSetFromSlice([]interface{}{"a"}), NewSet("a"), t) | |
61 | assertEqual(NewSetFromSlice([]interface{}{"a", "b"}), NewSet("a", "b"), t) | |
51 | 62 | } |
52 | 63 | |
53 | 64 | func Test_NewUnsafeSet(t *testing.T) { |
315 | 326 | } |
316 | 327 | } |
317 | 328 | |
329 | func Test_SetIsProperSubset(t *testing.T) { | |
330 | a := makeSet([]int{1, 2, 3, 5, 7}) | |
331 | b := makeSet([]int{7, 5, 3, 2, 1}) | |
332 | ||
333 | if !a.IsSubset(b) { | |
334 | t.Error("set a should be a subset of set b") | |
335 | } | |
336 | if a.IsProperSubset(b) { | |
337 | t.Error("set a should not be a proper subset of set b (they're equal)") | |
338 | } | |
339 | ||
340 | b.Add(72) | |
341 | ||
342 | if !a.IsSubset(b) { | |
343 | t.Error("set a should be a subset of set b") | |
344 | } | |
345 | if !a.IsProperSubset(b) { | |
346 | t.Error("set a should be a proper subset of set b") | |
347 | } | |
348 | } | |
349 | ||
318 | 350 | func Test_UnsafeSetIsSubset(t *testing.T) { |
319 | 351 | a := makeUnsafeSet([]int{1, 2, 3, 5, 7}) |
320 | 352 | |
334 | 366 | } |
335 | 367 | } |
336 | 368 | |
337 | func Test_SetIsSuperSet(t *testing.T) { | |
369 | func Test_UnsafeSetIsProperSubset(t *testing.T) { | |
370 | a := makeUnsafeSet([]int{1, 2, 3, 5, 7}) | |
371 | b := NewThreadUnsafeSet() | |
372 | b.Add(7) | |
373 | b.Add(1) | |
374 | b.Add(5) | |
375 | b.Add(3) | |
376 | b.Add(2) | |
377 | ||
378 | if !a.IsSubset(b) { | |
379 | t.Error("set a should be a subset of set b") | |
380 | } | |
381 | if a.IsProperSubset(b) { | |
382 | t.Error("set a should not be a proper subset of set b (they're equal)") | |
383 | } | |
384 | ||
385 | b.Add(72) | |
386 | ||
387 | if !a.IsSubset(b) { | |
388 | t.Error("set a should be a subset of set b") | |
389 | } | |
390 | if !a.IsProperSubset(b) { | |
391 | t.Error("set a should be a proper subset of set b because set b has 72") | |
392 | } | |
393 | } | |
394 | ||
395 | func Test_SetIsSuperset(t *testing.T) { | |
338 | 396 | a := NewSet() |
339 | 397 | a.Add(9) |
340 | 398 | a.Add(5) |
354 | 412 | b.Add(42) |
355 | 413 | |
356 | 414 | if a.IsSuperset(b) { |
357 | t.Error("set a should not be a superset of set b because set a has a 42") | |
358 | } | |
359 | } | |
360 | ||
361 | func Test_UnsafeSetIsSuperSet(t *testing.T) { | |
415 | t.Error("set a should not be a superset of set b because set b has a 42") | |
416 | } | |
417 | } | |
418 | ||
419 | func Test_SetIsProperSuperset(t *testing.T) { | |
420 | a := NewSet() | |
421 | a.Add(5) | |
422 | a.Add(2) | |
423 | a.Add(11) | |
424 | ||
425 | b := NewSet() | |
426 | b.Add(2) | |
427 | b.Add(5) | |
428 | b.Add(11) | |
429 | ||
430 | if !a.IsSuperset(b) { | |
431 | t.Error("set a should be a superset of set b") | |
432 | } | |
433 | if a.IsProperSuperset(b) { | |
434 | t.Error("set a should not be a proper superset of set b (they're equal)") | |
435 | } | |
436 | ||
437 | a.Add(9) | |
438 | ||
439 | if !a.IsSuperset(b) { | |
440 | t.Error("set a should be a superset of set b") | |
441 | } | |
442 | if !a.IsProperSuperset(b) { | |
443 | t.Error("set a not be a proper superset of set b because set a has a 9") | |
444 | } | |
445 | ||
446 | b.Add(42) | |
447 | ||
448 | if a.IsSuperset(b) { | |
449 | t.Error("set a should not be a superset of set b because set b has a 42") | |
450 | } | |
451 | if a.IsProperSuperset(b) { | |
452 | t.Error("set a should not be a proper superset of set b because set b has a 42") | |
453 | } | |
454 | } | |
455 | ||
456 | func Test_UnsafeSetIsSuperset(t *testing.T) { | |
362 | 457 | a := NewThreadUnsafeSet() |
363 | 458 | a.Add(9) |
364 | 459 | a.Add(5) |
379 | 474 | |
380 | 475 | if a.IsSuperset(b) { |
381 | 476 | t.Error("set a should not be a superset of set b because set a has a 42") |
477 | } | |
478 | } | |
479 | ||
480 | func Test_UnsafeSetIsProperSuperset(t *testing.T) { | |
481 | a := NewThreadUnsafeSet() | |
482 | a.Add(5) | |
483 | a.Add(2) | |
484 | a.Add(11) | |
485 | ||
486 | b := NewThreadUnsafeSet() | |
487 | b.Add(2) | |
488 | b.Add(5) | |
489 | b.Add(11) | |
490 | ||
491 | if !a.IsSuperset(b) { | |
492 | t.Error("set a should be a superset of set b") | |
493 | } | |
494 | if a.IsProperSuperset(b) { | |
495 | t.Error("set a should not be a proper superset of set b (they're equal)") | |
496 | } | |
497 | ||
498 | a.Add(9) | |
499 | ||
500 | if !a.IsSuperset(b) { | |
501 | t.Error("set a should be a superset of set b") | |
502 | } | |
503 | if !a.IsProperSuperset(b) { | |
504 | t.Error("set a not be a proper superset of set b because set a has a 9") | |
505 | } | |
506 | ||
507 | b.Add(42) | |
508 | ||
509 | if a.IsSuperset(b) { | |
510 | t.Error("set a should not be a superset of set b because set b has a 42") | |
511 | } | |
512 | if a.IsProperSuperset(b) { | |
513 | t.Error("set a should not be a proper superset of set b because set b has a 42") | |
382 | 514 | } |
383 | 515 | } |
384 | 516 | |
414 | 546 | |
415 | 547 | g := f.Union(e) |
416 | 548 | if g.Cardinality() != 8 { |
417 | t.Error("set g should still ahve 8 elements in it after being unioned with set f that has duplicates") | |
549 | t.Error("set g should still have 8 elements in it after being unioned with set f that has duplicates") | |
418 | 550 | } |
419 | 551 | } |
420 | 552 | |
450 | 582 | |
451 | 583 | g := f.Union(e) |
452 | 584 | if g.Cardinality() != 8 { |
453 | t.Error("set g should still ahve 8 elements in it after being unioned with set f that has duplicates") | |
585 | t.Error("set g should still have 8 elements in it after being unioned with set f that has duplicates") | |
454 | 586 | } |
455 | 587 | } |
456 | 588 | |
716 | 848 | } |
717 | 849 | } |
718 | 850 | |
719 | func Test_Iterator(t *testing.T) { | |
851 | func Test_Each(t *testing.T) { | |
720 | 852 | a := NewSet() |
721 | 853 | |
722 | 854 | a.Add("Z") |
725 | 857 | a.Add("W") |
726 | 858 | |
727 | 859 | b := NewSet() |
728 | for val := range a.Iter() { | |
729 | b.Add(val) | |
730 | } | |
731 | ||
732 | if !a.Equal(b) { | |
733 | t.Error("The sets are not equal after iterating through the first set") | |
734 | } | |
735 | } | |
736 | ||
737 | func Test_UnsafeIterator(t *testing.T) { | |
738 | a := NewThreadUnsafeSet() | |
860 | a.Each(func(elem interface{}) bool { | |
861 | b.Add(elem) | |
862 | return false | |
863 | }) | |
864 | ||
865 | if !a.Equal(b) { | |
866 | t.Error("The sets are not equal after iterating (Each) through the first set") | |
867 | } | |
868 | ||
869 | var count int | |
870 | a.Each(func(elem interface{}) bool { | |
871 | if count == 2 { | |
872 | return true | |
873 | } | |
874 | count++ | |
875 | return false | |
876 | }) | |
877 | if count != 2 { | |
878 | t.Error("Iteration should stop on the way") | |
879 | } | |
880 | } | |
881 | ||
882 | func Test_Iter(t *testing.T) { | |
883 | a := NewSet() | |
739 | 884 | |
740 | 885 | a.Add("Z") |
741 | 886 | a.Add("Y") |
742 | 887 | a.Add("X") |
743 | 888 | a.Add("W") |
744 | 889 | |
890 | b := NewSet() | |
891 | for val := range a.Iter() { | |
892 | b.Add(val) | |
893 | } | |
894 | ||
895 | if !a.Equal(b) { | |
896 | t.Error("The sets are not equal after iterating (Iter) through the first set") | |
897 | } | |
898 | } | |
899 | ||
900 | func Test_UnsafeIter(t *testing.T) { | |
901 | a := NewThreadUnsafeSet() | |
902 | ||
903 | a.Add("Z") | |
904 | a.Add("Y") | |
905 | a.Add("X") | |
906 | a.Add("W") | |
907 | ||
745 | 908 | b := NewThreadUnsafeSet() |
746 | 909 | for val := range a.Iter() { |
747 | 910 | b.Add(val) |
748 | 911 | } |
749 | 912 | |
750 | 913 | if !a.Equal(b) { |
751 | t.Error("The sets are not equal after iterating through the first set") | |
914 | t.Error("The sets are not equal after iterating (Iter) through the first set") | |
915 | } | |
916 | } | |
917 | ||
918 | func Test_Iterator(t *testing.T) { | |
919 | a := NewSet() | |
920 | ||
921 | a.Add("Z") | |
922 | a.Add("Y") | |
923 | a.Add("X") | |
924 | a.Add("W") | |
925 | ||
926 | b := NewSet() | |
927 | for val := range a.Iterator().C { | |
928 | b.Add(val) | |
929 | } | |
930 | ||
931 | if !a.Equal(b) { | |
932 | t.Error("The sets are not equal after iterating (Iterator) through the first set") | |
933 | } | |
934 | } | |
935 | ||
936 | func Test_UnsafeIterator(t *testing.T) { | |
937 | a := NewThreadUnsafeSet() | |
938 | ||
939 | a.Add("Z") | |
940 | a.Add("Y") | |
941 | a.Add("X") | |
942 | a.Add("W") | |
943 | ||
944 | b := NewThreadUnsafeSet() | |
945 | for val := range a.Iterator().C { | |
946 | b.Add(val) | |
947 | } | |
948 | ||
949 | if !a.Equal(b) { | |
950 | t.Error("The sets are not equal after iterating (Iterator) through the first set") | |
951 | } | |
952 | } | |
953 | ||
954 | func Test_IteratorStop(t *testing.T) { | |
955 | a := NewSet() | |
956 | ||
957 | a.Add("Z") | |
958 | a.Add("Y") | |
959 | a.Add("X") | |
960 | a.Add("W") | |
961 | ||
962 | it := a.Iterator() | |
963 | it.Stop() | |
964 | for range it.C { | |
965 | t.Error("The iterating (Iterator) did not stop after Stop() has been called") | |
966 | } | |
967 | } | |
968 | ||
969 | func Test_PopSafe(t *testing.T) { | |
970 | a := NewSet() | |
971 | ||
972 | a.Add("a") | |
973 | a.Add("b") | |
974 | a.Add("c") | |
975 | a.Add("d") | |
976 | ||
977 | captureSet := NewSet() | |
978 | captureSet.Add(a.Pop()) | |
979 | captureSet.Add(a.Pop()) | |
980 | captureSet.Add(a.Pop()) | |
981 | captureSet.Add(a.Pop()) | |
982 | finalNil := a.Pop() | |
983 | ||
984 | if captureSet.Cardinality() != 4 { | |
985 | t.Error("unexpected captureSet cardinality; should be 4") | |
986 | } | |
987 | ||
988 | if a.Cardinality() != 0 { | |
989 | t.Error("unepxected a cardinality; should be zero") | |
990 | } | |
991 | ||
992 | if !captureSet.Contains("c", "a", "d", "b") { | |
993 | t.Error("unexpected result set; should be a,b,c,d (any order is fine") | |
994 | } | |
995 | ||
996 | if finalNil != nil { | |
997 | t.Error("when original set is empty, further pops should result in nil") | |
998 | } | |
999 | } | |
1000 | ||
1001 | func Test_PopUnsafe(t *testing.T) { | |
1002 | a := NewThreadUnsafeSet() | |
1003 | ||
1004 | a.Add("a") | |
1005 | a.Add("b") | |
1006 | a.Add("c") | |
1007 | a.Add("d") | |
1008 | ||
1009 | captureSet := NewThreadUnsafeSet() | |
1010 | captureSet.Add(a.Pop()) | |
1011 | captureSet.Add(a.Pop()) | |
1012 | captureSet.Add(a.Pop()) | |
1013 | captureSet.Add(a.Pop()) | |
1014 | finalNil := a.Pop() | |
1015 | ||
1016 | if captureSet.Cardinality() != 4 { | |
1017 | t.Error("unexpected captureSet cardinality; should be 4") | |
1018 | } | |
1019 | ||
1020 | if a.Cardinality() != 0 { | |
1021 | t.Error("unepxected a cardinality; should be zero") | |
1022 | } | |
1023 | ||
1024 | if !captureSet.Contains("c", "a", "d", "b") { | |
1025 | t.Error("unexpected result set; should be a,b,c,d (any order is fine") | |
1026 | } | |
1027 | ||
1028 | if finalNil != nil { | |
1029 | t.Error("when original set is empty, further pops should result in nil") | |
752 | 1030 | } |
753 | 1031 | } |
754 | 1032 | |
763 | 1041 | b := a.PowerSet() |
764 | 1042 | if b.Cardinality() != 16 { |
765 | 1043 | t.Error("unexpected PowerSet cardinality") |
1044 | } | |
1045 | } | |
1046 | ||
1047 | func Test_PowerSetThreadSafe(t *testing.T) { | |
1048 | set := NewSet().PowerSet() | |
1049 | _, setIsThreadSafe := set.(*threadSafeSet) | |
1050 | if !setIsThreadSafe { | |
1051 | t.Error("result of PowerSet should be thread safe") | |
1052 | } | |
1053 | ||
1054 | subset := set.Pop() | |
1055 | _, subsetIsThreadSafe := subset.(*threadSafeSet) | |
1056 | if !subsetIsThreadSafe { | |
1057 | t.Error("subsets in PowerSet result should be thread safe") | |
766 | 1058 | } |
767 | 1059 | } |
768 | 1060 | |
780 | 1072 | b.Add(3) |
781 | 1073 | b.Add(4) |
782 | 1074 | |
783 | c := NewSet() | |
784 | ||
785 | 1075 | if !empty.IsSubset(a) || !empty.IsSubset(b) { |
786 | 1076 | t.Error("The empty set is supposed to be a subset of all sets") |
787 | 1077 | } |
794 | 1084 | t.Error("The empty set is supposed to be a subset and a superset of itself") |
795 | 1085 | } |
796 | 1086 | |
797 | c = a.Union(empty) | |
1087 | c := a.Union(empty) | |
798 | 1088 | if !c.Equal(a) { |
799 | 1089 | t.Error("The union of any set with the empty set is supposed to be equal to itself") |
800 | 1090 | } |
849 | 1139 | d = empty.CartesianProduct(b) |
850 | 1140 | |
851 | 1141 | if c.Cardinality() != 0 || d.Cardinality() != 0 { |
852 | t.Error("Cartesian product of any set and the emtpy set Ax0 || 0xA must be the empty set") | |
1142 | t.Error("Cartesian product of any set and the empty set Ax0 || 0xA must be the empty set") | |
853 | 1143 | } |
854 | 1144 | } |
855 | 1145 |
61 | 61 | return ret |
62 | 62 | } |
63 | 63 | |
64 | func (set *threadSafeSet) IsProperSubset(other Set) bool { | |
65 | o := other.(*threadSafeSet) | |
66 | ||
67 | set.RLock() | |
68 | defer set.RUnlock() | |
69 | o.RLock() | |
70 | defer o.RUnlock() | |
71 | ||
72 | return set.s.IsProperSubset(&o.s) | |
73 | } | |
74 | ||
64 | 75 | func (set *threadSafeSet) IsSuperset(other Set) bool { |
65 | 76 | return other.IsSubset(set) |
66 | 77 | } |
67 | 78 | |
79 | func (set *threadSafeSet) IsProperSuperset(other Set) bool { | |
80 | return other.IsProperSubset(set) | |
81 | } | |
82 | ||
68 | 83 | func (set *threadSafeSet) Union(other Set) Set { |
69 | 84 | o := other.(*threadSafeSet) |
70 | 85 | |
107 | 122 | func (set *threadSafeSet) SymmetricDifference(other Set) Set { |
108 | 123 | o := other.(*threadSafeSet) |
109 | 124 | |
125 | set.RLock() | |
126 | o.RLock() | |
127 | ||
110 | 128 | unsafeDifference := set.s.SymmetricDifference(&o.s).(*threadUnsafeSet) |
111 | return &threadSafeSet{s: *unsafeDifference} | |
129 | ret := &threadSafeSet{s: *unsafeDifference} | |
130 | set.RUnlock() | |
131 | o.RUnlock() | |
132 | return ret | |
112 | 133 | } |
113 | 134 | |
114 | 135 | func (set *threadSafeSet) Clear() { |
127 | 148 | set.RLock() |
128 | 149 | defer set.RUnlock() |
129 | 150 | return len(set.s) |
151 | } | |
152 | ||
153 | func (set *threadSafeSet) Each(cb func(interface{}) bool) { | |
154 | set.RLock() | |
155 | for elem := range set.s { | |
156 | if cb(elem) { | |
157 | break | |
158 | } | |
159 | } | |
160 | set.RUnlock() | |
130 | 161 | } |
131 | 162 | |
132 | 163 | func (set *threadSafeSet) Iter() <-chan interface{} { |
144 | 175 | return ch |
145 | 176 | } |
146 | 177 | |
178 | func (set *threadSafeSet) Iterator() *Iterator { | |
179 | iterator, ch, stopCh := newIterator() | |
180 | ||
181 | go func() { | |
182 | set.RLock() | |
183 | L: | |
184 | for elem := range set.s { | |
185 | select { | |
186 | case <-stopCh: | |
187 | break L | |
188 | case ch <- elem: | |
189 | } | |
190 | } | |
191 | close(ch) | |
192 | set.RUnlock() | |
193 | }() | |
194 | ||
195 | return iterator | |
196 | } | |
197 | ||
147 | 198 | func (set *threadSafeSet) Equal(other Set) bool { |
148 | 199 | o := other.(*threadSafeSet) |
149 | 200 | |
174 | 225 | |
175 | 226 | func (set *threadSafeSet) PowerSet() Set { |
176 | 227 | set.RLock() |
177 | ret := set.s.PowerSet() | |
178 | set.RUnlock() | |
179 | return ret | |
228 | unsafePowerSet := set.s.PowerSet().(*threadUnsafeSet) | |
229 | set.RUnlock() | |
230 | ||
231 | ret := &threadSafeSet{s: newThreadUnsafeSet()} | |
232 | for subset := range unsafePowerSet.Iter() { | |
233 | unsafeSubset := subset.(*threadUnsafeSet) | |
234 | ret.Add(&threadSafeSet{s: *unsafeSubset}) | |
235 | } | |
236 | return ret | |
237 | } | |
238 | ||
239 | func (set *threadSafeSet) Pop() interface{} { | |
240 | set.Lock() | |
241 | defer set.Unlock() | |
242 | return set.s.Pop() | |
180 | 243 | } |
181 | 244 | |
182 | 245 | func (set *threadSafeSet) CartesianProduct(other Set) Set { |
193 | 256 | } |
194 | 257 | |
195 | 258 | func (set *threadSafeSet) ToSlice() []interface{} { |
196 | set.RLock() | |
197 | 259 | keys := make([]interface{}, 0, set.Cardinality()) |
260 | set.RLock() | |
198 | 261 | for elem := range set.s { |
199 | 262 | keys = append(keys, elem) |
200 | 263 | } |
201 | 264 | set.RUnlock() |
202 | 265 | return keys |
203 | 266 | } |
267 | ||
268 | func (set *threadSafeSet) MarshalJSON() ([]byte, error) { | |
269 | set.RLock() | |
270 | b, err := set.s.MarshalJSON() | |
271 | set.RUnlock() | |
272 | ||
273 | return b, err | |
274 | } | |
275 | ||
276 | func (set *threadSafeSet) UnmarshalJSON(p []byte) error { | |
277 | set.RLock() | |
278 | err := set.s.UnmarshalJSON(p) | |
279 | set.RUnlock() | |
280 | ||
281 | return err | |
282 | } |
25 | 25 | package mapset |
26 | 26 | |
27 | 27 | import ( |
28 | "encoding/json" | |
28 | 29 | "math/rand" |
29 | 30 | "runtime" |
30 | 31 | "sync" |
32 | "sync/atomic" | |
31 | 33 | "testing" |
32 | 34 | ) |
33 | 35 | |
135 | 137 | } |
136 | 138 | |
137 | 139 | var wg sync.WaitGroup |
138 | for _ = range ints { | |
140 | for range ints { | |
141 | wg.Add(1) | |
139 | 142 | go func() { |
140 | 143 | s.Contains(interfaces...) |
144 | wg.Done() | |
141 | 145 | }() |
142 | 146 | } |
143 | 147 | wg.Wait() |
148 | 152 | |
149 | 153 | s, ss := NewSet(), NewSet() |
150 | 154 | ints := rand.Perm(N) |
151 | interfaces := make([]interface{}, 0) | |
152 | for _, v := range ints { | |
153 | s.Add(v) | |
154 | ss.Add(v) | |
155 | interfaces = append(interfaces, v) | |
156 | } | |
157 | ||
158 | var wg sync.WaitGroup | |
159 | for _ = range ints { | |
155 | for _, v := range ints { | |
156 | s.Add(v) | |
157 | ss.Add(v) | |
158 | } | |
159 | ||
160 | var wg sync.WaitGroup | |
161 | for range ints { | |
162 | wg.Add(1) | |
160 | 163 | go func() { |
161 | 164 | s.Difference(ss) |
165 | wg.Done() | |
162 | 166 | }() |
163 | 167 | } |
164 | 168 | wg.Wait() |
169 | 173 | |
170 | 174 | s, ss := NewSet(), NewSet() |
171 | 175 | ints := rand.Perm(N) |
172 | interfaces := make([]interface{}, 0) | |
173 | for _, v := range ints { | |
174 | s.Add(v) | |
175 | ss.Add(v) | |
176 | interfaces = append(interfaces, v) | |
177 | } | |
178 | ||
179 | var wg sync.WaitGroup | |
180 | for _ = range ints { | |
176 | for _, v := range ints { | |
177 | s.Add(v) | |
178 | ss.Add(v) | |
179 | } | |
180 | ||
181 | var wg sync.WaitGroup | |
182 | for range ints { | |
183 | wg.Add(1) | |
181 | 184 | go func() { |
182 | 185 | s.Equal(ss) |
186 | wg.Done() | |
183 | 187 | }() |
184 | 188 | } |
185 | 189 | wg.Wait() |
190 | 194 | |
191 | 195 | s, ss := NewSet(), NewSet() |
192 | 196 | ints := rand.Perm(N) |
193 | interfaces := make([]interface{}, 0) | |
194 | for _, v := range ints { | |
195 | s.Add(v) | |
196 | ss.Add(v) | |
197 | interfaces = append(interfaces, v) | |
198 | } | |
199 | ||
200 | var wg sync.WaitGroup | |
201 | for _ = range ints { | |
197 | for _, v := range ints { | |
198 | s.Add(v) | |
199 | ss.Add(v) | |
200 | } | |
201 | ||
202 | var wg sync.WaitGroup | |
203 | for range ints { | |
204 | wg.Add(1) | |
202 | 205 | go func() { |
203 | 206 | s.Intersect(ss) |
207 | wg.Done() | |
204 | 208 | }() |
205 | 209 | } |
206 | 210 | wg.Wait() |
211 | 215 | |
212 | 216 | s, ss := NewSet(), NewSet() |
213 | 217 | ints := rand.Perm(N) |
214 | interfaces := make([]interface{}, 0) | |
215 | for _, v := range ints { | |
216 | s.Add(v) | |
217 | ss.Add(v) | |
218 | interfaces = append(interfaces, v) | |
219 | } | |
220 | ||
221 | var wg sync.WaitGroup | |
222 | for _ = range ints { | |
218 | for _, v := range ints { | |
219 | s.Add(v) | |
220 | ss.Add(v) | |
221 | } | |
222 | ||
223 | var wg sync.WaitGroup | |
224 | for range ints { | |
225 | wg.Add(1) | |
223 | 226 | go func() { |
224 | 227 | s.IsSubset(ss) |
228 | wg.Done() | |
229 | }() | |
230 | } | |
231 | wg.Wait() | |
232 | } | |
233 | ||
234 | func Test_IsProperSubsetConcurrent(t *testing.T) { | |
235 | runtime.GOMAXPROCS(2) | |
236 | ||
237 | s, ss := NewSet(), NewSet() | |
238 | ints := rand.Perm(N) | |
239 | for _, v := range ints { | |
240 | s.Add(v) | |
241 | ss.Add(v) | |
242 | } | |
243 | ||
244 | var wg sync.WaitGroup | |
245 | for range ints { | |
246 | wg.Add(1) | |
247 | go func() { | |
248 | s.IsProperSubset(ss) | |
249 | wg.Done() | |
225 | 250 | }() |
226 | 251 | } |
227 | 252 | wg.Wait() |
232 | 257 | |
233 | 258 | s, ss := NewSet(), NewSet() |
234 | 259 | ints := rand.Perm(N) |
235 | interfaces := make([]interface{}, 0) | |
236 | for _, v := range ints { | |
237 | s.Add(v) | |
238 | ss.Add(v) | |
239 | interfaces = append(interfaces, v) | |
240 | } | |
241 | ||
242 | var wg sync.WaitGroup | |
243 | for _ = range ints { | |
260 | for _, v := range ints { | |
261 | s.Add(v) | |
262 | ss.Add(v) | |
263 | } | |
264 | ||
265 | var wg sync.WaitGroup | |
266 | for range ints { | |
267 | wg.Add(1) | |
244 | 268 | go func() { |
245 | 269 | s.IsSuperset(ss) |
246 | }() | |
247 | } | |
248 | wg.Wait() | |
270 | wg.Done() | |
271 | }() | |
272 | } | |
273 | wg.Wait() | |
274 | } | |
275 | ||
276 | func Test_IsProperSupersetConcurrent(t *testing.T) { | |
277 | runtime.GOMAXPROCS(2) | |
278 | ||
279 | s, ss := NewSet(), NewSet() | |
280 | ints := rand.Perm(N) | |
281 | for _, v := range ints { | |
282 | s.Add(v) | |
283 | ss.Add(v) | |
284 | } | |
285 | ||
286 | var wg sync.WaitGroup | |
287 | for range ints { | |
288 | wg.Add(1) | |
289 | go func() { | |
290 | s.IsProperSuperset(ss) | |
291 | wg.Done() | |
292 | }() | |
293 | } | |
294 | wg.Wait() | |
295 | } | |
296 | ||
297 | func Test_EachConcurrent(t *testing.T) { | |
298 | runtime.GOMAXPROCS(2) | |
299 | concurrent := 10 | |
300 | ||
301 | s := NewSet() | |
302 | ints := rand.Perm(N) | |
303 | for _, v := range ints { | |
304 | s.Add(v) | |
305 | } | |
306 | ||
307 | var count int64 | |
308 | wg := new(sync.WaitGroup) | |
309 | wg.Add(concurrent) | |
310 | for n := 0; n < concurrent; n++ { | |
311 | go func() { | |
312 | defer wg.Done() | |
313 | s.Each(func(elem interface{}) bool { | |
314 | atomic.AddInt64(&count, 1) | |
315 | return false | |
316 | }) | |
317 | }() | |
318 | } | |
319 | wg.Wait() | |
320 | ||
321 | if count != int64(N*concurrent) { | |
322 | t.Errorf("%v != %v", count, int64(N*concurrent)) | |
323 | } | |
249 | 324 | } |
250 | 325 | |
251 | 326 | func Test_IterConcurrent(t *testing.T) { |
258 | 333 | } |
259 | 334 | |
260 | 335 | cs := make([]<-chan interface{}, 0) |
261 | for _ = range ints { | |
336 | for range ints { | |
262 | 337 | cs = append(cs, s.Iter()) |
263 | 338 | } |
264 | 339 | |
277 | 352 | close(c) |
278 | 353 | }() |
279 | 354 | |
280 | for _ = range c { | |
355 | for range c { | |
281 | 356 | } |
282 | 357 | } |
283 | 358 | |
316 | 391 | |
317 | 392 | var wg sync.WaitGroup |
318 | 393 | wg.Add(len(ints)) |
319 | for _ = range ints { | |
320 | go func() { | |
321 | s.String() | |
394 | for range ints { | |
395 | go func() { | |
396 | _ = s.String() | |
322 | 397 | wg.Done() |
323 | 398 | }() |
324 | 399 | } |
330 | 405 | |
331 | 406 | s, ss := NewSet(), NewSet() |
332 | 407 | ints := rand.Perm(N) |
333 | interfaces := make([]interface{}, 0) | |
334 | for _, v := range ints { | |
335 | s.Add(v) | |
336 | ss.Add(v) | |
337 | interfaces = append(interfaces, v) | |
338 | } | |
339 | ||
340 | var wg sync.WaitGroup | |
341 | for _ = range ints { | |
408 | for _, v := range ints { | |
409 | s.Add(v) | |
410 | ss.Add(v) | |
411 | } | |
412 | ||
413 | var wg sync.WaitGroup | |
414 | for range ints { | |
415 | wg.Add(1) | |
342 | 416 | go func() { |
343 | 417 | s.SymmetricDifference(ss) |
418 | wg.Done() | |
344 | 419 | }() |
345 | 420 | } |
346 | 421 | wg.Wait() |
373 | 448 | } |
374 | 449 | } |
375 | 450 | } |
451 | ||
452 | // Test_ToSliceDeadlock - fixes issue: https://github.com/deckarep/golang-set/issues/36 | |
453 | // This code reveals the deadlock however it doesn't happen consistently. | |
454 | func Test_ToSliceDeadlock(t *testing.T) { | |
455 | runtime.GOMAXPROCS(2) | |
456 | ||
457 | var wg sync.WaitGroup | |
458 | set := NewSet() | |
459 | workers := 10 | |
460 | wg.Add(workers) | |
461 | for i := 1; i <= workers; i++ { | |
462 | go func() { | |
463 | for j := 0; j < 1000; j++ { | |
464 | set.Add(1) | |
465 | set.ToSlice() | |
466 | } | |
467 | wg.Done() | |
468 | }() | |
469 | } | |
470 | wg.Wait() | |
471 | } | |
472 | ||
473 | func Test_UnmarshalJSON(t *testing.T) { | |
474 | s := []byte(`["test", 1, 2, 3, ["4,5,6"]]`) | |
475 | expected := NewSetFromSlice( | |
476 | []interface{}{ | |
477 | json.Number("1"), | |
478 | json.Number("2"), | |
479 | json.Number("3"), | |
480 | "test", | |
481 | }, | |
482 | ) | |
483 | actual := NewSet() | |
484 | err := json.Unmarshal(s, actual) | |
485 | if err != nil { | |
486 | t.Errorf("Error should be nil: %v", err) | |
487 | } | |
488 | ||
489 | if !expected.Equal(actual) { | |
490 | t.Errorf("Expected no difference, got: %v", expected.Difference(actual)) | |
491 | } | |
492 | } | |
493 | ||
494 | func Test_MarshalJSON(t *testing.T) { | |
495 | expected := NewSetFromSlice( | |
496 | []interface{}{ | |
497 | json.Number("1"), | |
498 | "test", | |
499 | }, | |
500 | ) | |
501 | ||
502 | b, err := json.Marshal( | |
503 | NewSetFromSlice( | |
504 | []interface{}{ | |
505 | 1, | |
506 | "test", | |
507 | }, | |
508 | ), | |
509 | ) | |
510 | if err != nil { | |
511 | t.Errorf("Error should be nil: %v", err) | |
512 | } | |
513 | ||
514 | actual := NewSet() | |
515 | err = json.Unmarshal(b, actual) | |
516 | if err != nil { | |
517 | t.Errorf("Error should be nil: %v", err) | |
518 | } | |
519 | ||
520 | if !expected.Equal(actual) { | |
521 | t.Errorf("Expected no difference, got: %v", expected.Difference(actual)) | |
522 | } | |
523 | } |
25 | 25 | package mapset |
26 | 26 | |
27 | 27 | import ( |
28 | "bytes" | |
29 | "encoding/json" | |
28 | 30 | "fmt" |
29 | 31 | "reflect" |
30 | 32 | "strings" |
32 | 34 | |
33 | 35 | type threadUnsafeSet map[interface{}]struct{} |
34 | 36 | |
35 | type orderedPair struct { | |
36 | first interface{} | |
37 | second interface{} | |
37 | // An OrderedPair represents a 2-tuple of values. | |
38 | type OrderedPair struct { | |
39 | First interface{} | |
40 | Second interface{} | |
38 | 41 | } |
39 | 42 | |
40 | 43 | func newThreadUnsafeSet() threadUnsafeSet { |
41 | 44 | return make(threadUnsafeSet) |
42 | 45 | } |
43 | 46 | |
44 | func (pair *orderedPair) Equal(other orderedPair) bool { | |
45 | if pair.first == other.first && | |
46 | pair.second == other.second { | |
47 | // Equal says whether two 2-tuples contain the same values in the same order. | |
48 | func (pair *OrderedPair) Equal(other OrderedPair) bool { | |
49 | if pair.First == other.First && | |
50 | pair.Second == other.Second { | |
47 | 51 | return true |
48 | 52 | } |
49 | 53 | |
52 | 56 | |
53 | 57 | func (set *threadUnsafeSet) Add(i interface{}) bool { |
54 | 58 | _, found := (*set)[i] |
59 | if found { | |
60 | return false //False if it existed already | |
61 | } | |
62 | ||
55 | 63 | (*set)[i] = struct{}{} |
56 | return !found //False if it existed already | |
64 | return true | |
57 | 65 | } |
58 | 66 | |
59 | 67 | func (set *threadUnsafeSet) Contains(i ...interface{}) bool { |
67 | 75 | |
68 | 76 | func (set *threadUnsafeSet) IsSubset(other Set) bool { |
69 | 77 | _ = other.(*threadUnsafeSet) |
78 | if set.Cardinality() > other.Cardinality() { | |
79 | return false | |
80 | } | |
70 | 81 | for elem := range *set { |
71 | 82 | if !other.Contains(elem) { |
72 | 83 | return false |
75 | 86 | return true |
76 | 87 | } |
77 | 88 | |
89 | func (set *threadUnsafeSet) IsProperSubset(other Set) bool { | |
90 | return set.IsSubset(other) && !set.Equal(other) | |
91 | } | |
92 | ||
78 | 93 | func (set *threadUnsafeSet) IsSuperset(other Set) bool { |
79 | 94 | return other.IsSubset(set) |
95 | } | |
96 | ||
97 | func (set *threadUnsafeSet) IsProperSuperset(other Set) bool { | |
98 | return set.IsSuperset(other) && !set.Equal(other) | |
80 | 99 | } |
81 | 100 | |
82 | 101 | func (set *threadUnsafeSet) Union(other Set) Set { |
146 | 165 | return len(*set) |
147 | 166 | } |
148 | 167 | |
168 | func (set *threadUnsafeSet) Each(cb func(interface{}) bool) { | |
169 | for elem := range *set { | |
170 | if cb(elem) { | |
171 | break | |
172 | } | |
173 | } | |
174 | } | |
175 | ||
149 | 176 | func (set *threadUnsafeSet) Iter() <-chan interface{} { |
150 | 177 | ch := make(chan interface{}) |
151 | 178 | go func() { |
158 | 185 | return ch |
159 | 186 | } |
160 | 187 | |
188 | func (set *threadUnsafeSet) Iterator() *Iterator { | |
189 | iterator, ch, stopCh := newIterator() | |
190 | ||
191 | go func() { | |
192 | L: | |
193 | for elem := range *set { | |
194 | select { | |
195 | case <-stopCh: | |
196 | break L | |
197 | case ch <- elem: | |
198 | } | |
199 | } | |
200 | close(ch) | |
201 | }() | |
202 | ||
203 | return iterator | |
204 | } | |
205 | ||
161 | 206 | func (set *threadUnsafeSet) Equal(other Set) bool { |
162 | 207 | _ = other.(*threadUnsafeSet) |
163 | 208 | |
189 | 234 | return fmt.Sprintf("Set{%s}", strings.Join(items, ", ")) |
190 | 235 | } |
191 | 236 | |
192 | func (pair orderedPair) String() string { | |
193 | return fmt.Sprintf("(%v, %v)", pair.first, pair.second) | |
237 | // String outputs a 2-tuple in the form "(A, B)". | |
238 | func (pair OrderedPair) String() string { | |
239 | return fmt.Sprintf("(%v, %v)", pair.First, pair.Second) | |
240 | } | |
241 | ||
242 | func (set *threadUnsafeSet) Pop() interface{} { | |
243 | for item := range *set { | |
244 | delete(*set, item) | |
245 | return item | |
246 | } | |
247 | return nil | |
194 | 248 | } |
195 | 249 | |
196 | 250 | func (set *threadUnsafeSet) PowerSet() Set { |
227 | 281 | |
228 | 282 | for i := range *set { |
229 | 283 | for j := range *o { |
230 | elem := orderedPair{first: i, second: j} | |
284 | elem := OrderedPair{First: i, Second: j} | |
231 | 285 | cartProduct.Add(elem) |
232 | 286 | } |
233 | 287 | } |
243 | 297 | |
244 | 298 | return keys |
245 | 299 | } |
300 | ||
301 | // MarshalJSON creates a JSON array from the set, it marshals all elements | |
302 | func (set *threadUnsafeSet) MarshalJSON() ([]byte, error) { | |
303 | items := make([]string, 0, set.Cardinality()) | |
304 | ||
305 | for elem := range *set { | |
306 | b, err := json.Marshal(elem) | |
307 | if err != nil { | |
308 | return nil, err | |
309 | } | |
310 | ||
311 | items = append(items, string(b)) | |
312 | } | |
313 | ||
314 | return []byte(fmt.Sprintf("[%s]", strings.Join(items, ","))), nil | |
315 | } | |
316 | ||
317 | // UnmarshalJSON recreates a set from a JSON array, it only decodes | |
318 | // primitive types. Numbers are decoded as json.Number. | |
319 | func (set *threadUnsafeSet) UnmarshalJSON(b []byte) error { | |
320 | var i []interface{} | |
321 | ||
322 | d := json.NewDecoder(bytes.NewReader(b)) | |
323 | d.UseNumber() | |
324 | err := d.Decode(&i) | |
325 | if err != nil { | |
326 | return err | |
327 | } | |
328 | ||
329 | for _, v := range i { | |
330 | switch t := v.(type) { | |
331 | case []interface{}, map[string]interface{}: | |
332 | continue | |
333 | default: | |
334 | set.Add(t) | |
335 | } | |
336 | } | |
337 | ||
338 | return nil | |
339 | } |