github.com/observiq/carbon@v0.9.11-0.20200820160507-1b872e368a5e/pipeline/pipeline_test.go (about) 1 package pipeline 2 3 import ( 4 "testing" 5 6 "github.com/observiq/carbon/operator" 7 "github.com/observiq/carbon/testutil" 8 "github.com/stretchr/testify/mock" 9 "github.com/stretchr/testify/require" 10 "gonum.org/v1/gonum/graph" 11 "gonum.org/v1/gonum/graph/simple" 12 "gonum.org/v1/gonum/graph/topo" 13 ) 14 15 func TestUnorderableToCycles(t *testing.T) { 16 t.Run("SingleCycle", func(t *testing.T) { 17 mockOperator1 := testutil.NewMockOperator("operator1") 18 mockOperator2 := testutil.NewMockOperator("operator2") 19 mockOperator3 := testutil.NewMockOperator("operator3") 20 mockOperator1.On("Outputs").Return([]operator.Operator{mockOperator2}) 21 mockOperator2.On("Outputs").Return([]operator.Operator{mockOperator3}) 22 mockOperator3.On("Outputs").Return([]operator.Operator{mockOperator1}) 23 24 err := topo.Unorderable([][]graph.Node{{ 25 createOperatorNode(mockOperator1), 26 createOperatorNode(mockOperator2), 27 createOperatorNode(mockOperator3), 28 }}) 29 30 output := unorderableToCycles(err) 31 expected := `(operator1 -> operator2 -> operator3 -> operator1)` 32 33 require.Equal(t, expected, output) 34 }) 35 36 t.Run("MultipleCycles", func(t *testing.T) { 37 mockOperator1 := testutil.NewMockOperator("operator1") 38 mockOperator2 := testutil.NewMockOperator("operator2") 39 mockOperator3 := testutil.NewMockOperator("operator3") 40 mockOperator1.On("Outputs").Return([]operator.Operator{mockOperator2}) 41 mockOperator2.On("Outputs").Return([]operator.Operator{mockOperator3}) 42 mockOperator3.On("Outputs").Return([]operator.Operator{mockOperator1}) 43 44 mockOperator4 := testutil.NewMockOperator("operator4") 45 mockOperator5 := testutil.NewMockOperator("operator5") 46 mockOperator6 := testutil.NewMockOperator("operator6") 47 mockOperator4.On("Outputs").Return([]operator.Operator{mockOperator5}) 48 mockOperator5.On("Outputs").Return([]operator.Operator{mockOperator6}) 49 mockOperator6.On("Outputs").Return([]operator.Operator{mockOperator4}) 50 51 err := topo.Unorderable([][]graph.Node{{ 52 createOperatorNode(mockOperator1), 53 createOperatorNode(mockOperator2), 54 createOperatorNode(mockOperator3), 55 }, { 56 createOperatorNode(mockOperator4), 57 createOperatorNode(mockOperator5), 58 createOperatorNode(mockOperator6), 59 }}) 60 61 output := unorderableToCycles(err) 62 expected := `(operator1 -> operator2 -> operator3 -> operator1),(operator4 -> operator5 -> operator6 -> operator4)` 63 64 require.Equal(t, expected, output) 65 }) 66 } 67 68 func TestPipeline(t *testing.T) { 69 t.Run("MultipleStart", func(t *testing.T) { 70 pipeline, err := NewPipeline([]operator.Operator{}) 71 require.NoError(t, err) 72 73 err = pipeline.Start() 74 require.NoError(t, err) 75 76 err = pipeline.Start() 77 require.NoError(t, err) 78 79 pipeline.Stop() 80 }) 81 82 t.Run("MultipleStop", func(t *testing.T) { 83 pipeline, err := NewPipeline([]operator.Operator{}) 84 require.NoError(t, err) 85 86 err = pipeline.Start() 87 require.NoError(t, err) 88 89 pipeline.Stop() 90 pipeline.Stop() 91 }) 92 93 t.Run("DuplicateNodeIDs", func(t *testing.T) { 94 operator1 := testutil.NewMockOperator("operator1") 95 operator1.On("SetOutputs", mock.Anything).Return(nil) 96 operator1.On("Outputs").Return(nil) 97 operator2 := testutil.NewMockOperator("operator1") 98 operator2.On("SetOutputs", mock.Anything).Return(nil) 99 operator2.On("Outputs").Return(nil) 100 101 _, err := NewPipeline([]operator.Operator{operator1, operator2}) 102 require.Error(t, err) 103 require.Contains(t, err.Error(), "already exists") 104 }) 105 106 t.Run("OutputNotExist", func(t *testing.T) { 107 operator1 := testutil.NewMockOperator("operator1") 108 operator1.On("SetOutputs", mock.Anything).Return(nil) 109 operator1.On("Outputs").Return() 110 111 operator2 := testutil.NewMockOperator("operator2") 112 operator2.On("SetOutputs", mock.Anything).Return(nil) 113 operator2.On("Outputs").Return([]operator.Operator{operator1}) 114 115 _, err := NewPipeline([]operator.Operator{operator2}) 116 require.Error(t, err) 117 require.Contains(t, err.Error(), "does not exist") 118 }) 119 120 t.Run("OutputNotProcessor", func(t *testing.T) { 121 operator1 := &testutil.Operator{} 122 operator1.On("ID").Return("operator1") 123 operator1.On("CanProcess").Return(false) 124 operator1.On("CanOutput").Return(true) 125 operator1.On("SetOutputs", mock.Anything).Return(nil) 126 operator1.On("Outputs").Return(nil) 127 128 operator2 := testutil.NewMockOperator("operator2") 129 operator2.On("SetOutputs", mock.Anything).Return(nil) 130 operator2.On("Outputs").Return([]operator.Operator{operator1}) 131 132 _, err := NewPipeline([]operator.Operator{operator1, operator2}) 133 require.Error(t, err) 134 require.Contains(t, err.Error(), "can not process") 135 }) 136 137 t.Run("DuplicateEdges", func(t *testing.T) { 138 operator1 := testutil.NewMockOperator("operator1") 139 operator1.On("SetOutputs", mock.Anything).Return(nil) 140 operator1.On("Outputs").Return(nil) 141 142 operator2 := testutil.NewMockOperator("operator2") 143 operator2.On("SetOutputs", mock.Anything).Return(nil) 144 operator2.On("Outputs").Return([]operator.Operator{operator1, operator1}) 145 146 node1 := createOperatorNode(operator1) 147 node2 := createOperatorNode(operator2) 148 149 graph := simple.NewDirectedGraph() 150 graph.AddNode(node1) 151 graph.AddNode(node2) 152 edge := graph.NewEdge(node2, node1) 153 graph.SetEdge(edge) 154 155 err := connectNode(graph, node2) 156 require.Error(t, err) 157 require.Contains(t, err.Error(), "connection already exists") 158 }) 159 160 t.Run("Cyclical", func(t *testing.T) { 161 mockOperator1 := testutil.NewMockOperator("operator1") 162 mockOperator2 := testutil.NewMockOperator("operator2") 163 mockOperator3 := testutil.NewMockOperator("operator3") 164 mockOperator1.On("Outputs").Return([]operator.Operator{mockOperator2}) 165 mockOperator1.On("SetOutputs", mock.Anything).Return(nil) 166 mockOperator2.On("Outputs").Return([]operator.Operator{mockOperator3}) 167 mockOperator2.On("SetOutputs", mock.Anything).Return(nil) 168 mockOperator3.On("Outputs").Return([]operator.Operator{mockOperator1}) 169 mockOperator3.On("SetOutputs", mock.Anything).Return(nil) 170 171 _, err := NewPipeline([]operator.Operator{mockOperator1, mockOperator2, mockOperator3}) 172 require.Error(t, err) 173 require.Contains(t, err.Error(), "circular dependency") 174 }) 175 }