gorgonia.org/gorgonia@v0.9.17/x/vm/pubsub_test.go (about) 1 package xvm 2 3 import ( 4 "context" 5 "reflect" 6 "sync" 7 "testing" 8 9 "gorgonia.org/gorgonia" 10 ) 11 12 func Test_merge(t *testing.T) { 13 fortyTwo := gorgonia.F32(42.0) 14 fortyThree := gorgonia.F32(43.0) 15 t.Run("context cancel without value", func(t *testing.T) { 16 var wg sync.WaitGroup 17 wg.Add(1) 18 ctx, cancel := context.WithCancel(context.Background()) 19 c := make(<-chan gorgonia.Value, 0) 20 output := make(chan ioValue, 0) 21 merge(ctx, &wg, output, c) 22 cancel() 23 //<-output 24 }) 25 t.Run("context cancel with one value", func(t *testing.T) { 26 var wg sync.WaitGroup 27 wg.Add(1) 28 ctx, cancel := context.WithCancel(context.Background()) 29 c := make(chan gorgonia.Value, 1) 30 output := make(chan ioValue, 0) 31 merge(ctx, &wg, output, c) 32 c <- &fortyTwo 33 out := <-output 34 if !reflect.DeepEqual(fortyTwo.Data(), out.v.Data()) { 35 t.Errorf("Expected %v, got %v", fortyTwo, out) 36 } 37 c <- &fortyTwo 38 cancel() 39 }) 40 t.Run("with one value", func(t *testing.T) { 41 var wg sync.WaitGroup 42 wg.Add(1) 43 ctx := context.Background() 44 c := make(chan gorgonia.Value, 1) 45 output := make(chan ioValue, 0) 46 merge(ctx, &wg, output, c) 47 c <- &fortyTwo 48 out := <-output 49 if !reflect.DeepEqual(fortyTwo.Data(), out.v.Data()) { 50 t.Errorf("Expected %v, got %v", fortyTwo, out) 51 } 52 }) 53 t.Run("2 channels with two values", func(t *testing.T) { 54 var wg sync.WaitGroup 55 wg.Add(1) 56 ctx := context.Background() 57 lenChan := 2 58 // The size of the channels buffer controls how far behind the receivers 59 // of the fanOut channels can lag the other channels. 60 c0 := make(chan gorgonia.Value, 0) 61 c1 := make(chan gorgonia.Value, 0) 62 output := make(chan ioValue, 0) 63 merge(ctx, &wg, output, c0, c1) 64 c1 <- &fortyThree 65 c0 <- &fortyTwo 66 missFortyTwo := true 67 missFortyThree := true 68 for i := 0; i < lenChan; i++ { 69 out := <-output 70 switch { 71 case out.pos == 0 && out.v.Data().(float32) == 42.0: 72 missFortyTwo = false 73 case out.pos == 1 && out.v.Data().(float32) == 43.0: 74 missFortyThree = false 75 default: 76 t.Errorf("bad conbination %v/%v", out.pos, out.v.Data()) 77 } 78 } 79 if missFortyThree || missFortyTwo { 80 t.Error("Missing value") 81 } 82 }) 83 } 84 85 func Test_broadcast(t *testing.T) { 86 t.Run("context cancel without value", func(t *testing.T) { 87 var wg sync.WaitGroup 88 wg.Add(1) 89 ctx, cancel := context.WithCancel(context.Background()) 90 // The size of the channels buffer controls how far behind the receivers 91 // of the fanOut channels can lag the other channels. 92 cs := make(chan gorgonia.Value, 0) 93 c := make(<-chan gorgonia.Value, 0) 94 go broadcast(ctx, &wg, c, cs) 95 cancel() 96 }) 97 t.Run("context cancel without value", func(t *testing.T) { 98 var wg sync.WaitGroup 99 wg.Add(1) 100 ctx, cancel := context.WithCancel(context.Background()) 101 cs := make(chan gorgonia.Value, 0) 102 c := make(chan gorgonia.Value, 0) 103 go broadcast(ctx, &wg, c, cs) 104 c <- nil 105 cancel() 106 }) 107 t.Run("broadcast ", func(t *testing.T) { 108 var wg sync.WaitGroup 109 wg.Add(1) 110 fortyTwo := gorgonia.F32(42.0) 111 ctx := context.Background() 112 // The size of the channels buffer controls how far behind the receivers 113 // of the fanOut channels can lag the other channels. 114 cs0 := make(chan gorgonia.Value, 0) 115 cs1 := make(chan gorgonia.Value, 0) 116 c := make(chan gorgonia.Value, 0) 117 go broadcast(ctx, &wg, c, cs0, cs1) 118 c <- &fortyTwo 119 v0 := <-cs0 120 v1 := <-cs1 121 if !reflect.DeepEqual(v0, &fortyTwo) { 122 t.Errorf("broadcast want %v, got %v", &fortyTwo, v0) 123 } 124 if !reflect.DeepEqual(v1, &fortyTwo) { 125 t.Errorf("broadcast want %v, got %v", &fortyTwo, v1) 126 } 127 }) 128 } 129 130 func Test_pubsub_run(t *testing.T) { 131 i0 := make(chan gorgonia.Value, 0) 132 m0 := make(chan gorgonia.Value, 0) 133 m1 := make(chan gorgonia.Value, 0) 134 o0 := make(chan ioValue, 0) 135 type fields struct { 136 publishers []*publisher 137 subscribers []*subscriber 138 } 139 type args struct { 140 ctx context.Context 141 } 142 tests := []struct { 143 name string 144 fields fields 145 args args 146 }{ 147 { 148 "i0 -> m0 ; i0 -> m1; m0 -> o0; m1 -> o0", 149 fields{ 150 publishers: []*publisher{ 151 { 152 publisher: i0, 153 subscribers: []chan<- gorgonia.Value{ 154 m0, m1, 155 }, 156 }, 157 }, 158 subscribers: []*subscriber{ 159 { 160 publishers: []<-chan gorgonia.Value{ 161 m0, m1, 162 }, 163 subscriber: o0, 164 }, 165 }, 166 }, 167 args{ 168 context.TODO(), 169 }, 170 }, 171 } 172 for _, tt := range tests { 173 t.Run(tt.name, func(t *testing.T) { 174 p := &pubsub{ 175 publishers: tt.fields.publishers, 176 subscribers: tt.fields.subscribers, 177 } 178 fortyTwo := gorgonia.F32(42.0) 179 cancel, _ := p.run(tt.args.ctx) 180 i0 <- &fortyTwo 181 v1 := <-o0 182 v2 := <-o0 183 if v1.v.Data().(float32) != 42 { 184 t.Fail() 185 } 186 if v2.v.Data().(float32) != 42 { 187 t.Fail() 188 } 189 if v2.pos+v1.pos != 1 { 190 t.Fail() 191 } 192 //wg.Wait() 193 194 cancel() 195 }) 196 } 197 }