diff --git a/component/component.go b/component/component.go index 400517a..f1e2f7f 100644 --- a/component/component.go +++ b/component/component.go @@ -21,8 +21,8 @@ type Component struct { func NewComponent(name string) *Component { return &Component{ name: name, - inputs: port.NewPortsCollection(), - outputs: port.NewPortsCollection(), + inputs: port.NewCollection(), + outputs: port.NewCollection(), } } @@ -34,13 +34,13 @@ func (c *Component) WithDescription(description string) *Component { // WithInputs ads input ports func (c *Component) WithInputs(portNames ...string) *Component { - c.inputs = c.inputs.Add(port.NewPortGroup(portNames...)...) + c.inputs = c.inputs.Add(port.NewGroup(portNames...)...) return c } // WithOutputs adds output ports func (c *Component) WithOutputs(portNames ...string) *Component { - c.outputs = c.outputs.Add(port.NewPortGroup(portNames...)...) + c.outputs = c.outputs.Add(port.NewGroup(portNames...)...) return c } @@ -80,7 +80,7 @@ func (c *Component) MaybeActivate() (activationResult *ActivationResult) { defer func() { if r := recover(); r != nil { //Clear inputs and exit - c.inputs.ClearSignal() + c.inputs.ClearSignals() activationResult = c.newActivationCodePanicked(fmt.Errorf("panicked with: %v", r)) } }() @@ -92,7 +92,7 @@ func (c *Component) MaybeActivate() (activationResult *ActivationResult) { return } - if !c.inputs.AnyHasSignal() { + if !c.inputs.AnyHasSignals() { //No inputs set, stop here activationResult = c.newActivationCodeNoInput() @@ -106,14 +106,14 @@ func (c *Component) MaybeActivate() (activationResult *ActivationResult) { activationResult = c.newActivationCodeWaitingForInput() if !errors.Is(err, errWaitingForInputsKeep) { - c.inputs.ClearSignal() + c.inputs.ClearSignals() } return } //Clear inputs - c.inputs.ClearSignal() + c.inputs.ClearSignals() if err != nil { activationResult = c.newActivationCodeReturnedError(err) diff --git a/component/component_test.go b/component/component_test.go index 54d0507..7abb314 100644 --- a/component/component_test.go +++ b/component/component_test.go @@ -105,11 +105,11 @@ func TestComponent_Description(t *testing.T) { } func TestComponent_FlushOutputs(t *testing.T) { - sink := port.NewPort("sink") + sink := port.New("sink") componentWithAllOutputsSet := NewComponent("c1").WithOutputs("o1", "o2") - componentWithAllOutputsSet.Outputs().ByName("o1").PutSignal(signal.New(777)) - componentWithAllOutputsSet.Outputs().ByName("o1").PutSignal(signal.New(888)) + componentWithAllOutputsSet.Outputs().ByName("o1").PutSignals(signal.New(777)) + componentWithAllOutputsSet.Outputs().ByName("o1").PutSignals(signal.New(888)) componentWithAllOutputsSet.Outputs().ByName("o1").PipeTo(sink) componentWithAllOutputsSet.Outputs().ByName("o2").PipeTo(sink) @@ -133,7 +133,7 @@ func TestComponent_FlushOutputs(t *testing.T) { component: NewComponent("c1").WithOutputs("o1", "o2"), destPort: nil, assertions: func(t *testing.T, componentAfterFlush *Component, destPort *port.Port) { - assert.False(t, componentAfterFlush.Outputs().AnyHasSignal()) + assert.False(t, componentAfterFlush.Outputs().AnyHasSignals()) }, }, { @@ -141,10 +141,10 @@ func TestComponent_FlushOutputs(t *testing.T) { component: componentWithAllOutputsSet, destPort: sink, assertions: func(t *testing.T, componentAfterFlush *Component, destPort *port.Port) { - assert.Contains(t, destPort.Signal().Payloads(), 777) - assert.Contains(t, destPort.Signal().Payloads(), 888) - assert.Len(t, destPort.Signal().Payloads(), 2) - assert.False(t, componentAfterFlush.Outputs().AnyHasSignal()) + assert.Contains(t, destPort.Signals().AllPayloads(), 777) + assert.Contains(t, destPort.Signals().AllPayloads(), 888) + assert.Len(t, destPort.Signals().AllPayloads(), 2) + assert.False(t, componentAfterFlush.Outputs().AnyHasSignals()) }, }, } @@ -171,8 +171,8 @@ func TestComponent_Inputs(t *testing.T) { name: "with inputs", component: NewComponent("c1").WithInputs("i1", "i2"), want: port.Collection{ - "i1": port.NewPort("i1"), - "i2": port.NewPort("i2"), + "i1": port.New("i1"), + "i2": port.New("i2"), }, }, } @@ -200,8 +200,8 @@ func TestComponent_Outputs(t *testing.T) { name: "with outputs", component: NewComponent("c1").WithOutputs("o1", "o2"), want: port.Collection{ - "o1": port.NewPort("o1"), - "o2": port.NewPort("o2"), + "o1": port.New("o1"), + "o2": port.New("o2"), }, }, } @@ -229,7 +229,7 @@ func TestComponent_WithActivationFunc(t *testing.T) { component: NewComponent("c1"), args: args{ f: func(inputs port.Collection, outputs port.Collection) error { - outputs.ByName("out1").PutSignal(signal.New(23)) + outputs.ByName("out1").PutSignals(signal.New(23)) return nil }, }, @@ -240,10 +240,10 @@ func TestComponent_WithActivationFunc(t *testing.T) { componentAfter := tt.component.WithActivationFunc(tt.args.f) //Compare activation functions by they result and error - testInputs1 := port.NewPortsCollection().Add(port.NewPortGroup("in1", "in2")...) - testInputs2 := port.NewPortsCollection().Add(port.NewPortGroup("in1", "in2")...) - testOutputs1 := port.NewPortsCollection().Add(port.NewPortGroup("out1", "out2")...) - testOutputs2 := port.NewPortsCollection().Add(port.NewPortGroup("out1", "out2")...) + testInputs1 := port.NewCollection().Add(port.NewGroup("in1", "in2")...) + testInputs2 := port.NewCollection().Add(port.NewGroup("in1", "in2")...) + testOutputs1 := port.NewCollection().Add(port.NewGroup("out1", "out2")...) + testOutputs2 := port.NewCollection().Add(port.NewGroup("out1", "out2")...) err1 := componentAfter.f(testInputs1, testOutputs1) err2 := tt.args.f(testInputs2, testOutputs2) assert.Equal(t, err1, err2) @@ -306,8 +306,8 @@ func TestComponent_WithInputs(t *testing.T) { name: "c1", description: "", inputs: port.Collection{ - "p1": port.NewPort("p1"), - "p2": port.NewPort("p2"), + "p1": port.New("p1"), + "p2": port.New("p2"), }, outputs: port.Collection{}, f: nil, @@ -358,8 +358,8 @@ func TestComponent_WithOutputs(t *testing.T) { description: "", inputs: port.Collection{}, outputs: port.Collection{ - "p1": port.NewPort("p1"), - "p2": port.NewPort("p2"), + "p1": port.New("p1"), + "p2": port.New("p2"), }, f: nil, }, @@ -405,7 +405,7 @@ func TestComponent_MaybeActivate(t *testing.T) { name: "component with inputs set, but no activation func", getComponent: func() *Component { c := NewComponent("c1").WithInputs("i1") - c.Inputs().ByName("i1").PutSignal(signal.New(123)) + c.Inputs().ByName("i1").PutSignals(signal.New(123)) return c }, wantActivationResult: NewActivationResult("c1"). @@ -419,7 +419,7 @@ func TestComponent_MaybeActivate(t *testing.T) { WithInputs("i1", "i2"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - if !inputs.ByNames("i1", "i2").AllHaveSignal() { + if !inputs.ByNames("i1", "i2").AllHaveSignals() { return NewErrWaitForInputs(false) } @@ -438,14 +438,14 @@ func TestComponent_MaybeActivate(t *testing.T) { WithInputs("i1", "i2"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - if !inputs.ByNames("i1", "i2").AllHaveSignal() { + if !inputs.ByNames("i1", "i2").AllHaveSignals() { return NewErrWaitForInputs(false) } return nil }) //Only one input set - c.Inputs().ByName("i1").PutSignal(signal.New(123)) + c.Inputs().ByName("i1").PutSignals(signal.New(123)) return c }, wantActivationResult: NewActivationResult("c1"). @@ -459,14 +459,14 @@ func TestComponent_MaybeActivate(t *testing.T) { WithInputs("i1", "i2"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - if !inputs.ByNames("i1", "i2").AllHaveSignal() { + if !inputs.ByNames("i1", "i2").AllHaveSignals() { return NewErrWaitForInputs(true) } return nil }) //Only one input set - c.Inputs().ByName("i1").PutSignal(signal.New(123)) + c.Inputs().ByName("i1").PutSignals(signal.New(123)) return c }, wantActivationResult: NewActivationResult("c1"). @@ -482,7 +482,7 @@ func TestComponent_MaybeActivate(t *testing.T) { return errors.New("test error") }) //Only one input set - c.Inputs().ByName("i1").PutSignal(signal.New(123)) + c.Inputs().ByName("i1").PutSignals(signal.New(123)) return c }, wantActivationResult: NewActivationResult("c1"). @@ -497,11 +497,11 @@ func TestComponent_MaybeActivate(t *testing.T) { WithInputs("i1"). WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - port.ForwardSignal(inputs.ByName("i1"), outputs.ByName("o1")) + port.ForwardSignals(inputs.ByName("i1"), outputs.ByName("o1")) return nil }) //Only one input set - c.Inputs().ByName("i1").PutSignal(signal.New(123)) + c.Inputs().ByName("i1").PutSignals(signal.New(123)) return c }, wantActivationResult: NewActivationResult("c1"). @@ -515,12 +515,12 @@ func TestComponent_MaybeActivate(t *testing.T) { WithInputs("i1"). WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - port.ForwardSignal(inputs.ByName("i1"), outputs.ByName("o1")) + port.ForwardSignals(inputs.ByName("i1"), outputs.ByName("o1")) panic(errors.New("oh shrimps")) return nil }) //Only one input set - c.Inputs().ByName("i1").PutSignal(signal.New(123)) + c.Inputs().ByName("i1").PutSignals(signal.New(123)) return c }, wantActivationResult: NewActivationResult("c1"). @@ -535,12 +535,12 @@ func TestComponent_MaybeActivate(t *testing.T) { WithInputs("i1"). WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - port.ForwardSignal(inputs.ByName("i1"), outputs.ByName("o1")) + port.ForwardSignals(inputs.ByName("i1"), outputs.ByName("o1")) panic("oh shrimps") return nil }) //Only one input set - c.Inputs().ByName("i1").PutSignal(signal.New(123)) + c.Inputs().ByName("i1").PutSignals(signal.New(123)) return c }, wantActivationResult: NewActivationResult("c1"). diff --git a/fmesh_test.go b/fmesh_test.go index 3cb8b93..038bcbe 100644 --- a/fmesh_test.go +++ b/fmesh_test.go @@ -299,13 +299,13 @@ func TestFMesh_Run(t *testing.T) { WithInputs("i1"). WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - outputs.ByName("o1").PutSignal(signal.New(77)) + outputs.ByName("o1").PutSignals(signal.New(77)) return nil }), ), initFM: func(fm *FMesh) { //Fire the mesh - fm.Components().ByName("c1").Inputs().ByName("i1").PutSignal(signal.New("start c1")) + fm.Components().ByName("c1").Inputs().ByName("i1").PutSignals(signal.New("start c1")) }, want: cycle.NewCollection().Add( cycle.New(). @@ -327,7 +327,7 @@ func TestFMesh_Run(t *testing.T) { return errors.New("boom") })), initFM: func(fm *FMesh) { - fm.Components().ByName("c1").Inputs().ByName("i1").PutSignal(signal.New("start")) + fm.Components().ByName("c1").Inputs().ByName("i1").PutSignals(signal.New("start")) }, want: cycle.NewCollection().Add( cycle.New(). @@ -350,7 +350,7 @@ func TestFMesh_Run(t *testing.T) { WithInputs("i1"). WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - outputs.ByName("o1").PutSignal(signal.New(10)) + outputs.ByName("o1").PutSignals(signal.New(10)) return nil }), component.NewComponent("c2"). @@ -358,7 +358,7 @@ func TestFMesh_Run(t *testing.T) { WithInputs("i1"). WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - outputs.ByName("o1").PutSignal(inputs.ByName("i1").Signal()) + port.ForwardSignals(inputs.ByName("i1"), outputs.ByName("o1")) return nil }), component.NewComponent("c3"). @@ -384,8 +384,8 @@ func TestFMesh_Run(t *testing.T) { c2.Outputs().ByName("o1").PipeTo(c4.Inputs().ByName("i1")) //Input data - c1.Inputs().ByName("i1").PutSignal(signal.New("start c1")) - c3.Inputs().ByName("i1").PutSignal(signal.New("start c3")) + c1.Inputs().ByName("i1").PutSignals(signal.New("start c1")) + c3.Inputs().ByName("i1").PutSignals(signal.New("start c3")) }, want: cycle.NewCollection().Add( cycle.New(). @@ -448,7 +448,7 @@ func TestFMesh_Run(t *testing.T) { WithInputs("i1"). WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - outputs.ByName("o1").PutSignal(signal.New(10)) + outputs.ByName("o1").PutSignals(signal.New(10)) return nil }), component.NewComponent("c2"). @@ -456,7 +456,7 @@ func TestFMesh_Run(t *testing.T) { WithInputs("i1"). WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - outputs.ByName("o1").PutSignal(inputs.ByName("i1").Signal()) + port.ForwardSignals(inputs.ByName("i1"), outputs.ByName("o1")) return nil }), component.NewComponent("c3"). @@ -471,7 +471,7 @@ func TestFMesh_Run(t *testing.T) { WithInputs("i1"). WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - outputs.ByName("o1").PutSignal(inputs.ByName("i1").Signal()) + port.ForwardSignals(inputs.ByName("i1"), outputs.ByName("o1")) // Even component panicked, it managed to set some data on output "o1" // so that data will be available in next cycle @@ -483,7 +483,7 @@ func TestFMesh_Run(t *testing.T) { WithInputs("i1"). WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - outputs.ByName("o1").PutSignal(inputs.ByName("i1").Signal()) + port.ForwardSignals(inputs.ByName("i1"), outputs.ByName("o1")) return nil }), ), @@ -495,8 +495,8 @@ func TestFMesh_Run(t *testing.T) { c4.Outputs().ByName("o1").PipeTo(c5.Inputs().ByName("i1")) //Input data - c1.Inputs().ByName("i1").PutSignal(signal.New("start c1")) - c3.Inputs().ByName("i1").PutSignal(signal.New("start c3")) + c1.Inputs().ByName("i1").PutSignals(signal.New("start c1")) + c3.Inputs().ByName("i1").PutSignals(signal.New("start c3")) }, want: cycle.NewCollection().Add( //c1 and c3 activated, c3 finishes with error @@ -654,7 +654,7 @@ func TestFMesh_runCycle(t *testing.T) { WithInputs("i1"). WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - outputs.ByName("o1").PutSignal(signal.New("this signal will never be sent")) + outputs.ByName("o1").PutSignals(signal.New("this signal will never be sent")) return nil }), @@ -668,7 +668,7 @@ func TestFMesh_runCycle(t *testing.T) { WithInputs("i1", "i2"). WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - if !inputs.ByNames("i1", "i2").AllHaveSignal() { + if !inputs.ByNames("i1", "i2").AllHaveSignals() { return component.NewErrWaitForInputs(true) } return nil @@ -676,7 +676,7 @@ func TestFMesh_runCycle(t *testing.T) { ), initFM: func(fm *FMesh) { //Only i1 is set, while component is waiting for both i1 and i2 to be set - fm.Components().ByName("c3").Inputs().ByName("i1").PutSignal(signal.New(123)) + fm.Components().ByName("c3").Inputs().ByName("i1").PutSignals(signal.New(123)) }, want: cycle.New(). WithActivationResults( @@ -698,9 +698,9 @@ func TestFMesh_runCycle(t *testing.T) { }), ), initFM: func(fm *FMesh) { - fm.Components().ByName("c1").Inputs().ByName("i1").PutSignal(signal.New(1)) - fm.Components().ByName("c2").Inputs().ByName("i1").PutSignal(signal.New(2)) - fm.Components().ByName("c3").Inputs().ByName("i1").PutSignal(signal.New(3)) + fm.Components().ByName("c1").Inputs().ByName("i1").PutSignals(signal.New(1)) + fm.Components().ByName("c2").Inputs().ByName("i1").PutSignals(signal.New(2)) + fm.Components().ByName("c3").Inputs().ByName("i1").PutSignals(signal.New(3)) }, want: cycle.New().WithActivationResults( component.NewActivationResult("c1").SetActivated(true).WithActivationCode(component.ActivationCodeOK), @@ -748,10 +748,10 @@ func TestFMesh_drainComponents(t *testing.T) { }, assertionsAfterDrain: func(t *testing.T, fm *FMesh) { //All ports in all components are empty - assert.False(t, fm.Components().ByName("c1").Inputs().AnyHasSignal()) - assert.False(t, fm.Components().ByName("c1").Outputs().AnyHasSignal()) - assert.False(t, fm.Components().ByName("c2").Inputs().AnyHasSignal()) - assert.False(t, fm.Components().ByName("c2").Outputs().AnyHasSignal()) + assert.False(t, fm.Components().ByName("c1").Inputs().AnyHasSignals()) + assert.False(t, fm.Components().ByName("c1").Outputs().AnyHasSignals()) + assert.False(t, fm.Components().ByName("c2").Inputs().AnyHasSignals()) + assert.False(t, fm.Components().ByName("c2").Outputs().AnyHasSignals()) }, }, { @@ -762,17 +762,17 @@ func TestFMesh_drainComponents(t *testing.T) { ), initFM: func(fm *FMesh) { //Both components have signals on their outputs - fm.Components().ByName("c1").Outputs().ByName("o1").PutSignal(signal.New(1)) - fm.Components().ByName("c2").Outputs().ByName("o1").PutSignal(signal.New(1)) + fm.Components().ByName("c1").Outputs().ByName("o1").PutSignals(signal.New(1)) + fm.Components().ByName("c2").Outputs().ByName("o1").PutSignals(signal.New(1)) }, assertionsAfterDrain: func(t *testing.T, fm *FMesh) { //Output signals are still there - assert.True(t, fm.Components().ByName("c1").Outputs().ByName("o1").HasSignal()) - assert.True(t, fm.Components().ByName("c2").Outputs().ByName("o1").HasSignal()) + assert.True(t, fm.Components().ByName("c1").Outputs().ByName("o1").HasSignals()) + assert.True(t, fm.Components().ByName("c2").Outputs().ByName("o1").HasSignals()) //Inputs are clear - assert.False(t, fm.Components().ByName("c1").Inputs().ByName("i1").HasSignal()) - assert.False(t, fm.Components().ByName("c2").Inputs().ByName("i1").HasSignal()) + assert.False(t, fm.Components().ByName("c1").Inputs().ByName("i1").HasSignals()) + assert.False(t, fm.Components().ByName("c2").Inputs().ByName("i1").HasSignals()) }, }, { @@ -787,14 +787,14 @@ func TestFMesh_drainComponents(t *testing.T) { c1.Outputs().ByName("o1").PipeTo(c2.Inputs().ByName("i1")) //c1 has a signal which must go to c2.i1 after drain - c1.Outputs().ByName("o1").PutSignal(signal.New(123)) + c1.Outputs().ByName("o1").PutSignals(signal.New(123)) }, assertionsAfterDrain: func(t *testing.T, fm *FMesh) { c1, c2 := fm.Components().ByName("c1"), fm.Components().ByName("c2") - assert.True(t, c2.Inputs().ByName("i1").HasSignal()) //Signal is transferred to destination port - assert.False(t, c1.Outputs().ByName("o1").HasSignal()) //Source port is cleaned up - assert.Equal(t, c2.Inputs().ByName("i1").Signal().Payload().(int), 123) //The signal is correct + assert.True(t, c2.Inputs().ByName("i1").HasSignals()) //Signals is transferred to destination port + assert.False(t, c1.Outputs().ByName("o1").HasSignals()) //Source port is cleaned up + assert.Equal(t, c2.Inputs().ByName("i1").Signals().FirstPayload().(int), 123) //The signal is correct }, }, } diff --git a/integration_tests/computation/math_test.go b/integration_tests/computation/math_test.go index ebae1cb..6bfa36a 100644 --- a/integration_tests/computation/math_test.go +++ b/integration_tests/computation/math_test.go @@ -25,8 +25,8 @@ func Test_Math(t *testing.T) { WithInputs("num"). WithOutputs("res"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - num := inputs.ByName("num").Signal().Payload().(int) - outputs.ByName("res").PutSignal(signal.New(num + 2)) + num := inputs.ByName("num").Signals().FirstPayload().(int) + outputs.ByName("res").PutSignals(signal.New(num + 2)) return nil }) @@ -35,8 +35,8 @@ func Test_Math(t *testing.T) { WithInputs("num"). WithOutputs("res"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - num := inputs.ByName("num").Signal().Payload().(int) - outputs.ByName("res").PutSignal(signal.New(num * 3)) + num := inputs.ByName("num").Signals().FirstPayload().(int) + outputs.ByName("res").PutSignals(signal.New(num * 3)) return nil }) @@ -45,15 +45,15 @@ func Test_Math(t *testing.T) { return fmesh.New("fm").WithComponents(c1, c2).WithErrorHandlingStrategy(fmesh.StopOnFirstError) }, setInputs: func(fm *fmesh.FMesh) { - fm.Components().ByName("c1").Inputs().ByName("num").PutSignal(signal.New(32)) + fm.Components().ByName("c1").Inputs().ByName("num").PutSignals(signal.New(32)) }, assertions: func(t *testing.T, fm *fmesh.FMesh, cycles cycle.Collection, err error) { assert.NoError(t, err) assert.Len(t, cycles, 3) - resultSignal := fm.Components().ByName("c2").Outputs().ByName("res").Signal() - assert.Len(t, resultSignal.Payloads(), 1) - assert.Equal(t, 102, resultSignal.Payload().(int)) + resultSignals := fm.Components().ByName("c2").Outputs().ByName("res").Signals() + assert.Len(t, resultSignals, 1) + assert.Equal(t, 102, resultSignals.FirstPayload().(int)) }, }, } diff --git a/integration_tests/piping/multiplexing_test.go b/integration_tests/piping/multiplexing_test.go index 7530865..8449f67 100644 --- a/integration_tests/piping/multiplexing_test.go +++ b/integration_tests/piping/multiplexing_test.go @@ -27,7 +27,7 @@ func Test_Multiplexing(t *testing.T) { WithInputs("start"). WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - outputs.ByName("o1").PutSignal(signal.New(time.Now())) + outputs.ByName("o1").PutSignals(signal.New(time.Now())) return nil }), @@ -36,7 +36,7 @@ func Test_Multiplexing(t *testing.T) { WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { //Bypass received signal to output - port.ForwardSignal(inputs.ByName("i1"), outputs.ByName("o1")) + port.ForwardSignals(inputs.ByName("i1"), outputs.ByName("o1")) return nil }), @@ -45,7 +45,7 @@ func Test_Multiplexing(t *testing.T) { WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { //Bypass received signal to output - port.ForwardSignal(inputs.ByName("i1"), outputs.ByName("o1")) + port.ForwardSignals(inputs.ByName("i1"), outputs.ByName("o1")) return nil }), @@ -54,7 +54,7 @@ func Test_Multiplexing(t *testing.T) { WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { //Bypass received signal to output - port.ForwardSignal(inputs.ByName("i1"), outputs.ByName("o1")) + port.ForwardSignals(inputs.ByName("i1"), outputs.ByName("o1")) return nil }), ) @@ -68,19 +68,19 @@ func Test_Multiplexing(t *testing.T) { }, setInputs: func(fm *fmesh.FMesh) { //Fire the mesh - fm.Components().ByName("producer").Inputs().ByName("start").PutSignal(signal.New(struct{}{})) + fm.Components().ByName("producer").Inputs().ByName("start").PutSignals(signal.New(struct{}{})) }, assertions: func(t *testing.T, fm *fmesh.FMesh, cycles cycle.Collection, err error) { //All consumers received a signal c1, c2, c3 := fm.Components().ByName("consumer1"), fm.Components().ByName("consumer2"), fm.Components().ByName("consumer3") - assert.True(t, c1.Outputs().ByName("o1").HasSignal()) - assert.True(t, c2.Outputs().ByName("o1").HasSignal()) - assert.True(t, c3.Outputs().ByName("o1").HasSignal()) + assert.True(t, c1.Outputs().ByName("o1").HasSignals()) + assert.True(t, c2.Outputs().ByName("o1").HasSignals()) + assert.True(t, c3.Outputs().ByName("o1").HasSignals()) //All 3 signals are the same (literally the same address in memory) - sig1, sig2, sig3 := c1.Outputs().ByName("o1").Signal(), c2.Outputs().ByName("o1").Signal(), c3.Outputs().ByName("o1").Signal() - assert.Equal(t, sig1.Payload(), sig2.Payload()) - assert.Equal(t, sig2.Payload(), sig3.Payload()) + sig1, sig2, sig3 := c1.Outputs().ByName("o1").Signals(), c2.Outputs().ByName("o1").Signals(), c3.Outputs().ByName("o1").Signals() + assert.Equal(t, sig1.FirstPayload(), sig2.FirstPayload()) + assert.Equal(t, sig2.FirstPayload(), sig3.FirstPayload()) }, }, { @@ -90,7 +90,7 @@ func Test_Multiplexing(t *testing.T) { WithInputs("start"). WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - outputs.ByName("o1").PutSignal(signal.New(rand.Int())) + outputs.ByName("o1").PutSignals(signal.New(rand.Int())) return nil }) @@ -98,7 +98,7 @@ func Test_Multiplexing(t *testing.T) { WithInputs("start"). WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - outputs.ByName("o1").PutSignal(signal.New(rand.Int())) + outputs.ByName("o1").PutSignals(signal.New(rand.Int())) return nil }) @@ -106,7 +106,7 @@ func Test_Multiplexing(t *testing.T) { WithInputs("start"). WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { - outputs.ByName("o1").PutSignal(signal.New(rand.Int())) + outputs.ByName("o1").PutSignals(signal.New(rand.Int())) return nil }) consumer := component.NewComponent("consumer"). @@ -114,7 +114,7 @@ func Test_Multiplexing(t *testing.T) { WithOutputs("o1"). WithActivationFunc(func(inputs port.Collection, outputs port.Collection) error { //Bypass - port.ForwardSignal(inputs.ByName("i1"), outputs.ByName("o1")) + port.ForwardSignals(inputs.ByName("i1"), outputs.ByName("o1")) return nil }) @@ -125,21 +125,21 @@ func Test_Multiplexing(t *testing.T) { return fmesh.New("multiplexer").WithComponents(producer1, producer2, producer3, consumer) }, setInputs: func(fm *fmesh.FMesh) { - fm.Components().ByName("producer1").Inputs().ByName("start").PutSignal(signal.New(struct{}{})) - fm.Components().ByName("producer2").Inputs().ByName("start").PutSignal(signal.New(struct{}{})) - fm.Components().ByName("producer3").Inputs().ByName("start").PutSignal(signal.New(struct{}{})) + fm.Components().ByName("producer1").Inputs().ByName("start").PutSignals(signal.New(struct{}{})) + fm.Components().ByName("producer2").Inputs().ByName("start").PutSignals(signal.New(struct{}{})) + fm.Components().ByName("producer3").Inputs().ByName("start").PutSignals(signal.New(struct{}{})) }, assertions: func(t *testing.T, fm *fmesh.FMesh, cycles cycle.Collection, err error) { //Consumer received a signal - assert.True(t, fm.Components().ByName("consumer").Outputs().ByName("o1").HasSignal()) + assert.True(t, fm.Components().ByName("consumer").Outputs().ByName("o1").HasSignals()) //The signal is combined and consist of 3 payloads - resultSignal := fm.Components().ByName("consumer").Outputs().ByName("o1").Signal() - assert.Equal(t, resultSignal.Len(), 3) + resultSignals := fm.Components().ByName("consumer").Outputs().ByName("o1").Signals() + assert.Len(t, resultSignals, 3) //And they are all different - assert.NotEqual(t, resultSignal.Payloads()[0], resultSignal.Payloads()[1]) - assert.NotEqual(t, resultSignal.Payloads()[1], resultSignal.Payloads()[2]) + assert.NotEqual(t, resultSignals.FirstPayload(), resultSignals[1].Payload()) + assert.NotEqual(t, resultSignals[1].Payload(), resultSignals[2].Payload()) }, }, } diff --git a/port/collection.go b/port/collection.go index 5f44ca9..ebc6e6d 100644 --- a/port/collection.go +++ b/port/collection.go @@ -7,8 +7,8 @@ import ( // Collection is a port collection with useful methods type Collection map[string]*Port -// NewPortsCollection creates empty collection -func NewPortsCollection() Collection { +// NewCollection creates empty collection +func NewCollection() Collection { return make(Collection) } @@ -30,10 +30,10 @@ func (collection Collection) ByNames(names ...string) Collection { return selectedPorts } -// AnyHasSignal returns true if at least one port in collection has signal -func (collection Collection) AnyHasSignal() bool { +// AnyHasSignals returns true if at least one port in collection has signals +func (collection Collection) AnyHasSignals() bool { for _, p := range collection { - if p.HasSignal() { + if p.HasSignals() { return true } } @@ -41,10 +41,10 @@ func (collection Collection) AnyHasSignal() bool { return false } -// AllHaveSignal returns true when all ports in collection have signal -func (collection Collection) AllHaveSignal() bool { +// AllHaveSignals returns true when all ports in collection have signals +func (collection Collection) AllHaveSignals() bool { for _, p := range collection { - if !p.HasSignal() { + if !p.HasSignals() { return false } } @@ -52,17 +52,17 @@ func (collection Collection) AllHaveSignal() bool { return true } -// PutSignal puts a signal to all the port in collection -func (collection Collection) PutSignal(sig *signal.Signal) { +// PutSignals puts a signals to all the port in collection +func (collection Collection) PutSignals(signals ...*signal.Signal) { for _, p := range collection { - p.PutSignal(sig) + p.PutSignals(signals...) } } -// ClearSignal removes signals from all ports in collection -func (collection Collection) ClearSignal() { +// ClearSignals removes signals from all ports in collection +func (collection Collection) ClearSignals() { for _, p := range collection { - p.ClearSignal() + p.ClearSignals() } } diff --git a/port/collection_test.go b/port/collection_test.go index 7a09582..9d716f1 100644 --- a/port/collection_test.go +++ b/port/collection_test.go @@ -3,20 +3,16 @@ package port import ( "github.com/hovsep/fmesh/signal" "github.com/stretchr/testify/assert" - "reflect" "testing" ) func TestCollection_AllHaveSignal(t *testing.T) { - oneEmptyPorts := NewPortsCollection().Add(NewPortGroup("p1", "p2", "p3")...) - oneEmptyPorts.PutSignal(signal.New(123)) - oneEmptyPorts.ByName("p2").ClearSignal() + oneEmptyPorts := NewCollection().Add(NewGroup("p1", "p2", "p3")...) + oneEmptyPorts.PutSignals(signal.New(123)) + oneEmptyPorts.ByName("p2").ClearSignals() - allWithSignalPorts := NewPortsCollection().Add(NewPortGroup("out1", "out2", "out3")...) - allWithSignalPorts.PutSignal(signal.New(77)) - - allWithEmptySignalPorts := NewPortsCollection().Add(NewPortGroup("in1", "in2", "in3")...) - allWithEmptySignalPorts.PutSignal(signal.New()) + allWithSignalPorts := NewCollection().Add(NewGroup("out1", "out2", "out3")...) + allWithSignalPorts.PutSignals(signal.New(77)) tests := []struct { name string @@ -25,7 +21,7 @@ func TestCollection_AllHaveSignal(t *testing.T) { }{ { name: "all empty", - ports: NewPortsCollection().Add(NewPortGroup("p1", "p2")...), + ports: NewCollection().Add(NewGroup("p1", "p2")...), want: false, }, { @@ -38,25 +34,20 @@ func TestCollection_AllHaveSignal(t *testing.T) { ports: allWithSignalPorts, want: true, }, - { - name: "all set with empty signals", - ports: allWithEmptySignalPorts, - want: true, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := tt.ports.AllHaveSignal(); got != tt.want { - t.Errorf("AllHaveSignal() = %v, want %v", got, tt.want) + if got := tt.ports.AllHaveSignals(); got != tt.want { + t.Errorf("AllHaveSignals() = %v, want %v", got, tt.want) } }) } } func TestCollection_AnyHasSignal(t *testing.T) { - oneEmptyPorts := NewPortsCollection().Add(NewPortGroup("p1", "p2", "p3")...) - oneEmptyPorts.PutSignal(signal.New(123)) - oneEmptyPorts.ByName("p2").ClearSignal() + oneEmptyPorts := NewCollection().Add(NewGroup("p1", "p2", "p3")...) + oneEmptyPorts.PutSignals(signal.New(123)) + oneEmptyPorts.ByName("p2").ClearSignals() tests := []struct { name string @@ -70,22 +61,22 @@ func TestCollection_AnyHasSignal(t *testing.T) { }, { name: "all empty", - ports: NewPortsCollection().Add(NewPortGroup("p1", "p2", "p3")...), + ports: NewCollection().Add(NewGroup("p1", "p2", "p3")...), want: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := tt.ports.AnyHasSignal(); got != tt.want { - t.Errorf("AnyHasSignal() = %v, want %v", got, tt.want) + if got := tt.ports.AnyHasSignals(); got != tt.want { + t.Errorf("AnyHasSignals() = %v, want %v", got, tt.want) } }) } } func TestCollection_ByName(t *testing.T) { - portsWithSignals := NewPortsCollection().Add(NewPortGroup("p1", "p2")...) - portsWithSignals.PutSignal(signal.New(12)) + portsWithSignals := NewCollection().Add(NewGroup("p1", "p2")...) + portsWithSignals.PutSignals(signal.New(12)) type args struct { name string @@ -98,27 +89,27 @@ func TestCollection_ByName(t *testing.T) { }{ { name: "empty port found", - ports: NewPortsCollection().Add(NewPortGroup("p1", "p2")...), + ports: NewCollection().Add(NewGroup("p1", "p2")...), args: args{ name: "p1", }, - want: &Port{name: "p1", pipes: Group{}}, + want: &Port{name: "p1", pipes: Group{}, signals: signal.Group{}}, }, { - name: "port with signal found", + name: "port with signals found", ports: portsWithSignals, args: args{ name: "p2", }, want: &Port{ - name: "p2", - signal: signal.New(12), - pipes: Group{}, + name: "p2", + signals: signal.NewGroup(12), + pipes: Group{}, }, }, { name: "port not found", - ports: NewPortsCollection().Add(NewPortGroup("p1", "p2")...), + ports: NewCollection().Add(NewGroup("p1", "p2")...), args: args{ name: "p3", }, @@ -127,9 +118,8 @@ func TestCollection_ByName(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := tt.ports.ByName(tt.args.name); !reflect.DeepEqual(got, tt.want) { - t.Errorf("ByName() = %v, want %v", got, tt.want) - } + got := tt.ports.ByName(tt.args.name) + assert.Equal(t, tt.want, got) }) } } @@ -146,31 +136,32 @@ func TestCollection_ByNames(t *testing.T) { }{ { name: "single port found", - ports: NewPortsCollection().Add(NewPortGroup("p1", "p2")...), + ports: NewCollection().Add(NewGroup("p1", "p2")...), args: args{ names: []string{"p1"}, }, want: Collection{ "p1": &Port{ - name: "p1", - pipes: Group{}, + name: "p1", + pipes: Group{}, + signals: signal.Group{}, }, }, }, { name: "multiple ports found", - ports: NewPortsCollection().Add(NewPortGroup("p1", "p2")...), + ports: NewCollection().Add(NewGroup("p1", "p2")...), args: args{ names: []string{"p1", "p2"}, }, want: Collection{ - "p1": &Port{name: "p1", pipes: Group{}}, - "p2": &Port{name: "p2", pipes: Group{}}, + "p1": &Port{name: "p1", pipes: Group{}, signals: signal.Group{}}, + "p2": &Port{name: "p2", pipes: Group{}, signals: signal.Group{}}, }, }, { name: "single port not found", - ports: NewPortsCollection().Add(NewPortGroup("p1", "p2")...), + ports: NewCollection().Add(NewGroup("p1", "p2")...), args: args{ names: []string{"p7"}, }, @@ -178,32 +169,31 @@ func TestCollection_ByNames(t *testing.T) { }, { name: "some ports not found", - ports: NewPortsCollection().Add(NewPortGroup("p1", "p2")...), + ports: NewCollection().Add(NewGroup("p1", "p2")...), args: args{ names: []string{"p1", "p2", "p3"}, }, want: Collection{ - "p1": &Port{name: "p1", pipes: Group{}}, - "p2": &Port{name: "p2", pipes: Group{}}, + "p1": &Port{name: "p1", pipes: Group{}, signals: signal.Group{}}, + "p2": &Port{name: "p2", pipes: Group{}, signals: signal.Group{}}, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := tt.ports.ByNames(tt.args.names...); !reflect.DeepEqual(got, tt.want) { - t.Errorf("ByNames() = %v, want %v", got, tt.want) - } + got := tt.ports.ByNames(tt.args.names...) + assert.Equal(t, tt.want, got) }) } } func TestCollection_ClearSignal(t *testing.T) { t.Run("happy path", func(t *testing.T) { - ports := NewPortsCollection().Add(NewPortGroup("p1", "p2", "p3")...) - ports.PutSignal(signal.New(1, 2, 3)) - assert.True(t, ports.AllHaveSignal()) - ports.ClearSignal() - assert.False(t, ports.AnyHasSignal()) + ports := NewCollection().Add(NewGroup("p1", "p2", "p3")...) + ports.PutSignals(signal.NewGroup(1, 2, 3)...) + assert.True(t, ports.AllHaveSignals()) + ports.ClearSignals() + assert.False(t, ports.AnyHasSignals()) }) } @@ -219,7 +209,7 @@ func TestCollection_Add(t *testing.T) { }{ { name: "adding nothing to empty collection", - collection: NewPortsCollection(), + collection: NewCollection(), args: args{ ports: nil, }, @@ -229,9 +219,9 @@ func TestCollection_Add(t *testing.T) { }, { name: "adding to empty collection", - collection: NewPortsCollection(), + collection: NewCollection(), args: args{ - ports: NewPortGroup("p1", "p2"), + ports: NewGroup("p1", "p2"), }, assertions: func(t *testing.T, collection Collection) { assert.Len(t, collection, 2) @@ -240,9 +230,9 @@ func TestCollection_Add(t *testing.T) { }, { name: "adding to existing collection", - collection: NewPortsCollection().Add(NewPortGroup("p1", "p2")...), + collection: NewCollection().Add(NewGroup("p1", "p2")...), args: args{ - ports: NewPortGroup("p3", "p4"), + ports: NewGroup("p3", "p4"), }, assertions: func(t *testing.T, collection Collection) { assert.Len(t, collection, 4) diff --git a/port/group.go b/port/group.go index f53dc93..28ea3fc 100644 --- a/port/group.go +++ b/port/group.go @@ -3,11 +3,11 @@ package port // Group is just a slice of ports (useful to pass multiple ports as variadic argument) type Group []*Port -// NewPortGroup creates multiple ports -func NewPortGroup(names ...string) Group { +// NewGroup creates multiple ports +func NewGroup(names ...string) Group { group := make(Group, len(names)) for _, name := range names { - group = append(group, NewPort(name)) + group = append(group, New(name)) } return group } diff --git a/port/port.go b/port/port.go index 6358083..f0aa207 100644 --- a/port/port.go +++ b/port/port.go @@ -6,16 +6,17 @@ import ( // Port defines a connectivity point of a component type Port struct { - name string - signal *signal.Signal //Current signal set on the port - pipes Group //Refs to all outbound pipes connected to this port + name string + signals signal.Group //Current signals set on the port + pipes Group //Refs to all outbound pipes connected to this port } -// NewPort creates a new port -func NewPort(name string) *Port { +// New creates a new port +func New(name string) *Port { return &Port{ - name: name, - pipes: NewPortGroup(), + name: name, + pipes: NewGroup(), + signals: signal.NewGroup(), } } @@ -24,24 +25,26 @@ func (p *Port) Name() string { return p.name } -// Signal getter -func (p *Port) Signal() *signal.Signal { - return p.signal +// Signals getter +func (p *Port) Signals() signal.Group { + return p.signals } -// PutSignal adds a signal to current signal -func (p *Port) PutSignal(sig *signal.Signal) { - p.signal = sig.Combine(p.Signal()) +// PutSignals adds a signals to current signals +func (p *Port) PutSignals(signals ...*signal.Signal) { + for _, s := range signals { + p.signals = append(p.signals, s) + } } -// ClearSignal removes current signal from the port -func (p *Port) ClearSignal() { - p.signal = nil +// ClearSignals removes current signals from the port +func (p *Port) ClearSignals() { + p.signals = signal.NewGroup() } -// HasSignal says whether port signal is set or not -func (p *Port) HasSignal() bool { - return p.signal != nil +// HasSignals says whether port signals is set or not +func (p *Port) HasSignals() bool { + return len(p.signals) > 0 } // PipeTo creates one or multiple pipes to other port(s) @@ -54,20 +57,20 @@ func (p *Port) PipeTo(toPorts ...*Port) { } } -// Flush pushed current signal to pipes and clears the port +// Flush pushed current signals to pipes and clears the port func (p *Port) Flush() { - if !p.HasSignal() || len(p.pipes) == 0 { + if !p.HasSignals() || len(p.pipes) == 0 { return } for _, outboundPort := range p.pipes { //Fan-Out - ForwardSignal(p, outboundPort) + ForwardSignals(p, outboundPort) } - p.ClearSignal() + p.ClearSignals() } -// ForwardSignal puts a signal from source port to destination port, without removing it on source port -func ForwardSignal(source *Port, dest *Port) { - dest.PutSignal(source.Signal()) +// ForwardSignals puts signals from source port to destination port, without clearing the source port +func ForwardSignals(source *Port, dest *Port) { + dest.PutSignals(source.Signals()...) } diff --git a/port/port_test.go b/port/port_test.go index d926f7c..89b69a1 100644 --- a/port/port_test.go +++ b/port/port_test.go @@ -6,12 +6,9 @@ import ( "testing" ) -func TestPort_HasSignal(t *testing.T) { - portWithSignal := NewPort("portWithSignal") - portWithSignal.PutSignal(signal.New(123)) - - portWithEmptySignal := NewPort("portWithEmptySignal") - portWithEmptySignal.PutSignal(signal.New()) +func TestPort_HasSignals(t *testing.T) { + portWithSignal := New("portWithSignal") + portWithSignal.PutSignals(signal.New(123)) tests := []struct { name string @@ -20,68 +17,55 @@ func TestPort_HasSignal(t *testing.T) { }{ { name: "empty port", - port: NewPort("emptyPort"), + port: New("emptyPort"), want: false, }, { - name: "port has normal signal", + name: "port has normal signals", port: portWithSignal, want: true, }, - { - name: "port has empty signal", - port: portWithEmptySignal, - want: true, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := tt.port.HasSignal(); got != tt.want { - t.Errorf("HasSignal() = %v, want %v", got, tt.want) + if got := tt.port.HasSignals(); got != tt.want { + t.Errorf("HasSignals() = %v, want %v", got, tt.want) } }) } } -func TestPort_Signal(t *testing.T) { - portWithSignal := NewPort("portWithSignal") - portWithSignal.PutSignal(signal.New(123)) - - portWithEmptySignal := NewPort("portWithEmptySignal") - portWithEmptySignal.PutSignal(signal.New()) +func TestPort_Signals(t *testing.T) { + portWithSignal := New("portWithSignal") + portWithSignal.PutSignals(signal.New(123)) tests := []struct { name string port *Port - want *signal.Signal + want signal.Group }{ { - name: "no signal", - port: NewPort("noSignal"), - want: nil, + name: "no signals", + port: New("noSignal"), + want: signal.Group{}, }, { name: "with signal", port: portWithSignal, - want: signal.New(123), - }, - { - name: "with empty signal", - port: portWithEmptySignal, - want: signal.New(), + want: signal.NewGroup(123), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := tt.port.Signal() + got := tt.port.Signals() assert.Equal(t, tt.want, got) }) } } func TestPort_ClearSignal(t *testing.T) { - portWithSignal := NewPort("portWithSignal") - portWithSignal.PutSignal(signal.New(111)) + portWithSignal := New("portWithSignal") + portWithSignal.PutSignals(signal.New(111)) tests := []struct { name string @@ -91,24 +75,24 @@ func TestPort_ClearSignal(t *testing.T) { { name: "happy path", before: portWithSignal, - after: &Port{name: "portWithSignal", pipes: Group{}}, + after: &Port{name: "portWithSignal", pipes: Group{}, signals: signal.Group{}}, }, { name: "cleaning empty port", - before: NewPort("emptyPort"), - after: &Port{name: "emptyPort", pipes: Group{}}, + before: New("emptyPort"), + after: &Port{name: "emptyPort", pipes: Group{}, signals: signal.Group{}}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - tt.before.ClearSignal() + tt.before.ClearSignals() assert.Equal(t, tt.after, tt.before) }) } } func TestPort_PipeTo(t *testing.T) { - p1, p2, p3, p4 := NewPort("p1"), NewPort("p2"), NewPort("p3"), NewPort("p4") + p1, p2, p3, p4 := New("p1"), New("p2"), New("p3"), New("p4") type args struct { toPorts []*Port @@ -123,8 +107,9 @@ func TestPort_PipeTo(t *testing.T) { name: "happy path", before: p1, after: &Port{ - name: "p1", - pipes: Group{p2, p3}, + name: "p1", + pipes: Group{p2, p3}, + signals: signal.Group{}, }, args: args{ toPorts: []*Port{p2, p3}, @@ -134,8 +119,9 @@ func TestPort_PipeTo(t *testing.T) { name: "invalid ports are ignored", before: p4, after: &Port{ - name: "p4", - pipes: Group{p2}, + name: "p4", + pipes: Group{p2}, + signals: signal.Group{}, }, args: args{ toPorts: []*Port{p2, nil}, @@ -150,18 +136,18 @@ func TestPort_PipeTo(t *testing.T) { } } -func TestPort_PutSignal(t *testing.T) { - portWithSingleSignal := NewPort("portWithSingleSignal") - portWithSingleSignal.PutSignal(signal.New(11)) +func TestPort_PutSignals(t *testing.T) { + portWithSingleSignal := New("portWithSingleSignal") + portWithSingleSignal.PutSignals(signal.New(11)) - portWithMultipleSignals := NewPort("portWithMultipleSignals") - portWithMultipleSignals.PutSignal(signal.New(11, 12)) + portWithMultipleSignals := New("portWithMultipleSignals") + portWithMultipleSignals.PutSignals(signal.NewGroup(11, 12)...) - portWithMultipleSignals2 := NewPort("portWithMultipleSignals2") - portWithMultipleSignals2.PutSignal(signal.New(55, 66)) + portWithMultipleSignals2 := New("portWithMultipleSignals2") + portWithMultipleSignals2.PutSignals(signal.NewGroup(55, 66)...) type args struct { - sig *signal.Signal + signals []*signal.Signal } tests := []struct { name string @@ -171,68 +157,68 @@ func TestPort_PutSignal(t *testing.T) { }{ { name: "single signal to empty port", - before: NewPort("emptyPort"), + before: New("emptyPort"), after: &Port{ - name: "emptyPort", - signal: signal.New(11), - pipes: Group{}, + name: "emptyPort", + signals: signal.NewGroup(11), + pipes: Group{}, }, args: args{ - sig: signal.New(11), + signals: signal.NewGroup(11), }, }, { name: "multiple signals to empty port", - before: NewPort("p"), + before: New("p"), after: &Port{ - name: "p", - signal: signal.New(11, 12), - pipes: Group{}, + name: "p", + signals: signal.NewGroup(11, 12), + pipes: Group{}, }, args: args{ - sig: signal.New(11, 12), + signals: signal.NewGroup(11, 12), }, }, { name: "single signal to port with single signal", before: portWithSingleSignal, after: &Port{ - name: "portWithSingleSignal", - signal: signal.New(12, 11), //Notice LIFO order - pipes: Group{}, + name: "portWithSingleSignal", + signals: signal.NewGroup(11, 12), + pipes: Group{}, }, args: args{ - sig: signal.New(12), + signals: signal.NewGroup(12), }, }, { - name: "single signal to port with multiple signals", + name: "single signals to port with multiple signals", before: portWithMultipleSignals, after: &Port{ - name: "portWithMultipleSignals", - signal: signal.New(13, 11, 12), //Notice LIFO order - pipes: Group{}, + name: "portWithMultipleSignals", + signals: signal.NewGroup(11, 12, 13), //Notice LIFO order + pipes: Group{}, }, args: args{ - sig: signal.New(13), + signals: signal.NewGroup(13), }, }, { name: "multiple signals to port with multiple signals", before: portWithMultipleSignals2, after: &Port{ - name: "portWithMultipleSignals2", - signal: signal.New(13, 14, 55, 66), //Notice LIFO order - pipes: Group{}, + name: "portWithMultipleSignals2", + signals: signal.NewGroup(55, 66, 13, 14), //Notice LIFO order + pipes: Group{}, }, args: args{ - sig: signal.New(13, 14), + signals: signal.NewGroup(13, 14), }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - tt.before.PutSignal(tt.args.sig) + tt.before.PutSignals(tt.args.signals...) assert.Equal(t, tt.after, tt.before) }) } @@ -246,7 +232,7 @@ func TestPort_Name(t *testing.T) { }{ { name: "happy path", - port: NewPort("p777"), + port: New("p777"), want: "p777", }, } @@ -271,34 +257,42 @@ func TestNewPort(t *testing.T) { args: args{ name: "", }, - want: &Port{name: "", pipes: Group{}}, + want: &Port{ + name: "", + pipes: Group{}, + signals: signal.Group{}, + }, }, { name: "with name", args: args{ name: "p1", }, - want: &Port{name: "p1", pipes: Group{}}, + want: &Port{ + name: "p1", + pipes: Group{}, + signals: signal.Group{}, + }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.want, NewPort(tt.args.name)) + assert.Equal(t, tt.want, New(tt.args.name)) }) } } func TestPort_Flush(t *testing.T) { - portWithSignal1 := NewPort("portWithSignal1") - portWithSignal1.PutSignal(signal.New(777)) + portWithSignal1 := New("portWithSignal1") + portWithSignal1.PutSignals(signal.New(777)) - portWithSignal2 := NewPort("portWithSignal2") - portWithSignal2.PutSignal(signal.New(888)) + portWithSignal2 := New("portWithSignal2") + portWithSignal2.PutSignals(signal.New(888)) - portWithMultipleSignals := NewPort("portWithMultipleSignals") - portWithMultipleSignals.PutSignal(signal.New(11, 12)) + portWithMultipleSignals := New("portWithMultipleSignals") + portWithMultipleSignals.PutSignals(signal.NewGroup(11, 12)...) - emptyPort := NewPort("emptyPort") + emptyPort := New("emptyPort") tests := []struct { name string @@ -307,12 +301,12 @@ func TestPort_Flush(t *testing.T) { assertions func(t *testing.T, source *Port, dest *Port) }{ { - name: "port with no signal", - source: NewPort("empty_src"), - dest: NewPort("empty_dest"), + name: "port with no signals", + source: New("empty_src"), + dest: New("empty_dest"), assertions: func(t *testing.T, source *Port, dest *Port) { - assert.False(t, source.HasSignal()) - assert.False(t, dest.HasSignal()) + assert.False(t, source.HasSignals()) + assert.False(t, dest.HasSignals()) }, }, { @@ -321,25 +315,25 @@ func TestPort_Flush(t *testing.T) { dest: emptyPort, assertions: func(t *testing.T, source *Port, dest *Port) { //Source port is clear - assert.False(t, source.HasSignal()) + assert.False(t, source.HasSignals()) - //Signal transferred to destination port - assert.True(t, dest.HasSignal()) - assert.Equal(t, dest.Signal().Payload().(int), 777) + //Signals transferred to destination port + assert.True(t, dest.HasSignals()) + assert.Equal(t, dest.Signals().FirstPayload().(int), 777) }, }, { - name: "flush to port with signal", + name: "flush to port with signals", source: portWithSignal2, dest: portWithMultipleSignals, assertions: func(t *testing.T, source *Port, dest *Port) { //Source port is clear - assert.False(t, source.HasSignal()) + assert.False(t, source.HasSignals()) //Destination port now has 1 more signal - assert.True(t, dest.HasSignal()) - assert.Equal(t, 3, dest.Signal().Len()) - assert.Contains(t, dest.Signal().Payloads(), 888) + assert.True(t, dest.HasSignals()) + assert.Len(t, dest.Signals(), 3) + assert.Contains(t, dest.Signals().AllPayloads(), 888) }, }, } diff --git a/signal/group.go b/signal/group.go new file mode 100644 index 0000000..b27cf4f --- /dev/null +++ b/signal/group.go @@ -0,0 +1,30 @@ +package signal + +type Group []*Signal + +// NewGroup creates empty group +func NewGroup(payloads ...any) Group { + group := make(Group, 0) + for _, payload := range payloads { + group = append(group, New(payload)) + } + return group +} + +// FirstPayload returns the first signal payload in a group +func (group Group) FirstPayload() any { + if len(group) == 0 { + return nil + } + + return group[0].Payload() +} + +// AllPayloads returns a slice with all payloads of the all signals in the group +func (group Group) AllPayloads() []any { + all := make([]any, 0) + for _, s := range group { + all = append(all, s.Payload()) + } + return all +} diff --git a/signal/group_test.go b/signal/group_test.go new file mode 100644 index 0000000..4a6c15e --- /dev/null +++ b/signal/group_test.go @@ -0,0 +1,3 @@ +package signal + +//@TODO implement diff --git a/signal/signal.go b/signal/signal.go index 2c0058e..7c9bcc1 100644 --- a/signal/signal.go +++ b/signal/signal.go @@ -1,50 +1,16 @@ package signal -// Signal describes a piece of data sent between components +// Signal is a wrapper around the data flowing between components type Signal struct { - payloads []any //Signal can carry multiple payloads (e.g. when multiple signals are combined) + payload []any //Slice is used in order to support nil payload } // New creates a new signal from the given payloads -func New(payloads ...any) *Signal { - return &Signal{payloads: payloads} +func New(payload any) *Signal { + return &Signal{payload: []any{payload}} } -// Len returns a number of payloads -func (s *Signal) Len() int { - return len(s.payloads) -} - -// HasPayload must be used to check whether signal carries at least 1 payload -func (s *Signal) HasPayload() bool { - return s.Len() > 0 -} - -// Payloads returns all payloads -func (s *Signal) Payloads() []any { - return s.payloads -} - -// Payload returns the first payload (useful when you are sure signal has only one payload) -// It panics when used with signal that carries multiple payloads +// Payload getter func (s *Signal) Payload() any { - if s.Len() != 1 { - panic("signal has zero or multiple payloads") - } - return s.payloads[0] -} - -// Combine returns a new signal with combined payloads of 2 original signals -func (s *Signal) Combine(anotherSignal *Signal) *Signal { - //Merging with nothing - if anotherSignal == nil || anotherSignal.Payloads() == nil { - return s - } - - //Original signal is empty - if s.Payloads() == nil { - return anotherSignal - } - - return New(append(s.Payloads(), anotherSignal.Payloads()...)...) + return s.payload[0] } diff --git a/signal/signal_test.go b/signal/signal_test.go index 2a07014..e2e372f 100644 --- a/signal/signal_test.go +++ b/signal/signal_test.go @@ -1,13 +1,13 @@ package signal import ( - "reflect" + "github.com/stretchr/testify/assert" "testing" ) func TestNew(t *testing.T) { type args struct { - payloads []any + payload any } tests := []struct { name string @@ -15,161 +15,28 @@ func TestNew(t *testing.T) { want *Signal }{ { - name: "nil payloads", + name: "nil payload is valid", args: args{ - payloads: nil, + payload: nil, }, - want: &Signal{payloads: nil}, - }, - { - name: "empty slice", - args: args{ - payloads: []any{}, - }, - want: &Signal{payloads: []any{}}, - }, - { - name: "single payloads", - args: args{ - payloads: []any{123}, - }, - want: &Signal{payloads: []any{123}}, - }, - { - name: "multiple payloads", - args: args{ - payloads: []any{123, "hello", []int{1, 2, 3}, map[string]int{"key": 42}, []byte{}, nil}, - }, - want: &Signal{payloads: []any{123, "hello", []int{1, 2, 3}, map[string]int{"key": 42}, []byte{}, nil}}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := New(tt.args.payloads...); !reflect.DeepEqual(got, tt.want) { - t.Errorf("New() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestSignal_Len(t *testing.T) { - tests := []struct { - name string - signal *Signal - want int - }{ - { - name: "no args", - signal: New(), - want: 0, - }, - { - name: "nil payload is valid", - signal: New(nil), - want: 1, - }, - { - name: "single payload", - signal: New(123), - want: 1, - }, - { - name: "multiple payloads", - signal: New(123, "hello", []int{1, 2, 3}, map[string]int{"key": 42}, []byte{}, nil), - want: 6, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := tt.signal.Len(); got != tt.want { - t.Errorf("Len() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestSignal_Combine(t *testing.T) { - tests := []struct { - name string - sigA *Signal - sigB *Signal - want *Signal - }{ - { - name: "two nils", - sigA: New(), - sigB: New(), - want: &Signal{ - payloads: nil, - }, - }, - { - name: "a is nil", - sigA: New(), - sigB: New(12, 13), want: &Signal{ - payloads: []any{12, 13}, + payload: []any{nil}, }, }, { - name: "b is nil", - sigA: New(14, 15), - sigB: New(), - want: &Signal{ - payloads: []any{14, 15}, + name: "with payload", + args: args{ + payload: []any{123, "hello", []int{1, 2, 3}, map[string]int{"key": 42}, []byte{}, nil}, }, - }, - { - name: "single payloads", - sigA: New(16), - sigB: New(map[string]string{"k": "v"}), - want: &Signal{ - payloads: []any{16, map[string]string{"k": "v"}}, + want: &Signal{payload: []any{ + []any{123, "hello", []int{1, 2, 3}, map[string]int{"key": 42}, []byte{}, nil}}, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := tt.sigA.Combine(tt.sigB); !reflect.DeepEqual(got, tt.want) { - t.Errorf("Combine() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestSignal_Payloads(t *testing.T) { - tests := []struct { - name string - signal *Signal - want []any - }{ - { - name: "no arg", - signal: New(), - want: nil, - }, - { - name: "nil payload", - signal: New(nil), - want: []any{nil}, - }, - - { - name: "single payload", - signal: New(123), - want: []any{123}, - }, - { - name: "multiple payloads", - signal: New(123, "hello", []int{1, 2, 3}, map[string]int{"key": 42}, []byte{}, nil), - want: []any{123, "hello", []int{1, 2, 3}, map[string]int{"key": 42}, []byte{}, nil}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := tt.signal.Payloads(); !reflect.DeepEqual(got, tt.want) { - t.Errorf("Payloads() = %v, want %v", got, tt.want) - } + got := New(tt.args.payload) + assert.Equal(t, tt.want, got) }) } } @@ -182,25 +49,15 @@ func TestSignal_Payload(t *testing.T) { wantPanic bool }{ { - name: "no arg", - signal: New(), - wantPanic: true, - }, - { - name: "nil payload", + name: "nil payload is valid", signal: New(nil), want: nil, }, { - name: "single payload", + name: "with payload", signal: New(123), want: 123, }, - { - name: "multiple payloads", - signal: New(1, 2), - wantPanic: true, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -214,40 +71,9 @@ func TestSignal_Payload(t *testing.T) { t.Errorf("The code unexpectedly paniced") } }() - if got := tt.signal.Payload(); !reflect.DeepEqual(got, tt.want) { - t.Errorf("Payloads() = %v, want %v", got, tt.want) - } - }) - } -} + got := tt.signal.Payload() -func TestSignal_HasPayload(t *testing.T) { - tests := []struct { - name string - signal *Signal - want bool - }{ - { - name: "has payload", - signal: New(123), - want: true, - }, - { - name: "has no payload", - signal: New(), - want: false, - }, - { - name: "nil payload is valid", - signal: New(nil), - want: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := tt.signal.HasPayload(); got != tt.want { - t.Errorf("HasPayload() = %v, want %v", got, tt.want) - } + assert.Equal(t, tt.want, got) }) } }