lab.nexedi.com/kirr/go123@v0.0.0-20240207185015-8299741fa871/xsync/xsync_test.go (about)

     1  // Copyright (C) 2019-2020  Nexedi SA and Contributors.
     2  //                          Kirill Smelkov <kirr@nexedi.com>
     3  //
     4  // This program is free software: you can Use, Study, Modify and Redistribute
     5  // it under the terms of the GNU General Public License version 3, or (at your
     6  // option) any later version, as published by the Free Software Foundation.
     7  //
     8  // You can also Link and Combine this program with other software covered by
     9  // the terms of any of the Free Software licenses or any of the Open Source
    10  // Initiative approved licenses and Convey the resulting work. Corresponding
    11  // source of such a combination shall include the source code for all other
    12  // software used.
    13  //
    14  // This program is distributed WITHOUT ANY WARRANTY; without even the implied
    15  // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    16  //
    17  // See COPYING file for full licensing terms.
    18  // See https://www.nexedi.com/licensing for rationale and options.
    19  
    20  package xsync
    21  
    22  import (
    23  	"context"
    24  	"fmt"
    25  	"reflect"
    26  	"testing"
    27  )
    28  
    29  func TestWorkGroup(t *testing.T) {
    30  	ctx, cancel := context.WithCancel(context.Background())
    31  	_ = cancel
    32  
    33  	var l  []int // l[i] is data state for i'th worker
    34  	var wg *WorkGroup
    35  	// xwait waits for wg to complete, and asserts on returned error and state of l
    36  	xwait := func(eok string, lok ...int) {
    37  		t.Helper()
    38  		err := wg.Wait()
    39  		if eok == "" {
    40  			if err != nil {
    41  				t.Fatalf("xwait: failed: %q", err)
    42  			}
    43  		} else {
    44  			estr := ""
    45  			if err != nil {
    46  				estr = err.Error()
    47  			}
    48  			if estr != eok {
    49  				t.Fatalf("xwait: unexpected errror:\nhave: %q\nwant: %q", estr, eok)
    50  			}
    51  		}
    52  		if !reflect.DeepEqual(l, lok) {
    53  			t.Fatalf("xwait: unexpected l:\nhave: %v\nwant: %v", l, lok)
    54  		}
    55  	}
    56  
    57  	// t1=ok, t2=ok
    58  	wg = NewWorkGroup(ctx)
    59  	l  = []int{0, 0}
    60  	for i := 0; i < 2; i++ {
    61  		i := i
    62  		wg.Go(func(ctx context.Context) error {
    63  			l[i] = i+1
    64  			return nil
    65  		})
    66  	}
    67  	xwait("", 1, 2)
    68  
    69  	// t1=fail, t2=ok, does not look at ctx
    70  	wg = NewWorkGroup(ctx)
    71  	l  = []int{0, 0}
    72  	for i := 0; i < 2; i++ {
    73  		i := i
    74  		wg.Go(func(ctx context.Context) error {
    75  			l[i] = i+1
    76  			if i == 0 {
    77  				return fmt.Errorf("aaa")
    78  			}
    79  			return nil
    80  		})
    81  	}
    82  	xwait("aaa", 1, 2)
    83  
    84  	// t1=fail, t2=wait cancel, fail
    85  	wg = NewWorkGroup(ctx)
    86  	l  = []int{0, 0}
    87  	for i := 0; i < 2; i++ {
    88  		i := i
    89  		wg.Go(func(ctx context.Context) error {
    90  			l[i] = i+1
    91  			if i == 0 {
    92  				return fmt.Errorf("bbb")
    93  			}
    94  			if i == 1 {
    95  				<-ctx.Done()
    96  				return fmt.Errorf("ccc")
    97  			}
    98  			panic("unreachable")
    99  		})
   100  	}
   101  	xwait("bbb", 1, 2)
   102  
   103  	// t1=ok,wait cancel  t2=ok,wait cancel
   104  	// cancel parent
   105  	wg = NewWorkGroup(ctx)
   106  	l  = []int{0, 0}
   107  	for i := 0; i < 2; i++ {
   108  		i := i
   109  		wg.Go(func(ctx context.Context) error {
   110  			l[i] = i+1
   111  			<-ctx.Done()
   112  			return nil
   113  		})
   114  	}
   115  	cancel() // parent cancel - must be propagated into workgroup
   116  	xwait("", 1, 2)
   117  }